mobile/android/base/tests/testNativeCrypto.java

Wed, 31 Dec 2014 07:22:50 +0100

author
Michael Schloh von Bennewitz <michael@schloh.com>
date
Wed, 31 Dec 2014 07:22:50 +0100
branch
TOR_BUG_3246
changeset 4
fc2d59ddac77
permissions
-rw-r--r--

Correct previous dual key logic pending first delivery installment.

michael@0 1 /* This Source Code Form is subject to the terms of the Mozilla Public
michael@0 2 * License, v. 2.0. If a copy of the MPL was not distributed with this
michael@0 3 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
michael@0 4
michael@0 5 package org.mozilla.gecko.tests;
michael@0 6
michael@0 7 import static org.mozilla.gecko.tests.helpers.AssertionHelper.fAssertArrayEquals;
michael@0 8 import static org.mozilla.gecko.tests.helpers.AssertionHelper.fAssertEquals;
michael@0 9 import static org.mozilla.gecko.tests.helpers.AssertionHelper.fAssertNotNull;
michael@0 10 import static org.mozilla.gecko.tests.helpers.AssertionHelper.fFail;
michael@0 11
michael@0 12 import java.io.UnsupportedEncodingException;
michael@0 13 import java.security.GeneralSecurityException;
michael@0 14 import java.security.MessageDigest;
michael@0 15 import java.security.NoSuchAlgorithmException;
michael@0 16
michael@0 17 import org.mozilla.gecko.background.nativecode.NativeCrypto;
michael@0 18 import org.mozilla.gecko.sync.Utils;
michael@0 19 import org.mozilla.gecko.tests.helpers.GeckoHelper;
michael@0 20
michael@0 21 import android.os.SystemClock;
michael@0 22
michael@0 23 /**
michael@0 24 * Tests the Java wrapper over native implementations of crypto code. Test vectors from:
michael@0 25 * * PBKDF2SHA256:
michael@0 26 * - <https://github.com/ircmaxell/PHP-PasswordLib/blob/master/test/Data/Vectors/pbkdf2-draft-josefsson-sha256.test-vectors>
michael@0 27 - <https://gitorious.org/scrypt/nettle-scrypt/blobs/37c0d5288e991604fe33dba2f1724986a8dddf56/testsuite/pbkdf2-test.c>
michael@0 28 * SHA-1:
michael@0 29 - <http://oauth.googlecode.com/svn/code/c/liboauth/src/sha1.c>
michael@0 30 */
michael@0 31 public class testNativeCrypto extends UITest {
michael@0 32 private final static String LOGTAG = "testNativeCrypto";
michael@0 33
michael@0 34 /**
michael@0 35 * Robocop supports only a single test function per test class. Therefore, we
michael@0 36 * have a single top-level test function that dispatches to sub-tests,
michael@0 37 * accepting that we might fail part way through the cycle. Proper JUnit 3
michael@0 38 * testing can't land soon enough!
michael@0 39 *
michael@0 40 * @throws Exception
michael@0 41 */
michael@0 42 public void test() throws Exception {
michael@0 43 // This test could complete very quickly. If it completes too soon, the
michael@0 44 // minidumps directory may not be created before the process is
michael@0 45 // taken down, causing bug 722166. But we can't run the test and then block
michael@0 46 // for Gecko:Ready, since it may have arrived before we block. So we wait.
michael@0 47 // Again, JUnit 3 can't land soon enough!
michael@0 48 GeckoHelper.blockForReady();
michael@0 49
michael@0 50 _testPBKDF2SHA256A();
michael@0 51 _testPBKDF2SHA256B();
michael@0 52 _testPBKDF2SHA256C();
michael@0 53 _testPBKDF2SHA256scryptA();
michael@0 54 _testPBKDF2SHA256scryptB();
michael@0 55 _testPBKDF2SHA256InvalidLenArg();
michael@0 56
michael@0 57 _testSHA1();
michael@0 58 _testSHA1AgainstMessageDigest();
michael@0 59 }
michael@0 60
michael@0 61 public void _testPBKDF2SHA256A() throws UnsupportedEncodingException, GeneralSecurityException {
michael@0 62 final String p = "password";
michael@0 63 final String s = "salt";
michael@0 64 final int dkLen = 32;
michael@0 65
michael@0 66 checkPBKDF2SHA256(p, s, 1, dkLen, "120fb6cffcf8b32c43e7225256c4f837a86548c92ccc35480805987cb70be17b");
michael@0 67 checkPBKDF2SHA256(p, s, 4096, dkLen, "c5e478d59288c841aa530db6845c4c8d962893a001ce4e11a4963873aa98134a");
michael@0 68 }
michael@0 69
michael@0 70 public void _testPBKDF2SHA256B() throws UnsupportedEncodingException, GeneralSecurityException {
michael@0 71 final String p = "passwordPASSWORDpassword";
michael@0 72 final String s = "saltSALTsaltSALTsaltSALTsaltSALTsalt";
michael@0 73 final int dkLen = 40;
michael@0 74
michael@0 75 checkPBKDF2SHA256(p, s, 4096, dkLen, "348c89dbcbd32b2f32d814b8116e84cf2b17347ebc1800181c4e2a1fb8dd53e1c635518c7dac47e9");
michael@0 76 }
michael@0 77
michael@0 78 public void _testPBKDF2SHA256scryptA() throws UnsupportedEncodingException, GeneralSecurityException {
michael@0 79 final String p = "passwd";
michael@0 80 final String s = "salt";
michael@0 81 final int dkLen = 64;
michael@0 82
michael@0 83 checkPBKDF2SHA256(p, s, 1, dkLen, "55ac046e56e3089fec1691c22544b605f94185216dde0465e68b9d57c20dacbc49ca9cccf179b645991664b39d77ef317c71b845b1e30bd509112041d3a19783");
michael@0 84 }
michael@0 85
michael@0 86 public void _testPBKDF2SHA256scryptB() throws UnsupportedEncodingException, GeneralSecurityException {
michael@0 87 final String p = "Password";
michael@0 88 final String s = "NaCl";
michael@0 89 final int dkLen = 64;
michael@0 90
michael@0 91 checkPBKDF2SHA256(p, s, 80000, dkLen, "4ddcd8f60b98be21830cee5ef22701f9641a4418d04c0414aeff08876b34ab56a1d425a1225833549adb841b51c9b3176a272bdebba1d078478f62b397f33c8d");
michael@0 92 }
michael@0 93
michael@0 94 public void _testPBKDF2SHA256C() throws UnsupportedEncodingException, GeneralSecurityException {
michael@0 95 final String p = "pass\0word";
michael@0 96 final String s = "sa\0lt";
michael@0 97 final int dkLen = 16;
michael@0 98
michael@0 99 checkPBKDF2SHA256(p, s, 4096, dkLen, "89b69d0516f829893c696226650a8687");
michael@0 100 }
michael@0 101
michael@0 102 public void _testPBKDF2SHA256InvalidLenArg() throws UnsupportedEncodingException, GeneralSecurityException {
michael@0 103 final String p = "password";
michael@0 104 final String s = "salt";
michael@0 105 final int c = 1;
michael@0 106 final int dkLen = -1; // Should always be positive.
michael@0 107
michael@0 108 try {
michael@0 109 final byte[] key = NativeCrypto.pbkdf2SHA256(p.getBytes("US-ASCII"), s.getBytes("US-ASCII"), c, dkLen);
michael@0 110 fFail("Expected sha256 to throw with negative dkLen argument.");
michael@0 111 } catch (IllegalArgumentException e) { } // Expected.
michael@0 112 }
michael@0 113
michael@0 114 private void _testSHA1() throws UnsupportedEncodingException {
michael@0 115 final String[] inputs = new String[] {
michael@0 116 "abc",
michael@0 117 "abcdbcdecdefdefgefghfghighijhijkijkljklmklmnlmnomnopnopq",
michael@0 118 "" // To be filled in below.
michael@0 119 };
michael@0 120 final String baseStr = "01234567";
michael@0 121 final int repetitions = 80;
michael@0 122 final StringBuilder builder = new StringBuilder(baseStr.length() * repetitions);
michael@0 123 for (int i = 0; i < 80; ++i) {
michael@0 124 builder.append(baseStr);
michael@0 125 }
michael@0 126 inputs[2] = builder.toString();
michael@0 127
michael@0 128 final String[] expecteds = new String[] {
michael@0 129 "a9993e364706816aba3e25717850c26c9cd0d89d",
michael@0 130 "84983e441c3bd26ebaae4aa1f95129e5e54670f1",
michael@0 131 "dea356a2cddd90c7a7ecedc5ebb563934f460452"
michael@0 132 };
michael@0 133
michael@0 134 for (int i = 0; i < inputs.length; ++i) {
michael@0 135 final byte[] input = inputs[i].getBytes("US-ASCII");
michael@0 136 final String expected = expecteds[i];
michael@0 137
michael@0 138 final byte[] actual = NativeCrypto.sha1(input);
michael@0 139 fAssertNotNull("Hashed value is non-null", actual);
michael@0 140 assertExpectedBytes(expected, actual);
michael@0 141 }
michael@0 142 }
michael@0 143
michael@0 144 /**
michael@0 145 * Test to ensure the output of our SHA1 algo is the same as MessageDigest's. This is important
michael@0 146 * because we intend to replace MessageDigest in FHR with this SHA-1 algo (bug 959652).
michael@0 147 */
michael@0 148 private void _testSHA1AgainstMessageDigest() throws UnsupportedEncodingException,
michael@0 149 NoSuchAlgorithmException {
michael@0 150 final String[] inputs = {
michael@0 151 "password",
michael@0 152 "saranghae",
michael@0 153 "aoeusnthaoeusnthaoeusnth \0 12345098765432109876_!"
michael@0 154 };
michael@0 155
michael@0 156 final MessageDigest digest = MessageDigest.getInstance("SHA-1");
michael@0 157 for (final String input : inputs) {
michael@0 158 final byte[] inputBytes = input.getBytes("US-ASCII");
michael@0 159
michael@0 160 final byte[] mdBytes = digest.digest(inputBytes);
michael@0 161 final byte[] ourBytes = NativeCrypto.sha1(inputBytes);
michael@0 162 fAssertArrayEquals("MessageDigest hash is the same as NativeCrypto SHA-1 hash", mdBytes, ourBytes);
michael@0 163 }
michael@0 164 }
michael@0 165
michael@0 166 private void checkPBKDF2SHA256(String p, String s, int c, int dkLen, final String expectedStr)
michael@0 167 throws GeneralSecurityException, UnsupportedEncodingException {
michael@0 168 final long start = SystemClock.elapsedRealtime();
michael@0 169
michael@0 170 final byte[] key = NativeCrypto.pbkdf2SHA256(p.getBytes("US-ASCII"), s.getBytes("US-ASCII"), c, dkLen);
michael@0 171 fAssertNotNull("Hash result is non-null", key);
michael@0 172
michael@0 173 final long end = SystemClock.elapsedRealtime();
michael@0 174 dumpLog(LOGTAG, "SHA-256 " + c + " took " + (end - start) + "ms");
michael@0 175
michael@0 176 if (expectedStr == null) {
michael@0 177 return;
michael@0 178 }
michael@0 179
michael@0 180 fAssertEquals("Hash result is the appropriate length", dkLen,
michael@0 181 Utils.hex2Byte(expectedStr).length);
michael@0 182 assertExpectedBytes(expectedStr, key);
michael@0 183 }
michael@0 184
michael@0 185 private void assertExpectedBytes(final String expectedStr, byte[] key) {
michael@0 186 fAssertEquals("Expected string matches hash result", expectedStr, Utils.byte2Hex(key));
michael@0 187 final byte[] expected = Utils.hex2Byte(expectedStr);
michael@0 188
michael@0 189 fAssertEquals("Expected byte array length matches key length", expected.length, key.length);
michael@0 190 fAssertArrayEquals("Expected byte array matches key byte array", expected, key);
michael@0 191 }
michael@0 192 }

mercurial