@@ -74,30 +74,50 @@ public final class RSAPrivateCrtKeyImpl
7474 private transient AlgorithmParameterSpec keyParams ;
7575
7676 /**
77- * Generate a new key from its encoding. Returns a CRT key if possible
78- * and a non-CRT key otherwise. Used by RSAKeyFactory.
77+ * Generate a new RSAPrivate(Crt)Key from the specified type,
78+ * format and encoding. Returns a CRT key if possible and a non-CRT
79+ * key otherwise.
80+ * Also used by SunPKCS11 provider.
7981 */
80- public static RSAPrivateKey newKey (byte [] encoded )
81- throws InvalidKeyException {
82+ public static RSAPrivateKey newKey (KeyType type , String format ,
83+ byte [] encoded ) throws InvalidKeyException {
8284 if (encoded == null || encoded .length == 0 ) {
8385 throw new InvalidKeyException ("Missing key encoding" );
8486 }
85- RSAPrivateCrtKeyImpl key = new RSAPrivateCrtKeyImpl (encoded );
86- // check all CRT-specific components are available, if any one
87- // missing, return a non-CRT key instead
88- if ((key .getPublicExponent ().signum () == 0 ) ||
89- (key .getPrimeExponentP ().signum () == 0 ) ||
90- (key .getPrimeExponentQ ().signum () == 0 ) ||
91- (key .getPrimeP ().signum () == 0 ) ||
92- (key .getPrimeQ ().signum () == 0 ) ||
93- (key .getCrtCoefficient ().signum () == 0 )) {
94- return new RSAPrivateKeyImpl (
95- key .type , key .keyParams ,
96- key .getModulus (),
97- key .getPrivateExponent ()
98- );
99- } else {
100- return key ;
87+ switch (format ) {
88+ case "PKCS#8" :
89+ RSAPrivateCrtKeyImpl key = new RSAPrivateCrtKeyImpl (encoded );
90+ RSAKeyFactory .checkKeyAlgo (key , type .keyAlgo );
91+ // check all CRT-specific components are available, if any one
92+ // missing, return a non-CRT key instead
93+ if ((key .getPublicExponent ().signum () == 0 ) ||
94+ (key .getPrimeExponentP ().signum () == 0 ) ||
95+ (key .getPrimeExponentQ ().signum () == 0 ) ||
96+ (key .getPrimeP ().signum () == 0 ) ||
97+ (key .getPrimeQ ().signum () == 0 ) ||
98+ (key .getCrtCoefficient ().signum () == 0 )) {
99+ return new RSAPrivateKeyImpl (key .type , key .keyParams ,
100+ key .getModulus (), key .getPrivateExponent ());
101+ } else return key ;
102+ case "PKCS#1" :
103+ try {
104+ BigInteger [] comps = parseASN1 (encoded );
105+ if ((comps [1 ].signum () == 0 ) || (comps [3 ].signum () == 0 ) ||
106+ (comps [4 ].signum () == 0 ) || (comps [5 ].signum () == 0 ) ||
107+ (comps [6 ].signum () == 0 ) || (comps [7 ].signum () == 0 )) {
108+ return new RSAPrivateKeyImpl (type , null , comps [0 ],
109+ comps [2 ]);
110+ } else {
111+ return new RSAPrivateCrtKeyImpl (type , null , comps [0 ],
112+ comps [1 ], comps [2 ], comps [3 ], comps [4 ], comps [5 ],
113+ comps [6 ], comps [7 ]);
114+ }
115+ } catch (IOException ioe ) {
116+ throw new InvalidKeyException ("Invalid PKCS#1 encoding" , ioe );
117+ }
118+ default :
119+ throw new InvalidKeyException ("Unsupported RSA Private(Crt)Key "
120+ + "format: " + format );
101121 }
102122 }
103123
@@ -126,7 +146,7 @@ public static RSAPrivateKey newKey(KeyType type,
126146 /**
127147 * Construct a key from its encoding. Called from newKey above.
128148 */
129- RSAPrivateCrtKeyImpl (byte [] encoded ) throws InvalidKeyException {
149+ private RSAPrivateCrtKeyImpl (byte [] encoded ) throws InvalidKeyException {
130150 super (encoded );
131151 parseKeyBits ();
132152 RSAKeyFactory .checkRSAProviderKeyLengths (n .bitLength (), e );
@@ -258,37 +278,47 @@ public String toString() {
258278 + "\n modulus: " + n + "\n private exponent: " + d ;
259279 }
260280
281+ // utility method for parsing DER encoding of RSA private keys in PKCS#1
282+ // format as defined in RFC 8017 Appendix A.1.2, i.e. SEQ of version, n,
283+ // e, d, p, q, pe, qe, and coeff, and return the parsed components.
284+ private static BigInteger [] parseASN1 (byte [] raw ) throws IOException {
285+ DerValue derValue = new DerValue (raw );
286+ if (derValue .tag != DerValue .tag_Sequence ) {
287+ throw new IOException ("Not a SEQUENCE" );
288+ }
289+ int version = derValue .data .getInteger ();
290+ if (version != 0 ) {
291+ throw new IOException ("Version must be 0" );
292+ }
293+
294+ BigInteger [] result = new BigInteger [8 ]; // n, e, d, p, q, pe, qe, coeff
295+ /*
296+ * Some implementations do not correctly encode ASN.1 INTEGER values
297+ * in 2's complement format, resulting in a negative integer when
298+ * decoded. Correct the error by converting it to a positive integer.
299+ *
300+ * See CR 6255949
301+ */
302+ for (int i = 0 ; i < result .length ; i ++) {
303+ result [i ] = derValue .data .getPositiveBigInteger ();
304+ }
305+ if (derValue .data .available () != 0 ) {
306+ throw new IOException ("Extra data available" );
307+ }
308+ return result ;
309+ }
310+
261311 private void parseKeyBits () throws InvalidKeyException {
262312 try {
263- DerInputStream in = new DerInputStream (key );
264- DerValue derValue = in .getDerValue ();
265- if (derValue .tag != DerValue .tag_Sequence ) {
266- throw new IOException ("Not a SEQUENCE" );
267- }
268- DerInputStream data = derValue .data ;
269- int version = data .getInteger ();
270- if (version != 0 ) {
271- throw new IOException ("Version must be 0" );
272- }
273-
274- /*
275- * Some implementations do not correctly encode ASN.1 INTEGER values
276- * in 2's complement format, resulting in a negative integer when
277- * decoded. Correct the error by converting it to a positive integer.
278- *
279- * See CR 6255949
280- */
281- n = data .getPositiveBigInteger ();
282- e = data .getPositiveBigInteger ();
283- d = data .getPositiveBigInteger ();
284- p = data .getPositiveBigInteger ();
285- q = data .getPositiveBigInteger ();
286- pe = data .getPositiveBigInteger ();
287- qe = data .getPositiveBigInteger ();
288- coeff = data .getPositiveBigInteger ();
289- if (derValue .data .available () != 0 ) {
290- throw new IOException ("Extra data available" );
291- }
313+ BigInteger [] comps = parseASN1 (key );
314+ n = comps [0 ];
315+ e = comps [1 ];
316+ d = comps [2 ];
317+ p = comps [3 ];
318+ q = comps [4 ];
319+ pe = comps [5 ];
320+ qe = comps [6 ];
321+ coeff = comps [7 ];
292322 } catch (IOException e ) {
293323 throw new InvalidKeyException ("Invalid RSA private key" , e );
294324 }
0 commit comments