1 /*! rsapem-1.2.0.js (c) 2012-2017 Kenji Urushima | kjur.github.com/jsrsasign/license
  2  */
  3 /*
  4  * rsapem.js - Cryptographic Algorithm Provider class
  5  *
  6  * Copyright (c) 2013-2017 Kenji Urushima (kenji.urushima@gmail.com)
  7  *
  8  * This software is licensed under the terms of the MIT License.
  9  * http://kjur.github.com/jsrsasign/license
 10  *
 11  * The above copyright and license notice shall be 
 12  * included in all copies or substantial portions of the Software.
 13  */
 14 
 15 /**
 16  * @fileOverview
 17  * @name rsapem-1.1.js
 18  * @author Kenji Urushima kenji.urushima@gmail.com
 19  * @version 1.2.0 (2017-Jan-21)
 20  * @since jsrsasign 1.0
 21  * @license <a href="http://kjur.github.io/jsrsasign/license/">MIT License</a>
 22  */
 23 
 24 /**
 25  * static method to extract Base64 string from PKCS#5 PEM RSA private key.<br/>
 26  * @name pemToBase64
 27  * @memberOf RSAKey
 28  * @function
 29  * @param {String} sPEMPrivateKey PEM PKCS#1/5 s private key string
 30  * @return {String} Base64 string of private key
 31  * @description
 32  * removing PEM header, PEM footer and space characters including
 33  * new lines from PEM formatted RSA private key string.
 34  * @example
 35  * RSAKey.pemToBase64("----BEGIN PRIVATE KEY-...") → "MIICW..."
 36  */
 37 RSAKey.pemToBase64 = function(sPEMPrivateKey) {
 38     var s = sPEMPrivateKey;
 39     s = s.replace("-----BEGIN RSA PRIVATE KEY-----", "");
 40     s = s.replace("-----END RSA PRIVATE KEY-----", "");
 41     s = s.replace(/[ \n]+/g, "");
 42     return s;
 43 };
 44 
 45 /**
 46  * static method to get array of field positions from hexadecimal PKCS#5 RSA private key.<br/>
 47  * @name getPosArrayOfChildrenFromHex
 48  * @memberOf RSAKey
 49  * @function
 50  * @param {String} sPEMPrivateKey PEM PKCS#1/5 s private key string
 51  * @return {Array} array of field positions
 52  * @example
 53  * RSAKey.getPosArrayOfChildrenFromHex("3082...") → [8, 32, ...]
 54  */
 55 RSAKey.getPosArrayOfChildrenFromHex = function(hPrivateKey) {
 56     var a = new Array();
 57     var idx_v = ASN1HEX.getStartPosOfV_AtObj(hPrivateKey, 0);
 58     var idx_n = ASN1HEX.getPosOfNextSibling_AtObj(hPrivateKey, idx_v);
 59     var idx_e = ASN1HEX.getPosOfNextSibling_AtObj(hPrivateKey, idx_n);
 60     var idx_d = ASN1HEX.getPosOfNextSibling_AtObj(hPrivateKey, idx_e);
 61     var idx_p = ASN1HEX.getPosOfNextSibling_AtObj(hPrivateKey, idx_d);
 62     var idx_q = ASN1HEX.getPosOfNextSibling_AtObj(hPrivateKey, idx_p);
 63     var idx_dp = ASN1HEX.getPosOfNextSibling_AtObj(hPrivateKey, idx_q);
 64     var idx_dq = ASN1HEX.getPosOfNextSibling_AtObj(hPrivateKey, idx_dp);
 65     var idx_co = ASN1HEX.getPosOfNextSibling_AtObj(hPrivateKey, idx_dq);
 66     a.push(idx_v, idx_n, idx_e, idx_d, idx_p, idx_q, idx_dp, idx_dq, idx_co);
 67     return a;
 68 };
 69 
 70 /**
 71  * static method to get array of hex field values from hexadecimal PKCS#5 RSA private key.<br/>
 72  * @name getHexValueArrayOfChildrenFromHex
 73  * @memberOf RSAKey
 74  * @function
 75  * @param {String} sPEMPrivateKey PEM PKCS#1/5 s private key string
 76  * @return {Array} array of field hex value
 77  * @example
 78  * RSAKey.getHexValueArrayOfChildrenFromHex("3082...") → ["00", "3b42...", ...]
 79  */
 80 RSAKey.getHexValueArrayOfChildrenFromHex = function(hPrivateKey) {
 81     var posArray = RSAKey.getPosArrayOfChildrenFromHex(hPrivateKey);
 82     var h_v =  ASN1HEX.getHexOfV_AtObj(hPrivateKey, posArray[0]);
 83     var h_n =  ASN1HEX.getHexOfV_AtObj(hPrivateKey, posArray[1]);
 84     var h_e =  ASN1HEX.getHexOfV_AtObj(hPrivateKey, posArray[2]);
 85     var h_d =  ASN1HEX.getHexOfV_AtObj(hPrivateKey, posArray[3]);
 86     var h_p =  ASN1HEX.getHexOfV_AtObj(hPrivateKey, posArray[4]);
 87     var h_q =  ASN1HEX.getHexOfV_AtObj(hPrivateKey, posArray[5]);
 88     var h_dp = ASN1HEX.getHexOfV_AtObj(hPrivateKey, posArray[6]);
 89     var h_dq = ASN1HEX.getHexOfV_AtObj(hPrivateKey, posArray[7]);
 90     var h_co = ASN1HEX.getHexOfV_AtObj(hPrivateKey, posArray[8]);
 91     var a = new Array();
 92     a.push(h_v, h_n, h_e, h_d, h_p, h_q, h_dp, h_dq, h_co);
 93     return a;
 94 };
 95 
 96 /**
 97  * read PKCS#1 private key from a string<br/>
 98  * @name readPrivateKeyFromPEMString
 99  * @memberOf RSAKey#
100  * @function
101  * @param {String} keyPEM string of PKCS#1 private key.
102  */
103 RSAKey.prototype.readPrivateKeyFromPEMString = function(keyPEM) {
104     var keyB64 = RSAKey.pemToBase64(keyPEM);
105     var keyHex = b64tohex(keyB64) // depends base64.js
106     var a = RSAKey.getHexValueArrayOfChildrenFromHex(keyHex);
107     this.setPrivateEx(a[1],a[2],a[3],a[4],a[5],a[6],a[7],a[8]);
108 };
109 
110 /**
111  * (DEPRECATED) read RSA private key from a ASN.1 hexadecimal string<br/>
112  * @name readPrivateKeyFromASN1HexString
113  * @memberOf RSAKey#
114  * @function
115  * @param {String} keyHex ASN.1 hexadecimal string of PKCS#1 private key.
116  * @since rsapem 1.1.1
117  * @deprecated since jsrsasign 7.1.0 rsapem 1.2.0, please use {@link RSAKey.readPKCS5PrvKeyHex} instead.
118  */
119 RSAKey.prototype.readPrivateKeyFromASN1HexString = function(keyHex) {
120     this.readPKCS5PrvKeyHex(keyHex);
121 };
122 
123 /**
124  * read an ASN.1 hexadecimal string of PKCS#1/5 plain RSA private key<br/>
125  * @name readPKCS5PrvKeyHex
126  * @memberOf RSAKey#
127  * @function
128  * @param {String} h hexadecimal string of PKCS#1/5 plain RSA private key
129  * @since jsrsasign 7.1.0 rsapem 1.2.0
130  * @see {@link RSAKey.readPrivateKeyFromASN1HexString} former method
131  */
132 RSAKey.prototype.readPKCS5PrvKeyHex = function(h) {
133     var a = RSAKey.getHexValueArrayOfChildrenFromHex(h);
134     this.setPrivateEx(a[1],a[2],a[3],a[4],a[5],a[6],a[7],a[8]);
135 };
136 
137 /**
138  * read an ASN.1 hexadecimal string of PKCS#8 plain RSA private key<br/>
139  * @name readPKCS8PrvKeyHex
140  * @memberOf RSAKey#
141  * @function
142  * @param {String} h hexadecimal string of PKCS#8 plain RSA private key
143  * @since jsrsasign 7.1.0 rsapem 1.2.0
144  */
145 RSAKey.prototype.readPKCS8PrvKeyHex = function(h) {
146     var hN, hE, hD, hP, hQ, hDP, hDQ, hCO;
147     var _ASN1HEX = ASN1HEX;
148     var _getVbyList = _ASN1HEX.getVbyList;
149 
150     if (_ASN1HEX.isASN1HEX(h) === false)
151 	throw "not ASN.1 hex string";
152 
153     try {
154 	hN  = _getVbyList(h, 0, [2, 0, 1], "02");
155 	hE  = _getVbyList(h, 0, [2, 0, 2], "02");
156 	hD  = _getVbyList(h, 0, [2, 0, 3], "02");
157 	hP  = _getVbyList(h, 0, [2, 0, 4], "02");
158 	hQ  = _getVbyList(h, 0, [2, 0, 5], "02");
159 	hDP = _getVbyList(h, 0, [2, 0, 6], "02");
160 	hDQ = _getVbyList(h, 0, [2, 0, 7], "02");
161 	hCO = _getVbyList(h, 0, [2, 0, 8], "02");
162     } catch(ex) {
163 	throw "malformed PKCS#8 plain RSA private key";
164     }
165 
166     this.setPrivateEx(hN, hE, hD, hP, hQ, hDP, hDQ, hCO);
167 };
168 
169 /**
170  * read an ASN.1 hexadecimal string of PKCS#5 RSA public key<br/>
171  * @name readPKCS5PubKeyHex
172  * @memberOf RSAKey#
173  * @function
174  * @param {String} h hexadecimal string of PKCS#5 public key
175  * @since jsrsasign 7.1.0 rsapem 1.2.0
176  */
177 RSAKey.prototype.readPKCS5PubKeyHex = function(h) {
178     if (ASN1HEX.isASN1HEX(h) === false)
179 	throw "keyHex is not ASN.1 hex string";
180     var aIdx = ASN1HEX.getPosArrayOfChildren_AtObj(h, 0);
181     if (aIdx.length !== 2 ||
182 	h.substr(aIdx[0], 2) !== "02" ||
183 	h.substr(aIdx[1], 2) !== "02")
184 	throw "wrong hex for PKCS#5 public key";
185     var hN = ASN1HEX.getHexOfV_AtObj(h, aIdx[0]);
186     var hE = ASN1HEX.getHexOfV_AtObj(h, aIdx[1]);
187     this.setPublic(hN, hE);
188 };
189 
190 /**
191  * read an ASN.1 hexadecimal string of PKCS#8 RSA public key<br/>
192  * @name readPKCS8PubKeyHex
193  * @memberOf RSAKey#
194  * @function
195  * @param {String} h hexadecimal string of PKCS#8 public key
196  * @since jsrsasign 7.1.0 rsapem 1.2.0
197  */
198 RSAKey.prototype.readPKCS8PubKeyHex = function(h) {
199     if (ASN1HEX.isASN1HEX(h) === false)
200 	throw "not ASN.1 hex string";
201 
202     // 06092a864886f70d010101: OBJECT IDENTIFIER rsaEncryption (1 2 840 113549 1 1 1)
203     if (ASN1HEX.getDecendantHexTLVByNthList(h, 0, [0, 0]) !== "06092a864886f70d010101")
204 	throw "not PKCS8 RSA public key";
205 
206     var p5hex = ASN1HEX.getDecendantHexTLVByNthList(h, 0, [1, 0]);
207     this.readPKCS5PubKeyHex(p5hex);
208 };
209 
210 /**
211  * read an ASN.1 hexadecimal string of X.509 RSA public key certificate<br/>
212  * @name readCertPubKeyHex
213  * @memberOf RSAKey#
214  * @function
215  * @param {String} h hexadecimal string of X.509 RSA public key certificate
216  * @param {Integer} nthPKI nth index of publicKeyInfo. (DEFAULT: 6 for X509v3)
217  * @since jsrsasign 7.1.0 rsapem 1.2.0
218  */
219 RSAKey.prototype.readCertPubKeyHex = function(h, nthPKI) {
220     if (nthPKI !== 5) nthPKI = 6;
221     if (ASN1HEX.isASN1HEX(h) === false)
222 	throw "not ASN.1 hex string";
223 
224     var p8hex = ASN1HEX.getDecendantHexTLVByNthList(h, 0, [0, nthPKI]);
225     this.readPKCS8PubKeyHex(p8hex);
226 };
227