001: /*
002: * Licensed to the Apache Software Foundation (ASF) under one or more
003: * contributor license agreements. See the NOTICE file distributed with
004: * this work for additional information regarding copyright ownership.
005: * The ASF licenses this file to You under the Apache License, Version 2.0
006: * (the "License"); you may not use this file except in compliance with
007: * the License. You may obtain a copy of the License at
008: *
009: * http://www.apache.org/licenses/LICENSE-2.0
010: *
011: * Unless required by applicable law or agreed to in writing, software
012: * distributed under the License is distributed on an "AS IS" BASIS,
013: * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
014: * See the License for the specific language governing permissions and
015: * limitations under the License.
016: */
017:
018: package org.apache.harmony.security.tests.provider.crypto;
019:
020: import junit.framework.Test;
021: import junit.framework.TestCase;
022: import junit.framework.TestSuite;
023:
024: import org.apache.harmony.security.provider.crypto.SHA1Impl;
025:
026: import java.security.MessageDigest;
027:
028: /**
029: * Tests against methods in SHA1Impl class.
030: * The input data and results of computing are defined in Secure Hash Standard,
031: * see http://www.itl.nist.gov/fipspubs/fip180-1.htm
032: */
033:
034: public class SHA1ImplTest extends TestCase {
035:
036: // SHA1Data constant used in below methods
037: private static final int INDEX = SHA1Impl.BYTES_OFFSET;
038:
039: private static MessageDigest md;
040:
041: /*
042: * @see TestCase#setUp()
043: */
044: protected void setUp() throws Exception {
045: super .setUp();
046: md = MessageDigest.getInstance("SHA-1", "Crypto");
047: }
048:
049: /*
050: * The test checks out that for given three byte input
051: * a value returned by SHA1Impl is equal to both :
052: * - one defined in the Standard and
053: * - one calculated with alternative computation algorithm defined in the Standard.
054: */
055: public final void testOneBlockMessage() {
056:
057: int[] words = new int[INDEX + 6]; // working array to compute hash
058:
059: // values defined in examples in Secure Hash Standard
060: int[] hash1 = { 0x67452301, 0xEFCDAB89, 0x98BADCFE, 0x10325476,
061: 0xC3D2E1F0 };
062: int[] hash = { 0xA9993E36, 0x4706816A, 0xBA3E2571, 0x7850C26C,
063: 0x9CD0D89D };
064:
065: for (int i = 0; i < words.length; i++) {
066: words[i] = 0;
067: }
068: words[0] = 0x61626380; // constants from Secure Hash Standard
069: words[15] = 0x00000018;
070:
071: alternateHash(words, hash1);
072:
073: md.update(new byte[] { 0x61, 0x62, 0x63 });
074: byte[] dgst = md.digest();
075:
076: for (int k = 0; k < 5; k++) {
077: int i = k * 4;
078:
079: int j = ((dgst[i] & 0xff) << 24)
080: | ((dgst[i + 1] & 0xff) << 16)
081: | ((dgst[i + 2] & 0xff) << 8)
082: | (dgst[i + 3] & 0xff);
083:
084: assertTrue("false1: k=" + k + " hash1[k]="
085: + Integer.toHexString(hash1[k]),
086: hash[k] == hash1[k]);
087:
088: assertTrue("false2: k=" + k + " j="
089: + Integer.toHexString(j), hash[k] == j);
090: }
091: }
092:
093: /*
094: * The test checks out that SHA1Impl computes correct value
095: * if data supplied takes exactly fourteen words of sixteen word buffer.
096: */
097: public final void testMultiBlockMessage() {
098:
099: // values defined in examples in Secure Hash Standard
100: int[] hash = { 0x84983e44, 0x1c3bd26e, 0xbaae4aa1, 0xf95129e5,
101: 0xe54670f1 };
102:
103: // string defined in examples in Secure Hash Standard
104: md
105: .update("abcdbcdecdefdefgefghfghighijhijkijkljklmklmnlmnomnopnopq"
106: .getBytes());
107: byte[] dgst = md.digest();
108:
109: for (int k = 0; k < 5; k++) {
110: int i = k * 4;
111:
112: int j = ((dgst[i] & 0xff) << 24)
113: | ((dgst[i + 1] & 0xff) << 16)
114: | ((dgst[i + 2] & 0xff) << 8)
115: | (dgst[i + 3] & 0xff);
116:
117: assertTrue(
118: "false: k=" + k + " j=" + Integer.toHexString(j),
119: hash[k] == j);
120: }
121: }
122:
123: /*
124: * The test checks out that SHA1Impl returns correct values
125: * for four different cases of infilling internal buffer and computing intermediate hash.
126: */
127: public final void testLongMessage() {
128:
129: // values defined in examples in Secure Hash Standard
130: int[] hash = { 0x34aa973c, 0xd4c4daa4, 0xf61eeb2b, 0xdbad2731,
131: 0x6534016f };
132:
133: byte msgs[][] = new byte[][] { { 0x61 }, { 0x61, 0x61 },
134: { 0x61, 0x61, 0x61 }, { 0x61, 0x61, 0x61, 0x61 } };
135:
136: int lngs[] = new int[] { 1000000, 500000, 333333, 250000 };
137:
138: for (int n = 0; n < 4; n++) {
139:
140: for (int i = 0; i < lngs[n]; i++) {
141: md.update(msgs[n]);
142: }
143: if (n == 2) {
144: md.update(msgs[0]);
145: }
146:
147: byte[] dgst = md.digest();
148: for (int k = 0; k < 5; k++) {
149: int i = k * 4;
150:
151: int j = ((dgst[i] & 0xff) << 24)
152: | ((dgst[i + 1] & 0xff) << 16)
153: | ((dgst[i + 2] & 0xff) << 8)
154: | (dgst[i + 3] & 0xff);
155:
156: assertTrue("false: n =" + n + " k=" + k + " j"
157: + Integer.toHexString(j), hash[k] == j);
158: }
159: }
160: }
161:
162: /**
163: * implements alternative algorithm described in the SECURE HASH STANDARD
164: */
165: private void alternateHash(int[] bufW, int[] hash) {
166:
167: // constants defined in Secure Hash Standard
168: final int[] K = {
169:
170: 0x5A827999, 0x5A827999, 0x5A827999, 0x5A827999, 0x5A827999,
171: 0x5A827999, 0x5A827999, 0x5A827999, 0x5A827999,
172: 0x5A827999, 0x5A827999, 0x5A827999, 0x5A827999,
173: 0x5A827999, 0x5A827999, 0x5A827999, 0x5A827999,
174: 0x5A827999, 0x5A827999, 0x5A827999,
175:
176: 0x6ED9EBA1, 0x6ED9EBA1, 0x6ED9EBA1, 0x6ED9EBA1,
177: 0x6ED9EBA1, 0x6ED9EBA1, 0x6ED9EBA1, 0x6ED9EBA1,
178: 0x6ED9EBA1, 0x6ED9EBA1, 0x6ED9EBA1, 0x6ED9EBA1,
179: 0x6ED9EBA1, 0x6ED9EBA1, 0x6ED9EBA1, 0x6ED9EBA1,
180: 0x6ED9EBA1, 0x6ED9EBA1, 0x6ED9EBA1, 0x6ED9EBA1,
181:
182: 0x8F1BBCDC, 0x8F1BBCDC, 0x8F1BBCDC, 0x8F1BBCDC,
183: 0x8F1BBCDC, 0x8F1BBCDC, 0x8F1BBCDC, 0x8F1BBCDC,
184: 0x8F1BBCDC, 0x8F1BBCDC, 0x8F1BBCDC, 0x8F1BBCDC,
185: 0x8F1BBCDC, 0x8F1BBCDC, 0x8F1BBCDC, 0x8F1BBCDC,
186: 0x8F1BBCDC, 0x8F1BBCDC, 0x8F1BBCDC, 0x8F1BBCDC,
187:
188: 0xCA62C1D6, 0xCA62C1D6, 0xCA62C1D6, 0xCA62C1D6,
189: 0xCA62C1D6, 0xCA62C1D6, 0xCA62C1D6, 0xCA62C1D6,
190: 0xCA62C1D6, 0xCA62C1D6, 0xCA62C1D6, 0xCA62C1D6,
191: 0xCA62C1D6, 0xCA62C1D6, 0xCA62C1D6, 0xCA62C1D6,
192: 0xCA62C1D6, 0xCA62C1D6, 0xCA62C1D6, 0xCA62C1D6 };
193:
194: int a = hash[0]; //0x67452301 ;
195: int b = hash[1]; //0xEFCDAB89 ;
196: int c = hash[2]; //0x98BADCFE ;
197: int d = hash[3]; //0x10325476 ;
198: int e = hash[4]; //0xC3D2E1F0 ;
199:
200: // implementation constant and variables
201:
202: final int MASK = 0x0000000F;
203: int temp;
204: int s;
205: int tmp;
206:
207: // computation defined in Secure Hash Standard
208: for (int t = 0; t < 80; t++) {
209:
210: s = t & MASK;
211:
212: if (t >= 16) {
213:
214: tmp = bufW[(s + 13) & MASK] ^ bufW[(s + 8) & MASK]
215: ^ bufW[(s + 2) & MASK] ^ bufW[s];
216: bufW[s] = (tmp << 1) | (tmp >>> 31);
217: }
218:
219: temp = (a << 5) | (a >>> 27);
220:
221: if (t < 20) {
222: temp += (b & c) | ((~b) & d);
223: } else if (t < 40) {
224: temp += b ^ c ^ d;
225: } else if (t < 60) {
226: temp += (b & c) | (b & d) | (c & d);
227: } else {
228: temp += b ^ c ^ d;
229: }
230:
231: temp += e + bufW[s] + K[t];
232: e = d;
233: d = c;
234: c = (b << 30) | (b >>> 2);
235: b = a;
236: a = temp;
237: }
238: hash[0] += a;
239: hash[1] += b;
240: hash[2] += c;
241: hash[3] += d;
242: hash[4] += e;
243: }
244:
245: public static Test suite() {
246: return new TestSuite(SHA1ImplTest.class);
247: }
248:
249: public static void main(String[] args) {
250: junit.textui.TestRunner.run(suite());
251: }
252:
253: }
|