X-Git-Url: https://code.wpia.club/?p=gigi.git;a=blobdiff_plain;f=lib%2Fscrypt%2Fcom%2Flambdaworks%2Fcrypto%2FPBKDF.java;fp=lib%2Fscrypt%2Fcom%2Flambdaworks%2Fcrypto%2FPBKDF.java;h=43dc2f427427a267900e996b8c53e635ae9ffc42;hp=0000000000000000000000000000000000000000;hb=8cd6cfda6e99fd09acb1f0d158d57dbba7356cbc;hpb=aa9c6151c2b25a8ea71824aeb8aea94703ef3e68 diff --git a/lib/scrypt/com/lambdaworks/crypto/PBKDF.java b/lib/scrypt/com/lambdaworks/crypto/PBKDF.java new file mode 100644 index 00000000..43dc2f42 --- /dev/null +++ b/lib/scrypt/com/lambdaworks/crypto/PBKDF.java @@ -0,0 +1,87 @@ +// Copyright (C) 2011 - Will Glozer. All rights reserved. + +package com.lambdaworks.crypto; + +import javax.crypto.Mac; +import javax.crypto.spec.SecretKeySpec; +import java.security.GeneralSecurityException; +import static java.lang.System.arraycopy; + +/** + * An implementation of the Password-Based Key Derivation Function as specified + * in RFC 2898. + * + * @author Will Glozer + */ +public class PBKDF { + /** + * Implementation of PBKDF2 (RFC2898). + * + * @param alg HMAC algorithm to use. + * @param P Password. + * @param S Salt. + * @param c Iteration count. + * @param dkLen Intended length, in octets, of the derived key. + * + * @return The derived key. + * + * @throws GeneralSecurityException + */ + public static byte[] pbkdf2(String alg, byte[] P, byte[] S, int c, int dkLen) throws GeneralSecurityException { + Mac mac = Mac.getInstance(alg); + mac.init(new SecretKeySpec(P, alg)); + byte[] DK = new byte[dkLen]; + pbkdf2(mac, S, c, DK, dkLen); + return DK; + } + + /** + * Implementation of PBKDF2 (RFC2898). + * + * @param mac Pre-initialized {@link Mac} instance to use. + * @param S Salt. + * @param c Iteration count. + * @param DK Byte array that derived key will be placed in. + * @param dkLen Intended length, in octets, of the derived key. + * + * @throws GeneralSecurityException + */ + public static void pbkdf2(Mac mac, byte[] S, int c, byte[] DK, int dkLen) throws GeneralSecurityException { + int hLen = mac.getMacLength(); + + if (dkLen > (Math.pow(2, 32) - 1) * hLen) { + throw new GeneralSecurityException("Requested key length too long"); + } + + byte[] U = new byte[hLen]; + byte[] T = new byte[hLen]; + byte[] block1 = new byte[S.length + 4]; + + int l = (int) Math.ceil((double) dkLen / hLen); + int r = dkLen - (l - 1) * hLen; + + arraycopy(S, 0, block1, 0, S.length); + + for (int i = 1; i <= l; i++) { + block1[S.length + 0] = (byte) (i >> 24 & 0xff); + block1[S.length + 1] = (byte) (i >> 16 & 0xff); + block1[S.length + 2] = (byte) (i >> 8 & 0xff); + block1[S.length + 3] = (byte) (i >> 0 & 0xff); + + mac.update(block1); + mac.doFinal(U, 0); + arraycopy(U, 0, T, 0, hLen); + + for (int j = 1; j < c; j++) { + mac.update(U); + mac.doFinal(U, 0); + + for (int k = 0; k < hLen; k++) { + T[k] ^= U[k]; + } + } + + arraycopy(T, 0, DK, (i - 1) * hLen, (i == l ? r : hLen)); + } + } +}