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.