- cfpassphrase/src/com/lambdaworks/crypto/PBKDF.java
- 3 KB
- 87
1// Copyright (C) 2011 - Will Glozer. All rights reserved.
2
3package com.lambdaworks.crypto;
4
5import javax.crypto.Mac;
6import javax.crypto.spec.SecretKeySpec;
7import java.security.GeneralSecurityException;
8import static java.lang.System.arraycopy;
9
10/**
11 * An implementation of the Password-Based Key Derivation Function as specified
12 * in RFC 2898.
13 *
14 * @author Will Glozer
15 */
16public class PBKDF {
17 /**
18 * Implementation of PBKDF2 (RFC2898).
19 *
20 * @param alg HMAC algorithm to use.
21 * @param P Password.
22 * @param S Salt.
23 * @param c Iteration count.
24 * @param dkLen Intended length, in octets, of the derived key.
25 *
26 * @return The derived key.
27 *
28 * @throws GeneralSecurityException
29 */
30 public static byte[] pbkdf2(String alg, byte[] P, byte[] S, int c, int dkLen) throws GeneralSecurityException {
31 Mac mac = Mac.getInstance(alg);
32 mac.init(new SecretKeySpec(P, alg));
33 byte[] DK = new byte[dkLen];
34 pbkdf2(mac, S, c, DK, dkLen);
35 return DK;
36 }
37
38 /**
39 * Implementation of PBKDF2 (RFC2898).
40 *
41 * @param mac Pre-initialized {@link Mac} instance to use.
42 * @param S Salt.
43 * @param c Iteration count.
44 * @param DK Byte array that derived key will be placed in.
45 * @param dkLen Intended length, in octets, of the derived key.
46 *
47 * @throws GeneralSecurityException
48 */
49 public static void pbkdf2(Mac mac, byte[] S, int c, byte[] DK, int dkLen) throws GeneralSecurityException {
50 int hLen = mac.getMacLength();
51
52 if (dkLen > (Math.pow(2, 32) - 1) * hLen) {
53 throw new GeneralSecurityException("Requested key length too long");
54 }
55
56 byte[] U = new byte[hLen];
57 byte[] T = new byte[hLen];
58 byte[] block1 = new byte[S.length + 4];
59
60 int l = (int) Math.ceil((double) dkLen / hLen);
61 int r = dkLen - (l - 1) * hLen;
62
63 arraycopy(S, 0, block1, 0, S.length);
64
65 for (int i = 1; i <= l; i++) {
66 block1[S.length + 0] = (byte) (i >> 24 & 0xff);
67 block1[S.length + 1] = (byte) (i >> 16 & 0xff);
68 block1[S.length + 2] = (byte) (i >> 8 & 0xff);
69 block1[S.length + 3] = (byte) (i >> 0 & 0xff);
70
71 mac.update(block1);
72 mac.doFinal(U, 0);
73 arraycopy(U, 0, T, 0, hLen);
74
75 for (int j = 1; j < c; j++) {
76 mac.update(U);
77 mac.doFinal(U, 0);
78
79 for (int k = 0; k < hLen; k++) {
80 T[k] ^= U[k];
81 }
82 }
83
84 arraycopy(T, 0, DK, (i - 1) * hLen, (i == l ? r : hLen));
85 }
86 }
87}