001: package org.bouncycastle.jce.provider;
002:
003: import org.bouncycastle.crypto.DataLengthException;
004: import org.bouncycastle.crypto.DerivationFunction;
005: import org.bouncycastle.crypto.DerivationParameters;
006: import org.bouncycastle.crypto.Digest;
007: import org.bouncycastle.crypto.params.KDFParameters;
008:
009: /**
010: * Generator for PBE derived keys and ivs as defined by IEEE P1363a
011: * <br>
012: * This implementation is based on draft 9 of IEEE P1363a. <b>Note:</b>
013: * as this is still a draft the output of this generator may change, don't
014: * use it for anything that might be subject to long term storage.
015: */
016: public class BrokenKDF2BytesGenerator implements DerivationFunction {
017: private Digest digest;
018: private byte[] shared;
019: private byte[] iv;
020:
021: /**
022: * Construct a KDF2 Parameters generator. Generates key material
023: * according to IEEE P1363a - if you want orthodox results you should
024: * use a digest specified in the standard.
025: * <p>
026: * <b>Note:</b> IEEE P1363a standard is still a draft standard, if the standard
027: * changes this function, the output of this function will change as well.
028: * Don't use this routine for anything subject to long term storage.
029: *
030: * @param digest the digest to be used as the source of derived keys.
031: */
032: public BrokenKDF2BytesGenerator(Digest digest) {
033: this .digest = digest;
034: }
035:
036: public void init(DerivationParameters param) {
037: if (!(param instanceof KDFParameters)) {
038: throw new IllegalArgumentException(
039: "KDF parameters required for KDF2Generator");
040: }
041:
042: KDFParameters p = (KDFParameters) param;
043:
044: shared = p.getSharedSecret();
045: iv = p.getIV();
046: }
047:
048: /**
049: * return the underlying digest.
050: */
051: public Digest getDigest() {
052: return digest;
053: }
054:
055: /**
056: * fill len bytes of the output buffer with bytes generated from
057: * the derivation function.
058: *
059: * @throws IllegalArgumentException if the size of the request will cause an overflow.
060: * @throws DataLengthException if the out buffer is too small.
061: */
062: public int generateBytes(byte[] out, int outOff, int len)
063: throws DataLengthException, IllegalArgumentException {
064: if ((out.length - len) < outOff) {
065: throw new DataLengthException("output buffer too small");
066: }
067:
068: long oBits = len * 8;
069:
070: //
071: // this is at odds with the standard implementation, the
072: // maximum value should be hBits * (2^23 - 1) where hBits
073: // is the digest output size in bits. We can't have an
074: // array with a long index at the moment...
075: //
076: if (oBits > (digest.getDigestSize() * 8 * (2L ^ 32 - 1))) {
077: new IllegalArgumentException("Output length to large");
078: }
079:
080: int cThreshold = (int) (oBits / digest.getDigestSize());
081:
082: byte[] dig = null;
083:
084: dig = new byte[digest.getDigestSize()];
085:
086: for (int counter = 1; counter <= cThreshold; counter++) {
087: digest.update(shared, 0, shared.length);
088:
089: digest.update((byte) (counter & 0xff));
090: digest.update((byte) ((counter >> 8) & 0xff));
091: digest.update((byte) ((counter >> 16) & 0xff));
092: digest.update((byte) ((counter >> 24) & 0xff));
093:
094: digest.update(iv, 0, iv.length);
095:
096: digest.doFinal(dig, 0);
097:
098: if ((len - outOff) > dig.length) {
099: System.arraycopy(dig, 0, out, outOff, dig.length);
100: outOff += dig.length;
101: } else {
102: System.arraycopy(dig, 0, out, outOff, len - outOff);
103: }
104: }
105:
106: digest.reset();
107:
108: return len;
109: }
110: }
|