diff options
Diffstat (limited to 'core/src/main/java/org/bouncycastle/crypto/kems/RSAKeyEncapsulation.java')
-rwxr-xr-x | core/src/main/java/org/bouncycastle/crypto/kems/RSAKeyEncapsulation.java | 164 |
1 files changed, 164 insertions, 0 deletions
diff --git a/core/src/main/java/org/bouncycastle/crypto/kems/RSAKeyEncapsulation.java b/core/src/main/java/org/bouncycastle/crypto/kems/RSAKeyEncapsulation.java new file mode 100755 index 00000000..8c1a1724 --- /dev/null +++ b/core/src/main/java/org/bouncycastle/crypto/kems/RSAKeyEncapsulation.java @@ -0,0 +1,164 @@ +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. + */ +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. + * + * @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. + * + * @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"); + } + else + { + this.key = (RSAKeyParameters)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); + byte[] R = BigIntegers.asUnsignedByteArray((n.bitLength() + 7) / 8, r); + + // 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); + + + // 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); + } + + + /** + * 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. + * + * @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); + 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); + } + + /** + * 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); + } +} |