This content has moved permanently to:
https://blog.jonm.dev/posts/rsa-public-key-cryptography-in-java/
Friday, May 15, 2009
Subscribe to:
Post Comments (Atom)
The Art of Writing Software
This content has moved permanently to:
https://blog.jonm.dev/posts/rsa-public-key-cryptography-in-java/
All articles Copyright © 2007-2019 by Jon Moore. All rights reserved.
25 comments:
Well Done!!
After months of searching, finally solve the openssl DER format.
Thank you very much
Thanks a lot!!!
You saved my job!!!
Had I had this advice some six years earlier! :-)
How we generate public privet key without oopenssl. can we use tynica as somekind of CA to generate keys.
thanks in advance.
@Anonymous: Here you go: http://tinyurl.com/ygwvqow.
Thanks, Jon, for a clear and concise post. I'm trying to duplicate the functionality of this command in Java, and I've gotten most of the way there thanks to your help, but in the end, I get a different signature:
$ openssl dgst -sha1 -binary < SomeFileToSign | openssl dgst -dss1 -sign myprivatekey.pem > openssl.sig
I did the PEM->DER conversion as you suggest and am able to sign without exceptions, but the resulting bytes are different.
I've verified that I get the same SHA1 digest. I'm creating a KeyFactory of "DSA" type, and a Signature of "DSS" type. I figure I've left out some configuration of Signature, and I'm hoping you might know what it is off the top of your head. Thanks much!
Well, that was dumb. I realize now that the signature is different every time. Clearly, I need to figure out how to verify the signature generated by Java using OpenSSL, but I can't figure out the right command.
Thanks anyway!
@JetForMe: Not being as familiar with the DSA-DSS signatures as I am with RSA-SHA1, I'm not sure I can directly help.
There are often configuration options you can pass to the Signature.getInstance after the normal algorithm name that affect things like padding schemes, etc. Perhaps you need to more specifically specify the variant of Signature algorithm you want so that it matches what OpenSSL is doing.
I think I love you! I wasted one week trying to understand the right key format to give to Java to get this stupid PublicKey object, and nothing was working!
By the way, can anyone explain me why if I use PublicKey.toString() I get the key in nice clear text, but not if I use new String(PublicKey.getEncoded())?
How to I decode a DER key to see it in clear text?(and where the hell is the toString function overridden in PublicKey?)
@Federico: glad the article helped.
DER format is a binary format, which explains why you aren't seeing anything intelligible from new String(key.getEncoded()) -- you're basically saying "take this fairly random set of bytes and pretend it's a string", whereas PublicKey.toString() is explicitly meant to give you a proper String representation of the key.
toString() is probably being overridden in your cryptography provider (e.g. BouncyCastle or the like); that's where the object implementing the Key/PublicKey/RSAPublicKey interface hierarchy lives.
Thank you again for the explanation, and since you are so knowledgeable I would like to bother you with one more question if I may:
I tried to extract the public key from the CAcert root certificate in txt format (https://www.cacert.org/certs/root.txt), and use it in java, but of course without success.
Do you have any idea about how one might convert it into the correct DER format (since it is the only one Java understands)?
Thanks in advance, and again, great article :)
@Federico: without having lots of time to debug, you may see a plaintext section of that cert URL that has "BEGIN CERTIFICATE" and "END CERTIFICATE" lines. This should be a PEM-format public key; you ought to be able to use an openssl command similar to the ones in the article here to convert that to DER format.
I see, so that was indeed a key.
Thank you for the help, but as I feared, there is no pure programmatic way to handle and convert these keys in java. One must always rely on openssl...
Hi, thank you for this great article.
I managed to load my openssl RSA keys into java, but the original openssl key is 1024 bits, java is creating a PrivateKey with 4096 bits, thus resulting in a padding error in the cipher algorithm.
Any suggestions, why I got a mismatch in the keylength?
Thank you very much
Here is a small piece that accepts the PEM files directly no need of conversion to DER
public static PrivateKey getPriv(String filename) throws Exception {
File f = new File(filename);
FileInputStream fis = new FileInputStream(f);
DataInputStream dis = new DataInputStream(fis);
byte[] keyBytes = new byte[(int) f.length()];
dis.readFully(keyBytes);
dis.close();
//byte[] temp = new byte[keyBytes.length];
String temp = new String(keyBytes);
String privKeyPEM = temp.replace("-----BEGIN RSA PRIVATE KEY-----\n", "");
privKeyPEM = privKeyPEM.replace("-----END RSA PRIVATE KEY-----", "");
//System.out.println("Private key\n"+privKeyPEM);
Base64 b64 = new Base64();
byte [] decoded = b64.decode(privKeyPEM);
//dumphex(decoded,"PrivateKey");
PKCS8EncodedKeySpec spec = new PKCS8EncodedKeySpec(decoded);
KeyFactory kf = KeyFactory.getInstance("RSA");
return kf.generatePrivate(spec);
}
When I tried to read private_key.pem from the code specified, I am getting
Exception in thread "main" java.security.spec.InvalidKeySpecException: java.security.InvalidKeyException: IOException : algid parse error, not a sequence
at sun.security.rsa.RSAKeyFactory.engineGeneratePrivate(Unknown Source)
at java.security.KeyFactory.generatePrivate(Unknown Source)
at AsymmetricCipherTest.getPriv(AsymmetricCipherTest.java:286)
at AsymmetricCipherTest.main(AsymmetricCipherTest.java:59)
can any one give me complete code to use openssl generated key in rsa and dsa encryption and decryption
You're a genius my friend. Saved us hours of stupid debugging!!! Thanks!
Thank you! After many hours of searching the web, finally a post that worked!
I am signing a file with the command
openssl dgst -sha1 -sign mykey.pem -out my.jar.jar.sha1 my.jar
later on I used the following to verify the signature.
It returns false always. The publickey was created using the above code
public static boolean verify(PublicKey publicKey, byte[] sig, byte[] data) throws InvalidKeyException, SignatureException {
Signature signature= null;
try {
signature = Signature.getInstance("SHA1withRSA");
signature.initVerify(publicKey);
signature.update(data);
boolean verify = signature.verify(sig);
return verify;
} catch (NoSuchAlgorithmException e) {
//will not happen
}
return false;
}
ignore my question. It failed because I sent the digest to the verify method instead of the whole file
Really good!!! This article and this blog helped me making a program to create and verify Http-signature :-)
http://niels.nu/blog/2016/java-rsa.html
Post a Comment