mobile/android/tests/background/junit3/src/healthreport/TestEnvironmentV1HashAppender.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 /* Any copyright is dedicated to the Public Domain.
michael@0 2 http://creativecommons.org/publicdomain/zero/1.0/ */
michael@0 3
michael@0 4 package org.mozilla.gecko.background.healthreport;
michael@0 5
michael@0 6 import java.io.UnsupportedEncodingException;
michael@0 7 import java.security.MessageDigest;
michael@0 8 import java.security.NoSuchAlgorithmException;
michael@0 9 import java.util.Arrays;
michael@0 10 import java.util.LinkedList;
michael@0 11
michael@0 12 import org.mozilla.apache.commons.codec.binary.Base64;
michael@0 13 import org.mozilla.gecko.background.healthreport.EnvironmentV1.EnvironmentAppender;
michael@0 14 import org.mozilla.gecko.background.healthreport.EnvironmentV1.HashAppender;
michael@0 15 import org.mozilla.gecko.background.helpers.FakeProfileTestCase;
michael@0 16 import org.mozilla.gecko.sync.Utils;
michael@0 17
michael@0 18 /**
michael@0 19 * Tests the HashAppender functionality. Note that these tests must be run on an Android
michael@0 20 * device because the SHA-1 native library needs to be loaded.
michael@0 21 */
michael@0 22 public class TestEnvironmentV1HashAppender extends FakeProfileTestCase {
michael@0 23 // input and expected values via: http://oauth.googlecode.com/svn/code/c/liboauth/src/sha1.c
michael@0 24 private final static String[] INPUTS = new String[] {
michael@0 25 "abc",
michael@0 26 "abcdbcdecdefdefgefghfghighijhijkijkljklmklmnlmnomnopnopq",
michael@0 27 "" // To be filled in below.
michael@0 28 };
michael@0 29 static {
michael@0 30 final String baseStr = "01234567";
michael@0 31 final int repetitions = 80;
michael@0 32 final StringBuilder builder = new StringBuilder(baseStr.length() * repetitions);
michael@0 33 for (int i = 0; i < 80; ++i) {
michael@0 34 builder.append(baseStr);
michael@0 35 }
michael@0 36 INPUTS[2] = builder.toString();
michael@0 37 }
michael@0 38
michael@0 39 private final static String[] EXPECTEDS = new String[] {
michael@0 40 "a9993e364706816aba3e25717850c26c9cd0d89d",
michael@0 41 "84983e441c3bd26ebaae4aa1f95129e5e54670f1",
michael@0 42 "dea356a2cddd90c7a7ecedc5ebb563934f460452"
michael@0 43 };
michael@0 44 static {
michael@0 45 for (int i = 0; i < EXPECTEDS.length; ++i) {
michael@0 46 EXPECTEDS[i] = new Base64(-1, null, false).encodeAsString(Utils.hex2Byte(EXPECTEDS[i]));
michael@0 47 }
michael@0 48 }
michael@0 49
michael@0 50 public void testSHA1Hashing() throws Exception {
michael@0 51 for (int i = 0; i < INPUTS.length; ++i) {
michael@0 52 final String input = INPUTS[i];
michael@0 53 final String expected = EXPECTEDS[i];
michael@0 54
michael@0 55 final HashAppender appender = new HashAppender();
michael@0 56 addStringToAppenderInParts(appender, input);
michael@0 57 final String result = appender.toString();
michael@0 58
michael@0 59 assertEquals(expected, result);
michael@0 60 }
michael@0 61 }
michael@0 62
michael@0 63 /**
michael@0 64 * Tests to ensure output is the same as the former MessageDigest implementation (bug 959652).
michael@0 65 */
michael@0 66 public void testAgainstMessageDigestImpl() throws Exception {
michael@0 67 // List.add doesn't allow add(null) so we make a LinkedList here.
michael@0 68 final LinkedList<String> inputs = new LinkedList<String>(Arrays.asList(INPUTS));
michael@0 69 inputs.add(null);
michael@0 70
michael@0 71 for (final String input : inputs) {
michael@0 72 final HashAppender hAppender = new HashAppender();
michael@0 73 final MessageDigestHashAppender mdAppender = new MessageDigestHashAppender();
michael@0 74
michael@0 75 hAppender.append(input);
michael@0 76 mdAppender.append(input);
michael@0 77
michael@0 78 final String hResult = hAppender.toString();
michael@0 79 final String mdResult = mdAppender.toString();
michael@0 80 assertEquals(mdResult, hResult);
michael@0 81 }
michael@0 82 }
michael@0 83
michael@0 84 public void testIntegersAgainstMessageDigestImpl() throws Exception {
michael@0 85 final int[] INPUTS = {Integer.MIN_VALUE, -1337, -42, 0, 42, 1337, Integer.MAX_VALUE};
michael@0 86 for (final int input : INPUTS) {
michael@0 87 final HashAppender hAppender = new HashAppender();
michael@0 88 final MessageDigestHashAppender mdAppender = new MessageDigestHashAppender();
michael@0 89
michael@0 90 hAppender.append(input);
michael@0 91 mdAppender.append(input);
michael@0 92
michael@0 93 final String hResult = hAppender.toString();
michael@0 94 final String mdResult = mdAppender.toString();
michael@0 95 assertEquals(mdResult, hResult);
michael@0 96 }
michael@0 97 }
michael@0 98
michael@0 99 private void addStringToAppenderInParts(final EnvironmentAppender appender, final String input) {
michael@0 100 int substrInd = 0;
michael@0 101 int substrLength = 1;
michael@0 102 while (substrInd < input.length()) {
michael@0 103 final int endInd = Math.min(substrInd + substrLength, input.length());
michael@0 104
michael@0 105 appender.append(input.substring(substrInd, endInd));
michael@0 106
michael@0 107 substrInd = endInd;
michael@0 108 ++substrLength;
michael@0 109 }
michael@0 110 }
michael@0 111
michael@0 112 // --- COPY-PASTA'D CODE, FOR TESTING PURPOSES. ---
michael@0 113 public static class MessageDigestHashAppender extends EnvironmentAppender {
michael@0 114 final MessageDigest hasher;
michael@0 115
michael@0 116 public MessageDigestHashAppender() throws NoSuchAlgorithmException {
michael@0 117 // Note to the security-minded reader: we deliberately use SHA-1 here, not
michael@0 118 // a stronger hash. These identifiers don't strictly need a cryptographic
michael@0 119 // hash function, because there is negligible value in attacking the hash.
michael@0 120 // We use SHA-1 because it's *shorter* -- the exact same reason that Git
michael@0 121 // chose SHA-1.
michael@0 122 hasher = MessageDigest.getInstance("SHA-1");
michael@0 123 }
michael@0 124
michael@0 125 @Override
michael@0 126 public void append(String s) {
michael@0 127 try {
michael@0 128 hasher.update(((s == null) ? "null" : s).getBytes("UTF-8"));
michael@0 129 } catch (UnsupportedEncodingException e) {
michael@0 130 // This can never occur. Thanks, Java.
michael@0 131 }
michael@0 132 }
michael@0 133
michael@0 134 @Override
michael@0 135 public void append(int profileCreation) {
michael@0 136 append(Integer.toString(profileCreation, 10));
michael@0 137 }
michael@0 138
michael@0 139 @Override
michael@0 140 public String toString() {
michael@0 141 // We *could* use ASCII85… but the savings would be negated by the
michael@0 142 // inclusion of JSON-unsafe characters like double-quote.
michael@0 143 return new Base64(-1, null, false).encodeAsString(hasher.digest());
michael@0 144 }
michael@0 145 }
michael@0 146 }

mercurial