RSA keys and operations
Keys
The hardware JCE implementation (IBMJCECCA) extends the RSA keys that are available in the software JCE implementation. In the software JCE implementation, the actual RSA key material is stored in the key object. The IBMJCECCA implementation extends this by adding the following alternative representations:
-
An RSA key pair that was previously stored in the CCA key storage area. The key objects contain the CCA key storage area label for the keys.
The following example illustrates creating RSA key objects for a key pair that is already stored in the CCA key storage area with the label "MYRSA.KEYPAIR", then deleting the CCA key storage area entry.// create key objects for an existing CCA key storage area entry // (No checking is done to verify that the entry exists.) // KeyFactory rsaKeyFactory = KeyFactory.getInstance("RSA", "IBMJCECCA"); KeyLabelKeySpec spec = new KeyLabelKeySpec("MYRSA.KEYPAIR"); PublicKey pubKey = rsaKeyFactory.generatePublic(spec); PrivateKey privKey = rsaKeyFactory.generatePrivate(spec); // delete the entry from the CCA key storage area // (An exception is thrown if the CCA key storage area entry does not exist.) // ((RSAPrivateHWKey)privKey).deletePKDSEntry(); // // Note that, in this example, the Java key objects still // exist, but the CCA key storage area entry they represent has been deleted. // Any attempt to use the objects "pubKey" or "privKey" will // cause an exception containing a hardware return code and // reason code. //
-
An RSA key pair that is generated by an IBMJCECCA call to the underlying hardware, then stored in the CCA key storage area. The key objects contain the CCA key storage area label for the keys.
The following example illustrates generating an RSA key pair that is stored in the CCA key storage area with an automatically generated label and creating key objects that contains the label for the CCA key storage area entry.
The following example illustrates generating an RSA key pair that is stored in the CCA key storage area with the label "ANRSA.KEYPAIR" and creating key objects that contain the label for the CCA key storage area entry.// create a new CCA key storage area entry and key objects to represent it. // AlgorithmParameterSpec spec = new RSAKeyParameterSpec(1024, KeyHWAttributeValues.PKDS, KeyHWAttributeValues.KEYMANAGEMENT); KeyPairGenerator generator = KeyPairGenerator.getInstance("RSA", "IBMJCECCA"); generator.initialize(spec); KeyPair keyPair = generator.generateKeyPair(); PublicKey pubKey = keyPair.getPublic(); PrivateKey privKey = keyPair.getPrivate(); // delete the entry from the CCA key storage area // (An exception is thrown if the CCA key storage area entry does not exist.) // ((RSAPrivateHWKey)privKey).deletePKDSEntry(); // // Note that, in this example, the Java key objects still // exist, but the CCA key storage area entry they represent has been deleted. // Any attempt to use the objects "pubKey" or "privKey" will // cause an exception containing a hardware return code and // reason code. //
// create a new CCA key storage area entry and key objects to represent it // AlgorithmParameterSpec spec = new RSAKeyParameterSpec(1024, KeyHWAttributeValues.PKDS, KeyHWAttributeValues.KEYMANAGEMENT, "ANRSA.KEYPAIR"); KeyPairGenerator generator = KeyPairGenerator.getInstance("RSA", "IBMJCECCA"); generator.initialize(spec); KeyPair keyPair = generator.generateKeyPair(); PublicKey pubKey = keyPair.getPublic(); PrivateKey privKey = keyPair.getPrivate(); // delete the entry from the CCA key storage area // (An exception is thrown if the CCA key storage area entry does not exist.) // ((RSAPrivateHWKey)privKey).deletePKDSEntry(); // // Note that, in this example, the Java key objects still // exist, but the CCA key storage area entry they represent has been deleted. // Any attempt to use the objects "pubKey" or "privKey" will // cause an exception containing a hardware return code and // reason code. //
Operations
Both RSA encryption and decryption are available in the IBMJCECCA provider by using hardware cryptography. Because the RSA algorithm is quite compute intensive, using hardware cryptography provides significant performance improvements over software cryptography. Using hardware to perform the RSA encryption and decryption also allows use of the more secure method of storing key pairs in CCA key storage. With a key pair that is stored in the CCA key storage, the sensitive private key is never made available in the clear.
In software implementations of JCE providers (such as OpenJCEPlus), RSA encryption and decryption are implemented with PKCS 1 type 2 padding. RSA encryption and decryption with PKCS 1 type 2 padding is also implemented in hardware cryptography and is available with the IBMJCECCA provider.
However, there are two restrictions that are imposed by the hardware:
- The type of key pair that is needed. The hardware implementation of RSA requires that the keys that are used to encrypt and decrypt data are generated to have a key usage of KEYMANAGEMENT. This restriction means that when the RSA key pair is generated, the key usage must be set to KEYMANAGEMENT.
- The maximum length of the data that can be encrypted or decrypted. The hardware implementation of RSA limits the amount of data to be encrypted or decrypted to either 245 bytes or 11 bytes smaller than the modulus size of the key (in bytes), whichever is smaller.
The IBMJCECCA provider also implements RSA encryption and decryption with zero padding
.
This padding scheme is not supported by all JCE providers. The default padding scheme is PKCS 1 type
2 padding for the IBMJCECCA provider.
zero padding:
Cipher myCipher = Cipher.getInstance("RSA/ /ZeroPadding", "IBMJCECCA");
PKCS 1 type 2 padding:
Cipher myCipher = Cipher.getInstance("RSA/ /PKCS1Padding", "IBMJCECCA");
Cipher myCipher = Cipher.getInstance("RSA", "IBMJCECCA"); // accept the default padding
- A key object that contains a clear AES, DES, or triple DES key
- A key object that contains a CCA key storage area label for an encrypted AES, DES DATA, or triple DES DATA key
- A key object that contains a hardware token with an encrypted AES, DES DATA, or triple DES DATA key
The IBMJCECCA provider supports RSA unwrapping of a symmetric key for import from another host. By default, the resulting (unwrapped) key object contains a clear key.
If a CCAAlgorithmParameterSpec object is created with no type specified, or with type CCAAlgorithmParameterSpec.SECURE_INTERNAL_TOKEN specified, and the RSA Cipher is initialized with this CCAAlgorithmParameterSpec object, the resulting (unwrapped) key object contains a hardware token. This token contains the key that is encrypted with the host primary key. If a CCAAlgorithmParameterSpec object is created with type CAAlgorithmParameterSpec.CKDS, and the RSA Cipher is initialized with this CCAAlgorithmParameterSpec object, the resulting (unwrapped) key object contains the label for a CCA key storage area entry that contains a hardware token. This token contains the key that is encrypted with the host primary key.
// Generate a clear triple DES key
//
KeyGenerator keyGen =
KeyGenerator.getInstance("DESede", "IBMJCECCA");
Key tdesKey = keyGen.generateKey();
// Generate an RSA key pair
//
KeyPairGenerator rsaKeyPairGen =
KeyPairGenerator.getInstance("RSA","IBMJCECCA");
rsaKeyPairGen.initialize(1024);
KeyPair rsaKeyPair = rsaKeyPairGen.generateKeyPair();
PublicKey rsaPub = rsaKeyPair.getPublic();
PrivateKey rsaPriv = rsaKeyPair.getPrivate();
// Wrap the triple DES key as for export
//
Cipher rsaCipher = Cipher.getInstance("RSA","IBMJCECCA");
rsaCipher.init(Cipher.WRAP_MODE, rsaPub,
(AlgorithmParameters)null, null);
byte[] wrappedKey = rsaCipher.wrap(tdesKey);
// Unwrap the triple DES key as for import
// Unwrap to a clear key
//
Key unwrappedDesKey =
rsaCipher.unwrap(wrappedKey, "DESede", Cipher.SECRET_KEY);
// Generate a secure triple DES hardware key
//
CCAAlgorithmParameterSpec ccaAlgParmSpec =
new CCAAlgorithmParameterSpec();
KeyGenerator keyGen =
KeyGenerator.getInstance("DESede", "IBMJCECCA");
keyGen.init(ccaAlgParmSpec, null);
Key tdesKey = keyGen.generateKey();
// Generate an RSA key pair
//
KeyPairGenerator rsaKeyPairGen =
KeyPairGenerator.getInstance("RSA","IBMJCECCA");
rsaKeyPairGen.initialize(1024);
KeyPair rsaKeyPair = rsaKeyPairGen.generateKeyPair();
PublicKey rsaPub = rsaKeyPair.getPublic();
PrivateKey rsaPriv = rsaKeyPair.getPrivate();
// Wrap the triple DES hardware key as for export
//
Cipher rsaCipher = Cipher.getInstance("RSA","IBMJCECCA");
rsaCipher.init(Cipher.WRAP_MODE, rsaPub,
(AlgorithmParameters)null, null);
byte[] wrappedKey = rsaCipher.wrap(tdesKey);
// Unwrap the triple DES key as for import
// Unwrap to a secure hardware key
//
CCAAlgorithmParameterSpec ccaAlgParmSpec_forUnwrap =
new CCAAlgorithmParameterSpec();
rsaCipher.init(Cipher.UNWRAP_MODE, rsaPriv,
ccaAlgParmSpec_forUnwrap, null);
Key unwrappedDesKey =
rsaCipher.unwrap(wrappedKey, "DESede", Cipher.SECRET_KEY);
// Get the key store instance, open an input stream to the
// keystore file and load the key store.
//
KeyStore jceccaks = KeyStore.getInstance("JCECCAKS", "IBMJCECCA");
InputStream istream = new FileInputStream("keyStore.cca");
jceccaks.load(istream, "keystorePW".toCharArray());
// Given the alias for the CCA key storage area key entry, retrieve the private
// hardware key from the key store.
//
PrivateKey privateKey = (PrivateKey) jceccaks.getKey("MYRSAKEY", "myrsakeyPW".toCharArray());
// Delete the RSA hardware CCA key storage area key entry.
//
((RSAPrivateHWKey)privateKey).deletePKDSEntry();
// Delete the RSA key store object.
//
jceccaks.deleteEntry("MYRSAKEY");
// Write the modified key store contents to the key store file.
//
OutputStream ostream = new FileOutputStream("keyStore.cca");
jceccaks.store(ostream, "keystorePW".toCharArray());
Like OpenJCEPlus, the IBMJCECCA provider implements RSA wrapping and unwrapping with OAEP (Optimal Asymmetric Encryption Padding). The IBMJCECCA support differs from the software JCE implementation support in the following ways:
IBMJCECCA RSA wrapping with OAEP supports SHA-1, SHA-224, SHA-256, SHA-384, and SHA-512 padding algorithms.
OAEP with SHA-512 padding requires an RSA key size of 2048.
- IBMJCECCA RSA wrapping with OAEP can be used only to wrap SECURE_INTERNAL_TOKEN keys and encrypted keys in the CCA key storage area.
Cipher rsaCipher = Cipher.getInstance("RSA/ /OAEPPADDINGSHA-1", "IBMJCECCA");
Cipher rsaCipher = Cipher.getInstance("RSA/ /OAEPPADDINGSHA-256", "IBMJCECCA");
OAEPParameterSpec oaepSpec = new OAEPParameterSpec(
"SHA-256", "MGF1", MGF1ParameterSpec.SHA256, PSource.PSpecified.DEFAULT);
CCAAlgorithmParameterSpec ccaSpec = new CCAAlgorithmParameterSpec(CCAAlgorithmParameterSpec.SECURE_INTERNAL_TOKEN);
ccaSpec.setOAEPParameterSpec(oaepSpec);
rsaCipher.init(Cipher.WRAP_MODE, rsaPub,ccaSpec, null);
byte[] wrappedKey = rsaCipher.wrap(desKey);
OAEPParameterSpec oaepSpec = new OAEPParameterSpec(
"SHA-256", "MGF1", MGF1ParameterSpec.SHA256, PSource.PSpecified.DEFAULT);
CCAAlgorithmParameterSpec ccaSpec = new CCAAlgorithmParameterSpec(CCAAlgorithmParameterSpec.CKDS);
ccaSpec.setOAEPParameterSpec(oaepSpec);
rsaCipher.init(Cipher.UNWRAP_MODE, rsaPriv, ccaSpec, null);
Key unwrappedKey = rsaCipher.unwrap(wrappedKey, "DES" Cipher.SECRET_KEY);
The RSA cipher in the IBMJCECCA provider supports wrapping and unwrapping of AES transport keys, such as AES EXPORTER and AES IMPORTER keys, using RSA with OAEP. Note that IBMJCECCA transport key objects contain transient fields that might not persist through wrap and unwrap operations. For more information, see Symmetric transport keys (key encrypting keys).
The RSA cipher in the IBMJCECCA provider supports wrapping and unwrapping of DES and Triple DES keys, but only if they are DATA keys.