/* * The PRF is defined as: * * PRF(secret, label, seed) = P_MD5(S1, label + seed) XOR * P_SHA-1(S2, label + seed); * * P_hash is defined as: * * P_hash(secret, seed) = HMAC_hash(secret, A(1) + seed) + * HMAC_hash(secret, A(2) + seed) + * HMAC_hash(secret, A(3) + seed) + ... * * And A() is defined as: * * A(0) = seed * A(i) = HMAC_hash(secret, A(i-1)) * * For simplicity, we compute an 80-byte block on each call, which * corresponds to five iterations of MD5, and four of SHA-1. */ private synchronized void fillBuffer() { int len = hmac_md5.macSize(); for (int i = 0; i < buffer.length; i += len) { hmac_md5.update(md5_a, 0, md5_a.length); hmac_md5.update(seed, 0, seed.length); byte[] b = hmac_md5.digest(); hmac_md5.reset(); System.arraycopy(b, 0, buffer, i, len); hmac_md5.update(md5_a, 0, md5_a.length); md5_a = hmac_md5.digest(); hmac_md5.reset(); } len = hmac_sha.macSize(); for (int i = 0; i < buffer.length; i += len) { hmac_sha.update(sha_a, 0, sha_a.length); hmac_sha.update(seed, 0, seed.length); byte[] b = hmac_sha.digest(); hmac_sha.reset(); for (int j = 0; j < len; j++) { buffer[j + i] ^= b[j]; } hmac_sha.update(sha_a, 0, sha_a.length); sha_a = hmac_sha.digest(); hmac_sha.reset(); } idx = 0; }
public void init(Map attributes) { HashMap sha_attr = new HashMap(); HashMap md5_attr = new HashMap(); byte[] secret = (byte[]) attributes.get(SECRET); if (secret != null) { int l = (secret.length >>> 1) + (secret.length & 1); byte[] s1 = Util.trim(secret, 0, l); byte[] s2 = Util.trim(secret, secret.length - l, l); md5_attr.put(IMac.MAC_KEY_MATERIAL, s1); sha_attr.put(IMac.MAC_KEY_MATERIAL, s2); try { hmac_md5.init(md5_attr); hmac_sha.init(sha_attr); } catch (InvalidKeyException ike) { throw new Error(ike.toString()); } } else if (!init) { throw new IllegalArgumentException("no secret supplied"); } // else re-use byte[] seeed = (byte[]) attributes.get(SEED); if (seeed != null) { seed = (byte[]) seeed.clone(); } else if (!init) { throw new IllegalArgumentException("no seed supplied"); } // else re-use // A(0) is the seed, A(1) = HMAC_hash(secret, A(0)). hmac_md5.update(seed, 0, seed.length); md5_a = hmac_md5.digest(); hmac_md5.reset(); hmac_sha.update(seed, 0, seed.length); sha_a = hmac_sha.digest(); hmac_sha.reset(); fillBuffer(); init = true; }