-
Notifications
You must be signed in to change notification settings - Fork 82
Fix for PKCS8 EC private key support #267
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Conversation
Signed-off-by: Tero Saarni <tero.saarni@est.tech>
Thanks Tero, not sure all these |
Signed-off-by: Tero Saarni <tero.saarni@est.tech>
Sorry, I realize I broke ECDSA signing with the renaming! I now committed a change that should fix it, by introducing new method The reasoning is following: In case of
In this case, it really needs to return
It needs to be Docs mention that in the context of Java standard naming, An example: When looking at JDK KeyFactory standard names, it only list EC and not ECDSA. Regardless of the standard names, both EC and ECDSA are registered as BouncyCastle key factory algorithms: see this code which points to these classes - both seem to refer to the same provider configuration. With this code: import java.security.Security;
import org.bouncycastle.jce.provider.BouncyCastleProvider;
class KeyAlgorithms {
public static void main(String[] args) {
System.out.println("JDK KeyFactory algorithms: " + Security.getAlgorithms("KeyFactory"));
Security.addProvider(new BouncyCastleProvider());
System.out.println("BC KeyFactory algorithms: " + Security.getAlgorithms("KeyFactory"));
}
} I can observe following: $ java -cp /home/tsaarni/.m2/repository/org/bouncycastle/bcprov-jdk18on/1.71/bcprov-jdk18on-1.71.jar keyalgorithms.java
JDK KeyFactory algorithms: [RSA, X25519, DSA, DIFFIEHELLMAN, RSASSA-PSS, X448, XDH, EC]
BC KeyFactory algorithms: [ECDH, DH, X.509, DIFFIEHELLMAN, ECGOST3410-2012, X448, ECDHC, ED25519, COMPOSITE, GOST3410, ELGAMAL, DSA, EXTERNAL, ED448, DSTU4145, XDH, EC, ECDSA, RSA, X25519, ECGOST3410, OID.1.3.6.1.4.1.22554.4.2, LMS, 1.3.6.1.4.1.22554.4.2, RSASSA-PSS, OID.1.3.6.1.4.1.18227.2.1, 1.3.6.1.4.1.18227.2.1, SPHINCSPLUS, ECMQV, EDDSA] BC really seems to have registered both names while JDK does not. If grepping the BC source code, one can find that it uses PS: I have still the task to add a test case for EC keys! |
Small additional note: I found this old BouncyCastle issue where this topic was also touched. It was said this is handled by BC PKIX key manager. I can take this approach too, that is: keep the key type as |
👍 this is looking great. |
Signed-off-by: Tero Saarni <tero.saarni@est.tech>
PrivateKeyInfo pInfo = PrivateKeyInfo.getInstance(bytes); | ||
KeyFactory keyFactory = getKeyFactory( pInfo.getPrivateKeyAlgorithm() ); | ||
PrivateKey pKey = keyFactory.generatePrivate(new PKCS8EncodedKeySpec(pInfo.getEncoded())); | ||
return new KeyPair(null, pKey); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Note that the approach proposed here does not try to derive the public key from private key, like org.jruby.ext.openssl.impl.PKey.readPrivateKey()
attempted to do. Instead, it takes the same approach as reading encrypted PKCS#8 has done, here few lines below
return new KeyPair(null, privKey); |
This approach worked for me in TLS tests.
I have added a test case I did some further experiments as well (not included in PR): I wanted to add similar test case for encrypted PKCS#8 which I did not find existing. Something like: def test_read_pkcs8_enc_with_ec
key_file = File.join(File.dirname(__FILE__), 'private_key_pkcs8_enc.pem')
key = OpenSSL::PKey::read(File.read(key_file), 'password')
assert_equal '37273549501637553234010607973347901861080883009977847480473501706546896416762', key.private_key.to_s
assert_empty key.public_key.to_s
end I converted the PKCS#8 file I included in this PR to encrypted PKCS#8
It seems I cannot get the existing code to read encrypted PKCS#8 file either. That code was not changed by this PR. Few observations: (1) When trying to read encrypted PKCS#8 the code throws exception
(2) I then tried to create encrypted PKCS#8 with old algorithm instead, to see if we can succeed with that
Now that made the code execute jruby-openssl/src/main/java/org/jruby/ext/openssl/x509store/PEMInputOutput.java Lines 397 to 398 in 1f95043
I searched for SecretKeyFactory algorithm that is supported by JDK from
and then the test passed! (3) I also noticed that
I do not need encrypted PKCS#8 support myself now, but initially I thought I could quickly add a test. It seems bit more difficult, unless adding test data with that legacy PBE-MD5-DES encryption... |
Recall the issues you've mentioned, indeed PBES2 is not supported 100% by OpenJDK's provider. |
Hi @kares, I wanted to ask if there has been plans of making a new release in near future? I see there hasn't been many changes, but a release would make it easier to use this feature 😄 |
Hey Tero, planning to but I still haven't found time to look into another (EC) incompatibility: #241 Feel free to ping me again if I do not do anything in a week, so I can than just cut a release afterwards whatever is on master. |
Hi @kares 👋 Sorry to bother again, but just wondering how it is going with regards the release? And if there something I could try to help with :) |
Hey, give 0.14.1 a try and let us know if there's still issues on your end. |
@kares Thank you! |
This pull request fixes loading of PKCS#8 EC private keys.
The code did not parse the unencrypted PKCS8 file correctly in case of EC private key. The proposed fix skips calling the old method that did more complicated parsing. Instead it takes a similar approach to the existing code for encrypted PKCS#8, which seems to work for both RSA and EC private keys.
The change also proposes renaming
ECDSA
algorithm name toEC
. I'm uncertain if some of the instances should remain, but at least for the KeyManager the key type must beEC
: when the Java TLS stack calls the KeyManager (defined by jruby-openssl) to select the key alias, it uses typeEC
notECDSA
. Because the code previously usedECDSA
the TLS handshake still failed even after the loading of EC key was fixed, since no match was found for key typeEC
.Possible TODOs to improve the change:
Fixes #266
Signed-off-by: Tero Saarni tero.saarni@est.tech