3030import java .io .IOException ;
3131import java .math .BigInteger ;
3232
33- import java .security .GeneralSecurityException ;
3433import java .security .KeyFactory ;
3534import java .security .KeyPair ;
3635import java .security .NoSuchAlgorithmException ;
3938import java .security .interfaces .DSAParams ;
4039import java .security .interfaces .DSAPrivateKey ;
4140import java .security .interfaces .DSAPublicKey ;
41+ import java .security .interfaces .ECPrivateKey ;
42+ import java .security .interfaces .ECPublicKey ;
4243import java .security .interfaces .RSAPrivateCrtKey ;
4344import java .security .interfaces .RSAPublicKey ;
4445import java .security .spec .DSAPrivateKeySpec ;
4546import java .security .spec .DSAPublicKeySpec ;
47+ import java .security .spec .ECParameterSpec ;
48+ import java .security .spec .ECPrivateKeySpec ;
4649import java .security .spec .InvalidKeySpecException ;
4750import java .security .spec .KeySpec ;
51+ import java .security .spec .PKCS8EncodedKeySpec ;
4852import java .security .spec .RSAPrivateCrtKeySpec ;
4953import java .security .spec .RSAPublicKeySpec ;
54+ import java .security .spec .X509EncodedKeySpec ;
5055import javax .crypto .spec .DHParameterSpec ;
5156
5257import org .bouncycastle .asn1 .ASN1EncodableVector ;
5358import org .bouncycastle .asn1 .ASN1InputStream ;
5459import org .bouncycastle .asn1 .ASN1Integer ;
60+ import org .bouncycastle .asn1 .ASN1ObjectIdentifier ;
61+ import org .bouncycastle .asn1 .ASN1Primitive ;
5562import org .bouncycastle .asn1 .ASN1Sequence ;
5663import org .bouncycastle .asn1 .DLSequence ;
64+ import org .bouncycastle .asn1 .pkcs .PrivateKeyInfo ;
65+ import org .bouncycastle .asn1 .sec .ECPrivateKeyStructure ;
66+ import org .bouncycastle .asn1 .x509 .AlgorithmIdentifier ;
67+ import org .bouncycastle .asn1 .x509 .SubjectPublicKeyInfo ;
68+ import org .bouncycastle .asn1 .x9 .X9ObjectIdentifiers ;
69+ import org .bouncycastle .jce .ECNamedCurveTable ;
70+ import org .bouncycastle .jce .spec .ECNamedCurveParameterSpec ;
71+ import org .bouncycastle .jce .spec .ECPublicKeySpec ;
5772
5873import org .jruby .ext .openssl .SecurityHelper ;
5974
6580 */
6681public class PKey {
6782
68- public static KeyPair readPrivateKey (byte [] input , String type ) throws IOException , GeneralSecurityException {
83+ public static KeyPair readPrivateKey (final byte [] input , final String type )
84+ throws IOException , NoSuchAlgorithmException , InvalidKeySpecException {
6985 KeySpec pubSpec ; KeySpec privSpec ;
7086 ASN1Sequence seq = (ASN1Sequence ) new ASN1InputStream (input ).readObject ();
7187 if ( type .equals ("RSA" ) ) {
@@ -80,7 +96,8 @@ public static KeyPair readPrivateKey(byte[] input, String type) throws IOExcepti
8096 pubSpec = new RSAPublicKeySpec (mod .getValue (), pubExp .getValue ());
8197 privSpec = new RSAPrivateCrtKeySpec (mod .getValue (), pubExp .getValue (), privExp .getValue (), p1 .getValue (), p2 .getValue (), exp1 .getValue (),
8298 exp2 .getValue (), crtCoef .getValue ());
83- } else { // assume "DSA" for now.
99+ }
100+ else if ( type .equals ("DSA" ) ) {
84101 ASN1Integer p = (ASN1Integer ) seq .getObjectAt (1 );
85102 ASN1Integer q = (ASN1Integer ) seq .getObjectAt (2 );
86103 ASN1Integer g = (ASN1Integer ) seq .getObjectAt (3 );
@@ -89,6 +106,12 @@ public static KeyPair readPrivateKey(byte[] input, String type) throws IOExcepti
89106 privSpec = new DSAPrivateKeySpec (x .getValue (), p .getValue (), q .getValue (), g .getValue ());
90107 pubSpec = new DSAPublicKeySpec (y .getValue (), p .getValue (), q .getValue (), g .getValue ());
91108 }
109+ else if ( type .equals ("ECDSA" ) ) {
110+ return readECPrivateKey (input );
111+ }
112+ else {
113+ throw new IllegalStateException ("unsupported type: " + type );
114+ }
92115 KeyFactory fact = SecurityHelper .getKeyFactory (type );
93116 return new KeyPair (fact .generatePublic (pubSpec ), fact .generatePrivate (privSpec ));
94117 }
@@ -147,7 +170,6 @@ public static KeyPair readRSAPrivateKey(final byte[] input)
147170
148171 public static KeyPair readRSAPrivateKey (final KeyFactory rsaFactory , final byte [] input )
149172 throws IOException , InvalidKeySpecException {
150- // KeyFactory fact = SecurityHelper.getKeyFactory("RSA");
151173 ASN1Sequence seq = (ASN1Sequence ) new ASN1InputStream (input ).readObject ();
152174 if ( seq .size () == 9 ) {
153175 BigInteger mod = ((ASN1Integer ) seq .getObjectAt (1 )).getValue ();
@@ -232,6 +254,36 @@ public static DHParameterSpec readDHParameter(final byte[] input) throws IOExcep
232254 return new DHParameterSpec (p , g );
233255 }
234256
257+ public static KeyPair readECPrivateKey (final byte [] input )
258+ throws IOException , NoSuchAlgorithmException , InvalidKeySpecException {
259+ return readECPrivateKey (SecurityHelper .getKeyFactory ("ECDSA" ), input );
260+ }
261+
262+ public static KeyPair readECPrivateKey (final KeyFactory ecFactory , final byte [] input )
263+ throws IOException , InvalidKeySpecException {
264+ try {
265+ ECPrivateKeyStructure pKey = new ECPrivateKeyStructure ((ASN1Sequence ) ASN1Primitive .fromByteArray (input ));
266+ AlgorithmIdentifier algId = new AlgorithmIdentifier (X9ObjectIdentifiers .id_ecPublicKey , pKey .getParameters ());
267+ PrivateKeyInfo privInfo = new PrivateKeyInfo (algId , pKey .toASN1Primitive ());
268+ SubjectPublicKeyInfo pubInfo = new SubjectPublicKeyInfo (algId , pKey .getPublicKey ().getBytes ());
269+ PKCS8EncodedKeySpec privSpec = new PKCS8EncodedKeySpec (privInfo .getEncoded ());
270+ X509EncodedKeySpec pubSpec = new X509EncodedKeySpec (pubInfo .getEncoded ());
271+ //KeyFactory fact = KeyFactory.getInstance("ECDSA", provider);
272+
273+ ECPrivateKey privateKey = (ECPrivateKey ) ecFactory .generatePrivate (privSpec );
274+ if ( algId .getParameters () instanceof ASN1ObjectIdentifier ) {
275+ privateKey = ECPrivateKeyWithName .wrap (privateKey , (ASN1ObjectIdentifier ) algId .getParameters ());
276+ }
277+ return new KeyPair (ecFactory .generatePublic (pubSpec ), privateKey );
278+ }
279+ catch (ClassCastException ex ) {
280+ throw new IOException ("wrong ASN.1 object found in stream" , ex );
281+ }
282+ //catch (Exception ex) {
283+ // throw new IOException("problem parsing EC private key: " + ex);
284+ //}
285+ }
286+
235287 public static byte [] toDerRSAKey (RSAPublicKey pubKey , RSAPrivateCrtKey privKey ) throws IOException {
236288 ASN1EncodableVector vec = new ASN1EncodableVector ();
237289 if ( pubKey != null && privKey == null ) {
@@ -268,7 +320,7 @@ public static byte[] toDerDSAKey(DSAPublicKey pubKey, DSAPrivateKey privKey) thr
268320 return new DLSequence (vec ).getEncoded ();
269321 }
270322 if ( privKey == null ) {
271- throw new IllegalArgumentException ("passed private key as well as public key are null" );
323+ throw new IllegalArgumentException ("private key as well as public key are null" );
272324 }
273325 return privKey .getEncoded ();
274326 }
0 commit comments