1 /*! x509-1.1.js (c) 2012 Kenji Urushima | kjur.github.com/jsrsasign/license 2 */ 3 // 4 // x509.js - X509 class to read subject public key from certificate. 5 // 6 // version: 1.1 (10-May-2012) 7 // 8 // Copyright (c) 2010-2012 Kenji Urushima (kenji.urushima@gmail.com) 9 // 10 // This software is licensed under the terms of the MIT License. 11 // http://kjur.github.com/jsrsasign/license 12 // 13 // The above copyright and license notice shall be 14 // included in all copies or substantial portions of the Software. 15 // 16 17 // Depends: 18 // base64.js 19 // rsa.js 20 // asn1hex.js 21 22 function _x509_pemToBase64(sCertPEM) { 23 var s = sCertPEM; 24 s = s.replace("-----BEGIN CERTIFICATE-----", ""); 25 s = s.replace("-----END CERTIFICATE-----", ""); 26 s = s.replace(/[ \n]+/g, ""); 27 return s; 28 } 29 30 function _x509_pemToHex(sCertPEM) { 31 var b64Cert = _x509_pemToBase64(sCertPEM); 32 var hCert = b64tohex(b64Cert); 33 return hCert; 34 } 35 36 function _x509_getHexTbsCertificateFromCert(hCert) { 37 var pTbsCert = ASN1HEX.getStartPosOfV_AtObj(hCert, 0); 38 return pTbsCert; 39 } 40 41 // NOTE: privateKeyUsagePeriod field of X509v2 not supported. 42 // NOTE: v1 and v3 supported 43 function _x509_getSubjectPublicKeyInfoPosFromCertHex(hCert) { 44 var pTbsCert = ASN1HEX.getStartPosOfV_AtObj(hCert, 0); 45 var a = ASN1HEX.getPosArrayOfChildren_AtObj(hCert, pTbsCert); 46 if (a.length < 1) return -1; 47 if (hCert.substring(a[0], a[0] + 10) == "a003020102") { // v3 48 if (a.length < 6) return -1; 49 return a[6]; 50 } else { 51 if (a.length < 5) return -1; 52 return a[5]; 53 } 54 } 55 56 // NOTE: Without BITSTRING encapsulation. 57 function _x509_getSubjectPublicKeyPosFromCertHex(hCert) { 58 var pInfo = _x509_getSubjectPublicKeyInfoPosFromCertHex(hCert); 59 if (pInfo == -1) return -1; 60 var a = ASN1HEX.getPosArrayOfChildren_AtObj(hCert, pInfo); 61 if (a.length != 2) return -1; 62 var pBitString = a[1]; 63 if (hCert.substring(pBitString, pBitString + 2) != '03') return -1; 64 var pBitStringV = ASN1HEX.getStartPosOfV_AtObj(hCert, pBitString); 65 66 if (hCert.substring(pBitStringV, pBitStringV + 2) != '00') return -1; 67 return pBitStringV + 2; 68 } 69 70 function _x509_getPublicKeyHexArrayFromCertHex(hCert) { 71 var p = _x509_getSubjectPublicKeyPosFromCertHex(hCert); 72 var a = ASN1HEX.getPosArrayOfChildren_AtObj(hCert, p); 73 if (a.length != 2) return []; 74 var hN = ASN1HEX.getHexOfV_AtObj(hCert, a[0]); 75 var hE = ASN1HEX.getHexOfV_AtObj(hCert, a[1]); 76 if (hN != null && hE != null) { 77 return [hN, hE]; 78 } else { 79 return []; 80 } 81 } 82 83 function _x509_getPublicKeyHexArrayFromCertPEM(sCertPEM) { 84 var hCert = _x509_pemToHex(sCertPEM); 85 var a = _x509_getPublicKeyHexArrayFromCertHex(hCert); 86 return a; 87 } 88 89 // ===== get basic fields from hex ===================================== 90 /** 91 * get hexadecimal string of serialNumber field of certificate.<br/> 92 * @name getSerialNumberHex 93 * @memberOf X509# 94 * @function 95 */ 96 function _x509_getSerialNumberHex() { 97 return ASN1HEX.getDecendantHexVByNthList(this.hex, 0, [0, 1]); 98 } 99 100 /** 101 * get hexadecimal string of issuer field of certificate.<br/> 102 * @name getIssuerHex 103 * @memberOf X509# 104 * @function 105 */ 106 function _x509_getIssuerHex() { 107 return ASN1HEX.getDecendantHexTLVByNthList(this.hex, 0, [0, 3]); 108 } 109 110 /** 111 * get string of issuer field of certificate.<br/> 112 * @name getIssuerString 113 * @memberOf X509# 114 * @function 115 */ 116 function _x509_getIssuerString() { 117 return _x509_hex2dn(ASN1HEX.getDecendantHexTLVByNthList(this.hex, 0, [0, 3])); 118 } 119 120 /** 121 * get hexadecimal string of subject field of certificate.<br/> 122 * @name getSubjectHex 123 * @memberOf X509# 124 * @function 125 */ 126 function _x509_getSubjectHex() { 127 return ASN1HEX.getDecendantHexTLVByNthList(this.hex, 0, [0, 5]); 128 } 129 130 /** 131 * get string of subject field of certificate.<br/> 132 * @name getSubjectString 133 * @memberOf X509# 134 * @function 135 */ 136 function _x509_getSubjectString() { 137 return _x509_hex2dn(ASN1HEX.getDecendantHexTLVByNthList(this.hex, 0, [0, 5])); 138 } 139 140 /** 141 * get notBefore field string of certificate.<br/> 142 * @name getNotBefore 143 * @memberOf X509# 144 * @function 145 */ 146 function _x509_getNotBefore() { 147 var s = ASN1HEX.getDecendantHexVByNthList(this.hex, 0, [0, 4, 0]); 148 s = s.replace(/(..)/g, "%$1"); 149 s = decodeURIComponent(s); 150 return s; 151 } 152 153 /** 154 * get notAfter field string of certificate.<br/> 155 * @name getNotAfter 156 * @memberOf X509# 157 * @function 158 */ 159 function _x509_getNotAfter() { 160 var s = ASN1HEX.getDecendantHexVByNthList(this.hex, 0, [0, 4, 1]); 161 s = s.replace(/(..)/g, "%$1"); 162 s = decodeURIComponent(s); 163 return s; 164 } 165 166 // ===== read certificate ===================================== 167 168 _x509_DN_ATTRHEX = { 169 "0603550406": "C", 170 "060355040a": "O", 171 "060355040b": "OU", 172 "0603550403": "CN", 173 "0603550405": "SN", 174 "0603550408": "ST", 175 "0603550407": "L" }; 176 177 function _x509_hex2dn(hDN) { 178 var s = ""; 179 var a = ASN1HEX.getPosArrayOfChildren_AtObj(hDN, 0); 180 for (var i = 0; i < a.length; i++) { 181 var hRDN = ASN1HEX.getHexOfTLV_AtObj(hDN, a[i]); 182 s = s + "/" + _x509_hex2rdn(hRDN); 183 } 184 return s; 185 } 186 187 function _x509_hex2rdn(hRDN) { 188 var hType = ASN1HEX.getDecendantHexTLVByNthList(hRDN, 0, [0, 0]); 189 var hValue = ASN1HEX.getDecendantHexVByNthList(hRDN, 0, [0, 1]); 190 var type = ""; 191 try { type = _x509_DN_ATTRHEX[hType]; } catch (ex) { type = hType; } 192 hValue = hValue.replace(/(..)/g, "%$1"); 193 var value = decodeURIComponent(hValue); 194 return type + "=" + value; 195 } 196 197 // ===== read certificate ===================================== 198 199 200 /** 201 * read PEM formatted X.509 certificate from string.<br/> 202 * @name readCertPEM 203 * @memberOf X509# 204 * @function 205 * @param {String} sCertPEM string for PEM formatted X.509 certificate 206 */ 207 function _x509_readCertPEM(sCertPEM) { 208 var hCert = _x509_pemToHex(sCertPEM); 209 var a = _x509_getPublicKeyHexArrayFromCertHex(hCert); 210 var rsa = new RSAKey(); 211 rsa.setPublic(a[0], a[1]); 212 this.subjectPublicKeyRSA = rsa; 213 this.subjectPublicKeyRSA_hN = a[0]; 214 this.subjectPublicKeyRSA_hE = a[1]; 215 this.hex = hCert; 216 } 217 218 function _x509_readCertPEMWithoutRSAInit(sCertPEM) { 219 var hCert = _x509_pemToHex(sCertPEM); 220 var a = _x509_getPublicKeyHexArrayFromCertHex(hCert); 221 this.subjectPublicKeyRSA.setPublic(a[0], a[1]); 222 this.subjectPublicKeyRSA_hN = a[0]; 223 this.subjectPublicKeyRSA_hE = a[1]; 224 this.hex = hCert; 225 } 226 227 /** 228 * X.509 certificate class.<br/> 229 * @class X.509 certificate class 230 * @property {RSAKey} subjectPublicKeyRSA Tom Wu's RSAKey object 231 * @property {String} subjectPublicKeyRSA_hN hexadecimal string for modulus of RSA public key 232 * @property {String} subjectPublicKeyRSA_hE hexadecimal string for public exponent of RSA public key 233 * @property {String} hex hexacedimal string for X.509 certificate. 234 * @author Kenji Urushima 235 * @version 1.0.1 (08 May 2012) 236 * @see <a href="http://kjur.github.com/jsrsasigns/">'jwrsasign'(RSA Sign JavaScript Library) home page http://kjur.github.com/jsrsasign/</a> 237 */ 238 function X509() { 239 this.subjectPublicKeyRSA = null; 240 this.subjectPublicKeyRSA_hN = null; 241 this.subjectPublicKeyRSA_hE = null; 242 this.hex = null; 243 } 244 245 X509.prototype.readCertPEM = _x509_readCertPEM; 246 X509.prototype.readCertPEMWithoutRSAInit = _x509_readCertPEMWithoutRSAInit; 247 X509.prototype.getSerialNumberHex = _x509_getSerialNumberHex; 248 X509.prototype.getIssuerHex = _x509_getIssuerHex; 249 X509.prototype.getSubjectHex = _x509_getSubjectHex; 250 X509.prototype.getIssuerString = _x509_getIssuerString; 251 X509.prototype.getSubjectString = _x509_getSubjectString; 252 X509.prototype.getNotBefore = _x509_getNotBefore; 253 X509.prototype.getNotAfter = _x509_getNotAfter; 254 255