SHA1ImplTest.java revision 561ee011997c6c2f1befbfaa9d5f0a99771c1d63
1/*
2 *  Licensed to the Apache Software Foundation (ASF) under one or more
3 *  contributor license agreements.  See the NOTICE file distributed with
4 *  this work for additional information regarding copyright ownership.
5 *  The ASF licenses this file to You under the Apache License, Version 2.0
6 *  (the "License"); you may not use this file except in compliance with
7 *  the License.  You may obtain a copy of the License at
8 *
9 *     http://www.apache.org/licenses/LICENSE-2.0
10 *
11 *  Unless required by applicable law or agreed to in writing, software
12 *  distributed under the License is distributed on an "AS IS" BASIS,
13 *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14 *  See the License for the specific language governing permissions and
15 *  limitations under the License.
16 */
17
18
19package org.apache.harmony.security.tests.provider.crypto;
20
21
22import java.io.UnsupportedEncodingException;
23
24import junit.framework.Test;
25import junit.framework.TestCase;
26import junit.framework.TestSuite;
27
28import org.apache.harmony.security.provider.crypto.SHA1Impl;
29
30import java.security.MessageDigest;
31
32
33/**
34 * Tests against methods in SHA1Impl class.
35 * The input data and results of computing are defined in Secure Hash Standard,
36 * see http://www.itl.nist.gov/fipspubs/fip180-1.htm
37 */
38
39
40public class SHA1ImplTest extends TestCase {
41
42
43    // SHA1Data constant used in below methods
44    private static final int INDEX = SHA1Impl.BYTES_OFFSET;
45
46    private static MessageDigest md;
47
48
49    /*
50     * @see TestCase#setUp()
51     */
52    protected void setUp() throws Exception {
53        super.setUp();
54        md = MessageDigest.getInstance("SHA-1", "Crypto");
55    }
56
57
58    /*
59     * The test checks out that for given three byte input
60     * a value returned by SHA1Impl is equal to both :
61     * - one defined in the Standard and
62     * - one calculated with alternative computation algorithm defined in the Standard.
63     */
64    public final void testOneBlockMessage() {
65
66        int[] words = new int[INDEX +6];	// working array to compute hash
67
68        // values defined in examples in Secure Hash Standard
69        int[] hash1 = {0x67452301, 0xEFCDAB89, 0x98BADCFE, 0x10325476, 0xC3D2E1F0 };
70        int[] hash  = {0xA9993E36, 0x4706816A, 0xBA3E2571, 0x7850C26C, 0x9CD0D89D };
71
72        for (int i = 0; i < words.length; i++ ) {
73            words[i] = 0;
74        }
75        words[0]  = 0x61626380;    // constants from Secure Hash Standard
76        words[15] = 0x00000018;
77
78        alternateHash(words, hash1);
79
80
81        md.update(new byte[]{0x61,0x62,0x63});
82        byte[] dgst = md.digest();
83
84        for ( int k = 0; k < 5; k++ ) {
85            int i = k*4;
86
87            int j = ((dgst[i  ]&0xff)<<24) | ((dgst[i+1]&0xff)<<16) |
88                    ((dgst[i+2]&0xff)<<8 ) | (dgst[i+3]&0xff)  ;
89
90            assertTrue("false1: k=" + k + " hash1[k]=" + Integer.toHexString(hash1[k]),
91                       hash[k] == hash1[k] );
92
93            assertTrue("false2: k=" + k + " j=" + Integer.toHexString(j), hash[k] == j );
94        }
95    }
96
97
98
99
100    /*
101     * The test checks out that SHA1Impl computes correct value
102     * if data supplied takes exactly fourteen words of sixteen word buffer.
103     */
104    public final void testMultiBlockMessage() throws UnsupportedEncodingException {
105
106        // values defined in examples in Secure Hash Standard
107        int[] hash  = {0x84983e44, 0x1c3bd26e, 0xbaae4aa1, 0xf95129e5, 0xe54670f1 };
108
109        // string defined in examples in Secure Hash Standard
110        md.update("abcdbcdecdefdefgefghfghighijhijkijkljklmklmnlmnomnopnopq".getBytes("UTF-8"));
111        byte[] dgst = md.digest();
112
113        for ( int k = 0; k < 5; k++ ) {
114            int i = k*4;
115
116                int j = ((dgst[i  ]&0xff)<<24) | ((dgst[i+1]&0xff)<<16) |
117                        ((dgst[i+2]&0xff)<<8 ) | (dgst[i+3]&0xff)  ;
118
119            assertTrue("false: k=" + k + " j=" + Integer.toHexString(j), hash[k] == j );
120        }
121    }
122
123
124    /*
125     * The test checks out that SHA1Impl returns correct values
126     * for four different cases of infilling internal buffer and computing intermediate hash.
127     */
128    public final void testLongMessage() {
129
130        // values defined in examples in Secure Hash Standard
131        int[] hash  = {0x34aa973c, 0xd4c4daa4, 0xf61eeb2b, 0xdbad2731, 0x6534016f };
132
133        byte msgs[][] = new byte[][] { {0x61},
134                                       {0x61, 0x61},
135                                       {0x61, 0x61, 0x61},
136                                       {0x61, 0x61, 0x61, 0x61} };
137
138        int lngs[] = new int[]{1000000, 500000, 333333, 250000};
139
140        for ( int n = 0; n < 4; n++ ) {
141
142            for ( int i = 0; i < lngs[n]; i++) {
143                md.update(msgs[n]);
144            }
145            if ( n == 2 ) {
146                md.update(msgs[0]);
147            }
148
149            byte[] dgst = md.digest();
150            for ( int k = 0; k < 5; k++ ) {
151                int i = k*4;
152
153                int j = ((dgst[i  ]&0xff)<<24) | ((dgst[i+1]&0xff)<<16) |
154                        ((dgst[i+2]&0xff)<<8 ) | (dgst[i+3]&0xff)  ;
155
156                assertTrue("false: n =" + n + "  k=" + k + " j" + Integer.toHexString(j),
157                            hash[k] == j );
158            }
159        }
160    }
161
162
163    /**
164     * implements alternative algorithm described in the SECURE HASH STANDARD
165     */
166    private void alternateHash(int[] bufW, int[] hash) {
167
168        // constants defined in Secure Hash Standard
169        final int[] K = {
170
171            0x5A827999, 0x5A827999, 0x5A827999, 0x5A827999,
172            0x5A827999, 0x5A827999, 0x5A827999, 0x5A827999,
173            0x5A827999, 0x5A827999, 0x5A827999, 0x5A827999,
174            0x5A827999, 0x5A827999, 0x5A827999, 0x5A827999,
175            0x5A827999, 0x5A827999, 0x5A827999, 0x5A827999,
176
177            0x6ED9EBA1, 0x6ED9EBA1, 0x6ED9EBA1, 0x6ED9EBA1,
178            0x6ED9EBA1, 0x6ED9EBA1, 0x6ED9EBA1, 0x6ED9EBA1,
179            0x6ED9EBA1, 0x6ED9EBA1, 0x6ED9EBA1, 0x6ED9EBA1,
180            0x6ED9EBA1, 0x6ED9EBA1, 0x6ED9EBA1, 0x6ED9EBA1,
181            0x6ED9EBA1, 0x6ED9EBA1, 0x6ED9EBA1, 0x6ED9EBA1,
182
183            0x8F1BBCDC, 0x8F1BBCDC, 0x8F1BBCDC, 0x8F1BBCDC,
184            0x8F1BBCDC, 0x8F1BBCDC, 0x8F1BBCDC, 0x8F1BBCDC,
185            0x8F1BBCDC, 0x8F1BBCDC, 0x8F1BBCDC, 0x8F1BBCDC,
186            0x8F1BBCDC, 0x8F1BBCDC, 0x8F1BBCDC, 0x8F1BBCDC,
187            0x8F1BBCDC, 0x8F1BBCDC, 0x8F1BBCDC, 0x8F1BBCDC,
188
189            0xCA62C1D6, 0xCA62C1D6, 0xCA62C1D6, 0xCA62C1D6,
190            0xCA62C1D6, 0xCA62C1D6, 0xCA62C1D6, 0xCA62C1D6,
191            0xCA62C1D6, 0xCA62C1D6, 0xCA62C1D6, 0xCA62C1D6,
192            0xCA62C1D6, 0xCA62C1D6, 0xCA62C1D6, 0xCA62C1D6,
193            0xCA62C1D6, 0xCA62C1D6, 0xCA62C1D6, 0xCA62C1D6
194        };
195
196        int  a = hash[0]; //0x67452301 ;
197        int  b = hash[1]; //0xEFCDAB89 ;
198        int  c = hash[2]; //0x98BADCFE ;
199        int  d = hash[3]; //0x10325476 ;
200        int  e = hash[4]; //0xC3D2E1F0 ;
201
202        // implementation constant and variables
203
204        final int MASK = 0x0000000F;
205        int temp;
206        int s;
207        int tmp;
208
209        // computation defined in Secure Hash Standard
210        for ( int t = 0 ; t < 80 ; t++ ) {
211
212            s = t & MASK;
213
214            if ( t >= 16) {
215
216                tmp = bufW[ (s+13)&MASK ] ^ bufW[(s+8)&MASK ] ^ bufW[ (s+2)&MASK ] ^ bufW[s];
217                bufW[s] = ( tmp<<1 ) | ( tmp>>>31 );
218            }
219
220            temp = ( a << 5 ) | ( a >>> 27 );
221
222            if ( t < 20 ) {
223                temp += ( b & c ) | ( (~b) & d ) ;
224            } else if ( t < 40 ) {
225                temp += b ^ c ^ d ;
226            } else if ( t < 60 ) {
227                temp += ( b & c ) | ( b & d ) | ( c & d ) ;
228            } else {
229                temp += b ^ c ^ d ;
230            }
231
232            temp += e + bufW[s] + K[t] ;
233            e = d;
234            d = c;
235            c = ( b<<30 ) | ( b>>>2 ) ;
236            b = a;
237            a = temp;
238        }
239        hash[0] += a;
240        hash[1] += b;
241        hash[2] += c;
242        hash[3] += d;
243        hash[4] += e;
244    }
245
246
247    public static Test suite() {
248        return new TestSuite(SHA1ImplTest.class);
249    }
250
251    public static void main(String[] args) {
252        junit.textui.TestRunner.run(suite());
253    }
254
255 }
256