Skip to content

Commit

Permalink
[refactor] PKey read-er methods and return types
Browse files Browse the repository at this point in the history
  • Loading branch information
kares committed Apr 4, 2024
1 parent 585fb89 commit 0a1855a
Show file tree
Hide file tree
Showing 3 changed files with 46 additions and 54 deletions.
35 changes: 21 additions & 14 deletions src/main/java/org/jruby/ext/openssl/PKey.java
Original file line number Diff line number Diff line change
Expand Up @@ -27,10 +27,8 @@
***** END LICENSE BLOCK *****/
package org.jruby.ext.openssl;

import java.io.ByteArrayInputStream;
import java.io.Console;
import java.io.IOException;
import java.io.InputStreamReader;
import java.io.StringReader;
import java.math.BigInteger;
import java.security.*;
Expand All @@ -57,11 +55,12 @@
import org.jruby.runtime.ThreadContext;
import org.jruby.runtime.builtin.IRubyObject;
import org.jruby.runtime.Visibility;
import org.jruby.util.ByteList;

import org.jruby.ext.openssl.impl.CipherSpec;
import org.jruby.ext.openssl.x509store.PEMInputOutput;

import static org.jruby.ext.openssl.OpenSSL.*;
import org.jruby.ext.openssl.impl.CipherSpec;
import org.jruby.util.ByteList;

