package org.bouncycastle.crypto.kems;
import java.math.BigInteger;
import java.security.SecureRandom;
import org.bouncycastle.crypto.CipherParameters;
import org.bouncycastle.crypto.DerivationFunction;
import org.bouncycastle.crypto.KeyEncapsulation;
import org.bouncycastle.crypto.params.KDFParameters;
import org.bouncycastle.crypto.params.KeyParameter;
import org.bouncycastle.crypto.params.RSAKeyParameters;
import org.bouncycastle.util.BigIntegers;
The RSA Key Encapsulation Mechanism (RSA-KEM) from ISO 18033-2.
/**
* The RSA Key Encapsulation Mechanism (RSA-KEM) from ISO 18033-2.
*/
public class RSAKeyEncapsulation
implements KeyEncapsulation
{
private static final BigInteger ZERO = BigInteger.valueOf(0);
private static final BigInteger ONE = BigInteger.valueOf(1);
private DerivationFunction kdf;
private SecureRandom rnd;
private RSAKeyParameters key;
Set up the RSA-KEM.
Params: - kdf – the key derivation function to be used.
- rnd – the random source for the session key.
/**
* Set up the RSA-KEM.
*
* @param kdf the key derivation function to be used.
* @param rnd the random source for the session key.
*/
public RSAKeyEncapsulation(
DerivationFunction kdf,
SecureRandom rnd)
{
this.kdf = kdf;
this.rnd = rnd;
}
Initialise the RSA-KEM.
Params: - key – the recipient's public (for encryption) or private (for decryption) key.
/**
* Initialise the RSA-KEM.
*
* @param key the recipient's public (for encryption) or private (for decryption) key.
*/
public void init(CipherParameters key)
throws IllegalArgumentException
{
if (!(key instanceof RSAKeyParameters))
{
throw new IllegalArgumentException("RSA key required");
}
this.key = (RSAKeyParameters)key;
}
Generate and encapsulate a random session key.
Params: - out – the output buffer for the encapsulated key.
- outOff – the offset for the output buffer.
- keyLen – the length of the random session key.
Returns: the random session key.
/**
* Generate and encapsulate a random session key.
*
* @param out the output buffer for the encapsulated key.
* @param outOff the offset for the output buffer.
* @param keyLen the length of the random session key.
* @return the random session key.
*/
public CipherParameters encrypt(byte[] out, int outOff, int keyLen)
throws IllegalArgumentException
{
if (key.isPrivate())
{
throw new IllegalArgumentException("Public key required for encryption");
}
BigInteger n = key.getModulus();
BigInteger e = key.getExponent();
// Generate the ephemeral random and encode it
BigInteger r = BigIntegers.createRandomInRange(ZERO, n.subtract(ONE), rnd);
// Encrypt the random and encode it
BigInteger c = r.modPow(e, n);
byte[] C = BigIntegers.asUnsignedByteArray((n.bitLength() + 7) / 8, c);
System.arraycopy(C, 0, out, outOff, C.length);
return generateKey(n, r, keyLen);
}
Generate and encapsulate a random session key.
Params: - out – the output buffer for the encapsulated key.
- keyLen – the length of the random session key.
Returns: the random session key.
/**
* Generate and encapsulate a random session key.
*
* @param out the output buffer for the encapsulated key.
* @param keyLen the length of the random session key.
* @return the random session key.
*/
public CipherParameters encrypt(byte[] out, int keyLen)
{
return encrypt(out, 0, keyLen);
}
Decrypt an encapsulated session key.
Params: - in – the input buffer for the encapsulated key.
- inOff – the offset for the input buffer.
- inLen – the length of the encapsulated key.
- keyLen – the length of the session key.
Returns: the session key.
/**
* Decrypt an encapsulated session key.
*
* @param in the input buffer for the encapsulated key.
* @param inOff the offset for the input buffer.
* @param inLen the length of the encapsulated key.
* @param keyLen the length of the session key.
* @return the session key.
*/
public CipherParameters decrypt(byte[] in, int inOff, int inLen, int keyLen)
throws IllegalArgumentException
{
if (!key.isPrivate())
{
throw new IllegalArgumentException("Private key required for decryption");
}
BigInteger n = key.getModulus();
BigInteger d = key.getExponent();
// Decode the input
byte[] C = new byte[inLen];
System.arraycopy(in, inOff, C, 0, C.length);
BigInteger c = new BigInteger(1, C);
// Decrypt the ephemeral random and encode it
BigInteger r = c.modPow(d, n);
return generateKey(n, r, keyLen);
}
Decrypt an encapsulated session key.
Params: - in – the input buffer for the encapsulated key.
- keyLen – the length of the session key.
Returns: the session key.
/**
* Decrypt an encapsulated session key.
*
* @param in the input buffer for the encapsulated key.
* @param keyLen the length of the session key.
* @return the session key.
*/
public CipherParameters decrypt(byte[] in, int keyLen)
{
return decrypt(in, 0, in.length, keyLen);
}
protected KeyParameter generateKey(BigInteger n, BigInteger r, int keyLen)
{
byte[] R = BigIntegers.asUnsignedByteArray((n.bitLength() + 7) / 8, r);
// Initialise the KDF
kdf.init(new KDFParameters(R, null));
// Generate the secret key
byte[] K = new byte[keyLen];
kdf.generateBytes(K, 0, K.length);
return new KeyParameter(K);
}
}