1.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000 1.2 +++ b/mobile/android/base/sync/crypto/PBKDF2.java Wed Dec 31 06:09:35 2014 +0100 1.3 @@ -0,0 +1,78 @@ 1.4 +/* This Source Code Form is subject to the terms of the Mozilla Public 1.5 + * License, v. 2.0. If a copy of the MPL was not distributed with this 1.6 + * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ 1.7 + 1.8 +package org.mozilla.gecko.sync.crypto; 1.9 + 1.10 +import java.security.GeneralSecurityException; 1.11 +import java.util.Arrays; 1.12 + 1.13 +import javax.crypto.Mac; 1.14 +import javax.crypto.ShortBufferException; 1.15 +import javax.crypto.spec.SecretKeySpec; 1.16 + 1.17 +public class PBKDF2 { 1.18 + public static byte[] pbkdf2SHA256(byte[] password, byte[] salt, int c, int dkLen) 1.19 + throws GeneralSecurityException { 1.20 + final String algorithm = "HmacSHA256"; 1.21 + SecretKeySpec keyspec = new SecretKeySpec(password, algorithm); 1.22 + Mac prf = Mac.getInstance(algorithm); 1.23 + prf.init(keyspec); 1.24 + 1.25 + int hLen = prf.getMacLength(); 1.26 + 1.27 + byte U_r[] = new byte[hLen]; 1.28 + byte U_i[] = new byte[salt.length + 4]; 1.29 + byte scratch[] = new byte[hLen]; 1.30 + 1.31 + int l = Math.max(dkLen, hLen); 1.32 + int r = dkLen - (l - 1) * hLen; 1.33 + byte T[] = new byte[l * hLen]; 1.34 + int ti_offset = 0; 1.35 + for (int i = 1; i <= l; i++) { 1.36 + Arrays.fill(U_r, (byte) 0); 1.37 + F(T, ti_offset, prf, salt, c, i, U_r, U_i, scratch); 1.38 + ti_offset += hLen; 1.39 + } 1.40 + 1.41 + if (r < hLen) { 1.42 + // Incomplete last block. 1.43 + byte DK[] = new byte[dkLen]; 1.44 + System.arraycopy(T, 0, DK, 0, dkLen); 1.45 + return DK; 1.46 + } 1.47 + 1.48 + return T; 1.49 + } 1.50 + 1.51 + private static void F(byte[] dest, int offset, Mac prf, byte[] S, int c, int blockIndex, byte U_r[], byte U_i[], byte[] scratch) 1.52 + throws ShortBufferException, IllegalStateException { 1.53 + final int hLen = prf.getMacLength(); 1.54 + 1.55 + // U0 = S || INT (i); 1.56 + System.arraycopy(S, 0, U_i, 0, S.length); 1.57 + INT(U_i, S.length, blockIndex); 1.58 + 1.59 + for (int i = 0; i < c; i++) { 1.60 + prf.update(U_i); 1.61 + prf.doFinal(scratch, 0); 1.62 + U_i = scratch; 1.63 + xor(U_r, U_i); 1.64 + } 1.65 + 1.66 + System.arraycopy(U_r, 0, dest, offset, hLen); 1.67 + } 1.68 + 1.69 + private static void xor(byte[] dest, byte[] src) { 1.70 + for (int i = 0; i < dest.length; i++) { 1.71 + dest[i] ^= src[i]; 1.72 + } 1.73 + } 1.74 + 1.75 + private static void INT(byte[] dest, int offset, int i) { 1.76 + dest[offset + 0] = (byte) (i / (256 * 256 * 256)); 1.77 + dest[offset + 1] = (byte) (i / (256 * 256)); 1.78 + dest[offset + 2] = (byte) (i / (256)); 1.79 + dest[offset + 3] = (byte) (i); 1.80 + } 1.81 +}