From 16c996ceeb6ce449d4bba2ba0cbe9ff345514303 Mon Sep 17 00:00:00 2001 From: =?utf8?q?Felix=20D=C3=B6rre?= Date: Tue, 2 Dec 2014 01:47:54 +0100 Subject: [PATCH] upd: Remove nasty dependencies ;-) --- lib/scrypt/com/lambdaworks/crypto/SCrypt.java | 190 +++++++++++------- .../com/lambdaworks/crypto/SCryptUtil.java | 91 +++++---- .../crypto/test/SCryptUtilTest.java | 9 +- 3 files changed, 179 insertions(+), 111 deletions(-) diff --git a/lib/scrypt/com/lambdaworks/crypto/SCrypt.java b/lib/scrypt/com/lambdaworks/crypto/SCrypt.java index 62742389..9b212973 100644 --- a/lib/scrypt/com/lambdaworks/crypto/SCrypt.java +++ b/lib/scrypt/com/lambdaworks/crypto/SCrypt.java @@ -1,96 +1,124 @@ -// Copyright (C) 2011 - Will Glozer. All rights reserved. +// Copyright (C) 2011 - Will Glozer. All rights reserved. package com.lambdaworks.crypto; -import com.lambdaworks.jni.*; +import static java.lang.Integer.*; +import static java.lang.System.*; -import javax.crypto.Mac; -import javax.crypto.spec.SecretKeySpec; import java.security.GeneralSecurityException; -import static java.lang.Integer.MAX_VALUE; -import static java.lang.System.arraycopy; +import javax.crypto.Mac; +import javax.crypto.spec.SecretKeySpec; /** - * An implementation of the scrypt - * key derivation function. This class will attempt to load a native library - * containing the optimized C implementation from - * http://www.tarsnap.com/scrypt.html and - * fall back to the pure Java version if that fails. + * An implementation of the scrypt key derivation + * function. This class will attempt to load a native library containing the + * optimized C implementation from http + * ://www.tarsnap.com/scrypt.html and fall back to the pure Java version if + * that fails. * - * @author Will Glozer + * @author Will Glozer */ public class SCrypt { + private static final boolean native_library_loaded; static { - LibraryLoader loader = LibraryLoaders.loader(); - native_library_loaded = loader.load("scrypt", true); + // do not load native library + native_library_loaded = false; } /** - * Implementation of the scrypt KDF. - * Calls the native implementation {@link #scryptN} when the native library was successfully - * loaded, otherwise calls {@link #scryptJ}. - * - * @param passwd Password. - * @param salt Salt. - * @param N CPU cost parameter. - * @param r Memory cost parameter. - * @param p Parallelization parameter. - * @param dkLen Intended length of the derived key. + * Implementation of the scrypt KDF. Calls + * the native implementation {@link #scryptN} when the native library was + * successfully loaded, otherwise calls {@link #scryptJ}. * + * @param passwd + * Password. + * @param salt + * Salt. + * @param N + * CPU cost parameter. + * @param r + * Memory cost parameter. + * @param p + * Parallelization parameter. + * @param dkLen + * Intended length of the derived key. * @return The derived key. - * - * @throws GeneralSecurityException when HMAC_SHA256 is not available. + * @throws GeneralSecurityException + * when HMAC_SHA256 is not available. */ public static byte[] scrypt(byte[] passwd, byte[] salt, int N, int r, int p, int dkLen) throws GeneralSecurityException { return native_library_loaded ? scryptN(passwd, salt, N, r, p, dkLen) : scryptJ(passwd, salt, N, r, p, dkLen); } /** - * Native C implementation of the scrypt KDF using - * the code from http://www.tarsnap.com/scrypt.html. - * - * @param passwd Password. - * @param salt Salt. - * @param N CPU cost parameter. - * @param r Memory cost parameter. - * @param p Parallelization parameter. - * @param dkLen Intended length of the derived key. + * Native C implementation of the scrypt KDF using the + * code from http://www.tarsnap. + * com/scrypt.html. * + * @param passwd + * Password. + * @param salt + * Salt. + * @param N + * CPU cost parameter. + * @param r + * Memory cost parameter. + * @param p + * Parallelization parameter. + * @param dkLen + * Intended length of the derived key. * @return The derived key. */ public static native byte[] scryptN(byte[] passwd, byte[] salt, int N, int r, int p, int dkLen); /** - * Pure Java implementation of the scrypt KDF. - * - * @param passwd Password. - * @param salt Salt. - * @param N CPU cost parameter. - * @param r Memory cost parameter. - * @param p Parallelization parameter. - * @param dkLen Intended length of the derived key. + * Pure Java implementation of the scrypt KDF. * + * @param passwd + * Password. + * @param salt + * Salt. + * @param N + * CPU cost parameter. + * @param r + * Memory cost parameter. + * @param p + * Parallelization parameter. + * @param dkLen + * Intended length of the derived key. * @return The derived key. - * - * @throws GeneralSecurityException when HMAC_SHA256 is not available. + * @throws GeneralSecurityException + * when HMAC_SHA256 is not available. */ public static byte[] scryptJ(byte[] passwd, byte[] salt, int N, int r, int p, int dkLen) throws GeneralSecurityException { - if (N < 2 || (N & (N - 1)) != 0) throw new IllegalArgumentException("N must be a power of 2 greater than 1"); + if (N < 2 || (N & (N - 1)) != 0) { + throw new IllegalArgumentException("N must be a power of 2 greater than 1"); + } - if (N > MAX_VALUE / 128 / r) throw new IllegalArgumentException("Parameter N is too large"); - if (r > MAX_VALUE / 128 / p) throw new IllegalArgumentException("Parameter r is too large"); + if (N > MAX_VALUE / 128 / r) { + throw new IllegalArgumentException("Parameter N is too large"); + } + if (r > MAX_VALUE / 128 / p) { + throw new IllegalArgumentException("Parameter r is too large"); + } Mac mac = Mac.getInstance("HmacSHA256"); mac.init(new SecretKeySpec(passwd, "HmacSHA256")); byte[] DK = new byte[dkLen]; - byte[] B = new byte[128 * r * p]; + byte[] B = new byte[128 * r * p]; byte[] XY = new byte[256 * r]; - byte[] V = new byte[128 * r * N]; + byte[] V = new byte[128 * r * N]; int i; PBKDF.pbkdf2(mac, salt, 1, B, p * 128 * r); @@ -152,11 +180,11 @@ public class SCrypt { public static void salsa20_8(byte[] B) { int[] B32 = new int[16]; - int[] x = new int[16]; + int[] x = new int[16]; int i; for (i = 0; i < 16; i++) { - B32[i] = (B[i * 4 + 0] & 0xff) << 0; + B32[i] = (B[i * 4 + 0] & 0xff) << 0; B32[i] |= (B[i * 4 + 1] & 0xff) << 8; B32[i] |= (B[i * 4 + 2] & 0xff) << 16; B32[i] |= (B[i * 4 + 3] & 0xff) << 24; @@ -165,29 +193,47 @@ public class SCrypt { arraycopy(B32, 0, x, 0, 16); for (i = 8; i > 0; i -= 2) { - x[ 4] ^= R(x[ 0]+x[12], 7); x[ 8] ^= R(x[ 4]+x[ 0], 9); - x[12] ^= R(x[ 8]+x[ 4],13); x[ 0] ^= R(x[12]+x[ 8],18); - x[ 9] ^= R(x[ 5]+x[ 1], 7); x[13] ^= R(x[ 9]+x[ 5], 9); - x[ 1] ^= R(x[13]+x[ 9],13); x[ 5] ^= R(x[ 1]+x[13],18); - x[14] ^= R(x[10]+x[ 6], 7); x[ 2] ^= R(x[14]+x[10], 9); - x[ 6] ^= R(x[ 2]+x[14],13); x[10] ^= R(x[ 6]+x[ 2],18); - x[ 3] ^= R(x[15]+x[11], 7); x[ 7] ^= R(x[ 3]+x[15], 9); - x[11] ^= R(x[ 7]+x[ 3],13); x[15] ^= R(x[11]+x[ 7],18); - x[ 1] ^= R(x[ 0]+x[ 3], 7); x[ 2] ^= R(x[ 1]+x[ 0], 9); - x[ 3] ^= R(x[ 2]+x[ 1],13); x[ 0] ^= R(x[ 3]+x[ 2],18); - x[ 6] ^= R(x[ 5]+x[ 4], 7); x[ 7] ^= R(x[ 6]+x[ 5], 9); - x[ 4] ^= R(x[ 7]+x[ 6],13); x[ 5] ^= R(x[ 4]+x[ 7],18); - x[11] ^= R(x[10]+x[ 9], 7); x[ 8] ^= R(x[11]+x[10], 9); - x[ 9] ^= R(x[ 8]+x[11],13); x[10] ^= R(x[ 9]+x[ 8],18); - x[12] ^= R(x[15]+x[14], 7); x[13] ^= R(x[12]+x[15], 9); - x[14] ^= R(x[13]+x[12],13); x[15] ^= R(x[14]+x[13],18); + x[4] ^= R(x[0] + x[12], 7); + x[8] ^= R(x[4] + x[0], 9); + x[12] ^= R(x[8] + x[4], 13); + x[0] ^= R(x[12] + x[8], 18); + x[9] ^= R(x[5] + x[1], 7); + x[13] ^= R(x[9] + x[5], 9); + x[1] ^= R(x[13] + x[9], 13); + x[5] ^= R(x[1] + x[13], 18); + x[14] ^= R(x[10] + x[6], 7); + x[2] ^= R(x[14] + x[10], 9); + x[6] ^= R(x[2] + x[14], 13); + x[10] ^= R(x[6] + x[2], 18); + x[3] ^= R(x[15] + x[11], 7); + x[7] ^= R(x[3] + x[15], 9); + x[11] ^= R(x[7] + x[3], 13); + x[15] ^= R(x[11] + x[7], 18); + x[1] ^= R(x[0] + x[3], 7); + x[2] ^= R(x[1] + x[0], 9); + x[3] ^= R(x[2] + x[1], 13); + x[0] ^= R(x[3] + x[2], 18); + x[6] ^= R(x[5] + x[4], 7); + x[7] ^= R(x[6] + x[5], 9); + x[4] ^= R(x[7] + x[6], 13); + x[5] ^= R(x[4] + x[7], 18); + x[11] ^= R(x[10] + x[9], 7); + x[8] ^= R(x[11] + x[10], 9); + x[9] ^= R(x[8] + x[11], 13); + x[10] ^= R(x[9] + x[8], 18); + x[12] ^= R(x[15] + x[14], 7); + x[13] ^= R(x[12] + x[15], 9); + x[14] ^= R(x[13] + x[12], 13); + x[15] ^= R(x[14] + x[13], 18); } - for (i = 0; i < 16; ++i) B32[i] = x[i] + B32[i]; + for (i = 0; i < 16; ++i) { + B32[i] = x[i] + B32[i]; + } for (i = 0; i < 16; i++) { - B[i * 4 + 0] = (byte) (B32[i] >> 0 & 0xff); - B[i * 4 + 1] = (byte) (B32[i] >> 8 & 0xff); + B[i * 4 + 0] = (byte) (B32[i] >> 0 & 0xff); + B[i * 4 + 1] = (byte) (B32[i] >> 8 & 0xff); B[i * 4 + 2] = (byte) (B32[i] >> 16 & 0xff); B[i * 4 + 3] = (byte) (B32[i] >> 24 & 0xff); } @@ -204,7 +250,7 @@ public class SCrypt { Bi += (2 * r - 1) * 64; - n = (B[Bi + 0] & 0xff) << 0; + n = (B[Bi + 0] & 0xff) << 0; n |= (B[Bi + 1] & 0xff) << 8; n |= (B[Bi + 2] & 0xff) << 16; n |= (B[Bi + 3] & 0xff) << 24; diff --git a/lib/scrypt/com/lambdaworks/crypto/SCryptUtil.java b/lib/scrypt/com/lambdaworks/crypto/SCryptUtil.java index ca29a00c..6d794000 100644 --- a/lib/scrypt/com/lambdaworks/crypto/SCryptUtil.java +++ b/lib/scrypt/com/lambdaworks/crypto/SCryptUtil.java @@ -1,42 +1,46 @@ -// Copyright (C) 2011 - Will Glozer. All rights reserved. +// Copyright (C) 2011 - Will Glozer. All rights reserved. package com.lambdaworks.crypto; import java.io.UnsupportedEncodingException; import java.security.GeneralSecurityException; import java.security.SecureRandom; - -import static com.lambdaworks.codec.Base64.*; +import java.util.Base64; /** - * Simple {@link SCrypt} interface for hashing passwords using the - * scrypt key derivation function + * Simple {@link SCrypt} interface for hashing passwords using the scrypt key derivation function * and comparing a plain text password to a hashed one. The hashed output is an - * extended implementation of the Modular Crypt Format that also includes the scrypt - * algorithm parameters. - * - * Format: $s0$PARAMS$SALT$KEY. - * + * extended implementation of the Modular Crypt Format that also includes the + * scrypt algorithm parameters. Format: $s0$PARAMS$SALT$KEY. *
- *
PARAMS
32-bit hex integer containing log2(N) (16 bits), r (8 bits), and p (8 bits)
- *
SALT
base64-encoded salt
- *
KEY
base64-encoded derived key
+ *
PARAMS
+ *
32-bit hex integer containing log2(N) (16 bits), r (8 bits), and p (8 + * bits)
+ *
SALT
+ *
base64-encoded salt
+ *
KEY
+ *
base64-encoded derived key
*
+ * s0 identifies version 0 of the scrypt format, using a 128-bit + * salt and 256-bit derived key. * - * s0 identifies version 0 of the scrypt format, using a 128-bit salt and 256-bit derived key. - * - * @author Will Glozer + * @author Will Glozer */ public class SCryptUtil { + /** - * Hash the supplied plaintext password and generate output in the format described - * in {@link SCryptUtil}. - * - * @param passwd Password. - * @param N CPU cost parameter. - * @param r Memory cost parameter. - * @param p Parallelization parameter. + * Hash the supplied plaintext password and generate output in the format + * described in {@link SCryptUtil}. * + * @param passwd + * Password. + * @param N + * CPU cost parameter. + * @param r + * Memory cost parameter. + * @param p + * Parallelization parameter. * @return The hashed password. */ public static String scrypt(String passwd, int N, int r, int p) { @@ -50,8 +54,8 @@ public class SCryptUtil { StringBuilder sb = new StringBuilder((salt.length + derived.length) * 2); sb.append("$s0$").append(params).append('$'); - sb.append(encode(salt)).append('$'); - sb.append(encode(derived)); + sb.append(Base64.getEncoder().encodeToString(salt)).append('$'); + sb.append(Base64.getEncoder().encodeToString(derived)); return sb.toString(); } catch (UnsupportedEncodingException e) { @@ -64,9 +68,10 @@ public class SCryptUtil { /** * Compare the supplied plaintext password to a hashed password. * - * @param passwd Plaintext password. - * @param hashed scrypt hashed password. - * + * @param passwd + * Plaintext password. + * @param hashed + * scrypt hashed password. * @return true if passwd matches hashed value. */ public static boolean check(String passwd, String hashed) { @@ -78,16 +83,18 @@ public class SCryptUtil { } long params = Long.parseLong(parts[2], 16); - byte[] salt = decode(parts[3].toCharArray()); - byte[] derived0 = decode(parts[4].toCharArray()); + byte[] salt = Base64.getDecoder().decode(parts[3]); + byte[] derived0 = Base64.getDecoder().decode(parts[4]); int N = (int) Math.pow(2, params >> 16 & 0xffff); int r = (int) params >> 8 & 0xff; - int p = (int) params & 0xff; + int p = (int) params & 0xff; byte[] derived1 = SCrypt.scrypt(passwd.getBytes("UTF-8"), salt, N, r, p, 32); - if (derived0.length != derived1.length) return false; + if (derived0.length != derived1.length) { + return false; + } int result = 0; for (int i = 0; i < derived0.length; i++) { @@ -103,10 +110,22 @@ public class SCryptUtil { private static int log2(int n) { int log = 0; - if ((n & 0xffff0000 ) != 0) { n >>>= 16; log = 16; } - if (n >= 256) { n >>>= 8; log += 8; } - if (n >= 16 ) { n >>>= 4; log += 4; } - if (n >= 4 ) { n >>>= 2; log += 2; } + if ((n & 0xffff0000) != 0) { + n >>>= 16; + log = 16; + } + if (n >= 256) { + n >>>= 8; + log += 8; + } + if (n >= 16) { + n >>>= 4; + log += 4; + } + if (n >= 4) { + n >>>= 2; + log += 2; + } return log + (n >>> 1); } } diff --git a/tests/com/lambdaworks/crypto/test/SCryptUtilTest.java b/tests/com/lambdaworks/crypto/test/SCryptUtilTest.java index f673657e..2691a826 100644 --- a/tests/com/lambdaworks/crypto/test/SCryptUtilTest.java +++ b/tests/com/lambdaworks/crypto/test/SCryptUtilTest.java @@ -2,10 +2,13 @@ package com.lambdaworks.crypto.test; -import com.lambdaworks.codec.Base64; +import java.util.Base64; + import com.lambdaworks.crypto.SCryptUtil; + import org.junit.Assert; import org.junit.Test; + import static org.junit.Assert.*; public class SCryptUtilTest { @@ -22,8 +25,8 @@ public class SCryptUtilTest { assertEquals(5, parts.length); assertEquals("s0", parts[1]); - Assert.assertEquals(16, Base64.decode(parts[3].toCharArray()).length); - assertEquals(32, Base64.decode(parts[4].toCharArray()).length); + Assert.assertEquals(16, Base64.getDecoder().decode(parts[3]).length); + assertEquals(32, Base64.getDecoder().decode(parts[4]).length); int params = Integer.valueOf(parts[2], 16); -- 2.39.2