org.cryptacular.pbe.PBES2EncryptionScheme.java Source code

Java tutorial

Introduction

Here is the source code for org.cryptacular.pbe.PBES2EncryptionScheme.java

Source

/* See LICENSE for licensing and NOTICE for copyright. */
package org.cryptacular.pbe;

import org.bouncycastle.asn1.ASN1Integer;
import org.bouncycastle.asn1.ASN1OctetString;
import org.bouncycastle.asn1.ASN1Sequence;
import org.bouncycastle.asn1.pkcs.PBES2Parameters;
import org.bouncycastle.asn1.pkcs.PBKDF2Params;
import org.bouncycastle.crypto.CipherParameters;
import org.bouncycastle.crypto.PBEParametersGenerator;
import org.bouncycastle.crypto.engines.RC532Engine;
import org.bouncycastle.crypto.generators.PKCS5S2ParametersGenerator;
import org.bouncycastle.crypto.modes.CBCBlockCipher;
import org.bouncycastle.crypto.paddings.PKCS7Padding;
import org.bouncycastle.crypto.paddings.PaddedBufferedBlockCipher;
import org.bouncycastle.crypto.params.KeyParameter;
import org.bouncycastle.crypto.params.ParametersWithIV;
import org.bouncycastle.crypto.params.RC2Parameters;
import org.bouncycastle.crypto.params.RC5Parameters;

/**
 * Implements the PBES2 encryption scheme defined in PKCS#5v2.
 *
 * @author  Middleware Services
 * @version  $Revision: 2744 $
 */
public class PBES2EncryptionScheme extends AbstractEncryptionScheme {

    /** Size of derived key in bits. */
    private int keyLength;

    /**
     * Creates a new instance with the given parameters.
     *
     * @param  params  PBES2 parameters describing the key derivation function and
     *                 encryption scheme.
     * @param  password  Password used to derive key.
     */
    public PBES2EncryptionScheme(final PBES2Parameters params, final char[] password) {
        final PBKDF2Params kdfParams = PBKDF2Params.getInstance(params.getKeyDerivationFunc().getParameters());
        final byte[] salt = kdfParams.getSalt();
        final int iterations = kdfParams.getIterationCount().intValue();
        if (kdfParams.getKeyLength() != null) {
            keyLength = kdfParams.getKeyLength().intValue() * 8;
        }

        final PKCS5S2ParametersGenerator generator = new PKCS5S2ParametersGenerator();
        generator.init(PBEParametersGenerator.PKCS5PasswordToUTF8Bytes(password), salt, iterations);
        initCipher(generator, params.getEncryptionScheme());
    }

    /**
     * Initializes the block cipher and sets up its initialization parameters.
     *
     * @param  generator  Derived key generator.
     * @param  scheme  PKCS#5 encryption scheme.
     */
    private void initCipher(final PKCS5S2ParametersGenerator generator,
            final org.bouncycastle.asn1.pkcs.EncryptionScheme scheme) {
        final PBES2Algorithm alg = PBES2Algorithm.fromOid(scheme.getAlgorithm().getId());
        if (keyLength == 0) {
            keyLength = alg.getKeySize();
        }

        byte[] iv = null;
        CipherParameters cipherParameters = generator.generateDerivedParameters(keyLength);
        switch (alg) {

        case RC2:
            setCipher(alg.getCipherSpec().newInstance());

            final ASN1Sequence rc2Params = ASN1Sequence.getInstance(scheme.getParameters());
            if (rc2Params.size() > 1) {
                cipherParameters = new RC2Parameters(((KeyParameter) cipherParameters).getKey(),
                        ASN1Integer.getInstance(rc2Params.getObjectAt(0)).getValue().intValue());
                iv = ASN1OctetString.getInstance(rc2Params.getObjectAt(0)).getOctets();
            }
            break;

        case RC5:

            final ASN1Sequence rc5Params = ASN1Sequence.getInstance(scheme.getParameters());
            final int rounds = ASN1Integer.getInstance(rc5Params.getObjectAt(1)).getValue().intValue();
            final int blockSize = ASN1Integer.getInstance(rc5Params.getObjectAt(2)).getValue().intValue();
            if (blockSize == 32) {
                setCipher(new PaddedBufferedBlockCipher(new CBCBlockCipher(new RC532Engine()), new PKCS7Padding()));
            }
            cipherParameters = new RC5Parameters(((KeyParameter) cipherParameters).getKey(), rounds);
            if (rc5Params.size() > 3) {
                iv = ASN1OctetString.getInstance(rc5Params.getObjectAt(3)).getOctets();
            }
            break;

        default:
            setCipher(alg.getCipherSpec().newInstance());
            iv = ASN1OctetString.getInstance(scheme.getParameters()).getOctets();
        }
        if (iv != null) {
            cipherParameters = new ParametersWithIV(cipherParameters, iv);
        }
        setCipherParameters(cipherParameters);
    }
}