Meki Cherkaoui | 88d59cd | 2012-05-14 07:34:58 -0700 | [diff] [blame] | 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.
|
Jeff Thompson | 1a338f8 | 2012-12-29 17:07:04 -0800 | [diff] [blame] | 57 | // If pInfo is supplied, it is the position in hCert of the SubjectPublicKeyInfo.
|
| 58 | function _x509_getSubjectPublicKeyPosFromCertHex(hCert, pInfo) {
|
| 59 | if (pInfo == null)
|
| 60 | pInfo = _x509_getSubjectPublicKeyInfoPosFromCertHex(hCert);
|
Meki Cherkaoui | 88d59cd | 2012-05-14 07:34:58 -0700 | [diff] [blame] | 61 | if (pInfo == -1) return -1;
|
| 62 | var a = ASN1HEX.getPosArrayOfChildren_AtObj(hCert, pInfo);
|
| 63 |
|
| 64 | if (a.length != 2) return -1;
|
| 65 | var pBitString = a[1];
|
| 66 | if (hCert.substring(pBitString, pBitString + 2) != '03') return -1;
|
| 67 | var pBitStringV = ASN1HEX.getStartPosOfV_AtObj(hCert, pBitString);
|
| 68 |
|
| 69 | if (hCert.substring(pBitStringV, pBitStringV + 2) != '00') return -1;
|
| 70 | return pBitStringV + 2;
|
| 71 | }
|
| 72 |
|
Jeff Thompson | 1a338f8 | 2012-12-29 17:07:04 -0800 | [diff] [blame] | 73 | // If p is supplied, it is the public key position in hCert.
|
| 74 | function _x509_getPublicKeyHexArrayFromCertHex(hCert, p) {
|
| 75 | if (p == null)
|
| 76 | p = _x509_getSubjectPublicKeyPosFromCertHex(hCert);
|
Meki Cherkaoui | 88d59cd | 2012-05-14 07:34:58 -0700 | [diff] [blame] | 77 | var a = ASN1HEX.getPosArrayOfChildren_AtObj(hCert, p);
|
| 78 | //var a = ASN1HEX.getPosArrayOfChildren_AtObj(hCert, a[3]);
|
| 79 | if(LOG>4){
|
| 80 | console.log('a is now');
|
| 81 | console.log(a);
|
| 82 | }
|
| 83 |
|
| 84 | //if (a.length != 2) return [];
|
| 85 | if (a.length < 2) return [];
|
| 86 |
|
| 87 | var hN = ASN1HEX.getHexOfV_AtObj(hCert, a[0]);
|
| 88 | var hE = ASN1HEX.getHexOfV_AtObj(hCert, a[1]);
|
| 89 | if (hN != null && hE != null) {
|
| 90 | return [hN, hE];
|
| 91 | } else {
|
| 92 | return [];
|
| 93 | }
|
| 94 | }
|
| 95 |
|
| 96 | function _x509_getPublicKeyHexArrayFromCertPEM(sCertPEM) {
|
| 97 | var hCert = _x509_pemToHex(sCertPEM);
|
| 98 | var a = _x509_getPublicKeyHexArrayFromCertHex(hCert);
|
| 99 | return a;
|
| 100 | }
|
| 101 |
|
| 102 | // ===== get basic fields from hex =====================================
|
| 103 | /**
|
| 104 | * get hexadecimal string of serialNumber field of certificate.<br/>
|
| 105 | * @name getSerialNumberHex
|
| 106 | * @memberOf X509#
|
| 107 | * @function
|
| 108 | */
|
| 109 | function _x509_getSerialNumberHex() {
|
| 110 | return ASN1HEX.getDecendantHexVByNthList(this.hex, 0, [0, 1]);
|
| 111 | }
|
| 112 |
|
| 113 | /**
|
| 114 | * get hexadecimal string of issuer field of certificate.<br/>
|
| 115 | * @name getIssuerHex
|
| 116 | * @memberOf X509#
|
| 117 | * @function
|
| 118 | */
|
| 119 | function _x509_getIssuerHex() {
|
| 120 | return ASN1HEX.getDecendantHexTLVByNthList(this.hex, 0, [0, 3]);
|
| 121 | }
|
| 122 |
|
| 123 | /**
|
| 124 | * get string of issuer field of certificate.<br/>
|
| 125 | * @name getIssuerString
|
| 126 | * @memberOf X509#
|
| 127 | * @function
|
| 128 | */
|
| 129 | function _x509_getIssuerString() {
|
| 130 | return _x509_hex2dn(ASN1HEX.getDecendantHexTLVByNthList(this.hex, 0, [0, 3]));
|
| 131 | }
|
| 132 |
|
| 133 | /**
|
| 134 | * get hexadecimal string of subject field of certificate.<br/>
|
| 135 | * @name getSubjectHex
|
| 136 | * @memberOf X509#
|
| 137 | * @function
|
| 138 | */
|
| 139 | function _x509_getSubjectHex() {
|
| 140 | return ASN1HEX.getDecendantHexTLVByNthList(this.hex, 0, [0, 5]);
|
| 141 | }
|
| 142 |
|
| 143 | /**
|
| 144 | * get string of subject field of certificate.<br/>
|
| 145 | * @name getSubjectString
|
| 146 | * @memberOf X509#
|
| 147 | * @function
|
| 148 | */
|
| 149 | function _x509_getSubjectString() {
|
| 150 | return _x509_hex2dn(ASN1HEX.getDecendantHexTLVByNthList(this.hex, 0, [0, 5]));
|
| 151 | }
|
| 152 |
|
| 153 | /**
|
| 154 | * get notBefore field string of certificate.<br/>
|
| 155 | * @name getNotBefore
|
| 156 | * @memberOf X509#
|
| 157 | * @function
|
| 158 | */
|
| 159 | function _x509_getNotBefore() {
|
| 160 | var s = ASN1HEX.getDecendantHexVByNthList(this.hex, 0, [0, 4, 0]);
|
| 161 | s = s.replace(/(..)/g, "%$1");
|
| 162 | s = decodeURIComponent(s);
|
| 163 | return s;
|
| 164 | }
|
| 165 |
|
| 166 | /**
|
| 167 | * get notAfter field string of certificate.<br/>
|
| 168 | * @name getNotAfter
|
| 169 | * @memberOf X509#
|
| 170 | * @function
|
| 171 | */
|
| 172 | function _x509_getNotAfter() {
|
| 173 | var s = ASN1HEX.getDecendantHexVByNthList(this.hex, 0, [0, 4, 1]);
|
| 174 | s = s.replace(/(..)/g, "%$1");
|
| 175 | s = decodeURIComponent(s);
|
| 176 | return s;
|
| 177 | }
|
| 178 |
|
| 179 | // ===== read certificate =====================================
|
| 180 |
|
| 181 | _x509_DN_ATTRHEX = {
|
| 182 | "0603550406": "C",
|
| 183 | "060355040a": "O",
|
| 184 | "060355040b": "OU",
|
| 185 | "0603550403": "CN",
|
| 186 | "0603550405": "SN",
|
| 187 | "0603550408": "ST",
|
| 188 | "0603550407": "L" };
|
| 189 |
|
| 190 | function _x509_hex2dn(hDN) {
|
| 191 | var s = "";
|
| 192 | var a = ASN1HEX.getPosArrayOfChildren_AtObj(hDN, 0);
|
| 193 | for (var i = 0; i < a.length; i++) {
|
| 194 | var hRDN = ASN1HEX.getHexOfTLV_AtObj(hDN, a[i]);
|
| 195 | s = s + "/" + _x509_hex2rdn(hRDN);
|
| 196 | }
|
| 197 | return s;
|
| 198 | }
|
| 199 |
|
| 200 | function _x509_hex2rdn(hRDN) {
|
| 201 | var hType = ASN1HEX.getDecendantHexTLVByNthList(hRDN, 0, [0, 0]);
|
| 202 | var hValue = ASN1HEX.getDecendantHexVByNthList(hRDN, 0, [0, 1]);
|
| 203 | var type = "";
|
| 204 | try { type = _x509_DN_ATTRHEX[hType]; } catch (ex) { type = hType; }
|
| 205 | hValue = hValue.replace(/(..)/g, "%$1");
|
| 206 | var value = decodeURIComponent(hValue);
|
| 207 | return type + "=" + value;
|
| 208 | }
|
| 209 |
|
| 210 | // ===== read certificate =====================================
|
| 211 |
|
| 212 |
|
| 213 | /**
|
| 214 | * read PEM formatted X.509 certificate from string.<br/>
|
| 215 | * @name readCertPEM
|
| 216 | * @memberOf X509#
|
| 217 | * @function
|
| 218 | * @param {String} sCertPEM string for PEM formatted X.509 certificate
|
| 219 | */
|
| 220 | function _x509_readCertPEM(sCertPEM) {
|
| 221 | var hCert = _x509_pemToHex(sCertPEM);
|
| 222 | var a = _x509_getPublicKeyHexArrayFromCertHex(hCert);
|
| 223 | if(LOG>4){
|
| 224 | console.log('HEX VALUE IS ' + hCert);
|
| 225 | console.log('type of a' + typeof a);
|
| 226 | console.log('a VALUE IS ');
|
| 227 | console.log(a);
|
| 228 | console.log('a[0] VALUE IS ' + a[0]);
|
| 229 | console.log('a[1] VALUE IS ' + a[1]);
|
| 230 | }
|
| 231 | var rsa = new RSAKey();
|
| 232 | rsa.setPublic(a[0], a[1]);
|
| 233 | this.subjectPublicKeyRSA = rsa;
|
| 234 | this.subjectPublicKeyRSA_hN = a[0];
|
| 235 | this.subjectPublicKeyRSA_hE = a[1];
|
| 236 | this.hex = hCert;
|
| 237 | }
|
| 238 |
|
Jeff Thompson | d3d45c8 | 2012-12-29 16:15:49 -0800 | [diff] [blame] | 239 | /**
|
| 240 | * read hex formatted X.509 certificate from string.
|
| 241 | * @name readCertHex
|
| 242 | * @memberOf X509#
|
| 243 | * @function
|
| 244 | * @param {String} hCert string for hex formatted X.509 certificate
|
| 245 | */
|
| 246 | function _x509_readCertHex(hCert) {
|
| 247 | hCert = hCert.toLowerCase();
|
| 248 | var a = _x509_getPublicKeyHexArrayFromCertHex(hCert);
|
| 249 | var rsa = new RSAKey();
|
| 250 | rsa.setPublic(a[0], a[1]);
|
| 251 | this.subjectPublicKeyRSA = rsa;
|
| 252 | this.subjectPublicKeyRSA_hN = a[0];
|
| 253 | this.subjectPublicKeyRSA_hE = a[1];
|
| 254 | this.hex = hCert;
|
| 255 | }
|
| 256 |
|
Meki Cherkaoui | 88d59cd | 2012-05-14 07:34:58 -0700 | [diff] [blame] | 257 | function _x509_readCertPEMWithoutRSAInit(sCertPEM) {
|
| 258 | var hCert = _x509_pemToHex(sCertPEM);
|
| 259 | var a = _x509_getPublicKeyHexArrayFromCertHex(hCert);
|
| 260 | this.subjectPublicKeyRSA.setPublic(a[0], a[1]);
|
| 261 | this.subjectPublicKeyRSA_hN = a[0];
|
| 262 | this.subjectPublicKeyRSA_hE = a[1];
|
| 263 | this.hex = hCert;
|
| 264 | }
|
| 265 |
|
| 266 | /**
|
| 267 | * X.509 certificate class.<br/>
|
| 268 | * @class X.509 certificate class
|
| 269 | * @property {RSAKey} subjectPublicKeyRSA Tom Wu's RSAKey object
|
| 270 | * @property {String} subjectPublicKeyRSA_hN hexadecimal string for modulus of RSA public key
|
| 271 | * @property {String} subjectPublicKeyRSA_hE hexadecimal string for public exponent of RSA public key
|
| 272 | * @property {String} hex hexacedimal string for X.509 certificate.
|
| 273 | * @author Kenji Urushima
|
| 274 | * @version 1.0.1 (08 May 2012)
|
| 275 | * @see <a href="http://kjur.github.com/jsrsasigns/">'jwrsasign'(RSA Sign JavaScript Library) home page http://kjur.github.com/jsrsasign/</a>
|
| 276 | */
|
| 277 | function X509() {
|
| 278 | this.subjectPublicKeyRSA = null;
|
| 279 | this.subjectPublicKeyRSA_hN = null;
|
| 280 | this.subjectPublicKeyRSA_hE = null;
|
| 281 | this.hex = null;
|
| 282 | }
|
| 283 |
|
| 284 | X509.prototype.readCertPEM = _x509_readCertPEM;
|
Jeff Thompson | d3d45c8 | 2012-12-29 16:15:49 -0800 | [diff] [blame] | 285 | X509.prototype.readCertHex = _x509_readCertHex;
|
Meki Cherkaoui | 88d59cd | 2012-05-14 07:34:58 -0700 | [diff] [blame] | 286 | X509.prototype.readCertPEMWithoutRSAInit = _x509_readCertPEMWithoutRSAInit;
|
| 287 | X509.prototype.getSerialNumberHex = _x509_getSerialNumberHex;
|
| 288 | X509.prototype.getIssuerHex = _x509_getIssuerHex;
|
| 289 | X509.prototype.getSubjectHex = _x509_getSubjectHex;
|
| 290 | X509.prototype.getIssuerString = _x509_getIssuerString;
|
| 291 | X509.prototype.getSubjectString = _x509_getSubjectString;
|
| 292 | X509.prototype.getNotBefore = _x509_getNotBefore;
|
| 293 | X509.prototype.getNotAfter = _x509_getNotAfter;
|
| 294 |
|