diff --git a/src/main/java/org/jruby/ext/openssl/ASN1.java b/src/main/java/org/jruby/ext/openssl/ASN1.java index 8344b0d1..3e132b9c 100644 --- a/src/main/java/org/jruby/ext/openssl/ASN1.java +++ b/src/main/java/org/jruby/ext/openssl/ASN1.java @@ -281,8 +281,9 @@ private static void defaultObjects(final Ruby runtime) { addObject(runtime, 184, "AES-256-CBC", "aes-256-cbc","2.16.840.1.101.3.4.1.42"); addObject(runtime, 185, "AES-256-OFB", "aes-256-ofb","2.16.840.1.101.3.4.1.43"); addObject(runtime, 186, "AES-256-CFB", "aes-256-cfb","2.16.840.1.101.3.4.1.44"); + addObject(runtime, 187, "Ed25519", "ed25519", "1.3.101.112"); + addObject(runtime, 188, "X25519", "x25519", "1.3.101.110"); addObject(runtime, 672, "SHA256", "sha256", "2.16.840.1.101.3.4.2.1"); - addObject(runtime, 660, "street", "streetAddress", "2.5.4.9"); addObject(runtime, 391, "DC", "domainComponent", "0.9.2342.19200300.100.1.25"); //addObject(runtime, 509, null, "generationQualifier", "2.5.4.44"); diff --git a/src/main/java/org/jruby/ext/openssl/PKey.java b/src/main/java/org/jruby/ext/openssl/PKey.java index 51b99b48..5e131423 100644 --- a/src/main/java/org/jruby/ext/openssl/PKey.java +++ b/src/main/java/org/jruby/ext/openssl/PKey.java @@ -40,12 +40,17 @@ import java.security.spec.InvalidKeySpecException; import java.security.spec.PKCS8EncodedKeySpec; import java.security.spec.X509EncodedKeySpec; +import java.util.ArrayList; + +import javax.crypto.spec.DHParameterSpec; import org.bouncycastle.asn1.ASN1InputStream; import org.bouncycastle.asn1.ASN1Primitive; import org.bouncycastle.asn1.ASN1Sequence; import org.jruby.Ruby; import org.jruby.RubyClass; +import org.jruby.RubyException; +import org.jruby.RubyInteger; import org.jruby.RubyModule; import org.jruby.RubyObject; import org.jruby.RubyString; @@ -124,6 +129,8 @@ public static IRubyObject read(final ThreadContext context, IRubyObject recv, IR pass = args[1].isNil() ? null : args[1].toString().toCharArray(); } + ArrayList exceptions = new ArrayList<>(); + final RubyString str = readInitArg(context, data); KeyPair keyPair; // d2i_PrivateKey_bio @@ -131,6 +138,7 @@ public static IRubyObject read(final ThreadContext context, IRubyObject recv, IR keyPair = readPrivateKey(str, pass); } catch (IOException e) { debugStackTrace(runtime, "PKey readPrivateKey", e); /* ignore */ + exceptions.add(e); keyPair = null; } // PEM_read_bio_PrivateKey @@ -154,12 +162,14 @@ public static IRubyObject read(final ThreadContext context, IRubyObject recv, IR if (pubKey != null) return new PKeyRSA(runtime, (RSAPublicKey) pubKey); } catch (IOException e) { debugStackTrace(runtime, "PKey readRSAPublicKey", e); /* ignore */ + exceptions.add(e); } try { pubKey = PEMInputOutput.readDSAPublicKey(new StringReader(str.toString()), null); if (pubKey != null) return new PKeyDSA(runtime, (DSAPublicKey) pubKey); } catch (IOException e) { debugStackTrace(runtime, "PKey readDSAPublicKey", e); /* ignore */ + exceptions.add(e); } final byte[] input = StringHelper.readX509PEM(context, str); @@ -168,6 +178,7 @@ public static IRubyObject read(final ThreadContext context, IRubyObject recv, IR pubKey = org.jruby.ext.openssl.impl.PKey.readPublicKey(input); } catch (IOException e) { debugStackTrace(runtime, "PKey readPublicKey", e); /* ignore */ + exceptions.add(e); } // PEM_read_bio_PUBKEY if (pubKey == null) { @@ -175,7 +186,19 @@ public static IRubyObject read(final ThreadContext context, IRubyObject recv, IR pubKey = PEMInputOutput.readPubKey(new StringReader(str.toString())); } catch (IOException e) { debugStackTrace(runtime, "PKey readPubKey", e); /* ignore */ + exceptions.add(e); + } + } + + if (pubKey == null) { + try { + final PKeyDH dh = new PKeyDH(runtime, str); + return dh; + } catch (Exception e) { + debugStackTrace(runtime, "PKey read DH", e); /* ignore */ + exceptions.add(e); } + } if (pubKey instanceof RSAPublicKey) { @@ -188,7 +211,9 @@ public static IRubyObject read(final ThreadContext context, IRubyObject recv, IR return new PKeyEC(runtime, pubKey); } - throw newPKeyError(runtime, "Could not parse PKey: unsupported"); + exceptions.stream().forEach(Throwable::printStackTrace); + + throw newPKeyError(runtime, "Could not parse PKey: unsupported " + pubKey + " " + exceptions); } private static String getAlgorithm(final KeyPair key) { @@ -196,6 +221,25 @@ private static String getAlgorithm(final KeyPair key) { if ( key.getPublic() != null ) return key.getPublic().getAlgorithm(); return null; } + + @JRubyMethod(name = "generate_key", meta = true, required = 1, optional = 1) + public static IRubyObject generateKey(final ThreadContext context, IRubyObject recv, IRubyObject[] args) { + if (!(args[0] instanceof RubyString)) { + throw context.getRuntime().newNotImplementedError("generate_key not implemented for " + args[0].getMetaClass().getName()); + } + + + throw context.getRuntime().newNotImplementedError("generate_key not implemented for " + args[0].inspect()); + } + + @JRubyMethod(name = "generate_parameters", meta = true, required = 1, optional = 1) + public static IRubyObject generateParameters(final ThreadContext context, IRubyObject recv, IRubyObject[] args) { + if (!(args[0] instanceof RubyString)) { + throw context.getRuntime().newArgumentError("generate_parameters requires a string argument"); + } + + throw context.getRuntime().newNotImplementedError("generate_parameters not implemented for " + args[0].inspect() + " " + args[1].inspect()); + } } public PKey(Ruby runtime, RubyClass type) { @@ -222,6 +266,8 @@ public IRubyObject initialize(ThreadContext context) { public abstract RubyString to_pem(ThreadContext context, final IRubyObject[] args) ; + public abstract RubyString oid() ; + @JRubyMethod(name = "sign") public IRubyObject sign(IRubyObject digest, IRubyObject data) { final Ruby runtime = getRuntime(); @@ -246,6 +292,27 @@ public ASN1Primitive toASN1PublicInfo() throws IOException { return data; } + @JRubyMethod(name = "inspect") + public IRubyObject inspect() { + final Ruby runtime = getRuntime(); + final StringBuilder result = new StringBuilder(); + result.append("#<").append(getMetaClass().getName()).append(" "); + result.append("oid=").append(this.oid().asJavaString()); + result.append(">"); + return runtime.newString(result.toString()); + } + + @JRubyMethod(name = "compare?", required = 1) + public IRubyObject compare(ThreadContext context, IRubyObject other) { + if (other instanceof PKey) { + final PKey otherKey = (PKey) other; + if (this.getAlgorithm().equals(otherKey.getAlgorithm())) { + return context.runtime.newBoolean(this.to_der().equals(otherKey.to_der())); + } + } + return context.runtime.getFalse(); + } + @Override public Object toJava(final Class target) { if (PrivateKey.class.isAssignableFrom(target)) { diff --git a/src/main/java/org/jruby/ext/openssl/PKeyDH.java b/src/main/java/org/jruby/ext/openssl/PKeyDH.java index 159ef832..d9fe7732 100644 --- a/src/main/java/org/jruby/ext/openssl/PKeyDH.java +++ b/src/main/java/org/jruby/ext/openssl/PKeyDH.java @@ -86,6 +86,15 @@ static void createPKeyDH(final Ruby runtime, final RubyModule PKey, final RubyCl DH.defineAnnotatedMethods(PKeyDH.class); } + public PKeyDH(Ruby runtime, RubyString str) { + super(runtime, _DH(runtime)); + this.initialize(runtime.getCurrentContext(), new IRubyObject[] { str }); + } + + static RubyClass _DH(final Ruby runtime) { + return _PKey(runtime).getClass("DH"); + } + public static RaiseException newDHError(Ruby runtime, String message) { return Utils.newError(runtime, _PKey(runtime).getClass("DHError"), message); } @@ -431,6 +440,12 @@ public synchronized IRubyObject set_priv_key(IRubyObject arg) { return arg; } + @Override + @JRubyMethod + public RubyString oid() { + return getRuntime().newString("DH"); + } + @JRubyMethod public IRubyObject set_key(final ThreadContext context, IRubyObject pub_key, IRubyObject priv_key) { set_pub_key(pub_key); diff --git a/src/main/java/org/jruby/ext/openssl/PKeyDSA.java b/src/main/java/org/jruby/ext/openssl/PKeyDSA.java index be364fdf..4ca77223 100644 --- a/src/main/java/org/jruby/ext/openssl/PKeyDSA.java +++ b/src/main/java/org/jruby/ext/openssl/PKeyDSA.java @@ -467,7 +467,7 @@ public IRubyObject sysverify(IRubyObject data, IRubyObject sign) { } @JRubyMethod - public IRubyObject oid() { + public RubyString oid() { return getRuntime().newString("DSA"); } diff --git a/src/main/java/org/jruby/ext/openssl/PKeyEC.java b/src/main/java/org/jruby/ext/openssl/PKeyEC.java index 099bc75f..0994be90 100644 --- a/src/main/java/org/jruby/ext/openssl/PKeyEC.java +++ b/src/main/java/org/jruby/ext/openssl/PKeyEC.java @@ -551,7 +551,7 @@ public IRubyObject dh_compute_key(final ThreadContext context, final IRubyObject } @JRubyMethod - public IRubyObject oid() { + public RubyString oid() { return getRuntime().newString("id-ecPublicKey"); } diff --git a/src/main/java/org/jruby/ext/openssl/PKeyRSA.java b/src/main/java/org/jruby/ext/openssl/PKeyRSA.java index 5cc9059c..76650471 100644 --- a/src/main/java/org/jruby/ext/openssl/PKeyRSA.java +++ b/src/main/java/org/jruby/ext/openssl/PKeyRSA.java @@ -574,8 +574,9 @@ private RubyString doCipherRSA(final Ruby runtime, } } + @Override @JRubyMethod - public IRubyObject oid() { + public RubyString oid() { return getRuntime().newString("rsaEncryption"); } 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 c50726ae..8bc9ca03 100644 --- a/src/main/java/org/jruby/ext/openssl/impl/PKey.java +++ b/src/main/java/org/jruby/ext/openssl/impl/PKey.java @@ -86,10 +86,12 @@ */ public class PKey { - public enum Type { RSA, DSA, EC; } + public enum Type { + RSA, DSA, EC, Ed25519, X25519; + } public static KeyPair readPrivateKey(final Type type, final byte[] input) - throws IOException, NoSuchAlgorithmException, InvalidKeySpecException { + throws IOException, NoSuchAlgorithmException, InvalidKeySpecException { return readPrivateKey(type, mockPrivateKeyInfo(type, input)); } @@ -99,8 +101,10 @@ private static PrivateKeyInfo mockPrivateKeyInfo(final Type type, final byte[] i } public static KeyPair readPrivateKey(final Type type, final PrivateKeyInfo keyInfo) - throws IOException, NoSuchAlgorithmException, InvalidKeySpecException { - KeySpec pubSpec; KeySpec privSpec; ASN1Sequence seq; + throws IOException, NoSuchAlgorithmException, InvalidKeySpecException { + KeySpec pubSpec; + KeySpec privSpec; + ASN1Sequence seq; switch (type) { case RSA: seq = (ASN1Sequence) keyInfo.parsePrivateKey(); @@ -130,6 +134,10 @@ public static KeyPair readPrivateKey(final Type type, final PrivateKeyInfo keyIn break; case EC: return readECPrivateKey(SecurityHelper.getKeyFactory("EC"), keyInfo); + case Ed25519: + return readEd25519PrivateKey(SecurityHelper.getKeyFactory("Ed25519"), keyInfo); + case X25519: + return readX25519PrivateKey(SecurityHelper.getKeyFactory("X25519"), keyInfo); default: throw new AssertionError("unexpected key type: " + type); } @@ -141,19 +149,25 @@ public static KeyPair readPrivateKey(final Type type, final PrivateKeyInfo keyIn public static PublicKey readPublicKey(final byte[] input) throws IOException { try (Reader in = new InputStreamReader(new ByteArrayInputStream(input))) { Object pemObject = new PEMParser(in).readObject(); - SubjectPublicKeyInfo publicKeyInfo = SubjectPublicKeyInfo.getInstance(pemObject); - return new JcaPEMKeyConverter().getPublicKey(publicKeyInfo); + SubjectPublicKeyInfo publicKeyInfo; + try { + publicKeyInfo = SubjectPublicKeyInfo.getInstance(pemObject); + return new JcaPEMKeyConverter().getPublicKey(publicKeyInfo); + } catch (IllegalArgumentException ex) { + throw new IOException("problem parsing public key: " + ex + " (input: " + new String(input) + ")" + + " pemObject: " + pemObject); + } } } // d2i_RSAPrivateKey_bio public static KeyPair readRSAPrivateKey(final byte[] input) - throws IOException, NoSuchAlgorithmException, InvalidKeySpecException { + throws IOException, NoSuchAlgorithmException, InvalidKeySpecException { return readRSAPrivateKey(SecurityHelper.getKeyFactory("RSA"), input); } public static KeyPair readRSAPrivateKey(final KeyFactory rsaFactory, final byte[] input) - throws IOException, InvalidKeySpecException { + throws IOException, InvalidKeySpecException { ASN1Sequence seq; ASN1Primitive obj = new ASN1InputStream(input).readObject(); if (obj instanceof ASN1Sequence && (seq = (ASN1Sequence) obj).size() == 9) { @@ -165,7 +179,8 @@ public static KeyPair readRSAPrivateKey(final KeyFactory rsaFactory, final byte[ BigInteger primeep = ((ASN1Integer) seq.getObjectAt(6)).getValue(); BigInteger primeeq = ((ASN1Integer) seq.getObjectAt(7)).getValue(); BigInteger crtcoeff = ((ASN1Integer) seq.getObjectAt(8)).getValue(); - PrivateKey priv = rsaFactory.generatePrivate(new RSAPrivateCrtKeySpec(mod, pubexp, privexp, primep, primeq, primeep, primeeq, crtcoeff)); + PrivateKey priv = rsaFactory.generatePrivate( + new RSAPrivateCrtKeySpec(mod, pubexp, privexp, primep, primeq, primeep, primeeq, crtcoeff)); PublicKey pub = rsaFactory.generatePublic(new RSAPublicKeySpec(mod, pubexp)); return new KeyPair(pub, priv); } @@ -174,12 +189,12 @@ public static KeyPair readRSAPrivateKey(final KeyFactory rsaFactory, final byte[ // d2i_RSAPublicKey_bio public static PublicKey readRSAPublicKey(final byte[] input) - throws IOException, NoSuchAlgorithmException, InvalidKeySpecException { + throws IOException, NoSuchAlgorithmException, InvalidKeySpecException { return readRSAPublicKey(SecurityHelper.getKeyFactory("RSA"), input); } public static PublicKey readRSAPublicKey(final KeyFactory rsaFactory, final byte[] input) - throws IOException, InvalidKeySpecException { + throws IOException, InvalidKeySpecException { ASN1Sequence seq; ASN1Primitive obj = new ASN1InputStream(input).readObject(); if (obj instanceof ASN1Sequence && (seq = (ASN1Sequence) obj).size() == 2) { @@ -192,12 +207,12 @@ public static PublicKey readRSAPublicKey(final KeyFactory rsaFactory, final byte // d2i_DSAPrivateKey_bio public static KeyPair readDSAPrivateKey(final byte[] input) - throws IOException, NoSuchAlgorithmException, InvalidKeySpecException { + throws IOException, NoSuchAlgorithmException, InvalidKeySpecException { return readDSAPrivateKey(SecurityHelper.getKeyFactory("DSA"), input); } public static KeyPair readDSAPrivateKey(final KeyFactory dsaFactory, final byte[] input) - throws IOException, InvalidKeySpecException { + throws IOException, InvalidKeySpecException { ASN1Sequence seq; ASN1Primitive obj = new ASN1InputStream(input).readObject(); if (obj instanceof ASN1Sequence && (seq = (ASN1Sequence) obj).size() == 6) { @@ -215,12 +230,12 @@ public static KeyPair readDSAPrivateKey(final KeyFactory dsaFactory, final byte[ // d2i_DSA_PUBKEY_bio public static PublicKey readDSAPublicKey(final byte[] input) - throws IOException, NoSuchAlgorithmException, InvalidKeySpecException { + throws IOException, NoSuchAlgorithmException, InvalidKeySpecException { return readDSAPublicKey(SecurityHelper.getKeyFactory("DSA"), input); } public static PublicKey readDSAPublicKey(final KeyFactory dsaFactory, final byte[] input) - throws IOException, InvalidKeySpecException { + throws IOException, InvalidKeySpecException { ASN1Sequence seq; ASN1Primitive obj = new ASN1InputStream(input).readObject(); if (obj instanceof ASN1Sequence) { @@ -232,8 +247,8 @@ public static PublicKey readDSAPublicKey(final KeyFactory dsaFactory, final byte BigInteger g = ((ASN1Integer) seq.getObjectAt(3)).getValue(); return dsaFactory.generatePublic(new DSAPublicKeySpec(y, p, q, g)); } else if (seq.size() == 2 && seq.getObjectAt(1) instanceof DERBitString) { - ASN1Integer y = (ASN1Integer) - new ASN1InputStream(((DERBitString) seq.getObjectAt(1)).getBytes()).readObject(); + ASN1Integer y = (ASN1Integer) new ASN1InputStream(((DERBitString) seq.getObjectAt(1)).getBytes()) + .readObject(); seq = (ASN1Sequence) ((ASN1Sequence) seq.getObjectAt(0)).getObjectAt(1); BigInteger p = ((ASN1Integer) seq.getObjectAt(0)).getValue(); BigInteger q = ((ASN1Integer) seq.getObjectAt(1)).getValue(); @@ -254,17 +269,17 @@ public static DHParameterSpec readDHParameter(final byte[] input) throws IOExcep } public static KeyPair readECPrivateKey(final byte[] input) - throws IOException, NoSuchAlgorithmException, InvalidKeySpecException { + throws IOException, NoSuchAlgorithmException, InvalidKeySpecException { return readECPrivateKey(SecurityHelper.getKeyFactory("EC"), input); } public static KeyPair readECPrivateKey(final KeyFactory keyFactory, final byte[] input) - throws IOException, InvalidKeySpecException { + throws IOException, InvalidKeySpecException { return readECPrivateKey(keyFactory, mockPrivateKeyInfo(Type.EC, input)); } public static KeyPair readECPrivateKey(final KeyFactory keyFactory, final PrivateKeyInfo keyInfo) - throws IOException, InvalidKeySpecException { + throws IOException, InvalidKeySpecException { try { ASN1Sequence seq = ASN1Sequence.getInstance(keyInfo.parsePrivateKey()); @@ -276,23 +291,57 @@ public static KeyPair readECPrivateKey(final KeyFactory keyFactory, final Privat final SubjectPublicKeyInfo pubInfo = new SubjectPublicKeyInfo(algId, key.getPublicKey().getBytes()); final PrivateKeyInfo privInfo = new PrivateKeyInfo(algId, key); - ECPrivateKey privateKey = (ECPrivateKey) keyFactory.generatePrivate(new PKCS8EncodedKeySpec(privInfo.getEncoded())); + ECPrivateKey privateKey = (ECPrivateKey) keyFactory + .generatePrivate(new PKCS8EncodedKeySpec(privInfo.getEncoded())); if (algId.getParameters() instanceof ASN1ObjectIdentifier) { privateKey = ECPrivateKeyWithName.wrap(privateKey, (ASN1ObjectIdentifier) algId.getParameters()); } return new KeyPair(keyFactory.generatePublic(new X509EncodedKeySpec(pubInfo.getEncoded())), privateKey); + } catch (ClassCastException ex) { + throw new IOException("wrong ASN.1 object found in stream", ex); } - catch (ClassCastException ex) { + // catch (Exception ex) { + // throw new IOException("problem parsing EC private key: " + ex); + // } + } + + public static KeyPair readEd25519PrivateKey(final KeyFactory keyFactory, final byte[] input) + throws IOException, InvalidKeySpecException { + return readEd25519PrivateKey(keyFactory, mockPrivateKeyInfo(Type.Ed25519, input)); + } + + public static KeyPair readEd25519PrivateKey(final KeyFactory keyFactory, final PrivateKeyInfo keyInfo) + throws IOException, InvalidKeySpecException { + try { + ASN1Sequence seq = ASN1Sequence.getInstance(keyInfo.parsePrivateKey()); + org.bouncycastle.crypto.params.AsymmetricKeyParameter key = org.bouncycastle.crypto.util.OpenSSHPrivateKeyUtil + .parsePrivateKeyBlob(seq.getObjectAt(1).toASN1Primitive().getEncoded()); + throw new IOException("key is " + key); + + } catch (ClassCastException ex) { throw new IOException("wrong ASN.1 object found in stream", ex); } - //catch (Exception ex) { - // throw new IOException("problem parsing EC private key: " + ex); - //} + } + + public static KeyPair readX25519PrivateKey(final KeyFactory keyFactory, final PrivateKeyInfo keyInfo) + throws IOException, InvalidKeySpecException { + try { + ASN1Sequence seq = ASN1Sequence.getInstance(keyInfo.parsePrivateKey()); + org.bouncycastle.crypto.params.AsymmetricKeyParameter key = org.bouncycastle.crypto.util.OpenSSHPrivateKeyUtil + .parsePrivateKeyBlob(seq.getObjectAt(1).toASN1Primitive().getEncoded()); + throw new IOException("key is " + key); + + } catch (ClassCastException ex) { + throw new IOException("wrong ASN.1 object found in stream", ex); + } } public static byte[] toDerRSAKey(RSAPublicKey pubKey, RSAPrivateCrtKey privKey) throws IOException { - if ( pubKey != null && privKey == null ) { - return toDerRSAPublicKey(pubKey); + if (pubKey != null && privKey == null) { + // pubKey.getEncoded() : + return KeyUtil.getEncodedSubjectPublicKeyInfo( + new AlgorithmIdentifier(PKCSObjectIdentifiers.rsaEncryption, DERNull.INSTANCE), + toASN1Primitive(pubKey)); } ASN1EncodableVector vec = new ASN1EncodableVector(); vec.add(new ASN1Integer(BigInteger.ZERO)); @@ -310,8 +359,8 @@ public static byte[] toDerRSAKey(RSAPublicKey pubKey, RSAPrivateCrtKey privKey) public static byte[] toDerRSAPublicKey(final RSAPublicKey pubKey) throws IOException { // pubKey.getEncoded() : return KeyUtil.getEncodedSubjectPublicKeyInfo( - new AlgorithmIdentifier(PKCSObjectIdentifiers.rsaEncryption, DERNull.INSTANCE), toASN1Primitive(pubKey) - ); + new AlgorithmIdentifier(PKCSObjectIdentifiers.rsaEncryption, DERNull.INSTANCE), + toASN1Primitive(pubKey)); } public static ASN1Sequence toASN1Primitive(final RSAPublicKey publicKey) { @@ -323,10 +372,20 @@ public static ASN1Sequence toASN1Primitive(final RSAPublicKey publicKey) { } public static byte[] toDerDSAKey(DSAPublicKey pubKey, DSAPrivateKey privKey) throws IOException { - if ( pubKey != null && privKey == null ) { - return toDerDSAPublicKey(pubKey); + if (pubKey != null && privKey == null) { + // pubKey.getEncoded() : + final DSAParams params = pubKey.getParams(); + if (params == null) { + return new SubjectPublicKeyInfo( + new AlgorithmIdentifier(X9ObjectIdentifiers.id_dsa), + toASN1Primitive(pubKey)).getEncoded(ASN1Encoding.DER); + } + return new SubjectPublicKeyInfo( + new AlgorithmIdentifier(X9ObjectIdentifiers.id_dsa, + new DSAParameter(params.getP(), params.getQ(), params.getG())), + toASN1Primitive(pubKey)).getEncoded(ASN1Encoding.DER); } - if ( privKey != null && pubKey != null ) { + if (privKey != null && pubKey != null) { ASN1EncodableVector vec = new ASN1EncodableVector(); final DSAParams params = privKey.getParams(); vec.add(new ASN1Integer(BigInteger.ZERO)); @@ -337,15 +396,14 @@ public static byte[] toDerDSAKey(DSAPublicKey pubKey, DSAPrivateKey privKey) thr vec.add(new ASN1Integer(privKey.getX())); return new DERSequence(vec).toASN1Primitive().getEncoded(ASN1Encoding.DER); } - if ( privKey == null ) { + if (privKey == null) { throw new IllegalArgumentException("private key as well as public key are null"); } final DSAParams params = privKey.getParams(); return new PrivateKeyInfo( new AlgorithmIdentifier(X9ObjectIdentifiers.id_dsa, new DSAParameter(params.getP(), params.getQ(), params.getG())), - new ASN1Integer(privKey.getX()) - ).getEncoded(ASN1Encoding.DER); + new ASN1Integer(privKey.getX())).getEncoded(ASN1Encoding.DER); } public static byte[] toDerDSAPublicKey(final DSAPublicKey pubKey) throws IOException { @@ -354,15 +412,12 @@ public static byte[] toDerDSAPublicKey(final DSAPublicKey pubKey) throws IOExcep if (params == null) { return new SubjectPublicKeyInfo( new AlgorithmIdentifier(X9ObjectIdentifiers.id_dsa), - toASN1Primitive(pubKey) - ).getEncoded(ASN1Encoding.DER); + toASN1Primitive(pubKey)).getEncoded(ASN1Encoding.DER); } return new SubjectPublicKeyInfo( new AlgorithmIdentifier(X9ObjectIdentifiers.id_dsa, - new DSAParameter(params.getP(), params.getQ(), params.getG()) - ), - toASN1Primitive(pubKey) - ).getEncoded(ASN1Encoding.DER); + new DSAParameter(params.getP(), params.getQ(), params.getG())), + toASN1Primitive(pubKey)).getEncoded(ASN1Encoding.DER); } public static ASN1Primitive toASN1Primitive(DSAPublicKey pubKey) { @@ -371,8 +426,10 @@ public static ASN1Primitive toASN1Primitive(DSAPublicKey pubKey) { public static byte[] toDerDHKey(BigInteger p, BigInteger g) throws IOException { ASN1EncodableVector vec = new ASN1EncodableVector(); - if ( p != null ) vec.add( new ASN1Integer(p) ); - if ( g != null ) vec.add( new ASN1Integer(g) ); + if (p != null) + vec.add(new ASN1Integer(p)); + if (g != null) + vec.add(new ASN1Integer(g)); 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 b515a9d8..123377da 100644 --- a/src/main/java/org/jruby/ext/openssl/x509store/PEMInputOutput.java +++ b/src/main/java/org/jruby/ext/openssl/x509store/PEMInputOutput.java @@ -98,6 +98,7 @@ import org.bouncycastle.asn1.ASN1ObjectIdentifier; import org.bouncycastle.asn1.ASN1Primitive; import org.bouncycastle.asn1.cms.ContentInfo; +import org.bouncycastle.asn1.edec.EdECObjectIdentifiers; import org.bouncycastle.asn1.pkcs.EncryptionScheme; import org.bouncycastle.asn1.pkcs.PBES2Parameters; import org.bouncycastle.asn1.pkcs.PBKDF2Params; @@ -263,6 +264,9 @@ else if ( line.indexOf(BEG_STRING_X509_REQ) != -1 ) { throw new IOException("problem creating X509 REQ: " + e.toString(), e); } } + else if ( line.indexOf(BEF_G) != -1 ) { + throw new IOException("unknown PEM object: " + line); + } } return null; } @@ -305,6 +309,9 @@ else if ( line.indexOf(BEG_STRING_X509_REQ) != -1 ) { throw new IOException("problem reading PEM X509 REQ: " + e.toString(), e); } } + else if ( line.indexOf(BEF_G) != -1 ) { + throw new IOException("unknown PEM object: " + line); + } } return null; } @@ -1499,6 +1506,12 @@ private static Type getPrivateKeyType(final AlgorithmIdentifier algId) { if (X9ObjectIdentifiers.id_dsa.equals(algIdentifier)) { return Type.DSA; } + if (EdECObjectIdentifiers.id_X25519.equals(algIdentifier)) { + return Type.X25519; + } + if (EdECObjectIdentifiers.id_Ed25519.equals(algIdentifier)) { + return Type.Ed25519; + } return Type.valueOf(algIdentifier.getId()); }