September 19, 2020
Hot Topics:

Java Applet for Signing with a Smart Card

  • By Svetlin Nakov
  • Send Email »
  • More Articles »

Using the Sun PKCS#11 Provider Without a Configuration File

If you do not want to use an external configuration file, you can set the settings of the Sun PKCS#11 Provider dynamically by a stream. This can be done in the following way:

String pkcs11config =
   "name = SmartCardn" +
   "library = c:\windows\system32\pkcs201n.dll";
byte[] pkcs11configBytes = pkcs11config.getBytes();
ByteArrayInputStream configStream =
Provider pkcs11Provider =
   new sun.security.pkcs11.SunPKCS11(configStream);

In this example, you create a stream that reads the configuration settings, not from a text file but from a string. You first convert the string to a byte array and later create a stream from it. At last, you initialize the Sun PKCS#11 provider by passing this stream to it.

Unregistering the Sun PKCS#11 Provider

When you no longer need the PKCS#11 security provider, you should unregister it to deallocate the resources used. This can be done in the following way:

Provider pkcs11Provider = ...;
String pkcs11ProviderName = pkcs11Provider.getName();

Some PKCS#11 native implementations require the provider to be unregistered after you've finished signing. Otherwise, an active session with the smart card can remain open and can cause all further signing attempts to fail. Another possibility for unregistering the PKCS#11 security provider is the following:


The name of the provider is constructed by the prefix "SunPKCS11-," followed by the name given in the configuration file (pkcs11.cfg).

Extracting a Keystore from a Smart Card

After you have registered and configured successfully the Sun PKCS#11 Provider, you can use it to access certificates and keys from the smart card. This is performed with the standard Java class for accessing protected certificate keystores:


The following code is an example of how you can establish secured access to a protected certificate keystore located on a smart card:

char [] pin = {'1', '2', '3', '4'};
KeyStore smartCardKeyStore = KeyStore.getInstance("PKCS11");
smartCardKeyStore.load(null, pin);

The source code shown above expects that the Sun PKCS#11 Provider has been successfully registered and configured. For the smart card's keystore to be read, it is necessary to provide the correct PIN code to access the smart card.

Obtaining Certificates and Private Keys from a Smart Card

After you have established access to the smart card keystore, you can extract the keys and certificates from it, as from a normal keystore. All keys, certificates, and certification chains are stored under aliases in the keystore. The names can be extracted through an iterator.

Here is an example in which all certificates from a given keystore, together with the information for their private keys, are extracted and printed:

KeyStore keyStore = ...;

Enumeration aliasesEnum = keyStore.aliases();
while (aliasesEnum.hasMoreElements()) {
   String alias = (String)aliasesEnum.nextElement();
   System.out.println("Alias: " + alias);
   X509Certificate cert =
   (X509Certificate) keyStore.getCertificate(alias);
   System.out.println("Certificate: " + cert);
   PrivateKey privateKey =
      (PrivateKey) keyStore.getKey(alias, null);
   System.out.println("Private key: " + privateKey);

This example usually works for the common keystores, as well as for keystores placed on a smart card. A password is not required in the case of accessing private keys stored on a smart card. This is true because the PIN code is sent beforehand during the creation of the KeyStore object. That's why in the example the null value is set as a password.

At first sight, it looks as though the private key can be extracted from a smart card, but in practice this is not the case. The smart cards do not allow the extraction of keys, but only indirect access to them for signing, verifying signatures, encrypting, or decrypting. In the example above, the private key is not extracted, but only an interface to access it is given.

Signing Data with a Smart Card

After the interface for a given private key is extracted from a smart card, it can be used for the signing of data, as any other private key. The real signing is performed by calculation of the hash value of the document to be signed and sending this hash value to the smart card so that it will be signed with its cryptoprocessor. If the operation is successful, the card returns a calculated signature as a result of the hash value's signing. This way, the private key is preserved away from risk because it is kept in secret, hidden somewhere on the card. Here is an example of signing data with a given interface to a private key (extracted from a smart card):

private static byte[] signDocument(byte[] aDocument,
                                   PrivateKey aPrivateKey)
throws GeneralSecurityException {
   Signature signatureAlgorithm =
   byte[] digitalSignature = signatureAlgorithm.sign();
   return digitalSignature;

Java Applet for Signing with a Smart Card

In the article NakovDocumentSigner: A System for Digitally Signing Documents in Web Applications, you learned how to develop an applet (DigitalSignerApplet) that signs documents with a certificate, extracted from a PKCS#12 keystore (PFX file). You now will modify this applet to make it sign documents with a smart card. As a result, you will create an applet called SmartCardSignerApplet that is very similar to the old one (DigitalSignerApplet).

System Requirements for Accessing Smart Cards with Java Applets

The Java applet for signing with a smart card requires you to have installed Java Plug-In, version 5.0 or newer, on the client's computer. This is needed because the applet uses the Sun PKCS#11 Provider, which is included in Java from version 5.0 onwards.

Implementation of the Applet for Signing with a Smart Card

You will not see a big difference between signing in with a Smart Card than you would by using a "PFX" file. In fact, the only difference is in the way of instantiating the certificate keystore. When operating with PKCS#12, the keystore is loaded from a PFX file, and when operating with a smart card, the store is loaded from the card through the PKCS#11 interface. The other difference is that instead of an access password, a smart card is required to have the PIN code. Everything else is the same, from the loading of the certificate to the signing of the file.

How the signing applet is designed and how it works has already been covered in my earlier article, NakovDocumentSigner: A System for Digitally Signing Documents in Web Applications . In this article, the applet is signed to gain access to the file system of the local machine. It looks like a button that is placed in a given HTML form with which it interacts.

This applet's source code can be found in the Listing 1 code. The class SmartCardSignerApplet implements its main functionality. (Note: Listings are on the pages following this article )

The main class of the applet uses another additional class, PKCS11LibraryFileAndPINCodeDialog, which prompts the user to provide a PKCS#11 implementation library and the PIN code for accessing the smart card as seen in the listing found in Listing 2.

The applet also uses the class found in this hyperlink, Base64Utils for BASE64 encoding and decoding. Note that this is the same as in the applet for signing with PFX file.

Page 2 of 8

This article was originally published on February 24, 2006

Enterprise Development Update

Don't miss an article. Subscribe to our newsletter below.

Thanks for your registration, follow us on our social networks to keep up-to-date