/**
* @author <a href="mailto:[email protected]">Ola Bini</a>
Expand Down Expand Up @@ -111,14 +110,16 @@ public static IRubyObject read(final ThreadContext context, IRubyObject recv, IR
}

final RubyString str = readInitArg(context, data);
Object key = null;
KeyPair keyPair;
// d2i_PrivateKey_bio
try {
key = readPrivateKey(str, pass);
} catch (IOException e) { /* ignore */ }
keyPair = readPrivateKey(str, pass);
} catch (IOException e) {
debugStackTrace(runtime, "PKey readPrivateKey", e); /* ignore */
keyPair = null;
}
// PEM_read_bio_PrivateKey
if (key != null) {
final KeyPair keyPair = (KeyPair) key;
if (keyPair != null) {
final String alg = getAlgorithm(keyPair);
if ( "RSA".equals(alg) ) {
return new PKeyRSA(runtime, _PKey(runtime).getClass("RSA"),
Expand All @@ -141,17 +142,23 @@ public static IRubyObject read(final ThreadContext context, IRubyObject recv, IR
try {
pubKey = PEMInputOutput.readRSAPublicKey(new StringReader(str.toString()), null);
return new PKeyRSA(runtime, (RSAPublicKey) pubKey);
} catch (IOException e) { /* ignore */ }
} catch (IOException e) {
debugStackTrace(runtime, "PKey readRSAPublicKey", e); /* ignore */
}
try {
pubKey = PEMInputOutput.readDSAPublicKey(new StringReader(str.toString()), null);
return new PKeyDSA(runtime, (DSAPublicKey) pubKey);
} catch (IOException e) { /* ignore */ }
} catch (IOException e) {
debugStackTrace(runtime, "PKey readDSAPublicKey", e); /* ignore */
}

final byte[] input = StringHelper.readX509PEM(context, str);
// d2i_PUBKEY_bio
try {
pubKey = org.jruby.ext.openssl.impl.PKey.readPublicKey(input);
} catch (IOException|GeneralSecurityException e) { /* ignore */ }
} catch (IOException|GeneralSecurityException e) {
debugStackTrace(runtime, "PKey readPublicKey", e); /* ignore */
}
// PEM_read_bio_PUBKEY
if (pubKey == null) {
try {
Expand Down Expand Up @@ -431,12 +438,12 @@ protected static boolean ttySTDIN(final ThreadContext context) {
catch (RaiseException ex) { return false; }
}

static Object readPrivateKey(final String str, final char[] passwd)
static KeyPair readPrivateKey(final String str, final char[] passwd)
throws PEMInputOutput.PasswordRequiredException, IOException {
return PEMInputOutput.readPrivateKey(new StringReader(str), passwd);
}

static Object readPrivateKey(final RubyString str, final char[] passwd)
static KeyPair readPrivateKey(final RubyString str, final char[] passwd)
throws PEMInputOutput.PasswordRequiredException, IOException {
return readPrivateKey(str.toString(), passwd);
}
Expand Down
45 changes: 15 additions & 30 deletions src/main/java/org/jruby/ext/openssl/impl/PKey.java
Original file line number Diff line number Diff line change
Expand Up @@ -88,9 +88,13 @@
public class PKey {

public static KeyPair readPrivateKey(final byte[] input, final String type)
throws IOException, NoSuchAlgorithmException, InvalidKeySpecException {
return readPrivateKey((ASN1Sequence) new ASN1InputStream(input).readObject(), type);
}

public static KeyPair readPrivateKey(final ASN1Sequence seq, final String type)
throws IOException, NoSuchAlgorithmException, InvalidKeySpecException {
KeySpec pubSpec; KeySpec privSpec;
ASN1Sequence seq = (ASN1Sequence) new ASN1InputStream(input).readObject();
if ( type.equals("RSA") ) {
ASN1Integer mod = (ASN1Integer) seq.getObjectAt(1);
ASN1Integer pubExp = (ASN1Integer) seq.getObjectAt(2);
Expand All @@ -114,7 +118,7 @@ else if ( type.equals("DSA") ) {
pubSpec = new DSAPublicKeySpec(y.getValue(), p.getValue(), q.getValue(), g.getValue());
}
else if ( type.equals("EC") ) {
return readECPrivateKey(input);
return readECPrivateKey(SecurityHelper.getKeyFactory("EC"), seq);
}
else {
throw new IllegalStateException("unsupported type: " + type);
Expand All @@ -123,29 +127,6 @@ else if ( type.equals("EC") ) {
return new KeyPair(fact.generatePublic(pubSpec), fact.generatePrivate(privSpec));
}

// d2i_PrivateKey_bio
public static KeyPair readPrivateKey(byte[] input) throws IOException,
NoSuchAlgorithmException, InvalidKeySpecException {
KeyPair key = null;
try {
key = readRSAPrivateKey(input);
}
catch (NoSuchAlgorithmException e) { throw e; /* should not happen */ }
catch (InvalidKeySpecException e) {
// ignore
}
if (key == null) {
try {
key = readDSAPrivateKey(input);
}
catch (NoSuchAlgorithmException e) { throw e; /* should not happen */ }
catch (InvalidKeySpecException e) {
// ignore
}
}
return key;
}

// d2i_PUBKEY_bio
public static PublicKey readPublicKey(byte[] input) throws IOException,
NoSuchAlgorithmException, InvalidKeySpecException {
Expand Down Expand Up @@ -281,22 +262,26 @@ public static KeyPair readECPrivateKey(final byte[] input)
return readECPrivateKey(SecurityHelper.getKeyFactory("EC"), input);
}

public static KeyPair readECPrivateKey(final KeyFactory ecFactory, final byte[] input)
public static KeyPair readECPrivateKey(final KeyFactory keyFactory, final byte[] input)
throws IOException, InvalidKeySpecException {
return readECPrivateKey(keyFactory, (ASN1Sequence) ASN1Primitive.fromByteArray(input));
}

public static KeyPair readECPrivateKey(final KeyFactory keyFactory, final ASN1Sequence input)
throws IOException, InvalidKeySpecException {
try {
org.bouncycastle.asn1.sec.ECPrivateKey pKey = org.bouncycastle.asn1.sec.ECPrivateKey.getInstance(ASN1Primitive.fromByteArray(input));
org.bouncycastle.asn1.sec.ECPrivateKey pKey = org.bouncycastle.asn1.sec.ECPrivateKey.getInstance(input);
AlgorithmIdentifier algId = new AlgorithmIdentifier(X9ObjectIdentifiers.id_ecPublicKey, pKey.getParametersObject().toASN1Primitive());
PrivateKeyInfo privInfo = new PrivateKeyInfo(algId, pKey.toASN1Primitive());
SubjectPublicKeyInfo pubInfo = new SubjectPublicKeyInfo(algId, pKey.getPublicKey().getBytes());
PKCS8EncodedKeySpec privSpec = new PKCS8EncodedKeySpec(privInfo.getEncoded());
X509EncodedKeySpec pubSpec = new X509EncodedKeySpec(pubInfo.getEncoded());
//KeyFactory fact = KeyFactory.getInstance("EC", provider);

ECPrivateKey privateKey = (ECPrivateKey) ecFactory.generatePrivate(privSpec);
ECPrivateKey privateKey = (ECPrivateKey) keyFactory.generatePrivate(privSpec);
if ( algId.getParameters() instanceof ASN1ObjectIdentifier ) {
privateKey = ECPrivateKeyWithName.wrap(privateKey, (ASN1ObjectIdentifier) algId.getParameters());
}
return new KeyPair(ecFactory.generatePublic(pubSpec), privateKey);
return new KeyPair(keyFactory.generatePublic(pubSpec), privateKey);
}
catch (ClassCastException ex) {
throw new IOException("wrong ASN.1 object found in stream", ex);
Expand Down
20 changes: 10 additions & 10 deletions src/main/java/org/jruby/ext/openssl/x509store/PEMInputOutput.java
Original file line number Diff line number Diff line change
Expand Up @@ -1486,23 +1486,23 @@ private static CMSSignedData readPKCS7(BufferedReader in, char[] p, String endMa

public static KeyFactory getKeyFactory(final AlgorithmIdentifier algId)
throws NoSuchAlgorithmException {
return SecurityHelper.getKeyFactory(getPrivateKeyType(algId));
}

private static String getPrivateKeyType(final AlgorithmIdentifier algId) {
final ASN1ObjectIdentifier algIdentifier = algId.getAlgorithm();

String algorithm = null;
if ( X9ObjectIdentifiers.id_ecPublicKey.equals(algIdentifier) ) {
algorithm = "EC";
if (X9ObjectIdentifiers.id_ecPublicKey.equals(algIdentifier)) {
return "EC";
}
else if ( PKCSObjectIdentifiers.rsaEncryption.equals(algIdentifier) ) {
algorithm = "RSA";
if (PKCSObjectIdentifiers.rsaEncryption.equals(algIdentifier)) {
return "RSA";
}
else if ( X9ObjectIdentifiers.id_dsa.equals(algIdentifier) ) {
algorithm = "DSA";
if (X9ObjectIdentifiers.id_dsa.equals(algIdentifier)) {
return "DSA";
}

if ( algorithm == null ) algorithm = algIdentifier.getId();

return SecurityHelper.getKeyFactory(algorithm);
return algIdentifier.getId();
}

private static CertificateFactory getX509CertificateFactory() {
Expand Down

0 comments on commit 0a1855a

Please sign in to comment.