RSA

This algorithm is a block cipher with a variable-length key, whose block size is equal to the key size. RSA is patented in the United States by RSA Data Security. The RSA cipher will operate in one of five modes, depending on the padding requested. If “PKCS1Padding” is requested, the processing is performed as described in PKCS#1. If “NoPadding” is requested, the processing is performed as specified in X.509 for raw RSA.

NOTE   Currently the RSA Cipher only supports encryption or decryption of a single block. Any attempt to pass more data than a single block will result in a RuntimeException.

RSA Cipher Initialization

This cipher supports both only ECB mode, and may be used with NoPadding or PKCS1Padding. To create an instance of this class, use the Cipher.getInstance() method with “SAFENET” as the provider and one of the following strings as the transformation:

>RSA

>RSA/ECB/NoPadding

>RSA/ECB/PKCS1Padding

>RSA/ECB/OAEP

>RSA/ECB/OAEPPadding

Using the “RSA” transformation, the Cipher will default to ECB and PKCS1Padding. The NoPadding option will result in “RAW” RSA, where each block will be 0 padded.

The block size of this cipher is dependent on the key size in use. The block size is equal to the number of bytes of the RSA modulus. If the modulus is k bytes long, then the encrypted output size is always k. For the “NoPadding” mode, the plaintext input must be equal to or less than k; with the “PKCS1Padding” mode, the plaintext input must be equal to or less than k-11 bytes.

This Cipher will only accept a SafeNet ProtectToolkit-J provider-based key during initialization. This key must be generated by the SafeNet ProtectToolkit-J RSA KeyFactory, KeyPairGenerator or KeyStore.

This Cipher does not support initialization with algorithm parameters, and so the Cipher.getParameters() method will always return null.

RSA Key

The RSA Cipher requires either a SafeNet ProtectToolkit-J RSA public or private Key during initialization. The RSA key may be any length between 512 and 4096 bits (inclusive).

A new SafeNet ProtectToolkit-J RSA key can be generated randomly using the KeyPairGenerator as described in section Public Keys, or a provider-independent form as described in section Key Specifications. The RSA key may also be stored in the SafeNet ProtectToolkit-J KeyStore, as described in Key Storage .

The SafeNet ProtectToolkit-J RSA key will return the string “RSA” as its algorithm name, the public key type will return “X.509” as its encoding (the private key types will return “RAW”) as its encoding. However, since the key is stored within the hardware, the actual key encoding may not be available (private keys will return null from the getEncoded() method). If the public key is available, the getEncoded() method will return the key as a DER-encoded X.509 SubjectPublicKeyInfo block containing the public key as defined in PKCS#1.

The key value can only be extracted from a key if the associated Cryptoki key is not marked as Sensitive. The keys generated in SafeNet ProtectToolkit-J will always be marked as sensitive. It is possible, however, to access any Cryptoki keys stored on the device, and it is possible that the attributes of these keys have been modified.

RSA KeyPairGenerator

The RSA KeyPairGenerator is used to generate random RSA key pairs. The generated key pair will consist of two hardware keys, the public key and a private key with the Cryptoki CKA_SENSITIVE attribute set. The public exponent for this key generator is fixed to the Fermat-4 value (hex 0x100001).

During initialization, the strength parameter may be any length from 512 to 4096. The default key size is 1024 bits. The random parameter is ignored as the hardware includes a cryptographically-secure random source.

Keys generated using the KeyPairGenerator are not thread-safe. That is, a SafeNet ProtectToolkit-J Key instance may only be used by a single Cipher instance (as well as a single MAC instance) at any given time. SeeKey Generation for information on threading and SafeNet ProtectToolkit-J keys.

RSA KeyFactory

The RSA KeyFactory is used to construct SafeNet ProtectToolkit-J keys from their provider-independent form. There are three standard provider-independent forms for RSA keys, one for public keys, and two for private keys. They are:

>java.security.spec.RSAPublicKeySpec

>java.security.spec.RSAPrivateKeySpec

>java.security.spec.RSAPrivateCrtKeySpec

Additionally, there is the au.com.safenet.crypto.spec.AsciiEncodedKeySpec class which can be used for keys encoded as hexadecimal strings. For more information on this KeySpec, see Key Specifications.

Keys generated using the KeyFactory are not thread-safe. That is, a SafeNet ProtectToolkit-J Key instance may only be used by a single Cipher instance (as well as a single MAC instance) at any given time. SeeKey Generation for information on threading and SafeNet ProtectToolkit-J keys.

To convert one of these supported KeySpec classes into a SafeNet ProtectToolkit-J provider key:

KeyFactory rsaKeyFact = KeyFactory.getInstance(“RSA”,
                                               “SAFENET”);
PublicKey pubKey = rsaKeyFact.generatePublic(pubKeySpec);
PrivateKey privKey = rsaKeyFact.generatePrivate(privKeySpec);  

The RSA KeyFactory cannot currently convert SafeNet ProtectToolkit-J keys into their provider-independent format, so the getKeySpec() method will throw an InvalidKeySpecException. The class also cannot perform any key translation via the translateKey() method.

RSA Example Code

The following example code will create a random RSA key pair, then create a RSA cipher in ECB mode with PKCS1Padding. Next it initializes the cipher for encryption using the public key from a newly-created key pair. Finally, we encrypt the string "hello world".

To perform the decryption, we re-initialize the cipher in decrypt mode, with the private key from the key pair.

KeyPairGenerator keyGen = KeyPairGenerator.getInstance("RSA",
                                               "SAFENET");
KeyPair rsaPair = keyGen.generateKeyPair();
Cipher rsaCipher = Cipher.getInstance("RSA/ECB/PKCS1Padding",
                                      "SAFENET");
rsaCipher.init(Cipher.ENCRYPT_MODE, rsaPair.getPublic());
byte[] cipherText = rsaCipher.doFinal(
                                   "hello world".getBytes());
rsaCipher.init(Cipher.DECRYPT_MODE, rsaPair.getPrivate());
byte[] plainText = rsaCipher.doFinal(cipherText);