Showing posts with label smart cards. Show all posts
Showing posts with label smart cards. Show all posts

2012/04/09

Using Smart Card as Keystore in Java, signing

This is the promised sequel of the article from September 8th 2011.
It does not represent the only one way how to achieve the desired result, especially when it comes to manipulation with certificates and keys certificate management.

Loading Certificate into the Card


It seems that the easiest approach is to prepare the key store on disk and load it  into the card when ready. For that we use mostly two tools - openssl to transform keys and certificates and keytool to manage the key store.

Create the key store on disk and fill with certificates

Create a private key entry, i.e. a certificate containing a private key, by converting our certificate and private key to PKCS12 format: openssl pkcs12 -export -out cert.p12 -in cert.pem -inkey key.pem

I used org.apache.commons.ssl.KeyStoreBuilder to build a keystore from the p12 file. The password is used both for decryption of private key and encryption of the newly created Java key store. 
java -cp commons-ssl.jar org.apache.commons.ssl.KeyStoreBuilder password cert.p12

Now you can check the content of the file-based key store: keytool -keystore newkeystore.jks -list

Load the file-base key store into the card

keytool -keystore NONE -storetype PKCS11 -providerName SunPKCS11-OpenSC-PKCS11 -importkeystore -srckeystore newkeystore.jks

Check the content of the on-card key store.
keytool -keystore NONE -storetype PKCS11 -providerName SunPKCS11-OpenSC-PKCS11 -list

Signing and Verification with the On-Card Certificate


All the error handling was intentionally removed to make following example shorter. I also skipped creation of PKCS7 signed messages - you can you Bouncy Castle CMSSignedDataGenerator for that easily.

import java.security.*;
import java.security.cert.*;
import java.security.cert.Certificate;
import java.io.*;

...

// loading the key from file:
KeyStore keyStore = KeyStore.getInstance("JCEKS");
FileInputStream inputStream = new FileInputStream(storeFileName);
keyStore.load(inputStream, storePassword.toCharArray());
KeyStore.ProtectionParameter protectParameter = new KeyStore.PasswordProtection(certPass.toCharArray()); }

// loading the key from token:
KeyStore keyStore = KeyStore.getInstance("PKCS11");
KeyStore.ProtectionParameter protectParameter = null;
keyStore.load(null, storePassword.toCharArray());

// the rest does not depend on the type of the store: 
String signatureAlgorithmName = "SHA1withRSA";
KeyStore.Entry entry = keyStore.getEntry(alias, protectParam);
boolean isPrivateKeyEntry = keyStore.entryInstanceOf(alias, KeyStore.PrivateKeyEntry.class);
if (isPrivateKeyEntry)
{
  Signature signatureAlgorithm = Signature.getInstance(signatureAlgorithmName);

  // signing
  KeyStore.PrivateKeyEntry privateKeyEntry = (KeyStore.PrivateKeyEntry)entry;
  PrivateKey privateKey = privateKeyEntry.getPrivateKey();  
  signatureAlgorithm.initSign (privateKey);
  signatureAlgorithm.update (message);
  byte[] signature = signatureAlgorithm.sign();

  // verification
  Certificate[] chain = privateKeyEntry.getCertificateChain();
  X509Certificate certificate = (X509Certificate) chain[chain.length-1];
  PublicKey publicKey = certificate.getPublicKey();
  signatureAlgorithm.initVerify(publicKey);
  signatureAlgorithm.update (data);
  boolean verified = signatureAlgorithm.verify(signature);
}

2011/09/18

Using Smart Card as Keystore in Java, setup

Using a smart card as a key store promises stronger security compared to storing keys or certificates on a disk. This can be further improved by using a card reader with a PIN pad, an effective counter-measure against key loggers.

This article should provide basic information how to use smart card as key store for Java applications. You do not need an expensive card for such application - a cheaper, specialized crypto-card will do. The installation instructions in this article focus on Linux, as it is my preferred platform and the setup a bit more complicated than on Windows.

The stack

                 application
                      |
           java.security.Keystore
                      |
                     JVM
                      |
                PKCS11 provider
                      |
              PC/SC middleware
                      |
                    CCID
                      |
            USB smart card reader
                      |
                 smart card 

Installing Software
  1. Download a driver for your smart card reader from its producer's page and install it.
  2. Download and install PC/SC middleware - PCSC-Lite. It does not require  any configuration if you use USB reader.
  3. Get PKCS11 provider for your card. You can use open-source (OpenSC) or producer 's implementation, depending on which one works better with Java.

Setting PKCS11 Token for Java 

First you have to configure PKCS11 provider for Java. Open $JAVA_HOME/jre/lib/security/java.security and look for registered security providers - find lines starting with text security.provider. Add a new security provider by adding line security.provider.9=sun.security.pkcs11.SunPKCS11 /etc/pkcs11_java.cfg . Sun PKCS#11 provider allows integration of PKCS11 tokens with Java platform by interfacing a native library, usually delivered by the token producer.

The configuration file following the provider's fully qualified name may contain various PKCS11 settings. It usually contains only the three lines we can see in this setting for OpenSC:

name = OpenSC-PKCS11
description = SunPKCS11 via OpenSC
library = /usr/lib/opensc-pkcs11.so

The entry name serves as name of the PKCS11 provider and description is AFAIK optional. The most important is the library property, it contains a path to the PKCS11 implementation we want to use. 

Depending on environment in which the application will be used we would need  need to create a custom security policy,  the name of the provider is prefixed with "SunPKCS11-" :

grant { 
       permission java.security.SecurityPermission
       "authProvider.SunPKCS11-OpenSC-PKCS11";
 };


In the second part we will see how to create key and certificate, load them into the card and use the key on card to sign and verify.