mirror of
https://gitlab.winehq.org/wine/wine-gecko.git
synced 2024-09-13 09:24:08 -07:00
Bug 915312 - Part 3: Add NativeCrypto Java interface. r=nalexander
This commit is contained in:
parent
e2a9e2ac3b
commit
a531628bad
@ -534,6 +534,7 @@ sync_java_files = [
|
||||
'background/healthreport/upload/ObsoleteDocumentTracker.java',
|
||||
'background/healthreport/upload/SubmissionClient.java',
|
||||
'background/healthreport/upload/SubmissionPolicy.java',
|
||||
'background/nativecode/NativeCrypto.java',
|
||||
'background/preferences/PreferenceFragment.java',
|
||||
'background/preferences/PreferenceManagerCompat.java',
|
||||
'browserid/ASNUtils.java',
|
||||
|
27
mobile/android/base/background/nativecode/NativeCrypto.java
Normal file
27
mobile/android/base/background/nativecode/NativeCrypto.java
Normal file
@ -0,0 +1,27 @@
|
||||
/* This Source Code Form is subject to the terms of the Mozilla Public
|
||||
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
|
||||
|
||||
package org.mozilla.gecko.background.nativecode;
|
||||
|
||||
import org.mozilla.gecko.mozglue.RobocopTarget;
|
||||
|
||||
import java.security.GeneralSecurityException;
|
||||
|
||||
@RobocopTarget
|
||||
public class NativeCrypto {
|
||||
static {
|
||||
System.loadLibrary("mozglue");
|
||||
}
|
||||
|
||||
/**
|
||||
* Wrapper to perform PBKDF2-HMAC-SHA-256 in native code.
|
||||
*/
|
||||
public native static byte[] pbkdf2SHA256(byte[] password, byte[] salt, int c, int dkLen)
|
||||
throws GeneralSecurityException;
|
||||
|
||||
/**
|
||||
* Wrapper to perform SHA-1 in native code.
|
||||
*/
|
||||
public native static byte[] sha1(byte[] str);
|
||||
}
|
@ -4,30 +4,14 @@
|
||||
|
||||
package org.mozilla.gecko.sync.crypto;
|
||||
|
||||
import java.io.UnsupportedEncodingException;
|
||||
import java.security.GeneralSecurityException;
|
||||
import java.util.Arrays;
|
||||
|
||||
import javax.crypto.Mac;
|
||||
import javax.crypto.SecretKey;
|
||||
import javax.crypto.SecretKeyFactory;
|
||||
import javax.crypto.spec.PBEKeySpec;
|
||||
import javax.crypto.ShortBufferException;
|
||||
import javax.crypto.spec.SecretKeySpec;
|
||||
|
||||
public class PBKDF2 {
|
||||
public static byte[] pbkdf2SHA1(byte[] password, byte[] salt, int c, int dkLen)
|
||||
throws GeneralSecurityException {
|
||||
// Won't work on API level 8, but this is trivial.
|
||||
SecretKeyFactory factory = SecretKeyFactory.getInstance("PBKDF2WithHmacSHA1");
|
||||
PBEKeySpec keySpec;
|
||||
try {
|
||||
keySpec = new PBEKeySpec(new String(password, "UTF-8").toCharArray(), salt, c, dkLen * 8);
|
||||
} catch (UnsupportedEncodingException e) {
|
||||
throw new GeneralSecurityException(e);
|
||||
}
|
||||
SecretKey key = factory.generateSecret(keySpec);
|
||||
return key.getEncoded();
|
||||
}
|
||||
|
||||
public static byte[] pbkdf2SHA256(byte[] password, byte[] salt, int c, int dkLen)
|
||||
throws GeneralSecurityException {
|
||||
final String algorithm = "HmacSHA256";
|
||||
@ -36,12 +20,18 @@ public class PBKDF2 {
|
||||
prf.init(keyspec);
|
||||
|
||||
int hLen = prf.getMacLength();
|
||||
|
||||
byte U_r[] = new byte[hLen];
|
||||
byte U_i[] = new byte[salt.length + 4];
|
||||
byte scratch[] = new byte[hLen];
|
||||
|
||||
int l = Math.max(dkLen, hLen);
|
||||
int r = dkLen - (l - 1) * hLen;
|
||||
byte T[] = new byte[l * hLen];
|
||||
int ti_offset = 0;
|
||||
for (int i = 1; i <= l; i++) {
|
||||
F(T, ti_offset, prf, salt, c, i);
|
||||
Arrays.fill(U_r, (byte) 0);
|
||||
F(T, ti_offset, prf, salt, c, i, U_r, U_i, scratch);
|
||||
ti_offset += hLen;
|
||||
}
|
||||
|
||||
@ -55,17 +45,18 @@ public class PBKDF2 {
|
||||
return T;
|
||||
}
|
||||
|
||||
private static void F(byte[] dest, int offset, Mac prf, byte[] S, int c, int blockIndex) {
|
||||
private static void F(byte[] dest, int offset, Mac prf, byte[] S, int c, int blockIndex, byte U_r[], byte U_i[], byte[] scratch)
|
||||
throws ShortBufferException, IllegalStateException {
|
||||
final int hLen = prf.getMacLength();
|
||||
byte U_r[] = new byte[hLen];
|
||||
|
||||
// U0 = S || INT (i);
|
||||
byte U_i[] = new byte[S.length + 4];
|
||||
System.arraycopy(S, 0, U_i, 0, S.length);
|
||||
INT(U_i, S.length, blockIndex);
|
||||
|
||||
for (int i = 0; i < c; i++) {
|
||||
U_i = prf.doFinal(U_i);
|
||||
prf.update(U_i);
|
||||
prf.doFinal(scratch, 0);
|
||||
U_i = scratch;
|
||||
xor(U_r, U_i);
|
||||
}
|
||||
|
||||
|
@ -43,6 +43,7 @@ BACKGROUND_TESTS_JAVA_FILES := \
|
||||
src/helpers/DBHelpers.java \
|
||||
src/helpers/DBProviderTestCase.java \
|
||||
src/helpers/FakeProfileTestCase.java \
|
||||
src/nativecode/test/TestNativeCrypto.java \
|
||||
src/sync/helpers/BookmarkHelpers.java \
|
||||
src/sync/helpers/DefaultBeginDelegate.java \
|
||||
src/sync/helpers/DefaultCleanDelegate.java \
|
||||
|
@ -0,0 +1,102 @@
|
||||
/* Any copyright is dedicated to the Public Domain.
|
||||
http://creativecommons.org/publicdomain/zero/1.0/ */
|
||||
|
||||
package org.mozilla.gecko.background.nativecode.test;
|
||||
|
||||
import java.io.UnsupportedEncodingException;
|
||||
import java.security.GeneralSecurityException;
|
||||
|
||||
import junit.framework.TestCase;
|
||||
|
||||
import org.mozilla.gecko.background.nativecode.NativeCrypto;
|
||||
import org.mozilla.gecko.sync.Utils;
|
||||
|
||||
// Test vectors from
|
||||
// SHA-256: <https://github.com/ircmaxell/PHP-PasswordLib/blob/master/test/Data/Vectors/pbkdf2-draft-josefsson-sha256.test-vectors>
|
||||
// <https://gitorious.org/scrypt/nettle-scrypt/blobs/37c0d5288e991604fe33dba2f1724986a8dddf56/testsuite/pbkdf2-test.c>
|
||||
public class TestNativeCrypto extends TestCase {
|
||||
|
||||
public final void testPBKDF2SHA256A() throws UnsupportedEncodingException, GeneralSecurityException {
|
||||
String p = "password";
|
||||
String s = "salt";
|
||||
int dkLen = 32;
|
||||
|
||||
checkPBKDF2SHA256(p, s, 1, dkLen, "120fb6cffcf8b32c43e7225256c4f837a86548c92ccc35480805987cb70be17b");
|
||||
checkPBKDF2SHA256(p, s, 4096, dkLen, "c5e478d59288c841aa530db6845c4c8d962893a001ce4e11a4963873aa98134a");
|
||||
}
|
||||
|
||||
public final void testPBKDF2SHA256B() throws UnsupportedEncodingException, GeneralSecurityException {
|
||||
String p = "passwordPASSWORDpassword";
|
||||
String s = "saltSALTsaltSALTsaltSALTsaltSALTsalt";
|
||||
int dkLen = 40;
|
||||
|
||||
checkPBKDF2SHA256(p, s, 4096, dkLen, "348c89dbcbd32b2f32d814b8116e84cf2b17347ebc1800181c4e2a1fb8dd53e1c635518c7dac47e9");
|
||||
}
|
||||
|
||||
public final void testPBKDF2SHA256scryptA() throws UnsupportedEncodingException, GeneralSecurityException {
|
||||
String p = "passwd";
|
||||
String s = "salt";
|
||||
int dkLen = 64;
|
||||
|
||||
checkPBKDF2SHA256(p, s, 1, dkLen, "55ac046e56e3089fec1691c22544b605f94185216dde0465e68b9d57c20dacbc49ca9cccf179b645991664b39d77ef317c71b845b1e30bd509112041d3a19783");
|
||||
}
|
||||
|
||||
public final void testPBKDF2SHA256scryptB() throws UnsupportedEncodingException, GeneralSecurityException {
|
||||
String p = "Password";
|
||||
String s = "NaCl";
|
||||
int dkLen = 64;
|
||||
|
||||
checkPBKDF2SHA256(p, s, 80000, dkLen, "4ddcd8f60b98be21830cee5ef22701f9641a4418d04c0414aeff08876b34ab56a1d425a1225833549adb841b51c9b3176a272bdebba1d078478f62b397f33c8d");
|
||||
}
|
||||
|
||||
public final void testPBKDF2SHA256C() throws UnsupportedEncodingException, GeneralSecurityException {
|
||||
String p = "pass\0word";
|
||||
String s = "sa\0lt";
|
||||
int dkLen = 16;
|
||||
|
||||
checkPBKDF2SHA256(p, s, 4096, dkLen, "89b69d0516f829893c696226650a8687");
|
||||
}
|
||||
|
||||
/*
|
||||
// This test takes two or three minutes to run, so we don't.
|
||||
public final void testPBKDF2SHA256D() throws UnsupportedEncodingException, GeneralSecurityException {
|
||||
String p = "password";
|
||||
String s = "salt";
|
||||
int dkLen = 32;
|
||||
|
||||
checkPBKDF2SHA256(p, s, 16777216, dkLen, "cf81c66fe8cfc04d1f31ecb65dab4089f7f179e89b3b0bcb17ad10e3ac6eba46");
|
||||
}
|
||||
*/
|
||||
|
||||
public final void testTimePBKDF2SHA256() throws UnsupportedEncodingException, GeneralSecurityException {
|
||||
checkPBKDF2SHA256("password", "salt", 80000, 32, null);
|
||||
}
|
||||
|
||||
private void checkPBKDF2SHA256(String p, String s, int c, int dkLen,
|
||||
final String expectedStr)
|
||||
throws GeneralSecurityException, UnsupportedEncodingException {
|
||||
long start = System.currentTimeMillis();
|
||||
byte[] key = NativeCrypto.pbkdf2SHA256(p.getBytes("US-ASCII"), s.getBytes("US-ASCII"), c, dkLen);
|
||||
assertNotNull(key);
|
||||
|
||||
long end = System.currentTimeMillis();
|
||||
|
||||
System.err.println("SHA-256 " + c + " took " + (end - start) + "ms");
|
||||
if (expectedStr == null) {
|
||||
return;
|
||||
}
|
||||
|
||||
assertEquals(dkLen, Utils.hex2Byte(expectedStr).length);
|
||||
assertExpectedBytes(expectedStr, key);
|
||||
}
|
||||
|
||||
private void assertExpectedBytes(final String expectedStr, byte[] key) {
|
||||
assertEquals(expectedStr, Utils.byte2Hex(key));
|
||||
byte[] expected = Utils.hex2Byte(expectedStr);
|
||||
|
||||
assertEquals(expected.length, key.length);
|
||||
for (int i = 0; i < key.length; i++) {
|
||||
assertEquals(expected[i], key[i]);
|
||||
}
|
||||
}
|
||||
}
|
Loading…
Reference in New Issue
Block a user