Skip to content

Commit c197ac8

Browse files
committed
[fix] stop assuming (JDK) EC key identifier
it's "EC" with Sun provider but "ECDSA" with BC
1 parent f7f1009 commit c197ac8

File tree

8 files changed

+43
-110
lines changed

8 files changed

+43
-110
lines changed

src/main/java/org/jruby/ext/openssl/NetscapeSPKI.java

Lines changed: 1 addition & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -45,7 +45,6 @@
4545
import org.jruby.RubyClass;
4646
import org.jruby.RubyModule;
4747
import org.jruby.RubyObject;
48-
import org.jruby.RubyString;
4948
import org.jruby.anno.JRubyMethod;
5049
import org.jruby.exceptions.RaiseException;
5150
import org.jruby.ext.openssl.impl.Base64;
@@ -57,8 +56,6 @@
5756
// org.bouncycastle.jce.netscape.NetscapeCertRequest emulator:
5857
import org.jruby.ext.openssl.impl.NetscapeCertRequest;
5958

60-
import static org.jruby.ext.openssl.PKeyDSA._DSA;
61-
import static org.jruby.ext.openssl.PKeyRSA._RSA;
6259
import static org.jruby.ext.openssl.OpenSSL.*;
6360

6461
/**
@@ -102,19 +99,7 @@ public IRubyObject initialize(final ThreadContext context, final IRubyObject[] a
10299
catch (GeneralSecurityException e) { throw newSPKIError(e); }
103100
catch (IllegalArgumentException e) { throw newSPKIError(e); }
104101

105-
final PublicKey publicKey = cert.getPublicKey();
106-
final String algorithm = publicKey.getAlgorithm();
107-
final RubyString pub_key = RubyString.newString(runtime, publicKey.getEncoded());
108-
109-
if ( "RSA".equalsIgnoreCase(algorithm) ) {
110-
this.public_key = _RSA(runtime).callMethod(context, "new", pub_key);
111-
}
112-
else if ( "DSA".equalsIgnoreCase(algorithm) ) {
113-
this.public_key = _DSA(runtime).callMethod(context, "new", pub_key);
114-
}
115-
else {
116-
throw runtime.newLoadError("not implemented algo for public key: " + algorithm);
117-
}
102+
this.public_key = PKey.newInstance(runtime, cert.getPublicKey());
118103
}
119104
return this;
120105
}

src/main/java/org/jruby/ext/openssl/PKey.java

Lines changed: 28 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -34,6 +34,7 @@
3434
import java.security.*;
3535
import java.security.interfaces.DSAPrivateKey;
3636
import java.security.interfaces.DSAPublicKey;
37+
import java.security.interfaces.ECPublicKey;
3738
import java.security.interfaces.RSAPrivateCrtKey;
3839
import java.security.interfaces.RSAPublicKey;
3940
import java.security.spec.InvalidKeySpecException;
@@ -88,6 +89,20 @@ public static RaiseException newPKeyError(Ruby runtime, String message) {
8889
return Utils.newError(runtime, (RubyClass) _PKey(runtime).getConstantAt("PKeyError"), message);
8990
}
9091

92+
public static PKey newInstance(final Ruby runtime, final PublicKey publicKey) {
93+
if (publicKey instanceof RSAPublicKey) {
94+
return new PKeyRSA(runtime, (RSAPublicKey) publicKey);
95+
}
96+
if (publicKey instanceof DSAPublicKey) {
97+
return new PKeyDSA(runtime, (DSAPublicKey) publicKey);
98+
}
99+
if (publicKey instanceof ECPublicKey) {
100+
return new PKeyEC(runtime, publicKey);
101+
}
102+
assert publicKey != null;
103+
throw runtime.newNotImplementedError("public key algorithm: " + (publicKey != null ? publicKey.getAlgorithm() : "nil"));
104+
}
105+
91106
static RubyModule _PKey(final Ruby runtime) {
92107
return (RubyModule) runtime.getModule("OpenSSL").getConstantAt("PKey");
93108
}
@@ -122,20 +137,15 @@ public static IRubyObject read(final ThreadContext context, IRubyObject recv, IR
122137
if (keyPair != null) {
123138
final String alg = getAlgorithm(keyPair);
124139
if ( "RSA".equals(alg) ) {
125-
return new PKeyRSA(runtime, _PKey(runtime).getClass("RSA"),
126-
(RSAPrivateCrtKey) keyPair.getPrivate(), (RSAPublicKey) keyPair.getPublic()
127-
);
140+
return new PKeyRSA(runtime, _PKey(runtime).getClass("RSA"), (RSAPrivateCrtKey) keyPair.getPrivate(), (RSAPublicKey) keyPair.getPublic());
128141
}
129142
if ( "DSA".equals(alg) ) {
130-
return new PKeyDSA(runtime, _PKey(runtime).getClass("DSA"),
131-
(DSAPrivateKey) keyPair.getPrivate(), (DSAPublicKey) keyPair.getPublic()
132-
);
143+
return new PKeyDSA(runtime, _PKey(runtime).getClass("DSA"), (DSAPrivateKey) keyPair.getPrivate(), (DSAPublicKey) keyPair.getPublic());
133144
}
134-
if ( "EC".equals(alg) ) {
135-
return new PKeyEC(runtime, _PKey(runtime).getClass("EC"),
136-
keyPair.getPrivate(), keyPair.getPublic()
137-
);
145+
if ( "EC".equals(alg) || "ECDSA".equals(alg) ) { // Sun vs BC provider naming
146+
return new PKeyEC(runtime, _PKey(runtime).getClass("EC"), keyPair.getPrivate(), keyPair.getPublic());
138147
}
148+
debug(runtime, "PKey readPrivateKey unexpected key pair algorithm: " + alg);
139149
}
140150

141151
PublicKey pubKey = null;
@@ -168,16 +178,14 @@ public static IRubyObject read(final ThreadContext context, IRubyObject recv, IR
168178
}
169179
}
170180

171-
if (pubKey != null) {
172-
if ( "RSA".equals(pubKey.getAlgorithm()) ) {
173-
return new PKeyRSA(runtime, (RSAPublicKey) pubKey);
174-
}
175-
if ( "DSA".equals(pubKey.getAlgorithm()) ) {
176-
return new PKeyDSA(runtime, (DSAPublicKey) pubKey);
177-
}
178-
if ( "EC".equals(pubKey.getAlgorithm()) ) {
179-
return new PKeyEC(runtime, pubKey);
180-
}
181+
if (pubKey instanceof RSAPublicKey) {
182+
return new PKeyRSA(runtime, (RSAPublicKey) pubKey);
183+
}
184+
if (pubKey instanceof DSAPublicKey) {
185+
return new PKeyDSA(runtime, (DSAPublicKey) pubKey);
186+
}
187+
if (pubKey instanceof ECPublicKey) {
188+
return new PKeyEC(runtime, pubKey);
181189
}
182190

183191
throw newPKeyError(runtime, "Could not parse PKey: unsupported");
@@ -188,7 +196,6 @@ private static String getAlgorithm(final KeyPair key) {
188196
if ( key.getPublic() != null ) return key.getPublic().getAlgorithm();
189197
return null;
190198
}
191-
192199
}
193200

194201
public PKey(Ruby runtime, RubyClass type) {

src/main/java/org/jruby/ext/openssl/PKeyDSA.java

Lines changed: 0 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -169,12 +169,6 @@ private static PKeyDSA dsaGenerate(final Ruby runtime,
169169
}
170170
}
171171

172-
static PKeyDSA newInstance(final Ruby runtime, final PublicKey publicKey) {
173-
//if ( publicKey instanceof DSAPublicKey ) {
174-
return new PKeyDSA(runtime, (DSAPublicKey) publicKey);
175-
//}
176-
}
177-
178172
@JRubyMethod(rest = true, visibility = Visibility.PRIVATE)
179173
public IRubyObject initialize(final ThreadContext context, final IRubyObject[] args, final Block block) {
180174
final Ruby runtime = context.runtime;

src/main/java/org/jruby/ext/openssl/PKeyEC.java

Lines changed: 0 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -98,10 +98,6 @@ public final class PKeyEC extends PKey {
9898
public PKeyEC allocate(Ruby runtime, RubyClass klass) { return new PKeyEC(runtime, klass); }
9999
};
100100

101-
static PKeyEC newInstance(final Ruby runtime, final PublicKey publicKey) {
102-
return new PKeyEC(runtime, publicKey);
103-
}
104-
105101
static void createPKeyEC(final Ruby runtime, final RubyModule PKey, final RubyClass PKeyPKey, final RubyClass OpenSSLError) {
106102
RubyClass EC = PKey.defineClassUnder("EC", PKeyPKey, ALLOCATOR);
107103

src/main/java/org/jruby/ext/openssl/PKeyRSA.java

Lines changed: 0 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -213,12 +213,6 @@ private static PKeyRSA rsaGenerate(final Ruby runtime,
213213
return rsa;
214214
}
215215

216-
static PKeyRSA newInstance(final Ruby runtime, final PublicKey publicKey) {
217-
//if ( publicKey instanceof RSAPublicKey ) {
218-
return new PKeyRSA(runtime, (RSAPublicKey) publicKey);
219-
//}
220-
}
221-
222216
@JRubyMethod(rest = true, visibility = Visibility.PRIVATE)
223217
public IRubyObject initialize(final ThreadContext context, final IRubyObject[] args, final Block block) {
224218
final Ruby runtime = context.runtime;

src/main/java/org/jruby/ext/openssl/SecurityHelper.java

Lines changed: 6 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -606,23 +606,26 @@ static boolean verify(final X509CRL crl, final PublicKey publicKey, final boolea
606606
try {
607607
final DigestAlgorithmIdentifierFinder digestAlgFinder = new DefaultDigestAlgorithmIdentifierFinder();
608608
final ContentVerifierProvider verifierProvider;
609-
if ( "DSA".equalsIgnoreCase( publicKey.getAlgorithm() )) {
609+
if (publicKey instanceof DSAPublicKey) {
610610
BigInteger y = ((DSAPublicKey) publicKey).getY();
611611
DSAParams params = ((DSAPublicKey) publicKey).getParams();
612612
DSAParameters parameters = new DSAParameters(params.getP(), params.getQ(), params.getG());
613613
AsymmetricKeyParameter dsaKey = new DSAPublicKeyParameters(y, parameters);
614614
verifierProvider = new BcDSAContentVerifierProviderBuilder(digestAlgFinder).build(dsaKey);
615615
}
616-
else if ( "EC".equalsIgnoreCase( publicKey.getAlgorithm() )) {
616+
else if (publicKey instanceof ECPublicKey) {
617617
AsymmetricKeyParameter ecKey = ECUtil.generatePublicKeyParameter(publicKey);
618618
verifierProvider = new BcECContentVerifierProviderBuilder(digestAlgFinder).build(ecKey);
619619
}
620-
else {
620+
else if (publicKey instanceof RSAPublicKey) {
621621
BigInteger mod = ((RSAPublicKey) publicKey).getModulus();
622622
BigInteger exp = ((RSAPublicKey) publicKey).getPublicExponent();
623623
AsymmetricKeyParameter rsaKey = new RSAKeyParameters(false, mod, exp);
624624
verifierProvider = new BcRSAContentVerifierProviderBuilder(digestAlgFinder).build(rsaKey);
625625
}
626+
else {
627+
throw new IllegalStateException("unsupported public key type: " + (publicKey != null ? publicKey.getClass() : null));
628+
}
626629
return new X509CRLHolder(crl.getEncoded()).isSignatureValid( verifierProvider );
627630
}
628631
catch (OperatorException e) {

src/main/java/org/jruby/ext/openssl/X509Cert.java

Lines changed: 5 additions & 29 deletions
Original file line numberDiff line numberDiff line change
@@ -41,9 +41,9 @@
4141
import java.security.cert.CertificateEncodingException;
4242
import java.security.cert.CertificateException;
4343
import java.security.cert.X509Certificate;
44+
4445
import java.security.interfaces.DSAPublicKey;
4546
import java.security.interfaces.RSAPublicKey;
46-
4747
import java.util.ArrayList;
4848
import java.util.Collection;
4949
import java.util.LinkedHashMap;
@@ -82,7 +82,6 @@
8282
import org.jruby.ext.openssl.x509store.PEMInputOutput;
8383
import org.jruby.ext.openssl.x509store.X509AuxCertificate;
8484
import org.jruby.runtime.Block;
85-
import org.jruby.runtime.ObjectAllocator;
8685
import org.jruby.runtime.ThreadContext;
8786
import org.jruby.runtime.Visibility;
8887
import org.jruby.runtime.builtin.IRubyObject;
@@ -359,7 +358,7 @@ public IRubyObject to_text(final ThreadContext context) {
359358
final PublicKey publicKey = getPublicKey();
360359
text.append(S20,0,12).append("Public Key Algorithm: ").append(publicKey.getAlgorithm()).append('\n');
361360

362-
if ( "RSA".equals( publicKey.getAlgorithm() ) ) {
361+
if (publicKey instanceof RSAPublicKey) {
363362
final RSAPublicKey rsaKey = ((RSAPublicKey) publicKey);
364363
text.append(S20,0,16).append("Public-Key: (").append( rsaKey.getModulus().bitLength() ).append(" bit)\n");
365364

@@ -370,13 +369,13 @@ public IRubyObject to_text(final ThreadContext context) {
370369
text.append(S20,0,16).append("Exponent: ").append(exponent).
371370
append(" (0x").append( exponent.toString(16) ).append(")\n");
372371
}
373-
else if ( "DSA".equals( publicKey.getAlgorithm() ) ) {
372+
else if (publicKey instanceof DSAPublicKey) {
374373
final DSAPublicKey dsaKey = ((DSAPublicKey) publicKey);
375374
text.append(S20,0,16).append("Public-Key: (").append( dsaKey.getY().bitLength() ).append(" bit)\n");
376375

377376
text.append(S20,0,16).append("TODO: not-implemented (PR HOME-WORK)").append('\n'); // left-TODO
378377
}
379-
else {
378+
else { // "EC" or "ECDSA"
380379
text.append(S20,0,16).append("TODO: not-implemented (PRs WELCOME!)").append('\n'); // left-TODO
381380
}
382381

@@ -540,30 +539,7 @@ private void initializePublicKey() throws RaiseException {
540539
throw newCertificateError(runtime, "no certificate");
541540
}
542541

543-
final PublicKey publicKey = cert.getPublicKey();
544-
545-
final String algorithm = publicKey.getAlgorithm();
546-
547-
if ( "RSA".equalsIgnoreCase(algorithm) ) {
548-
//if ( public_key == null ) {
549-
// throw new IllegalStateException("no public key encoded data");
550-
//}
551-
set_public_key( PKeyRSA.newInstance(runtime, publicKey) );
552-
}
553-
else if ( "DSA".equalsIgnoreCase(algorithm) ) {
554-
//if ( public_key == null ) {
555-
// throw new IllegalStateException("no public key encoded data");
556-
//}
557-
set_public_key( PKeyDSA.newInstance(runtime, publicKey) );
558-
}
559-
else if ( "EC".equalsIgnoreCase(algorithm) ) {
560-
set_public_key( PKeyEC.newInstance(runtime, publicKey) );
561-
}
562-
else {
563-
String message = "unsupported algorithm";
564-
if ( algorithm != null ) message += " '" + algorithm + "'";
565-
throw newCertificateError(runtime, message);
566-
}
542+
set_public_key(PKey.newInstance(runtime, cert.getPublicKey()));
567543

568544
this.changed = changed;
569545
}

src/main/java/org/jruby/ext/openssl/X509Request.java

Lines changed: 3 additions & 25 deletions
Original file line numberDiff line numberDiff line change
@@ -45,7 +45,6 @@
4545
import org.bouncycastle.asn1.pkcs.Attribute;
4646
import org.bouncycastle.asn1.x500.X500Name;
4747
import org.bouncycastle.asn1.x509.AlgorithmIdentifier;
48-
import org.bouncycastle.operator.DefaultSignatureNameFinder;
4948

5049
import org.jruby.Ruby;
5150
import org.jruby.RubyArray;
@@ -111,30 +110,14 @@ public IRubyObject initialize(final ThreadContext context, final IRubyObject[] a
111110
throw newRequestError(runtime, "invalid certificate request data", e);
112111
}
113112

114-
final String algorithm;
115-
final byte[] encoded;
113+
final PublicKey publicKey;
116114
try {
117-
final PublicKey pkey = request.generatePublicKey();
118-
algorithm = pkey.getAlgorithm();
119-
encoded = pkey.getEncoded();
115+
publicKey = request.generatePublicKey();
120116
}
121117
catch (IOException|GeneralSecurityException e) {
122118
throw newRequestError(runtime, e);
123119
}
124-
125-
final RubyString enc = RubyString.newString(runtime, encoded);
126-
if ( "RSA".equalsIgnoreCase(algorithm) ) {
127-
this.public_key = newPKeyImplInstance(context, "RSA", enc);
128-
}
129-
else if ( "DSA".equalsIgnoreCase(algorithm) ) {
130-
this.public_key = newPKeyImplInstance(context, "DSA", enc);
131-
}
132-
else if ( "EC".equalsIgnoreCase(algorithm) ) {
133-
this.public_key = newPKeyImplInstance(context, "EC", enc);
134-
}
135-
else {
136-
throw runtime.newNotImplementedError("public key algorithm: " + algorithm);
137-
}
120+
this.public_key = PKey.newInstance(runtime, publicKey);
138121

139122
this.subject = newName( context, request.getSubject() );
140123

@@ -155,11 +138,6 @@ else if ( "EC".equalsIgnoreCase(algorithm) ) {
155138
return this;
156139
}
157140

158-
private static PKey newPKeyImplInstance(final ThreadContext context,
159-
final String className, final RubyString encoded) { // OpenSSL::PKey::RSA.new(encoded)
160-
return (PKey) _PKey(context.runtime).getClass(className).callMethod(context, "new", encoded);
161-
}
162-
163141
private static X509Attribute newAttribute(final ThreadContext context,
164142
final ASN1ObjectIdentifier type, final ASN1Set values) throws IOException {
165143
return X509Attribute.newAttribute(context.runtime, type, values);

0 commit comments

Comments
 (0)