Skip to content

Commit

Permalink
S: re-invent readECPrivateKey
Browse files Browse the repository at this point in the history
  • Loading branch information
kares committed Apr 4, 2024
1 parent 0798733 commit 8c0ce72
Show file tree
Hide file tree
Showing 2 changed files with 13 additions and 119 deletions.
126 changes: 8 additions & 118 deletions src/main/java/org/jruby/ext/openssl/impl/PKey.java
Original file line number Diff line number Diff line change
Expand Up @@ -43,11 +43,6 @@
import java.security.interfaces.RSAPublicKey;
import java.security.spec.DSAPrivateKeySpec;
import java.security.spec.DSAPublicKeySpec;
import java.security.spec.ECParameterSpec;
import java.security.spec.ECPoint;
import java.security.spec.ECPrivateKeySpec;
import java.security.spec.ECPublicKeySpec;
import java.security.spec.EncodedKeySpec;
import java.security.spec.InvalidKeySpecException;
import java.security.spec.KeySpec;
import java.security.spec.PKCS8EncodedKeySpec;
Expand All @@ -72,23 +67,9 @@
import org.bouncycastle.asn1.x509.AlgorithmIdentifier;
import org.bouncycastle.asn1.x509.DSAParameter;
import org.bouncycastle.asn1.x509.SubjectPublicKeyInfo;
import org.bouncycastle.asn1.x9.ECNamedCurveTable;
import org.bouncycastle.asn1.x9.X962Parameters;
import org.bouncycastle.asn1.x9.X9ECParameters;
import org.bouncycastle.asn1.x9.X9ObjectIdentifiers;
import org.bouncycastle.crypto.params.ECDomainParameters;
import org.bouncycastle.crypto.params.ECPrivateKeyParameters;
import org.bouncycastle.crypto.params.ECPublicKeyParameters;
import org.bouncycastle.crypto.util.PrivateKeyFactory;
import org.bouncycastle.crypto.util.PublicKeyFactory;
import org.bouncycastle.jcajce.provider.asymmetric.util.EC5Util;
import org.bouncycastle.jcajce.provider.asymmetric.util.ECUtil;
import org.bouncycastle.jcajce.provider.asymmetric.util.KeyUtil;
import org.bouncycastle.jcajce.spec.OpenSSHPrivateKeySpec;

import org.bouncycastle.jce.spec.ECNamedCurveSpec;
import org.bouncycastle.openssl.PEMKeyPair;
import org.bouncycastle.openssl.PEMParser;
import org.jruby.ext.openssl.SecurityHelper;

