I’ve been testing my Content-Signature framework discussed earlier and wanted to see if I could exchange digital signatures generated and verified from both Python and Java code. After a bit of research here’s what I’ve found so far on how to do this.
Generate keys with openssl
The first step is to generate a private key and a certificate using the openssl program. This is a common utility. Do a search if it is not available on your computer and you’ll find support and instructions to install on various platforms. It came with my macbook pro (I think maybe with Darwin tools). You’ll have to generate the keys in both .pem format (for Python) and .der format (for Java).
# generate pems
$ openssl req -x509 -nodes -days 365 -newkey rsa:1024 -keyout mycert-private.pem -out mycert.pem
# create private key .der file
$ openssl pkcs8 -topk8 -nocrypt -in mycert-private.pem -out mycert-private.der -outform der
# create certificate .der file
$ openssl x509 -in mycert.pem -out mycert.der -outform der
From this you should have 2 sets of files: mycert-private.pem, mycert-private.der and mycert.pem and mycert.der
Import private key sign in Java
Here’s a nice tool for loading in the .der files created into a Java KeyStore. I’ve extracted some of the code so that you can see the whole manual, programmatic process of importing a private key and signing a message.
import org.jboss.resteasy.util.Hex;
import java.io.DataInputStream;
import java.io.*;
import java.security.*;
import java.security.cert.*;
import java.security.spec.PKCS8EncodedKeySpec;
public class ExampleSignTest
{
@Test
public void testDerFile() throws Exception
{
// import private key
InputStream is = Thread.currentThread().getContextClassLoader().getResourceAsStream("mycert-private.der");
DataInputStream dis = new DataInputStream(is);
byte[] derFile = new byte[dis.available()];
dis.readFully(derFile);
KeyFactory kf = KeyFactory.getInstance("RSA");
PKCS8EncodedKeySpec spec = new PKCS8EncodedKeySpec(derFile);
PrivateKey privateKey = kf.generatePrivate(spec);
Signature instance = Signature.getInstance("SHA256withRSA");
instance.initSign(privateKey);
instance.update("from-java".getBytes());
byte[] signatureBytes = instance.sign();
System.out.println("Signature: ");
System.out.println(Hex.encodeHex(signatureBytes));
}
}
The code prints out the signature in hex using a simple routine from Resteasy.
Import certificate and verify in Java
Here’s an example of verifying:
@Test
public void testDerFile() throws Exception
{
CertificateFactory cf = CertificateFactory.getInstance("X.509");
is = Thread.currentThread().getContextClassLoader().getResourceAsStream("mycert.der");
Certificate cert = cf.generateCertificate(is);
PublicKey publicKey = cert.getPublicKey();
String hexSignature = "4e3014a3a0ff296c07927e846221ee68f70e0b06ed54a1fe974944ea17b836b92279635a7e0bb6b8923df94f4023de95ef07fa76506888897a88ac440eb185b6b117f4c906cba989ffb4e1f81c6677db12e7dc22d51d9369df92165709817792dc3e647dae6b70a0d84c386b0228c2442c9a6a0107381aac8e4cb4c367435d52";
// loading CertificateChain
Signature verify = Signature.getInstance("SHA256withRSA");
verify.initVerify(publicKey);
verify.update("from-python".getBytes());
Assert.assertTrue(verify.verify(Hex.decodeHex(pythonHexSignature)));
}
The code has hardcoded a generated signature produced from signing the “from-python” string.
Import private key and sign in Python
The Python code requires the M2Crypto library. I tried PyCrypto, but I could get it to work. My code was tested on macbook pro with Python 2.6.1 M2Crypto version 0.21.1. Also notice that the .pem files are used instead of .der. I couldn’t figure out if M2Crypto fully supported .der so I just used the .pems.
from M2Crypto import EVP, RSA, X509
import binascii
key = EVP.load_key("mycert-private.pem")
key.reset_context(md='sha256')
key.sign_init()
key.sign_update("from-python")
signature = key.sign_final()
print "Signature:"
print binascii.b2a_hex(signature)
Importing certificate and verifying in Python
Here’s the verification:
rom M2Crypto import EVP, RSA, X509
import binascii
hexSignature = "0a11ab4ebcd2b0803d6e280a1d45b5b5d5d53688949f5a4f2d6436f15df3b10633c79760b9fe3b64eb9d84371c35e8b7d946052dfdd99ebb5cf7f3092762e1a91b261117e6675f2d28afe2ec4\
d90abfe3559a1259d2c66f3dc42ca3bfce7498705833445170bd8c293d60448b6c599abfe2d06882d3fff9ef887379eb7da3fe0"
java_sig = binascii.a2b_hex(hexSignature)
cert = X509.load_cert("mycert.pem")
pubkey = cert.get_pubkey()
pubkey.reset_context(md="sha256")
pubkey.verify_init()
pubkey.verify_update("from-java")
assert pubkey.verify_final(java_sig) == 1
Hope you enjoy. If you know a better way to set up the certs and key files, let me know. Using openssl was the best way I could find.
Like this:
Like Loading...