/* * Copyright (C) 2009 The Android Open Source Project * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package tests.security; import java.io.IOException; import java.io.InputStream; import java.security.MessageDigest; import java.security.NoSuchAlgorithmException; import junit.framework.TestCase; public abstract class MessageDigestTest extends TestCase { private String digestAlgorithmName; protected MessageDigestTest(String digestAlgorithmName) { super(); this.digestAlgorithmName = digestAlgorithmName; } private MessageDigest digest; private InputStream sourceData; private byte[] checkDigest; @Override protected void setUp() throws Exception { super.setUp(); this.source3 = getLongMessage(1000000); this.digest = getMessageDigest(); this.sourceData = getSourceData(); this.checkDigest = getCheckDigest(); } @Override public void tearDown() throws Exception { super.tearDown(); // This is critical. The MessageDigest tests consume a lot of memory due // to the 1 MB buffers being allocated. We need to make sure all data is // freed after each test. Otherwise the Android runtime simply dies at // some point. source1 = null; source2 = null; source3 = null; expected1 = null; expected2 = null; expected3 = null; digest = null; sourceData.close(); sourceData = null; checkDigest = null; System.gc(); } MessageDigest getMessageDigest() { try { return MessageDigest.getInstance(digestAlgorithmName); } catch (NoSuchAlgorithmException e) { fail("failed to get digest instance: " + e); return null; } } InputStream getSourceData() { InputStream sourceStream = getClass().getResourceAsStream(digestAlgorithmName + ".data"); assertNotNull("digest source data not found: " + digestAlgorithmName, sourceStream); return sourceStream; } byte[] getCheckDigest() { InputStream checkDigestStream = getClass().getResourceAsStream(digestAlgorithmName + ".check"); byte[] checkDigest = new byte[digest.getDigestLength()]; int read = 0; int index = 0; try { while ((read = checkDigestStream.read()) != -1) { checkDigest[index++] = (byte)read; } checkDigestStream.close(); } catch (IOException e) { fail("failed to read digest golden data: " + digestAlgorithmName); } return checkDigest; } public void testMessageDigest1() { byte[] buf = new byte[128]; int read = 0; try { while ((read = sourceData.read(buf)) != -1) { digest.update(buf, 0, read); } sourceData.close(); } catch (IOException e) { fail("failed to read digest data"); } byte[] computedDigest = digest.digest(); assertNotNull("computed digest is is null", computedDigest); assertEquals("digest length mismatch", checkDigest.length, computedDigest.length); for (int i = 0; i < checkDigest.length; i++) { assertEquals("byte " + i + " of computed and check digest differ", checkDigest[i], computedDigest[i]); } } public void testMessageDigest2() { int val; try { while ((val = sourceData.read()) != -1) { digest.update((byte)val); } sourceData.close(); } catch (IOException e) { fail("failed to read digest data"); } byte[] computedDigest = digest.digest(); assertNotNull("computed digest is is null", computedDigest); assertEquals("digest length mismatch", checkDigest.length, computedDigest.length); for (int i = 0; i < checkDigest.length; i++) { assertEquals("byte " + i + " of computed and check digest differ", checkDigest[i], computedDigest[i]); } } /** * Official FIPS180-2 testcases */ protected String source1; protected String source2; protected String source3; protected String expected1; protected String expected2; protected String expected3; String getLongMessage(int length) { StringBuilder sourceBuilder = new StringBuilder(length); for (int i = 0; i < length / 10; i++) { sourceBuilder.append("aaaaaaaaaa"); } return sourceBuilder.toString(); } public void testfips180_2_singleblock() { digest.update(source1.getBytes(), 0, source1.length()); byte[] computedDigest = digest.digest(); assertNotNull("computed digest is null", computedDigest); StringBuilder sb = new StringBuilder(); for (int i = 0; i < computedDigest.length; i++) { String res = Integer.toHexString(computedDigest[i] & 0xFF); sb.append((res.length() == 1 ? "0" : "") + res); } assertEquals("computed and check digest differ", expected1, sb.toString()); } public void testfips180_2_multiblock() { digest.update(source2.getBytes(), 0, source2.length()); byte[] computedDigest = digest.digest(); assertNotNull("computed digest is null", computedDigest); StringBuilder sb = new StringBuilder(); for (int i = 0; i < computedDigest.length; i++) { String res = Integer.toHexString(computedDigest[i] & 0xFF); sb.append((res.length() == 1 ? "0" : "") + res); } assertEquals("computed and check digest differ", expected2, sb.toString()); } public void testfips180_2_longMessage() { digest.update(source3.getBytes(), 0, source3.length()); byte[] computedDigest = digest.digest(); assertNotNull("computed digest is null", computedDigest); StringBuilder sb = new StringBuilder(); for (int i = 0; i < computedDigest.length; i++) { String res = Integer.toHexString(computedDigest[i] & 0xFF); sb.append((res.length() == 1 ? "0" : "") + res); } assertEquals("computed and check digest differ", expected3, sb.toString()); } }