001: package org.bouncycastle.crypto.generators;
002:
003: import org.bouncycastle.crypto.CipherParameters;
004: import org.bouncycastle.crypto.Digest;
005: import org.bouncycastle.crypto.PBEParametersGenerator;
006: import org.bouncycastle.crypto.digests.MD5Digest;
007: import org.bouncycastle.crypto.params.KeyParameter;
008: import org.bouncycastle.crypto.params.ParametersWithIV;
009:
010: /**
011: * Generator for PBE derived keys and ivs as usd by OpenSSL.
012: * <p>
013: * The scheme is a simple extension of PKCS 5 V2.0 Scheme 1 using MD5 with an
014: * iteration count of 1.
015: * <p>
016: */
017: public class OpenSSLPBEParametersGenerator extends
018: PBEParametersGenerator {
019: private Digest digest = new MD5Digest();
020:
021: /**
022: * Construct a OpenSSL Parameters generator.
023: */
024: public OpenSSLPBEParametersGenerator() {
025: }
026:
027: /**
028: * Initialise - note the iteration count for this algorithm is fixed at 1.
029: *
030: * @param password password to use.
031: * @param salt salt to use.
032: */
033: public void init(byte[] password, byte[] salt) {
034: super .init(password, salt, 1);
035: }
036:
037: /**
038: * the derived key function, the ith hash of the password and the salt.
039: */
040: private byte[] generateDerivedKey(int bytesNeeded) {
041: byte[] buf = new byte[digest.getDigestSize()];
042: byte[] key = new byte[bytesNeeded];
043: int offset = 0;
044:
045: for (;;) {
046: digest.update(password, 0, password.length);
047: digest.update(salt, 0, salt.length);
048:
049: digest.doFinal(buf, 0);
050:
051: int len = (bytesNeeded > buf.length) ? buf.length
052: : bytesNeeded;
053: System.arraycopy(buf, 0, key, offset, len);
054: offset += len;
055:
056: // check if we need any more
057: bytesNeeded -= len;
058: if (bytesNeeded == 0) {
059: break;
060: }
061:
062: // do another round
063: digest.reset();
064: digest.update(buf, 0, buf.length);
065: }
066:
067: return key;
068: }
069:
070: /**
071: * Generate a key parameter derived from the password, salt, and iteration
072: * count we are currently initialised with.
073: *
074: * @param keySize the size of the key we want (in bits)
075: * @return a KeyParameter object.
076: * @exception IllegalArgumentException if the key length larger than the base hash size.
077: */
078: public CipherParameters generateDerivedParameters(int keySize) {
079: keySize = keySize / 8;
080:
081: byte[] dKey = generateDerivedKey(keySize);
082:
083: return new KeyParameter(dKey, 0, keySize);
084: }
085:
086: /**
087: * Generate a key with initialisation vector parameter derived from
088: * the password, salt, and iteration count we are currently initialised
089: * with.
090: *
091: * @param keySize the size of the key we want (in bits)
092: * @param ivSize the size of the iv we want (in bits)
093: * @return a ParametersWithIV object.
094: * @exception IllegalArgumentException if keySize + ivSize is larger than the base hash size.
095: */
096: public CipherParameters generateDerivedParameters(int keySize,
097: int ivSize) {
098: keySize = keySize / 8;
099: ivSize = ivSize / 8;
100:
101: byte[] dKey = generateDerivedKey(keySize + ivSize);
102:
103: return new ParametersWithIV(new KeyParameter(dKey, 0, keySize),
104: dKey, keySize, ivSize);
105: }
106:
107: /**
108: * Generate a key parameter for use with a MAC derived from the password,
109: * salt, and iteration count we are currently initialised with.
110: *
111: * @param keySize the size of the key we want (in bits)
112: * @return a KeyParameter object.
113: * @exception IllegalArgumentException if the key length larger than the base hash size.
114: */
115: public CipherParameters generateDerivedMacParameters(int keySize) {
116: return generateDerivedParameters(keySize);
117: }
118: }
|