org.bouncycastle.openpgp.operator.RFC6637KDFCalculator Maven / Gradle / Ivy
Go to download
Show more of this group Show more artifacts with this name
Show all versions of bcpg-jdk15on Show documentation
Show all versions of bcpg-jdk15on Show documentation
The Bouncy Castle Java API for handling the OpenPGP protocol. This jar contains the OpenPGP API for JDK 1.5 to JDK 1.7. The APIs can be used in conjunction with a JCE/JCA provider such as the one provided with the Bouncy Castle Cryptography APIs.
package org.bouncycastle.openpgp.operator;
import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.io.OutputStream;
import org.bouncycastle.asn1.ASN1ObjectIdentifier;
import org.bouncycastle.bcpg.PublicKeyAlgorithmTags;
import org.bouncycastle.bcpg.SymmetricKeyAlgorithmTags;
import org.bouncycastle.math.ec.ECPoint;
import org.bouncycastle.openpgp.PGPException;
import org.bouncycastle.util.encoders.Hex;
/**
* Calculator for the EC based KDF algorithm described in RFC 6637
* @deprecated this class is no longer required and will be removed.
*/
public class RFC6637KDFCalculator
{
// "Anonymous Sender ", which is the octet sequence
private static final byte[] ANONYMOUS_SENDER = Hex.decode("416E6F6E796D6F75732053656E64657220202020");
private final PGPDigestCalculator digCalc;
private final int keyAlgorithm;
public RFC6637KDFCalculator(PGPDigestCalculator digCalc, int keyAlgorithm)
{
this.digCalc = digCalc;
this.keyAlgorithm = keyAlgorithm;
}
public byte[] createKey(ASN1ObjectIdentifier curveOID, ECPoint s, byte[] recipientFingerPrint)
throws PGPException
{
try
{
// RFC 6637 - Section 8
// curve_OID_len = (byte)len(curve_OID);
// Param = curve_OID_len || curve_OID || public_key_alg_ID || 03
// || 01 || KDF_hash_ID || KEK_alg_ID for AESKeyWrap || "Anonymous
// Sender " || recipient_fingerprint;
// Z_len = the key size for the KEK_alg_ID used with AESKeyWrap
// Compute Z = KDF( S, Z_len, Param );
ByteArrayOutputStream pOut = new ByteArrayOutputStream();
byte[] encOid = curveOID.getEncoded();
pOut.write(encOid, 1, encOid.length - 1);
pOut.write(PublicKeyAlgorithmTags.ECDH);
pOut.write(0x03);
pOut.write(0x01);
pOut.write(digCalc.getAlgorithm());
pOut.write(keyAlgorithm);
pOut.write(ANONYMOUS_SENDER);
pOut.write(recipientFingerPrint);
return KDF(digCalc, s, getKeyLen(keyAlgorithm), pOut.toByteArray());
}
catch (IOException e)
{
throw new PGPException("Exception performing KDF: " + e.getMessage(), e);
}
}
// RFC 6637 - Section 7
// Implements KDF( X, oBits, Param );
// Input: point X = (x,y)
// oBits - the desired size of output
// hBits - the size of output of hash function Hash
// Param - octets representing the parameters
// Assumes that oBits <= hBits
// Convert the point X to the octet string, see section 6:
// ZB' = 04 || x || y
// and extract the x portion from ZB'
// ZB = x;
// MB = Hash ( 00 || 00 || 00 || 01 || ZB || Param );
// return oBits leftmost bits of MB.
private static byte[] KDF(PGPDigestCalculator digCalc, ECPoint s, int keyLen, byte[] param)
throws IOException
{
byte[] ZB = s.getXCoord().getEncoded();
OutputStream dOut = digCalc.getOutputStream();
dOut.write(0x00);
dOut.write(0x00);
dOut.write(0x00);
dOut.write(0x01);
dOut.write(ZB);
dOut.write(param);
byte[] digest = digCalc.getDigest();
byte[] key = new byte[keyLen];
System.arraycopy(digest, 0, key, 0, key.length);
return key;
}
private static int getKeyLen(int algID)
throws PGPException
{
switch (algID)
{
case SymmetricKeyAlgorithmTags.AES_128:
return 16;
case SymmetricKeyAlgorithmTags.AES_192:
return 24;
case SymmetricKeyAlgorithmTags.AES_256:
return 32;
default:
throw new PGPException("unknown symmetric algorithm ID: " + algID);
}
}
}