-// 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 <a href="http://www.tarsnap.com/scrypt/scrypt.pdf"/>scrypt</a>
- * key derivation function. This class will attempt to load a native library
- * containing the optimized C implementation from
- * <a href="http://www.tarsnap.com/scrypt.html">http://www.tarsnap.com/scrypt.html<a> and
- * fall back to the pure Java version if that fails.
+ * An implementation of the <a
+ * href="http://www.tarsnap.com/scrypt/scrypt.pdf"/>scrypt</a> key derivation
+ * function. This class will attempt to load a native library containing the
+ * optimized C implementation from <a
+ * href="http://www.tarsnap.com/scrypt.html">http
+ * ://www.tarsnap.com/scrypt.html<a> 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 <a href="http://www.tarsnap.com/scrypt/scrypt.pdf"/>scrypt KDF</a>.
- * 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 <a
+ * href="http://www.tarsnap.com/scrypt/scrypt.pdf"/>scrypt KDF</a>. 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 <a href="http://www.tarsnap.com/scrypt/scrypt.pdf"/>scrypt KDF</a> using
- * the code from <a href="http://www.tarsnap.com/scrypt.html">http://www.tarsnap.com/scrypt.html<a>.
- *
- * @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 <a
+ * href="http://www.tarsnap.com/scrypt/scrypt.pdf"/>scrypt KDF</a> using the
+ * code from <a
+ * href="http://www.tarsnap.com/scrypt.html">http://www.tarsnap.
+ * com/scrypt.html<a>.
*
+ * @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 <a href="http://www.tarsnap.com/scrypt/scrypt.pdf"/>scrypt KDF</a>.
- *
- * @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 <a
+ * href="http://www.tarsnap.com/scrypt/scrypt.pdf"/>scrypt KDF</a>.
*
+ * @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 (r <= 0) {
+ throw new IllegalArgumentException("Parameter r zero or negative");
+ }
+ if (p <= 0) {
+ throw new IllegalArgumentException("Parameter p zero or negative");
+ }
- 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);
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;
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);
- }
-
- for (i = 0; i < 16; ++i) B32[i] = x[i] + B32[i];
+ 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++) {
- 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);
}
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;