diff --git a/src/main/java/org/jruby/ext/openssl/PKey.java b/src/main/java/org/jruby/ext/openssl/PKey.java index 1bf3dacf..ba01b401 100644 --- a/src/main/java/org/jruby/ext/openssl/PKey.java +++ b/src/main/java/org/jruby/ext/openssl/PKey.java @@ -129,7 +129,7 @@ public static IRubyObject read(final ThreadContext context, IRubyObject recv, IR (DSAPrivateKey) keyPair.getPrivate(), (DSAPublicKey) keyPair.getPublic() ); } - if ( "ECDSA".equals(alg) ) { + if ( "EC".equals(alg) ) { return new PKeyEC(runtime, _PKey(runtime).getClass("EC"), (PrivateKey) keyPair.getPrivate(), (PublicKey) keyPair.getPublic() ); @@ -165,7 +165,7 @@ public static IRubyObject read(final ThreadContext context, IRubyObject recv, IR if ( "DSA".equals(pubKey.getAlgorithm()) ) { return new PKeyDSA(runtime, (DSAPublicKey) pubKey); } - if ( "ECDSA".equals(pubKey.getAlgorithm()) ) { + if ( "EC".equals(pubKey.getAlgorithm()) ) { return new PKeyEC(runtime, pubKey); } } @@ -197,6 +197,8 @@ public IRubyObject initialize(ThreadContext context) { public String getAlgorithm() { return "NONE"; } + public String getKeyType() { return getAlgorithm(); } + public boolean isPrivateKey() { return getPrivateKey() != null; } public abstract RubyString to_der() ; diff --git a/src/main/java/org/jruby/ext/openssl/PKeyEC.java b/src/main/java/org/jruby/ext/openssl/PKeyEC.java index 45700f60..9fd590eb 100644 --- a/src/main/java/org/jruby/ext/openssl/PKeyEC.java +++ b/src/main/java/org/jruby/ext/openssl/PKeyEC.java @@ -222,6 +222,9 @@ public PKeyEC(Ruby runtime, RubyClass type) { @Override public String getAlgorithm() { return "ECDSA"; } + @Override + public String getKeyType() { return "EC"; } + @JRubyMethod(rest = true, visibility = Visibility.PRIVATE) public IRubyObject initialize(final ThreadContext context, final IRubyObject[] args, Block block) { final Ruby runtime = context.runtime; @@ -254,13 +257,13 @@ public IRubyObject initialize(final ThreadContext context, final IRubyObject[] a Object key = null; final KeyFactory ecdsaFactory; try { - ecdsaFactory = SecurityHelper.getKeyFactory("ECDSA"); + ecdsaFactory = SecurityHelper.getKeyFactory("EC"); } catch (NoSuchAlgorithmException e) { - throw runtime.newRuntimeError("unsupported key algorithm (ECDSA)"); + throw runtime.newRuntimeError("unsupported key algorithm (EC)"); } catch (RuntimeException e) { - throw runtime.newRuntimeError("unsupported key algorithm (ECDSA) " + e); + throw runtime.newRuntimeError("unsupported key algorithm (EC) " + e); } // TODO: ugly NoClassDefFoundError catching for no BC env. How can we remove this? boolean noClassDef = false; @@ -380,7 +383,7 @@ public PKeyEC generate_key(final ThreadContext context) { // final ECDomainParameters params = getDomainParameters(); try { ECGenParameterSpec genSpec = new ECGenParameterSpec(getCurveName()); - KeyPairGenerator gen = SecurityHelper.getKeyPairGenerator("ECDSA"); // "BC" + KeyPairGenerator gen = SecurityHelper.getKeyPairGenerator("EC"); // "BC" gen.initialize(genSpec, new SecureRandom()); KeyPair pair = gen.generateKeyPair(); this.publicKey = (ECPublicKey) pair.getPublic(); @@ -517,7 +520,7 @@ public IRubyObject set_public_key(final ThreadContext context, final IRubyObject final Point point = (Point) arg; ECPublicKeySpec keySpec = new ECPublicKeySpec(point.asECPoint(), getParamSpec()); try { - this.publicKey = (ECPublicKey) SecurityHelper.getKeyFactory("ECDSA").generatePublic(keySpec); + this.publicKey = (ECPublicKey) SecurityHelper.getKeyFactory("EC").generatePublic(keySpec); return arg; } catch (GeneralSecurityException ex) { @@ -555,7 +558,7 @@ public IRubyObject set_private_key(final ThreadContext context, final IRubyObjec } ECPrivateKeySpec keySpec = new ECPrivateKeySpec(s, getParamSpec()); try { - this.privateKey = SecurityHelper.getKeyFactory("ECDSA").generatePrivate(keySpec); + this.privateKey = SecurityHelper.getKeyFactory("EC").generatePrivate(keySpec); return arg; } catch (GeneralSecurityException ex) { @@ -942,4 +945,4 @@ else if (length > bytes.length) { } } -} \ No newline at end of file +} diff --git a/src/main/java/org/jruby/ext/openssl/SSLContext.java b/src/main/java/org/jruby/ext/openssl/SSLContext.java index 4e7b6397..76380b5d 100644 --- a/src/main/java/org/jruby/ext/openssl/SSLContext.java +++ b/src/main/java/org/jruby/ext/openssl/SSLContext.java @@ -994,12 +994,12 @@ private class InternalContext { if ( pKey != null && xCert != null ) { this.privateKey = pKey.getPrivateKey(); - this.keyAlgorithm = pKey.getAlgorithm(); + this.keyType = pKey.getKeyType(); this.cert = xCert.getAuxCert(); } else { this.privateKey = null; - this.keyAlgorithm = null; + this.keyType = null; this.cert = null; } @@ -1047,7 +1047,7 @@ void initSSLContext(final ThreadContext context) throws KeyManagementException { final Store store; final X509AuxCertificate cert; - final String keyAlgorithm; + final String keyType; final PrivateKey privateKey; final int verifyMode; @@ -1098,7 +1098,7 @@ public String chooseEngineClientAlias(String[] keyType, java.security.Principal[ if (internalContext.privateKey == null) return null; for (int i = 0; i < keyType.length; i++) { - if (keyType[i].equalsIgnoreCase(internalContext.keyAlgorithm)) { + if (keyType[i].equalsIgnoreCase(internalContext.keyType)) { return keyType[i]; } } @@ -1109,7 +1109,7 @@ public String chooseEngineClientAlias(String[] keyType, java.security.Principal[ public String chooseEngineServerAlias(String keyType, java.security.Principal[] issuers, javax.net.ssl.SSLEngine engine) { if (internalContext.privateKey == null) return null; - if (keyType.equalsIgnoreCase(internalContext.keyAlgorithm)) { + if (keyType.equalsIgnoreCase(internalContext.keyType)) { return keyType; } return null; diff --git a/src/main/java/org/jruby/ext/openssl/impl/PKey.java b/src/main/java/org/jruby/ext/openssl/impl/PKey.java index 98c99997..d54d5817 100644 --- a/src/main/java/org/jruby/ext/openssl/impl/PKey.java +++ b/src/main/java/org/jruby/ext/openssl/impl/PKey.java @@ -113,7 +113,7 @@ else if ( type.equals("DSA") ) { privSpec = new DSAPrivateKeySpec(x.getValue(), p.getValue(), q.getValue(), g.getValue()); pubSpec = new DSAPublicKeySpec(y.getValue(), p.getValue(), q.getValue(), g.getValue()); } - else if ( type.equals("ECDSA") ) { + else if ( type.equals("EC") ) { return readECPrivateKey(input); } else { @@ -278,7 +278,7 @@ public static DHParameterSpec readDHParameter(final byte[] input) throws IOExcep public static KeyPair readECPrivateKey(final byte[] input) throws IOException, NoSuchAlgorithmException, InvalidKeySpecException { - return readECPrivateKey(SecurityHelper.getKeyFactory("ECDSA"), input); + return readECPrivateKey(SecurityHelper.getKeyFactory("EC"), input); } public static KeyPair readECPrivateKey(final KeyFactory ecFactory, final byte[] input) @@ -290,7 +290,7 @@ public static KeyPair readECPrivateKey(final KeyFactory ecFactory, final byte[] SubjectPublicKeyInfo pubInfo = new SubjectPublicKeyInfo(algId, pKey.getPublicKey().getBytes()); PKCS8EncodedKeySpec privSpec = new PKCS8EncodedKeySpec(privInfo.getEncoded()); X509EncodedKeySpec pubSpec = new X509EncodedKeySpec(pubInfo.getEncoded()); - //KeyFactory fact = KeyFactory.getInstance("ECDSA", provider); + //KeyFactory fact = KeyFactory.getInstance("EC", provider); ECPrivateKey privateKey = (ECPrivateKey) ecFactory.generatePrivate(privSpec); if ( algId.getParameters() instanceof ASN1ObjectIdentifier ) { @@ -383,5 +383,3 @@ public static byte[] toDerDHKey(BigInteger p, BigInteger g) throws IOException { return new DLSequence(vec).getEncoded(); } } - - diff --git a/src/main/java/org/jruby/ext/openssl/x509store/PEMInputOutput.java b/src/main/java/org/jruby/ext/openssl/x509store/PEMInputOutput.java index 6da0d83d..3e554f12 100644 --- a/src/main/java/org/jruby/ext/openssl/x509store/PEMInputOutput.java +++ b/src/main/java/org/jruby/ext/openssl/x509store/PEMInputOutput.java @@ -340,7 +340,7 @@ else if ( line.indexOf(BEG_STRING_DSA) != -1 ) { } else if ( line.indexOf(BEG_STRING_ECPRIVATEKEY) != -1) { try { - return readKeyPair(reader, passwd, "ECDSA", BEF_E + PEM_STRING_ECPRIVATEKEY); + return readKeyPair(reader, passwd, "EC", BEF_E + PEM_STRING_ECPRIVATEKEY); } catch (Exception e) { throw mapReadException("problem creating DSA private key: ", e); @@ -349,9 +349,10 @@ else if ( line.indexOf(BEG_STRING_ECPRIVATEKEY) != -1) { else if ( line.indexOf(BEG_STRING_PKCS8INF) != -1) { try { byte[] bytes = readBase64Bytes(reader, BEF_E + PEM_STRING_PKCS8INF); - PrivateKeyInfo info = PrivateKeyInfo.getInstance(bytes); - String type = getPrivateKeyTypeFromObjectId(info.getPrivateKeyAlgorithm().getAlgorithm()); - return org.jruby.ext.openssl.impl.PKey.readPrivateKey(((ASN1Object) info.parsePrivateKey()).getEncoded(ASN1Encoding.DER), type); + PrivateKeyInfo pInfo = PrivateKeyInfo.getInstance(bytes); + KeyFactory keyFactory = getKeyFactory( pInfo.getPrivateKeyAlgorithm() ); + PrivateKey pKey = keyFactory.generatePrivate(new PKCS8EncodedKeySpec(pInfo.getEncoded())); + return new KeyPair(null, pKey); } catch (Exception e) { throw mapReadException("problem creating private key: ", e); @@ -605,7 +606,7 @@ public static ECPublicKey readECPubKey(Reader in) throws IOException { while ( ( line = reader.readLine() ) != null ) { if ( line.indexOf(BEG_STRING_EC_PUBLIC) != -1 ) { try { - return (ECPublicKey) readPublicKey(reader, "ECDSA", BEF_E + "EC PUBLIC KEY"); + return (ECPublicKey) readPublicKey(reader, "EC", BEF_E + "EC PUBLIC KEY"); } catch (Exception e) { throw mapReadException("problem creating ECDSA public key: ", e); @@ -621,7 +622,7 @@ public static ECPublicKey readECPublicKey(final Reader in, final char[] passwd) while ( ( line = reader.readLine() ) != null ) { if ( line.indexOf(BEG_STRING_PUBLIC) != -1 ) { try { - return (ECPublicKey) readPublicKey(reader, "ECDSA", BEF_E + PEM_STRING_PUBLIC); + return (ECPublicKey) readPublicKey(reader, "EC", BEF_E + PEM_STRING_PUBLIC); } catch (Exception e) { throw mapReadException("problem creating ECDSA public key: ", e); @@ -638,7 +639,7 @@ public static KeyPair readECPrivateKey(final Reader in, final char[] passwd) while ( ( line = reader.readLine() ) != null ) { if ( line.indexOf(BEG_STRING_EC) != -1 ) { try { - return readKeyPair(reader, passwd, "ECDSA", BEF_E + "EC PRIVATE KEY"); + return readKeyPair(reader, passwd, "EC", BEF_E + "EC PRIVATE KEY"); } catch (Exception e) { throw mapReadException("problem creating ECDSA private key: ", e); @@ -1171,6 +1172,8 @@ public static void writeDHParameters(Writer _out, DHParameterSpec params) throws private static String getPrivateKeyTypeFromObjectId(ASN1ObjectIdentifier oid) { if ( ASN1Registry.oid2nid(oid) == ASN1Registry.NID_rsaEncryption ) { return "RSA"; + } else if ( ASN1Registry.oid2nid(oid) == ASN1Registry.NID_X9_62_id_ecPublicKey ) { + return "EC"; } else { return "DSA"; } @@ -1226,7 +1229,7 @@ private static PublicKey readPublicKey(BufferedReader in, String alg, String end private static PublicKey readPublicKey(BufferedReader in, String endMarker) throws IOException { byte[] input = readBase64Bytes(in, endMarker); - String[] algs = { "RSA", "DSA", "ECDSA" }; + String[] algs = { "RSA", "DSA", "EC" }; for (int i = 0; i < algs.length; i++) { PublicKey key = readPublicKey(input, algs[i], endMarker); if (key != null) { @@ -1488,7 +1491,7 @@ public static KeyFactory getKeyFactory(final AlgorithmIdentifier algId) String algorithm = null; if ( X9ObjectIdentifiers.id_ecPublicKey.equals(algIdentifier) ) { - algorithm = "ECDSA"; + algorithm = "EC"; } else if ( PKCSObjectIdentifiers.rsaEncryption.equals(algIdentifier) ) { algorithm = "RSA"; diff --git a/src/test/ruby/ec/private_key_pkcs8.pem b/src/test/ruby/ec/private_key_pkcs8.pem new file mode 100644 index 00000000..d49cbf95 --- /dev/null +++ b/src/test/ruby/ec/private_key_pkcs8.pem @@ -0,0 +1,5 @@ +-----BEGIN PRIVATE KEY----- +MIGHAgEAMBMGByqGSM49AgEGCCqGSM49AwEHBG0wawIBAQQgUmgU1rG7E9WJmB4A +D1RZ+PP+aYEH2ZZxWTGVR0gDr/qhRANCAAR5d0hOX+W8RznN62sAzIeozl4OBl6K +nKdpKKiZTAua05NCaWJR5mGnrCyn4g+sQV4pUgmp9NzSMwmXAzJt3GK9 +-----END PRIVATE KEY----- diff --git a/src/test/ruby/ec/test_ec.rb b/src/test/ruby/ec/test_ec.rb index a92b1867..2ac4a041 100644 --- a/src/test/ruby/ec/test_ec.rb +++ b/src/test/ruby/ec/test_ec.rb @@ -51,6 +51,14 @@ def test_read_pem2 #puts signature.inspect end + def test_read_pkcs8_with_ec + key_file = File.join(File.dirname(__FILE__), 'private_key_pkcs8.pem') + + key = OpenSSL::PKey::read(File.read(key_file)) + assert_equal '37273549501637553234010607973347901861080883009977847480473501706546896416762', key.private_key.to_s + assert_empty key.public_key.to_s + end + def test_point group = OpenSSL::PKey::EC::Group.new('prime256v1') client_public_key_bn = OpenSSL::BN.new('58089019511196532477248433747314139754458690644712400444716868601190212265537817278966641566813745621284958192417192818318052462970895792919572995957754854') @@ -311,4 +319,4 @@ def test_dsa_sign_verify # end # end -end \ No newline at end of file +end