Showing posts with label Code signing. Show all posts
Showing posts with label Code signing. Show all posts

July 12, 2011

How to sign stuff and then verify it using PKCS7

You'd think security is about obfuscation when trying to find resources on how to do stuff. We end up with people not really knowing how to implement security and implement it wrongly.
I might be one of those people so be warned, but if you need to a resource to get started at least, you can look here. So let's begin.

What we're doing is creating a pair of X509 keys; a private key and a public key. Both keys will be stored in a file called a keystore file. This file exists on your computer and is unlocked by a password. Once the file is unlocked, you need to unlock the key as well, so two passwords are needed, unless you use the same password for both.

You can use the private key to sign data and public key to verify the signature. Here's what I think happens during the process.

1. Sign some data using the private.
2. Optionally include the public key and data in the signature so that it can be verified.
3. Send the signature to the recipient.
4. Recipient verifies the data in the signature
5. Recipient verifies the signature with the certificate containing the Public key shared earlier.
6. If both 4 and 5 are verified correct, then the data can be considered to the signed.

Here's some code using the free bouncy castle library for Java.

Here we open the keyfile and unlock it using the keyfile password.


KeyStore keystore = KeyStore.getInstance("jks");
InputStream input = new FileInputStream("c:\\keyfile.jks");
try {
keystore.load(input, password);
} catch (IOException e) {
}


Now we get the private key for the key pair that we have in the keystore. The keypair is identified by an alias. Again we use the password to unlock the private key.

    PrivateKey privateKey = (PrivateKey) keystore.getKey(alias, password.toCharArray());



Next we get the Certificate for the key pair to include in the signature. The certificate is not protected by a password. This means its OK to share it with others. It's not ok to share the Private key as it will enable others to sign stuff on your behalf.

    Certificate cert = keystore.getCertificate(alias);


Here is the signing code. First we add the provider to the Security Manager. It will then be reference using the provider code "BC". We create a data generator, initialize it with a signer, wrap our data in a content wrapper and finally generate the signature based on the content, and the "BC" security provider.


// Create the provider
Security.addProvider(new BouncyCastleProvider());
// Create a generator
CMSSignedDataGenerator generator = new CMSSignedDataGenerator();
// initialize the signer
generator.addSigner(privateKey, (X509Certificate) cert, CMSSignedDataGenerator.DIGEST_SHA1);
// turn our data into content
byte[] data = "ABC123".getBytes();
CMSProcessable content = new CMSProcessableByteArray(data);
// sign the data
CMSSignedData signedData = generator.generate(content, true, "BC")



The results gets put into bytes and sent out. You probably want to encode it somewhat using BASE64. I'll leave that to you.

    byte[] result = signedData.getEncoded();


That's it for signing. Now what about verification of the signature. Remember that we will share the certificate containing the Public key with the recipient - probably ahead of time. If not you need to verify the credentials within the certificate. This will probably involve a Certificate authority. If the certificate was exchanged securely the CA should not be an issue.

Next comes the data and the signature. We receive the signature as an array of bytes and we wrap it.

    CMSSignedData s = new CMSSignedData(result);


We extract the public key from the keystore in the usual way. But this would be the keystore of the recipient. It would not have the private key.

    PublicKey publicKey = cert.getPublicKey();


We can extract the content from the signature in this way. Notice its an array of bytes so, re-encode it in ASCII or other format. This covers step 4 above. I will not go into details of how to verify it. For me, it was sufficient to print it out and verify it was indeed what I signed in the first place.

    byte[] signedContent = (byte[]) s.getSignedContent().getContent();



Now we verify. We iterate the list of signers, and ensure one of the signers is the party we expect. If verified returns true for at least one signer, that's ok for us. Your rules for verification may be different. For example, it may need to be signed by three people or at least two out of three.

    java.util.Iterator i = signers.getSigners().iterator();
while ( i.hasNext()) {
SignerInformation signer = (SignerInformation) i.next();
verified = signer.verify(publicKey, "BC");
}


That's it. Take it for what you paid for it. Nothing.

July 02, 2007

Code signing J2ME apps

I do a range of diverse things, so its a bit cool that I can talk about Kerberos and LDAP one day and talk about ASP shell scripts and J2ME code signing the next. There are a few good websites that talk about J2ME code signing. I know because I read them and followed their advice. That said, I still had work to do on my own J2ME project because some things just aren't documented. Perhaps an expert takes these things for granted and so the problem never occurs to the expert and as such, the expert doesn't document that. Anyway enough talk.

First step is to create a keystore. You can do this via command line using keytool which is distributed with the JDK. I used netbeans because sometimes I make typo errors. Typo errors are easier to correct via GUI than CLI. You will create a keystore, which is protected by a keystore password and a key-pair which is given an alias (a friendly name) and a key-pair password. Remember these passwords well.

Lets call our keystore file keystorefile.ks and our key-pair mykey. This makes examples easier to understand. Once the keystore is created you can do little things to them using keytool.
For example:


  • View keys in the keystore

  • keytool.exe -list -keystore keystorefile.ks

  • Export keys into a file

  • keytool.exe -export -alias mykey -keystore keystorefile.ks -file mykey.crt

  • Export keys into a readable format

  • keytool.exe -export -alias mykey -keystore keystorefile.ks -rfc -file mykey.crt

  • Print a key from the file to the screen

  • keytool.exe -printcert -file vtoken.crt



Note: Once you export your key to a file, we start calling that a certificate. Who knows why?

Now that you're done playing with yourself, you probably want to get a Certificate Authority (CA) to sign the cert. So you have to create a certificate signing request (CSR) and send it to the CA.

keytool.exe -certreq -alias mykey-keystore keystorefile.ks –file mykey.csr

mykey.csr is a text which starts with
----BEGIN NEW CERTIFICATE REQUEST-----
and ends with
-----END NEW CERTIFICATE REQUEST-----

You will send this to the CA, through their website. I used Verisign because apparently they are supported by the most number of phones. After Verisign has signed the cert, they will send it back to you. You will need to import it back into the SAME keystore file and the SAME alias. I told you those passwords are important. Its a good thing you didn't flipflop on your decision to buy the cert and prolong a 1 day process into a 3 month nightmare complaining that making online purchases is against company policy and that its terribly difficult faxing things overseas, and making international phone calls as well as arm-twisting your vendor to give you the certificate for free. Yes its a good thing you didn't do that.

Now that you've found your keystore file and certificate alias and the passwords to your keystore and key-pair, its time to import the signed cert.

keytool -import -file c:\casigned.cert -keystore keystorefile.ks -alias mykey

Done. Now you can sign J2ME applications by unlocking the keystore and key-pair.