/**
Expand All @@ -103,22 +84,12 @@ public enum Type { RSA, DSA, EC; }

public static KeyPair readPrivateKey(final Type type, final byte[] input)
throws IOException, NoSuchAlgorithmException, InvalidKeySpecException {
if (type == Type.EC) {
if (false) new PEMParser(null);
}
//OpenSSHPrivateKeyUtil parsePrivateKeyBlob
return readPrivateKey(type, mockPrivateKeyInfo(type, input));
}

private static PrivateKeyInfo mockPrivateKeyInfo(final Type type, final byte[] input) throws IOException {
assert type != null;
AlgorithmIdentifier algId = null;
if (type == Type.EC) {
//algId = new AlgorithmIdentifier(X9ObjectIdentifiers.id_ecPublicKey); // due readECPrivateKey
//algId = new AlgorithmIdentifier(X9ObjectIdentifiers.id_ecPublicKey, new X962Parameters(DERNull.INSTANCE)); // due readECPrivateKey
}
return new PrivateKeyInfo(algId, new ASN1InputStream(input).readObject());
//return PrivateKeyInfo.getInstance(input); NOPE!
return new PrivateKeyInfo(null, new ASN1InputStream(input).readObject());
}

public static KeyPair readPrivateKey(final Type type, final PrivateKeyInfo keyInfo)
Expand Down Expand Up @@ -298,107 +269,26 @@ public static KeyPair readECPrivateKey(final byte[] input)
public static KeyPair readECPrivateKey(final KeyFactory keyFactory, final byte[] input)
throws IOException, InvalidKeySpecException {
return readECPrivateKey(keyFactory, mockPrivateKeyInfo(Type.EC, input));

//PKCS8EncodedKeySpec spec = new PKCS8EncodedKeySpec(input);
//return new KeyPair(null, keyFactory.generatePrivate(spec));
}

// private static PublicKey resolveECPublicKey(final KeyFactory keyFactory, ECPrivateKey privateKey)
// throws InvalidKeySpecException {
//
// final ECParameterSpec params = privateKey.getParams();
// ECPoint q = params.getGenerator().multiply(privateKey.getS()); // getD
//
// ECPublicKeySpec publicKeySpec = new ECPublicKeySpec(q, ecParams);
//
// return keyFactory.generatePublic(publicKeySpec);
// }

public static KeyPair readECPrivateKey(final KeyFactory keyFactory, final PrivateKeyInfo keyInfo)
throws IOException, InvalidKeySpecException {
try {
ASN1Sequence seq = ASN1Sequence.getInstance(keyInfo.parsePrivateKey());

org.bouncycastle.asn1.sec.ECPrivateKey pKey = org.bouncycastle.asn1.sec.ECPrivateKey.getInstance(seq);
org.bouncycastle.asn1.sec.ECPrivateKey key = org.bouncycastle.asn1.sec.ECPrivateKey.getInstance(seq);
AlgorithmIdentifier algId = keyInfo.getPrivateKeyAlgorithm();
PrivateKeyInfo privInfo;
if (algId == null) {
algId = new AlgorithmIdentifier(X9ObjectIdentifiers.id_ecPublicKey, pKey.getParameters());
privInfo = new PrivateKeyInfo(algId, pKey);
} else {

if (algId == null) { // mockPrivateKeyInfo
algId = new AlgorithmIdentifier(X9ObjectIdentifiers.id_ecPublicKey, key.getParameters());
}
SubjectPublicKeyInfo pubInfo = new SubjectPublicKeyInfo(algId, pKey.getPublicKey().getBytes());
privInfo = new PrivateKeyInfo(algId, pKey);

if (true) {
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);
}


//ECPrivateKeyParameters privKeyParams = (ECPrivateKeyParameters) PrivateKeyFactory.createKey(keyInfo);
//AlgorithmIdentifier algId = keyInfo.getPrivateKeyAlgorithm();
// X962Parameters params = X962Parameters.getInstance(algId.getParameters());
//
// X9ECParameters x9;
// if (params.isNamedCurve())
// {
// ASN1ObjectIdentifier oid = ASN1ObjectIdentifier.getInstance(params.getParameters());
// x9 = ECNamedCurveTable.getByOID(oid);
// }
// else
// {
// x9 = X9ECParameters.getInstance(params.getParameters());
// }

org.bouncycastle.asn1.sec.ECPrivateKey ecPrivateKey = org.bouncycastle.asn1.sec.ECPrivateKey.getInstance(keyInfo.parsePrivateKey());

// ASN1ObjectIdentifier curveOID = ASN1ObjectIdentifier.getInstance(ecPrivateKey.getParametersObject());
// ECUtil.getNamedCurveByOid(curveOID);
// X9ECParameters x9Params = ECNamedCurveTable.getByOID(curveOID);
//
// ECDomainParameters dParams = new ECDomainParameters(x9Params.getCurve(), x9Params.getG(), x9Params.getN(), x9Params.getH(), x9Params.getSeed());
// ECPrivateKeyParameters privKeyParams = new ECPrivateKeyParameters(ecPrivateKey.getKey(), dParams);

// org.bouncycastle.asn1.sec.ECPrivateKey ecPrivateKey = org.bouncycastle.asn1.sec.ECPrivateKey.getInstance(keyInfo.parsePrivateKey());
// AlgorithmIdentifier algId = keyInfo.getPrivateKeyAlgorithm();

///
// if (key.getParameters() == null) {
//
// }
// ASN1ObjectIdentifier curveOID = ASN1ObjectIdentifier.getInstance(key.getParameters());
// X9ECParameters ecParams = ECNamedCurveTable.getByOID(curveOID);
// ECPrivateKeyParameters privKeyParams = new ECPrivateKeyParameters(key.getKey(), new ECDomainParameters(ecParams.getCurve(), ecParams.getG(), ecParams.getN(), ecParams.getH()));


// NOTE: should only happen when using mockPrivateKeyInfo(Type, byte[])
//if (algId == null) algId = new AlgorithmIdentifier(X9ObjectIdentifiers.id_ecPublicKey);

//SubjectPublicKeyInfo pubInfo = new SubjectPublicKeyInfo(algId, ecPrivateKey.getPublicKey().getBytes());
//ECPublicKeyParameters params = (ECPublicKeyParameters) PublicKeyFactory.createKey(pubInfo);
// key.getKey(); // publcKey BigInteger

System.out.println("publicInfo: " + pubInfo);
System.out.println("key: " + ecPrivateKey.getKey());
System.out.println("params: " + ecPrivateKey.getParameters());

//PKCS8EncodedKeySpec privSpec = new PKCS8EncodedKeySpec(keyInfo.getEncoded());
PKCS8EncodedKeySpec privSpec = new PKCS8EncodedKeySpec(ecPrivateKey.getEncoded());
//EncodedKeySpec privSpec = new OpenSSHPrivateKeySpec(ecPrivateKey.getEncoded());
X509EncodedKeySpec pubSpec = new X509EncodedKeySpec(pubInfo.getEncoded());

// ECPrivateKeySpec privSpec = new ECPrivateKeySpec(privKeyParams.getD(), EC5Util.convertToSpec(privKeyParams.getParameters()));
final SubjectPublicKeyInfo pubInfo = new SubjectPublicKeyInfo(algId, key.getPublicKey().getBytes());
final PrivateKeyInfo privInfo = new PrivateKeyInfo(algId, key);

ECPrivateKey privateKey = (ECPrivateKey) keyFactory.generatePrivate(privSpec);
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(pubSpec), privateKey);
return new KeyPair(keyFactory.generatePublic(new X509EncodedKeySpec(pubInfo.getEncoded())), privateKey);
}
catch (ClassCastException ex) {
throw new IOException("wrong ASN.1 object found in stream", ex);
Expand Down
6 changes: 5 additions & 1 deletion src/test/ruby/ec/test_ec.rb
Original file line number Diff line number Diff line change
Expand Up @@ -55,8 +55,12 @@ 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 OpenSSL::PKey::EC, key.class
assert_equal '37273549501637553234010607973347901861080883009977847480473501706546896416762', key.private_key.to_s
assert_empty key.public_key.to_s

assert_equal OpenSSL::PKey::EC::Point, key.public_key.class
public_key = '59992919564038617581477192805085606797983518604284049179473294859597640027055772972320536875319417493705914919226919250526441868144324498122209513139102397'
assert_equal public_key, key.public_key.to_bn.to_s
end

def test_point
Expand Down

0 comments on commit 8c0ce72

Please sign in to comment.