SHA1_MessageDigestTest.java revision e98fbf8686c5289bf03fe5c3de7ff82d3a77104d
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/*
19 * TODO
20 * Two testcases, one in testDigestbyteArrayintint01() and one in testUpdatebyteArrayintint01(),
21 * and testUpdatebyteArrayintint03() test are commented out because
22 * current implementations of the MessageDigest and MessageDigestSpi classes
23 * are not compatible with RI; see JIRA ## 1120 and 1148.
24 */
25
26
27package org.apache.harmony.security.tests.provider.crypto;
28
29
30import java.security.MessageDigest;
31import java.security.DigestException;
32
33import junit.framework.Test;
34import junit.framework.TestCase;
35import junit.framework.TestSuite;
36
37
38/**
39 * Tests against methods in MessageDigest class object using SHA1_MessageDigestImpl.
40 */
41
42
43public class SHA1_MessageDigestTest extends TestCase {
44
45
46    /*
47     * Data to compare with reference implementation;
48     * they were received by getting hash values for 11 messages
49     * whose length are in the LENGTHS array below.
50     * Numbers in the LENGTH array cover diapason from 1 to 9999
51     */
52    private static final byte[][] HASHTOCOMPARE = {
53                {
54                (byte) 0xbf, (byte) 0x8b, (byte) 0x45, (byte) 0x30,     //  1 n=0
55                (byte) 0xd8, (byte) 0xd2, (byte) 0x46, (byte) 0xdd,
56                (byte) 0x74, (byte) 0xac, (byte) 0x53, (byte) 0xa1,
57                (byte) 0x34, (byte) 0x71, (byte) 0xbb, (byte) 0xa1,
58                (byte) 0x79, (byte) 0x41, (byte) 0xdf, (byte) 0xf7
59                },{
60                (byte) 0x80, (byte) 0x47, (byte) 0xf8, (byte) 0x24,     //  63 n=1
61                (byte) 0x13, (byte) 0xbf, (byte) 0x4c, (byte) 0x0b,
62                (byte) 0x6e, (byte) 0xfb, (byte) 0x6e, (byte) 0xa0,
63                (byte) 0x91, (byte) 0xce, (byte) 0x08, (byte) 0x22,
64                (byte) 0x02, (byte) 0x0d, (byte) 0x2e, (byte) 0xfc
65                },{
66                (byte) 0x92, (byte) 0xcb, (byte) 0x89, (byte) 0xdf,     //  64 n=2
67                (byte) 0x62, (byte) 0xd9, (byte) 0x00, (byte) 0xb3,
68                (byte) 0x50, (byte) 0xd9, (byte) 0x3e, (byte) 0x42,
69                (byte) 0x25, (byte) 0xca, (byte) 0x6f, (byte) 0x08,
70                (byte) 0x1d, (byte) 0x54, (byte) 0x7a, (byte) 0x28
71                },{
72                (byte) 0x70, (byte) 0x59, (byte) 0xd4, (byte) 0x34,     //  65 n=3
73                (byte) 0xa3, (byte) 0xb6, (byte) 0x28, (byte) 0x25,
74                (byte) 0x5c, (byte) 0x3e, (byte) 0xf8, (byte) 0xc8,
75                (byte) 0x92, (byte) 0x83, (byte) 0x9a, (byte) 0xb3,
76                (byte) 0xb9, (byte) 0x1c, (byte) 0x4f, (byte) 0xe6
77                },{
78                (byte) 0x03, (byte) 0x2f, (byte) 0x1c, (byte) 0x65,     // 639 n=4
79                (byte) 0x44, (byte) 0xcc, (byte) 0x88, (byte) 0xf7,
80                (byte) 0x34, (byte) 0xac, (byte) 0xad, (byte) 0xd3,
81                (byte) 0xc4, (byte) 0xe2, (byte) 0x19, (byte) 0x32,
82                (byte) 0xdf, (byte) 0x6c, (byte) 0x88, (byte) 0xfe
83                },{
84                (byte) 0xe0, (byte) 0x14, (byte) 0xe7, (byte) 0x5d,     // 640 n=5
85                (byte) 0xb2, (byte) 0x8b, (byte) 0xe3, (byte) 0xbf,
86                (byte) 0xf7, (byte) 0x6d, (byte) 0xe0, (byte) 0xe7,
87                (byte) 0x35, (byte) 0xc3, (byte) 0x7e, (byte) 0xd0,
88                (byte) 0xe7, (byte) 0xde, (byte) 0x85, (byte) 0x59
89                },{
90                (byte) 0x8f, (byte) 0xb7, (byte) 0x8c, (byte) 0x50,     // 641 n=6
91                (byte) 0xf5, (byte) 0x57, (byte) 0xb1, (byte) 0x56,
92                (byte) 0x84, (byte) 0xae, (byte) 0x07, (byte) 0x4c,
93                (byte) 0x92, (byte) 0xc7, (byte) 0x05, (byte) 0xe3,
94                (byte) 0xd0, (byte) 0xe8, (byte) 0x98, (byte) 0xe8
95                },{
96                (byte) 0x9c, (byte) 0x59, (byte) 0xea, (byte) 0x66,     // 6399 n=7
97                (byte) 0xad, (byte) 0x49, (byte) 0xa5, (byte) 0xd8,
98                (byte) 0x2b, (byte) 0x15, (byte) 0x7f, (byte) 0x3d,
99                (byte) 0x5c, (byte) 0x8a, (byte) 0x4c, (byte) 0x16,
100                (byte) 0x16, (byte) 0x70, (byte) 0x2c, (byte) 0x16
101                },{
102                (byte) 0x92, (byte) 0x3f, (byte) 0x57, (byte) 0xce,    // 6400 n=8
103                (byte) 0x28, (byte) 0x5d, (byte) 0xb2, (byte) 0xd4,
104                (byte) 0x1e, (byte) 0xdc, (byte) 0x86, (byte) 0x04,
105                (byte) 0x50, (byte) 0x92, (byte) 0x2c, (byte) 0x2e,
106                (byte) 0xaf, (byte) 0x15, (byte) 0xef, (byte) 0x93
107                },{
108                (byte) 0x48, (byte) 0x45, (byte) 0x78, (byte) 0x0a,    // 6401 n=9
109                (byte) 0xf1, (byte) 0x9e, (byte) 0x08, (byte) 0x1f,
110                (byte) 0x32, (byte) 0x43, (byte) 0x1d, (byte) 0xb5,
111                (byte) 0x7b, (byte) 0x70, (byte) 0xdf, (byte) 0xe2,
112                (byte) 0xfd, (byte) 0x38, (byte) 0x50, (byte) 0x39
113                },{
114                (byte) 0xbf, (byte) 0x35, (byte) 0x8f, (byte) 0xbe,    // 9999 n=10
115                (byte) 0x88, (byte) 0xc5, (byte) 0x2d, (byte) 0x54,
116                (byte) 0x4e, (byte) 0x3c, (byte) 0x72, (byte) 0xf6,
117                (byte) 0xef, (byte) 0x68, (byte) 0xc3, (byte) 0x0c,
118                (byte) 0xed, (byte) 0xb7, (byte) 0x0a, (byte) 0x36
119                }
120            };
121
122    /*
123     * array of numbers for which above data were calculated
124     */
125    private static final int[] LENGTHS = { 1, 63,64,65, 639,640,641, 6399,6400,6401, 9999 };
126
127    private static final int DIGESTLENGTH = 20;      // implementation constants
128    private static final int LENGTH       = 100;     //
129
130    private static MessageDigest md;
131
132
133    /*
134     * @see TestCase#setUp()
135     */
136    protected void setUp() throws Exception {
137        super.setUp();
138        md = MessageDigest.getInstance("SHA-1", "Crypto");
139    }
140
141
142    /**
143     * test against the "Object clone()" method;
144     * test checks out that clone object has the same state that its origin
145     */
146    public final void testClone() throws CloneNotSupportedException {
147
148        MessageDigest clone = null;
149
150        byte digest[];            //   implementation variables
151        byte digestClone[];       //
152
153        byte[] bytes = new byte[LENGTH];
154        for (int i = 0; i < bytes.length; i++ ) {
155            bytes[i] = (byte) i;
156        }
157
158        md.update(bytes, 0, LENGTH);
159        clone = (MessageDigest)md.clone();
160        digest      = md.digest();
161        digestClone = clone.digest();
162
163        assertEquals("digest.length != digestClone.length :: " + digestClone.length,
164                      digest.length, digestClone.length);
165        for (int i = 0; i < digest.length; i++) {
166            assertEquals("digest[i] != digestClone[i] : i=" + i, digest[i], digestClone[i]);
167        }
168    }
169
170
171    /**
172     * test against the "byte[] digest()" method;
173     * it checks out that the method always return array of 20 bytes length
174     */
175    public final void testDigest01() {
176
177        byte[] bytes = null;
178
179        for ( int i = 0; i < LENGTH; i++ ) {
180
181            byte[] b = new byte[i];
182            for ( int j = 0; j < b.length; j++ ) {
183                b[j] = (byte) j;
184            }
185
186            md.update(b, 0, b.length);
187            bytes = md.digest();
188            assertEquals("length of digest != DIGESTLENGTH", bytes.length, DIGESTLENGTH);
189            if ( (i & 1) == 0 ) {
190                md.reset();
191            }
192        }
193    }
194
195
196    /**
197     * test against "byte[] digest()" method;
198     * it checks out that for given seed arrays
199     * hash arrays returned by the method are the same as in RI
200     */
201    public final void testDigest02() {
202
203        int i = 0;
204        byte[] results = null;
205
206        for ( int n = 0 ; n < LENGTHS.length; n++ ) {
207
208            for ( int j = 0; j < LENGTHS[n]; j++ ) {
209                md.update((byte)(j +1));
210            }
211            results = md.digest();
212
213            for ( int j = 0; j < DIGESTLENGTH; j++ ) {
214                assertEquals("results[j] != HASHTOCOMPARE[i][j] :: n=" + n + " j=" + j +
215                             " i=" + i, results[j], HASHTOCOMPARE[i][j]);
216            }
217            i++;
218        }
219    }
220
221    /**
222     * test against the "byte[] digest()" method;
223     * it checks out that "digest()" method resets engine
224     */
225    public final void testDigest03() {
226
227        byte[] bytes1 = null;
228        byte[] bytes2 = null;
229
230        for ( int i = 1; i < LENGTH; i++ ) {
231
232            byte[] b = new byte[i];
233            for ( int j = 0; j < b.length; j++ ) {
234                b[j] = (byte) j;
235            }
236
237            md.update(b, 0, b.length);
238            bytes1 = md.digest();
239
240            md.update(b, 0, b.length);
241            bytes2 = md.digest();
242
243            assertEquals("bytes1.length != bytes2.length", bytes1.length, bytes2.length);
244            for (int j = 0; j < DIGESTLENGTH ; j++ ) {
245                assertEquals("no equality for i=" +i + " j=" +j, bytes1[j], bytes2[j]);
246            }
247        }
248    }
249
250
251    /**
252     * test against "int digest(byte[], int, int)" method;
253     * it checks out correct throwing exceptions
254     */
255    public final void testDigestbyteArrayintint01() throws DigestException {
256
257        int offset = 0;
258        int len    = 0;
259
260        // IllegalArgumentException if byte[] is null
261        try {
262            md.digest(null, 0, DIGESTLENGTH);
263            fail("digest(null, 0, DIGESTLENGTH) : No IllegalArgumentException");
264        } catch (IllegalArgumentException e) {
265        }
266
267        // IllegalArgumentException if: (len + offset) <= buf.length
268        for ( offset = -5; offset < 5 ; offset++) {
269
270            try {
271                md.digest(new byte[19], offset, 25);
272                fail("md.digest(new byte[19],offset,25) :: offset=" + offset +
273                           " ::  No IllegalArgumentException");
274            } catch (IllegalArgumentException e) {
275            }
276        }
277        for ( len = -5; len < 5 ; len++) {
278
279            try {
280                md.digest(new byte[19], 25, len);
281                fail("md.digest(new byte[19],25,len) :: len=" + len +
282                     " :: No IllegalArgumentException");
283            } catch (IllegalArgumentException e) {
284            }
285        }
286
287        // DigestException if len < DIGESTLENGTH
288        for ( len = DIGESTLENGTH -1; len >=0 ; len-- ) {
289            try {
290                md.digest(new byte[DIGESTLENGTH], 0, len);
291                fail("md.digest(new byte[DIGESTLENGTH], 0, len) :: len=" +
292                      len + " :: No DigestException");
293            } catch (DigestException e) {
294            }
295        }
296
297        // ArrayIndexOutOfBoundsException if offset < 0
298//        for ( offset = -5;  offset < 0 ; offset++ ) {
299//            try {
300//                md.digest(new byte[30], offset, DIGESTLENGTH);
301//                fail("md.digest(new byte[30], offset, DIGESTLENGTH) :: " +
302//                     "offset=" + offset + " :: no ArrayIndexOutOfBoundsException");
303//            } catch (ArrayIndexOutOfBoundsException e) {
304//            }
305//        }
306    }
307
308
309    /**
310     * test agains "int digest(byte[], int, int)" method
311     * it checks out that for given seed arrays
312     * hash arrays returned by the method are the same as in RI
313     */
314    public final void testDigestbyteArrayintint02() throws DigestException {
315
316        byte[] bytes = null;
317        int i = 0;
318
319        for ( int n = 0 ; n < LENGTHS.length; n++ ) {
320            byte[] results = new byte[DIGESTLENGTH];
321
322            bytes = new byte[LENGTHS[n]];
323            for ( int j = 0; j < bytes.length; j++ ) {
324                bytes[j] = (byte)(j +1);
325            }
326
327            md.update(bytes, 0, bytes.length);
328            md.digest(results, 0, DIGESTLENGTH);
329
330            for ( int j = 0; j < DIGESTLENGTH; j++ ) {
331                assertEquals("results[j] != HASHTOCOMPARE[i][j] :: " + " n=" + n + " j=" +
332                             j + " i=" + i, results[j], HASHTOCOMPARE[i][j]);
333            }
334            i++;
335        }
336    }
337
338
339    /**
340     * test against "int engineDigest(byte[], int, int)" method
341     * it checks out that engine gets reset after call to the method
342     */
343    public final void testDigestbyteArrayintint03() throws DigestException {
344
345        byte[] bytes1 = new byte[DIGESTLENGTH];
346        byte[] bytes2 = new byte[DIGESTLENGTH];
347
348        for ( int n = 1 ; n < LENGTH; n++ ) {
349
350            byte[] b = new byte[n];
351            for ( int j = 0; j < b.length; j++ ) {
352                b[j] = (byte) j;
353            }
354            md.update(b, 0, b.length);
355            md.digest(bytes1, 0, DIGESTLENGTH);
356
357            md.update(b, 0, b.length);
358            md.digest(bytes2, 0, DIGESTLENGTH);
359
360            assertEquals("bytes1.length != bytes2.length", bytes1.length, bytes2.length);
361            for (int j = 0; j < DIGESTLENGTH ; j++ ) {
362                assertEquals("no equality for j=" + j, bytes1[j], bytes2[j]);
363            }
364        }
365    }
366
367
368    /**
369     * test against the "int GetDigestLength()" method;
370     * it checks out that the method returns the same value
371     * regardless of previous calls to other methods
372     */
373    public final void testGetDigestLength() throws DigestException {
374
375        int digestlength = md.getDigestLength();
376
377        byte[] bytes = new byte[LENGTH];
378
379        for (int i = 0; i < LENGTH; i++ ) {
380            bytes[i] = (byte)(i&0xFF);
381        }
382
383        for ( int i = 0; i < 8; i++ ) {
384            switch (i) {
385                case 0: md.digest();
386                        break;
387                case 1: md.digest(bytes, 0, bytes.length);
388                        break;
389                case 2: md.reset();
390                        break;
391                case 3: md.update(bytes[i]);
392                        break;
393                case 4: md.update(bytes, 0, LENGTH);
394                        break;
395                case 5: md.update(bytes[i]);
396                        break;
397                default:
398            }
399            assertEquals(" !=digestlength", md.getDigestLength(), digestlength);
400        }
401    }
402
403
404    /**
405     * test against the "void engineReset()" method;
406     * it checks out that digests returned after proceeding "engineReset()"
407     * is the same as in case of initial digest
408     */
409    public final void testReset() {
410
411        byte[] bytes = new byte[LENGTH];
412        byte[] digest1 = null;
413        byte[] digest2 = null;
414        boolean flag;
415
416        for (int i = 0; i < bytes.length; i++ ) {
417            bytes[i] = (byte)(i&0xFF);
418        }
419
420        digest1 = md.digest();
421        md.update(bytes, 0, LENGTH);
422        md.reset();
423        digest2 = md.digest();
424
425        flag = true;
426        for ( int i = 0; i < digest1.length; i++ ) {
427            flag &= digest1[i] == digest2[i];
428        }
429        assertTrue("digests are not the same", flag);
430    }
431
432
433    /**
434     * test against the "void update(byte)" method;
435     * it checks out that if one digest is update to its forerunner
436     * the digests are not the same
437     */
438    public final void testUpdatebyte() {
439
440        boolean flag;
441        byte[] digest1 = null;
442        byte[] digest2 = null;
443
444        for ( int j = 0; j < LENGTH ; j++) {
445
446            byte[] bytes = new byte[j];
447
448            for (int i = 0; i < bytes.length; i++ ) {
449                bytes[i] = (byte)(i&0xFF);
450            }
451
452            md.update(bytes, 0, bytes.length);
453            digest1 = md.digest();
454            md.update(bytes, 0, bytes.length);
455            md.update((byte) 0);
456            digest2 = md.digest();
457
458            flag = true;
459            for ( int i = 0; i < digest1.length; i++ ) {
460                flag &= digest1[i] == digest2[i];
461            }
462            assertFalse("digests are the same", flag);
463        }
464    }
465
466
467    /**
468     * test against the "void update(byte[], int, int)" method;
469     * it checks out throwing exceptions
470     */
471    public final void testUpdatebyteArrayintint01() {
472
473        // IllegalArgumentException if byte[] is null
474        try {
475            md.update(null, 0, 0);
476            fail("TESTCASE1 : update(null, 0, 0) :: No IllegalArgumentException");
477        } catch (IllegalArgumentException e) {
478        }
479
480        // ArrayIndexOutOfBoundsException if len>0 && offset < 0
481//        try {
482//            md.update(new byte[0], -1, 1);
483//            fail("update(new byte[0], -1, 1) : No ArrayIndexOutOfBoundsException");
484//        } catch (ArrayIndexOutOfBoundsException e) {
485//        }
486
487        // IllegalArgumentException if (offset + len) >= input.length
488        try {
489            md.update(new byte[1], 0, 2);
490            fail("update(new byte[1], 0, 2) : No IllegalArgumentException");
491        } catch (IllegalArgumentException e) {
492        }
493    }
494
495
496    /**
497     * test against the "void update(byte[],int,int)" method;
498     * it checks out that two sequential digest,
499     * second is byte array update to first,
500     * are different, provided length of the byte array > 0.
501     */
502    public final void testUpdatebyteArrayintint02() {
503
504        boolean flag;
505        byte[] digest1 = null;
506        byte[] digest2 = null;
507
508        for ( int j = 0; j < LENGTH ; j++) {
509
510            byte[] bytes = new byte[j];
511
512            for (int i = 0; i < bytes.length; i++ ) {
513                bytes[i] = (byte)(i&0xFF);
514            }
515
516            md.update((byte) 0);
517            digest1 = md.digest();
518            md.update((byte) 0);
519            md.update(bytes, 0, bytes.length);
520            digest2 = md.digest();
521
522            flag = true;
523            for ( int i = 0; i < digest1.length; i++ ) {
524                flag &= digest1[i] == digest2[i];
525            }
526            if ( j == 0 ) {
527                // no update if byte[] of zero length
528                assertTrue("ATTENTION: digests are not the same", flag);
529            } else {
530                assertFalse("ATTENTION: digests are the same; j=" +j, flag);
531            }
532        }
533    }
534
535
536    /**
537     * test against the "void update(byte[], int, int)" method;
538     * it checks that if the "len" argument <=0 the method just returns with
539     * no affect to MessageDigestImp object (note that such behavior complies with RI).
540     */
541//    public final void testUpdatebyteArrayintint03() {
542//
543//        boolean flag;
544//        byte[] digest1 = null;
545//        byte[] digest2 = null;
546//
547//        for ( int j = 0; j < LENGTH ; j++) {
548//
549//            byte[] bytes = new byte[j];
550//
551//            for (int i = 0; i < bytes.length; i++ ) {
552//                bytes[i] = (byte)(i&0xFF);
553//            }
554//
555//            md.update(bytes, 0, bytes.length);
556//            digest1 = md.digest();
557//            md.update(bytes, 0, bytes.length);
558//            md.update(new byte[1], 0, -1);
559//            md.update(new byte[1], 0, 0);
560//            digest2 = md.digest();
561//
562//            assertTrue("digest's lengths are different : length1=" +
563//                       digest1.length + " length2=" + digest2.length,
564//                       digest1.length == digest2.length );
565//
566//            for ( int i = 0; i < digest1.length ; i++ ) {
567//                assertTrue("different digests : i=" +i +
568//                           " digest1[i]=" + digest1[i] + " digest2[i]=" + digest2[i],
569//                           digest1[i] == digest2[i] );
570//            }
571//        }
572//    }
573
574
575    public static Test suite() {
576        return new TestSuite(SHA1_MessageDigestTest.class);
577    }
578
579 }
580