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