116f9ee464b68937f45d009d9c1b0eb9b544a8deeSergio Giropackage org.bouncycastle.crypto.generators;
216f9ee464b68937f45d009d9c1b0eb9b544a8deeSergio Giro
316f9ee464b68937f45d009d9c1b0eb9b544a8deeSergio Giroimport org.bouncycastle.crypto.CipherParameters;
416f9ee464b68937f45d009d9c1b0eb9b544a8deeSergio Giroimport org.bouncycastle.crypto.Digest;
516f9ee464b68937f45d009d9c1b0eb9b544a8deeSergio Giroimport org.bouncycastle.crypto.PBEParametersGenerator;
6c1040cb5656c3299f1c2d0fe0bd7c44b10466aafSergio Giro// BEGIN android-changed
7c1040cb5656c3299f1c2d0fe0bd7c44b10466aafSergio Giroimport org.bouncycastle.crypto.digests.AndroidDigestFactory;
816f9ee464b68937f45d009d9c1b0eb9b544a8deeSergio Giroimport org.bouncycastle.crypto.params.KeyParameter;
916f9ee464b68937f45d009d9c1b0eb9b544a8deeSergio Giroimport org.bouncycastle.crypto.params.ParametersWithIV;
107dad97b63c47edea4e3afb374dcd00c7b7a1bdd4Sergio Giro// BEGIN android-removed
117dad97b63c47edea4e3afb374dcd00c7b7a1bdd4Sergio Giro// import org.bouncycastle.crypto.util.DigestFactory;
127dad97b63c47edea4e3afb374dcd00c7b7a1bdd4Sergio Giro// END android-removed
1316f9ee464b68937f45d009d9c1b0eb9b544a8deeSergio Giro
1416f9ee464b68937f45d009d9c1b0eb9b544a8deeSergio Giro/**
1516f9ee464b68937f45d009d9c1b0eb9b544a8deeSergio Giro * Generator for PBE derived keys and ivs as usd by OpenSSL.
1616f9ee464b68937f45d009d9c1b0eb9b544a8deeSergio Giro * <p>
1716f9ee464b68937f45d009d9c1b0eb9b544a8deeSergio Giro * The scheme is a simple extension of PKCS 5 V2.0 Scheme 1 using MD5 with an
1816f9ee464b68937f45d009d9c1b0eb9b544a8deeSergio Giro * iteration count of 1.
1916f9ee464b68937f45d009d9c1b0eb9b544a8deeSergio Giro * <p>
2016f9ee464b68937f45d009d9c1b0eb9b544a8deeSergio Giro */
2116f9ee464b68937f45d009d9c1b0eb9b544a8deeSergio Giropublic class OpenSSLPBEParametersGenerator
2216f9ee464b68937f45d009d9c1b0eb9b544a8deeSergio Giro    extends PBEParametersGenerator
2316f9ee464b68937f45d009d9c1b0eb9b544a8deeSergio Giro{
24c1040cb5656c3299f1c2d0fe0bd7c44b10466aafSergio Giro    // BEGIN android-changed
25c1040cb5656c3299f1c2d0fe0bd7c44b10466aafSergio Giro    private Digest  digest = AndroidDigestFactory.getMD5();
26c1040cb5656c3299f1c2d0fe0bd7c44b10466aafSergio Giro    // END android-changed
2716f9ee464b68937f45d009d9c1b0eb9b544a8deeSergio Giro
2816f9ee464b68937f45d009d9c1b0eb9b544a8deeSergio Giro    /**
2916f9ee464b68937f45d009d9c1b0eb9b544a8deeSergio Giro     * Construct a OpenSSL Parameters generator.
3016f9ee464b68937f45d009d9c1b0eb9b544a8deeSergio Giro     */
3116f9ee464b68937f45d009d9c1b0eb9b544a8deeSergio Giro    public OpenSSLPBEParametersGenerator()
3216f9ee464b68937f45d009d9c1b0eb9b544a8deeSergio Giro    {
3316f9ee464b68937f45d009d9c1b0eb9b544a8deeSergio Giro    }
3416f9ee464b68937f45d009d9c1b0eb9b544a8deeSergio Giro
3516f9ee464b68937f45d009d9c1b0eb9b544a8deeSergio Giro    /**
3616f9ee464b68937f45d009d9c1b0eb9b544a8deeSergio Giro     * Initialise - note the iteration count for this algorithm is fixed at 1.
3716f9ee464b68937f45d009d9c1b0eb9b544a8deeSergio Giro     *
3816f9ee464b68937f45d009d9c1b0eb9b544a8deeSergio Giro     * @param password password to use.
3916f9ee464b68937f45d009d9c1b0eb9b544a8deeSergio Giro     * @param salt salt to use.
4016f9ee464b68937f45d009d9c1b0eb9b544a8deeSergio Giro     */
4116f9ee464b68937f45d009d9c1b0eb9b544a8deeSergio Giro    public void init(
4216f9ee464b68937f45d009d9c1b0eb9b544a8deeSergio Giro       byte[] password,
4316f9ee464b68937f45d009d9c1b0eb9b544a8deeSergio Giro       byte[] salt)
4416f9ee464b68937f45d009d9c1b0eb9b544a8deeSergio Giro    {
4516f9ee464b68937f45d009d9c1b0eb9b544a8deeSergio Giro        super.init(password, salt, 1);
4616f9ee464b68937f45d009d9c1b0eb9b544a8deeSergio Giro    }
4716f9ee464b68937f45d009d9c1b0eb9b544a8deeSergio Giro
4816f9ee464b68937f45d009d9c1b0eb9b544a8deeSergio Giro    /**
4916f9ee464b68937f45d009d9c1b0eb9b544a8deeSergio Giro     * the derived key function, the ith hash of the password and the salt.
5016f9ee464b68937f45d009d9c1b0eb9b544a8deeSergio Giro     */
5116f9ee464b68937f45d009d9c1b0eb9b544a8deeSergio Giro    private byte[] generateDerivedKey(
5216f9ee464b68937f45d009d9c1b0eb9b544a8deeSergio Giro        int bytesNeeded)
5316f9ee464b68937f45d009d9c1b0eb9b544a8deeSergio Giro    {
5416f9ee464b68937f45d009d9c1b0eb9b544a8deeSergio Giro        byte[]  buf = new byte[digest.getDigestSize()];
5516f9ee464b68937f45d009d9c1b0eb9b544a8deeSergio Giro        byte[]  key = new byte[bytesNeeded];
5616f9ee464b68937f45d009d9c1b0eb9b544a8deeSergio Giro        int     offset = 0;
5716f9ee464b68937f45d009d9c1b0eb9b544a8deeSergio Giro
5816f9ee464b68937f45d009d9c1b0eb9b544a8deeSergio Giro        for (;;)
5916f9ee464b68937f45d009d9c1b0eb9b544a8deeSergio Giro        {
6016f9ee464b68937f45d009d9c1b0eb9b544a8deeSergio Giro            digest.update(password, 0, password.length);
6116f9ee464b68937f45d009d9c1b0eb9b544a8deeSergio Giro            digest.update(salt, 0, salt.length);
6216f9ee464b68937f45d009d9c1b0eb9b544a8deeSergio Giro
6316f9ee464b68937f45d009d9c1b0eb9b544a8deeSergio Giro            digest.doFinal(buf, 0);
6416f9ee464b68937f45d009d9c1b0eb9b544a8deeSergio Giro
6516f9ee464b68937f45d009d9c1b0eb9b544a8deeSergio Giro            int len = (bytesNeeded > buf.length) ? buf.length : bytesNeeded;
6616f9ee464b68937f45d009d9c1b0eb9b544a8deeSergio Giro            System.arraycopy(buf, 0, key, offset, len);
6716f9ee464b68937f45d009d9c1b0eb9b544a8deeSergio Giro            offset += len;
6816f9ee464b68937f45d009d9c1b0eb9b544a8deeSergio Giro
6916f9ee464b68937f45d009d9c1b0eb9b544a8deeSergio Giro            // check if we need any more
7016f9ee464b68937f45d009d9c1b0eb9b544a8deeSergio Giro            bytesNeeded -= len;
7116f9ee464b68937f45d009d9c1b0eb9b544a8deeSergio Giro            if (bytesNeeded == 0)
7216f9ee464b68937f45d009d9c1b0eb9b544a8deeSergio Giro            {
7316f9ee464b68937f45d009d9c1b0eb9b544a8deeSergio Giro                break;
7416f9ee464b68937f45d009d9c1b0eb9b544a8deeSergio Giro            }
7516f9ee464b68937f45d009d9c1b0eb9b544a8deeSergio Giro
7616f9ee464b68937f45d009d9c1b0eb9b544a8deeSergio Giro            // do another round
7716f9ee464b68937f45d009d9c1b0eb9b544a8deeSergio Giro            digest.reset();
7816f9ee464b68937f45d009d9c1b0eb9b544a8deeSergio Giro            digest.update(buf, 0, buf.length);
7916f9ee464b68937f45d009d9c1b0eb9b544a8deeSergio Giro        }
8016f9ee464b68937f45d009d9c1b0eb9b544a8deeSergio Giro
8116f9ee464b68937f45d009d9c1b0eb9b544a8deeSergio Giro        return key;
8216f9ee464b68937f45d009d9c1b0eb9b544a8deeSergio Giro    }
8316f9ee464b68937f45d009d9c1b0eb9b544a8deeSergio Giro
8416f9ee464b68937f45d009d9c1b0eb9b544a8deeSergio Giro    /**
8516f9ee464b68937f45d009d9c1b0eb9b544a8deeSergio Giro     * Generate a key parameter derived from the password, salt, and iteration
8616f9ee464b68937f45d009d9c1b0eb9b544a8deeSergio Giro     * count we are currently initialised with.
8716f9ee464b68937f45d009d9c1b0eb9b544a8deeSergio Giro     *
8816f9ee464b68937f45d009d9c1b0eb9b544a8deeSergio Giro     * @param keySize the size of the key we want (in bits)
8916f9ee464b68937f45d009d9c1b0eb9b544a8deeSergio Giro     * @return a KeyParameter object.
9016f9ee464b68937f45d009d9c1b0eb9b544a8deeSergio Giro     * @exception IllegalArgumentException if the key length larger than the base hash size.
9116f9ee464b68937f45d009d9c1b0eb9b544a8deeSergio Giro     */
9216f9ee464b68937f45d009d9c1b0eb9b544a8deeSergio Giro    public CipherParameters generateDerivedParameters(
9316f9ee464b68937f45d009d9c1b0eb9b544a8deeSergio Giro        int keySize)
9416f9ee464b68937f45d009d9c1b0eb9b544a8deeSergio Giro    {
9516f9ee464b68937f45d009d9c1b0eb9b544a8deeSergio Giro        keySize = keySize / 8;
9616f9ee464b68937f45d009d9c1b0eb9b544a8deeSergio Giro
9716f9ee464b68937f45d009d9c1b0eb9b544a8deeSergio Giro        byte[]  dKey = generateDerivedKey(keySize);
9816f9ee464b68937f45d009d9c1b0eb9b544a8deeSergio Giro
9916f9ee464b68937f45d009d9c1b0eb9b544a8deeSergio Giro        return new KeyParameter(dKey, 0, keySize);
10016f9ee464b68937f45d009d9c1b0eb9b544a8deeSergio Giro    }
10116f9ee464b68937f45d009d9c1b0eb9b544a8deeSergio Giro
10216f9ee464b68937f45d009d9c1b0eb9b544a8deeSergio Giro    /**
10316f9ee464b68937f45d009d9c1b0eb9b544a8deeSergio Giro     * Generate a key with initialisation vector parameter derived from
10416f9ee464b68937f45d009d9c1b0eb9b544a8deeSergio Giro     * the password, salt, and iteration count we are currently initialised
10516f9ee464b68937f45d009d9c1b0eb9b544a8deeSergio Giro     * with.
10616f9ee464b68937f45d009d9c1b0eb9b544a8deeSergio Giro     *
10716f9ee464b68937f45d009d9c1b0eb9b544a8deeSergio Giro     * @param keySize the size of the key we want (in bits)
10816f9ee464b68937f45d009d9c1b0eb9b544a8deeSergio Giro     * @param ivSize the size of the iv we want (in bits)
10916f9ee464b68937f45d009d9c1b0eb9b544a8deeSergio Giro     * @return a ParametersWithIV object.
11016f9ee464b68937f45d009d9c1b0eb9b544a8deeSergio Giro     * @exception IllegalArgumentException if keySize + ivSize is larger than the base hash size.
11116f9ee464b68937f45d009d9c1b0eb9b544a8deeSergio Giro     */
11216f9ee464b68937f45d009d9c1b0eb9b544a8deeSergio Giro    public CipherParameters generateDerivedParameters(
11316f9ee464b68937f45d009d9c1b0eb9b544a8deeSergio Giro        int     keySize,
11416f9ee464b68937f45d009d9c1b0eb9b544a8deeSergio Giro        int     ivSize)
11516f9ee464b68937f45d009d9c1b0eb9b544a8deeSergio Giro    {
11616f9ee464b68937f45d009d9c1b0eb9b544a8deeSergio Giro        keySize = keySize / 8;
11716f9ee464b68937f45d009d9c1b0eb9b544a8deeSergio Giro        ivSize = ivSize / 8;
11816f9ee464b68937f45d009d9c1b0eb9b544a8deeSergio Giro
11916f9ee464b68937f45d009d9c1b0eb9b544a8deeSergio Giro        byte[]  dKey = generateDerivedKey(keySize + ivSize);
12016f9ee464b68937f45d009d9c1b0eb9b544a8deeSergio Giro
12116f9ee464b68937f45d009d9c1b0eb9b544a8deeSergio Giro        return new ParametersWithIV(new KeyParameter(dKey, 0, keySize), dKey, keySize, ivSize);
12216f9ee464b68937f45d009d9c1b0eb9b544a8deeSergio Giro    }
12316f9ee464b68937f45d009d9c1b0eb9b544a8deeSergio Giro
12416f9ee464b68937f45d009d9c1b0eb9b544a8deeSergio Giro    /**
12516f9ee464b68937f45d009d9c1b0eb9b544a8deeSergio Giro     * Generate a key parameter for use with a MAC derived from the password,
12616f9ee464b68937f45d009d9c1b0eb9b544a8deeSergio Giro     * salt, and iteration count we are currently initialised with.
12716f9ee464b68937f45d009d9c1b0eb9b544a8deeSergio Giro     *
12816f9ee464b68937f45d009d9c1b0eb9b544a8deeSergio Giro     * @param keySize the size of the key we want (in bits)
12916f9ee464b68937f45d009d9c1b0eb9b544a8deeSergio Giro     * @return a KeyParameter object.
13016f9ee464b68937f45d009d9c1b0eb9b544a8deeSergio Giro     * @exception IllegalArgumentException if the key length larger than the base hash size.
13116f9ee464b68937f45d009d9c1b0eb9b544a8deeSergio Giro     */
13216f9ee464b68937f45d009d9c1b0eb9b544a8deeSergio Giro    public CipherParameters generateDerivedMacParameters(
13316f9ee464b68937f45d009d9c1b0eb9b544a8deeSergio Giro        int keySize)
13416f9ee464b68937f45d009d9c1b0eb9b544a8deeSergio Giro    {
13516f9ee464b68937f45d009d9c1b0eb9b544a8deeSergio Giro        return generateDerivedParameters(keySize);
13616f9ee464b68937f45d009d9c1b0eb9b544a8deeSergio Giro    }
13716f9ee464b68937f45d009d9c1b0eb9b544a8deeSergio Giro}
138