All Downloads are FREE. Search and download functionalities are using the official Maven repository.

org.bouncycastle.openpgp.operator.RFC6637KDFCalculator Maven / Gradle / Ivy

Go to download

The Bouncy Castle Java APIs for the OpenPGP Protocol. The APIs are designed primarily to be used in conjunction with the BC FIPS provider. The APIs may also be used with other providers although if being used in a FIPS context it is the responsibility of the user to ensure that any other providers used are FIPS certified and used appropriately.

There is a newer version: 2.0.9
Show newest version
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);
        }
    }
}




© 2015 - 2024 Weber Informatics LLC | Privacy Policy