Providing Hardware-based Security to Java Applications by leveraging Intel® Identity Protection Technology and Java Cryptography Extensions


Introduction

Intel® Identity Protection Technology with public key infrastructure (Intel® IPT with PKI) provides the capability to generate and store RSA private keys directly in hardware. The keys can then be used for cryptographic operations such as creating and verifying digital signatures.  When Intel® IPT with PKI is employed, the keys are not accessible to the operating system, nor are they loaded into memory, or even stored on disk. Instead, the keys are managed and stored directly inside the chipset. This means no application can have access to the private keys and thus the possibility that the key can ever be compromised is greatly reduced. It’s like having your own smart card embedded right in the silicon of the chipset.    Developers can leverage Intel® IPT with PKI by using standard cryptographic programming interfaces such as those provided Microsoft Cryptographic Services or a Java Cryptography Extension. This article will focus on how Java applications can provide hardware-based security by leveraging Intel® IPT with PKI through a standard Java Cryptography Extension.

Java Security APIs

Java security technology provides a set of APIs that software developers can leverage for commonly used security algorithms such a cryptography, public key infrastructure, secure communication, authentication, and access control. Implementation of the security algorithms are provided through standard Java Cryptography Extensions (JCE). To use Intel® IPT from the Java platform you can leverage the standard Java security APIs. The only thing required by you as the developer is to tell the Java platform that you want to use Intel® IPT implementation of the standard security APIs. The security APIs are defined in the java.security namespace and you can tell Java to use the IntelJCE provider when calling the getInstance() method of of a specific security interface class.

obtaining instances to security classes

Default implementation

IntelJCE implementation

KeyPairGenerator.getInstance("RSA"); KeyPairGenerator.getInstance("RSA", "IntelJCE");
KeyStore.getInstance("PKI"; KeyStore.getInstance("PKI", "IntelJCE");
Signature.getInstance("SHA1withRSA"); Signature.getInstance("SHA1withRSA", "IntelJCE");

 

IntelJCE.jar

IntelJCE.jar is a Java Cryptography Extension that implements RSA key pair management directly in hardware. The IntelJCE accesses the hardware though a JNI library called IntelJCSP.dll (stands for Intel Java Cryptography Service Provider). IntelJCSP does not itself directly access the hardware, but indirectly accesses it through an Intel Cryptography Service Provider running in the operating system as shown below.

Intel JCE Architecture Diagram

To obtain a copy of the IntelJCE you need to contact your Intel representative. The rest of the stack should be available on any platform that supports Intel® IPT. 

 

The Code

Now let’s look at what the code would look like.  Before we being, keep in mind that when using the IntelJCE, the private portion of the RSA key is not accessible to Java applications or even the operating system.  Even though the APIs might expose an object call a “Private key”, it’s just a reference to the key stored in the hardware and does not actually contain the private exponent of the key.  However, the public portion of the key is accessible to Java applications and the operating system.

Adding the Provider

You can add the Intel provider programmatically or configure the JVM to load the provider for you.   In this case we will register programmatically by calling the static addProvider method of the java.security.Security class.

import java.security.*;

Security.addProvider(new com.intel.security.ipt.IntelJCE());

Generating a  key pair in hardware

Below is an example of creating a key pair using the IntelJCE provider.  The key generator is initialized with the desired size of the key. The key will be stored in the firmware under a default alias name of "MY" and can be retrieved later using the Keystore class.

//generate a RSA key pair using the IntelJCE Provider
KeyPairGenerator keygen = KeyPairGenerator.getInstance("RSA", "IntelJCE");

keygen.initialize(2048); // keysize of 2048 

KeyPair pair = keygen.generateKeyPair();

PublicKey privateKey = pair.getPrivate();
PrivateKey pubKey = pair.getPublic();

Generating a key pair with a specific alias name

Alternatively applications can initialize the key generator with a key parameter specification. This allows the application to specify the alias name were they key should be stored.  Storing a key under an application defined alias is recommended so other applications don't overwrite your key.

KeyPairGenerator keygen= KeyPairGenerator.getInstance("RSA", "IntelJCE");

keygen.initialize(new com.intel.security.ipt.ContainerGenParamaterSpec("myAppName",2048));

KeyPair pair = keygen.generateKeyPair();
PublicKey privateKey = pair.getPrivate();
PrivateKey pubKey = pair.getPublic();

Retrieving an exiting key from the hardware based keystore

Once a key has been generated with the key generator it can be retrieved from the persisted key store by its alias name.  If you did not generate the key with a key parameter spec then the key would be stored under the "MY" alias name.

KeyStore keystore = KeyStore.getInstance("PKI", "IntelJCE");
keystore.load(null,null);

PrivateKey privateKey = (PrivateKey)keystore.getKey("myAppName", null);

 

Creating an RSA Signature with a private key

An RSA signature can be generated using the key by obtaining an instance to the hardware based signature class as shown below: 

// now sign with the key
byte[] message = new String("Transfer $1,000,000 from my bank account").getBytes();

Signature sig = Signature.getInstance("SHA1withRSA", "IntelJCE");
sig.initSign(privateKey);
sig.update(message);
byte[] sigData=sig.sign();

Verifying the RSA Signature

The signature can be verified using the default implementation of the signature class since only the public key is needed

byte[] message = new String("Transfer $1,000,000 from my bank account").getBytes();

Signature sig = Signature.getInstance("SHA1withRSA");   
 // verify with the public key
 sig.initVerify(pubKey);//see generating a key pair in hardware
 sig.update(message);
 if (sig.verify(sigData)) //creating RSA signature 
    System.out.println("Singature matches!");

 

Enumerating all keystore alias names

All the alias names defined in the keystore can be enumerated as shown below:

KeyStore keystore = KeyStore.getInstance("PKI", "IntelJCE");
keystore.load(null,null);

//enumerate all the named containers with private keys
Enumeration<String> entries=keystore.aliases();
while (entries.hasMoreElements()) {
     String name = entries.nextElement();
     System.out.println(name);
}

Removing a private key from the keystore

A key can be removed from the keystore as shown below:

KeyStore keystore = KeyStore.getInstance("PKI", "IntelJCE");
keystore.load(null,null);
   
keystore.deleteEntry("MyApplicationKey");

 

Summary

Add hardware based security to a Java application running on  platform the support Intel® IPT is pretty straight forward.  The only thing a Java developer would need to do is ensure the platform supports Intel® IPT and then use the IntelJCE implementation stead of the default software based implementation. 

References

The Intel logo is a trademark of Intel Corporation in the U.S. and/or other countries.

Per informazioni più dettagliate sulle ottimizzazioni basate su compilatore, vedere il nostro Avviso sull'ottimizzazione.