Return-Path: Delivered-To: apmail-incubator-harmony-commits-archive@www.apache.org Received: (qmail 28834 invoked from network); 2 Nov 2006 11:21:43 -0000 Received: from hermes.apache.org (HELO mail.apache.org) (140.211.11.2) by minotaur.apache.org with SMTP; 2 Nov 2006 11:21:43 -0000 Received: (qmail 30327 invoked by uid 500); 2 Nov 2006 11:21:53 -0000 Delivered-To: apmail-incubator-harmony-commits-archive@incubator.apache.org Received: (qmail 30291 invoked by uid 500); 2 Nov 2006 11:21:53 -0000 Mailing-List: contact harmony-commits-help@incubator.apache.org; run by ezmlm Precedence: bulk List-Help: List-Unsubscribe: List-Post: List-Id: Reply-To: harmony-dev@incubator.apache.org Delivered-To: mailing list harmony-commits@incubator.apache.org Received: (qmail 30280 invoked by uid 99); 2 Nov 2006 11:21:53 -0000 Received: from herse.apache.org (HELO herse.apache.org) (140.211.11.133) by apache.org (qpsmtpd/0.29) with ESMTP; Thu, 02 Nov 2006 03:21:53 -0800 X-ASF-Spam-Status: No, hits=-9.4 required=10.0 tests=ALL_TRUSTED,NO_REAL_NAME X-Spam-Check-By: apache.org Received: from [140.211.11.3] (HELO eris.apache.org) (140.211.11.3) by apache.org (qpsmtpd/0.29) with ESMTP; Thu, 02 Nov 2006 03:21:40 -0800 Received: by eris.apache.org (Postfix, from userid 65534) id 25D811A9846; Thu, 2 Nov 2006 03:21:16 -0800 (PST) Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit Subject: svn commit: r470330 - in /incubator/harmony/enhanced/classlib/trunk/modules/security/src/test/impl/java/org/apache/harmony/security/tests/provider/crypto: SHA1_MessageDigestTest.java SHA1withDSA_SignatureTest.java Date: Thu, 02 Nov 2006 11:21:15 -0000 To: harmony-commits@incubator.apache.org From: smishura@apache.org X-Mailer: svnmailer-1.1.0 Message-Id: <20061102112116.25D811A9846@eris.apache.org> X-Virus-Checked: Checked by ClamAV on apache.org Author: smishura Date: Thu Nov 2 03:21:12 2006 New Revision: 470330 URL: http://svn.apache.org/viewvc?view=rev&rev=470330 Log: Apply patch for HARMONY-2026 ([classlib][security] crypto provider: tests against classes developed) Added: incubator/harmony/enhanced/classlib/trunk/modules/security/src/test/impl/java/org/apache/harmony/security/tests/provider/crypto/SHA1_MessageDigestTest.java (with props) incubator/harmony/enhanced/classlib/trunk/modules/security/src/test/impl/java/org/apache/harmony/security/tests/provider/crypto/SHA1withDSA_SignatureTest.java (with props) Added: incubator/harmony/enhanced/classlib/trunk/modules/security/src/test/impl/java/org/apache/harmony/security/tests/provider/crypto/SHA1_MessageDigestTest.java URL: http://svn.apache.org/viewvc/incubator/harmony/enhanced/classlib/trunk/modules/security/src/test/impl/java/org/apache/harmony/security/tests/provider/crypto/SHA1_MessageDigestTest.java?view=auto&rev=470330 ============================================================================== --- incubator/harmony/enhanced/classlib/trunk/modules/security/src/test/impl/java/org/apache/harmony/security/tests/provider/crypto/SHA1_MessageDigestTest.java (added) +++ incubator/harmony/enhanced/classlib/trunk/modules/security/src/test/impl/java/org/apache/harmony/security/tests/provider/crypto/SHA1_MessageDigestTest.java Thu Nov 2 03:21:12 2006 @@ -0,0 +1,583 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You 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. + */ + +/* + * TODO + * Two tescases, one in testDigestbyteArrayintint01() and one in testUpdatebyteArrayintint01(), + * and testUpdatebyteArrayintint03() test are commented out because + * current implementations of the MessageDigest and MessageDigestSpi classes + * are not compatibile with RI; see JIRA ## 1120 and 1148. + */ + + +package org.apache.harmony.security.tests.provider.crypto; + + +import java.security.MessageDigest; +import java.security.DigestException; + +import junit.framework.Test; +import junit.framework.TestCase; +import junit.framework.TestSuite; + + +/** + * Tests against methods in MessageDigest class object using SHA1_MessageDigestImpl. + */ + + +public class SHA1_MessageDigestTest extends TestCase { + + + /* + * Data to compare with reference implementation; + * they were received by getting hash values for 11 messages + * whose length are in the LENGTHS array below. + * Numbers in the LENGTH array cover diapason from 1 to 9999 + */ + private static final byte[][] HASHTOCOMPARE = { + { + (byte) 0xbf, (byte) 0x8b, (byte) 0x45, (byte) 0x30, // 1 n=0 + (byte) 0xd8, (byte) 0xd2, (byte) 0x46, (byte) 0xdd, + (byte) 0x74, (byte) 0xac, (byte) 0x53, (byte) 0xa1, + (byte) 0x34, (byte) 0x71, (byte) 0xbb, (byte) 0xa1, + (byte) 0x79, (byte) 0x41, (byte) 0xdf, (byte) 0xf7 + },{ + (byte) 0x80, (byte) 0x47, (byte) 0xf8, (byte) 0x24, // 63 n=1 + (byte) 0x13, (byte) 0xbf, (byte) 0x4c, (byte) 0x0b, + (byte) 0x6e, (byte) 0xfb, (byte) 0x6e, (byte) 0xa0, + (byte) 0x91, (byte) 0xce, (byte) 0x08, (byte) 0x22, + (byte) 0x02, (byte) 0x0d, (byte) 0x2e, (byte) 0xfc + },{ + (byte) 0x92, (byte) 0xcb, (byte) 0x89, (byte) 0xdf, // 64 n=2 + (byte) 0x62, (byte) 0xd9, (byte) 0x00, (byte) 0xb3, + (byte) 0x50, (byte) 0xd9, (byte) 0x3e, (byte) 0x42, + (byte) 0x25, (byte) 0xca, (byte) 0x6f, (byte) 0x08, + (byte) 0x1d, (byte) 0x54, (byte) 0x7a, (byte) 0x28 + },{ + (byte) 0x70, (byte) 0x59, (byte) 0xd4, (byte) 0x34, // 65 n=3 + (byte) 0xa3, (byte) 0xb6, (byte) 0x28, (byte) 0x25, + (byte) 0x5c, (byte) 0x3e, (byte) 0xf8, (byte) 0xc8, + (byte) 0x92, (byte) 0x83, (byte) 0x9a, (byte) 0xb3, + (byte) 0xb9, (byte) 0x1c, (byte) 0x4f, (byte) 0xe6 + },{ + (byte) 0x03, (byte) 0x2f, (byte) 0x1c, (byte) 0x65, // 639 n=4 + (byte) 0x44, (byte) 0xcc, (byte) 0x88, (byte) 0xf7, + (byte) 0x34, (byte) 0xac, (byte) 0xad, (byte) 0xd3, + (byte) 0xc4, (byte) 0xe2, (byte) 0x19, (byte) 0x32, + (byte) 0xdf, (byte) 0x6c, (byte) 0x88, (byte) 0xfe + },{ + (byte) 0xe0, (byte) 0x14, (byte) 0xe7, (byte) 0x5d, // 640 n=5 + (byte) 0xb2, (byte) 0x8b, (byte) 0xe3, (byte) 0xbf, + (byte) 0xf7, (byte) 0x6d, (byte) 0xe0, (byte) 0xe7, + (byte) 0x35, (byte) 0xc3, (byte) 0x7e, (byte) 0xd0, + (byte) 0xe7, (byte) 0xde, (byte) 0x85, (byte) 0x59 + },{ + (byte) 0x8f, (byte) 0xb7, (byte) 0x8c, (byte) 0x50, // 641 n=6 + (byte) 0xf5, (byte) 0x57, (byte) 0xb1, (byte) 0x56, + (byte) 0x84, (byte) 0xae, (byte) 0x07, (byte) 0x4c, + (byte) 0x92, (byte) 0xc7, (byte) 0x05, (byte) 0xe3, + (byte) 0xd0, (byte) 0xe8, (byte) 0x98, (byte) 0xe8 + },{ + (byte) 0x9c, (byte) 0x59, (byte) 0xea, (byte) 0x66, // 6399 n=7 + (byte) 0xad, (byte) 0x49, (byte) 0xa5, (byte) 0xd8, + (byte) 0x2b, (byte) 0x15, (byte) 0x7f, (byte) 0x3d, + (byte) 0x5c, (byte) 0x8a, (byte) 0x4c, (byte) 0x16, + (byte) 0x16, (byte) 0x70, (byte) 0x2c, (byte) 0x16 + },{ + (byte) 0x92, (byte) 0x3f, (byte) 0x57, (byte) 0xce, // 6400 n=8 + (byte) 0x28, (byte) 0x5d, (byte) 0xb2, (byte) 0xd4, + (byte) 0x1e, (byte) 0xdc, (byte) 0x86, (byte) 0x04, + (byte) 0x50, (byte) 0x92, (byte) 0x2c, (byte) 0x2e, + (byte) 0xaf, (byte) 0x15, (byte) 0xef, (byte) 0x93 + },{ + (byte) 0x48, (byte) 0x45, (byte) 0x78, (byte) 0x0a, // 6401 n=9 + (byte) 0xf1, (byte) 0x9e, (byte) 0x08, (byte) 0x1f, + (byte) 0x32, (byte) 0x43, (byte) 0x1d, (byte) 0xb5, + (byte) 0x7b, (byte) 0x70, (byte) 0xdf, (byte) 0xe2, + (byte) 0xfd, (byte) 0x38, (byte) 0x50, (byte) 0x39 + },{ + (byte) 0xbf, (byte) 0x35, (byte) 0x8f, (byte) 0xbe, // 9999 n=10 + (byte) 0x88, (byte) 0xc5, (byte) 0x2d, (byte) 0x54, + (byte) 0x4e, (byte) 0x3c, (byte) 0x72, (byte) 0xf6, + (byte) 0xef, (byte) 0x68, (byte) 0xc3, (byte) 0x0c, + (byte) 0xed, (byte) 0xb7, (byte) 0x0a, (byte) 0x36 + } + }; + + /* + * array of numbers for which above data were calculated + */ + private static final int[] LENGTHS = { 1, 63,64,65, 639,640,641, 6399,6400,6401, 9999 }; + + private static final int DIGESTLENGTH = 20; // implementation constants + private static final int LENGTH = 100; // + + private static MessageDigest md; + + + /* + * @see TestCase#setUp() + */ + protected void setUp() throws Exception { + super.setUp(); + md = MessageDigest.getInstance("SHA-1", "Crypto"); + } + + + /** + * test against the "Object clone()" method; + * test checks out that clone object has the same state that its origin + */ + public final void testClone() throws CloneNotSupportedException { + + MessageDigest clone = null; + + byte digest[]; // implementation variables + byte digestClone[]; // + + byte[] bytes = new byte[LENGTH]; + for (int i = 0; i < bytes.length; i++ ) { + bytes[i] = (byte) i; + } + + md.update(bytes, 0, LENGTH); + clone = (MessageDigest)md.clone(); + digest = md.digest(); + digestClone = clone.digest(); + + assertEquals("digest.length != digestClone.length :: " + digestClone.length, + digest.length, digestClone.length); + for (int i = 0; i < digest.length; i++) { + assertEquals("digest[i] != digestClone[i] : i=" + i, digest[i], digestClone[i]); + } + } + + + /** + * test against the "byte[] digest()" method; + * it checks out that the method always return array of 20 bytes length + */ + public final void testDigest01() { + + byte[] bytes = null; + + for ( int i = 0; i < LENGTH; i++ ) { + + byte[] b = new byte[i]; + for ( int j = 0; j < b.length; j++ ) { + b[j] = (byte) j; + } + + md.update(b, 0, b.length); + bytes = md.digest(); + assertEquals("length of digest != DIGESTLENGTH", bytes.length, DIGESTLENGTH); + if ( (i & 1) == 0 ) { + md.reset(); + } + } + } + + + /** + * test against "byte[] digest()" method; + * it checks out that for given seed arrays + * hash arrays returned by the method are the same as in RI + */ + public final void testDigest02() { + + int i = 0; + byte[] results = null; + + for ( int n = 0 ; n < LENGTHS.length; n++ ) { + + for ( int j = 0; j < LENGTHS[n]; j++ ) { + md.update((byte)(j +1)); + } + results = md.digest(); + + for ( int j = 0; j < DIGESTLENGTH; j++ ) { + assertEquals("results[j] != HASHTOCOMPARE[i][j] :: n=" + n + " j=" + j + + " i=" + i, results[j], HASHTOCOMPARE[i][j]); + } + i++; + } + } + + /** + * test against the "byte[] digest()" method; + * it checks out that "digest()" method resets engine + */ + public final void testDigest03() { + + byte[] bytes1 = null; + byte[] bytes2 = null; + + for ( int i = 1; i < LENGTH; i++ ) { + + byte[] b = new byte[i]; + for ( int j = 0; j < b.length; j++ ) { + b[j] = (byte) j; + } + + md.update(b, 0, b.length); + bytes1 = md.digest(); + + md.update(b, 0, b.length); + bytes2 = md.digest(); + + assertEquals("bytes1.length != bytes2.length", bytes1.length, bytes2.length); + for (int j = 0; j < DIGESTLENGTH ; j++ ) { + assertEquals("no equality for i=" +i + " j=" +j, bytes1[j], bytes2[j]); + } + } + } + + + /** + * test against "int digest(byte[], int, int)" method; + * it checks out correct throwing exceptions + */ + public final void testDigestbyteArrayintint01() throws DigestException { + + int offset = 0; + int len = 0; + + // IllegalArgumentException if byte[] is null + try { + md.digest(null, 0, DIGESTLENGTH); + fail("digest(null, 0, DIGESTLENGTH) : No IllegalArgumentException"); + } catch (IllegalArgumentException e) { + } + + // IllegalArgumentException if: (len + offset) <= buf.length + for ( offset = -5; offset < 5 ; offset++) { + + try { + md.digest(new byte[19], offset, 25); + fail("md.digest(new byte[19],offset,25) :: offset=" + offset + + " :: No IllegalArgumentException"); + } catch (IllegalArgumentException e) { + } + } + for ( len = -5; len < 5 ; len++) { + + try { + md.digest(new byte[19], 25, len); + fail("md.digest(new byte[19],25,len) :: len=" + len + + " :: No IllegalArgumentException"); + } catch (IllegalArgumentException e) { + } + } + + // DigestException if len < DIGESTLENGTH + for ( len = DIGESTLENGTH -1; len >=0 ; len-- ) { + try { + md.digest(new byte[DIGESTLENGTH], 0, len); + fail("md.digest(new byte[DIGESTLENGTH], 0, len) :: len=" + + len + " :: No DigestException"); + } catch (DigestException e) { + } + } + + // ArrayIndexOutOfBoundsException if offset < 0 +// for ( offset = -5; offset < 0 ; offset++ ) { +// try { +// md.digest(new byte[30], offset, DIGESTLENGTH); +// fail("md.digest(new byte[30], offset, DIGESTLENGTH) :: " + +// "offset=" + offset + " :: no ArrayIndexOutOfBoundsException"); +// } catch (ArrayIndexOutOfBoundsException e) { +// } +// } + } + + + /** + * test agains "int digest(byte[], int, int)" method + * it checks out that for given seed arrays + * hash arrays returned by the method are the same as in RI + */ + public final void testDigestbyteArrayintint02() throws DigestException { + + byte[] bytes = null; + int i = 0; + + for ( int n = 0 ; n < LENGTHS.length; n++ ) { + byte[] results = new byte[DIGESTLENGTH]; + + bytes = new byte[LENGTHS[n]]; + for ( int j = 0; j < bytes.length; j++ ) { + bytes[j] = (byte)(j +1); + } + + md.update(bytes, 0, bytes.length); + md.digest(results, 0, DIGESTLENGTH); + + for ( int j = 0; j < DIGESTLENGTH; j++ ) { + assertEquals("results[j] != HASHTOCOMPARE[i][j] :: " + " n=" + n + " j=" + + j + " i=" + i, results[j], HASHTOCOMPARE[i][j]); + } + i++; + } + } + + + /** + * test against "int engineDigest(byte[], int, int)" method + * it checks out that engine gets reset after call to the method + */ + public final void testDigestbyteArrayintint03() throws DigestException { + + byte[] bytes1 = new byte[DIGESTLENGTH]; + byte[] bytes2 = new byte[DIGESTLENGTH]; + + for ( int n = 1 ; n < LENGTH; n++ ) { + + byte[] b = new byte[n]; + for ( int j = 0; j < b.length; j++ ) { + b[j] = (byte) j; + } + md.update(b, 0, b.length); + md.digest(bytes1, 0, DIGESTLENGTH); + + md.update(b, 0, b.length); + md.digest(bytes2, 0, DIGESTLENGTH); + + assertEquals("bytes1.length != bytes2.length", bytes1.length, bytes2.length); + for (int j = 0; j < DIGESTLENGTH ; j++ ) { + assertEquals("no equality for j=" + j, bytes1[j], bytes2[j]); + } + } + } + + + /** + * test against the "int GetDigestLength()" method; + * it checks out that the method returns the same value + * regardless of previous calls to other methods + */ + public final void testGetDigestLength() throws DigestException { + + int digestlength = md.getDigestLength(); + + byte[] bytes = new byte[LENGTH]; + + for (int i = 0; i < LENGTH; i++ ) { + bytes[i] = (byte)(i&0xFF); + } + + for ( int i = 0; i < 8; i++ ) { + switch (i) { + case 0: md.digest(); + break; + case 1: md.digest(bytes, 0, bytes.length); + break; + case 2: md.reset(); + break; + case 3: md.update(bytes[i]); + break; + case 4: md.update(bytes, 0, LENGTH); + break; + case 5: md.update(bytes[i]); + break; + default: + } + assertEquals(" !=digestlength", md.getDigestLength(), digestlength); + } + } + + + /** + * test against the "void engineReset()" method; + * it checks out that digests returned after preceeding "engineReset()" + * is the same as in case of initial digest + */ + public final void testReset() { + + byte[] bytes = new byte[LENGTH]; + byte[] digest1 = null; + byte[] digest2 = null; + boolean flag; + + for (int i = 0; i < bytes.length; i++ ) { + bytes[i] = (byte)(i&0xFF); + } + + digest1 = md.digest(); + md.update(bytes, 0, LENGTH); + md.reset(); + digest2 = md.digest(); + + flag = true; + for ( int i = 0; i < digest1.length; i++ ) { + flag &= digest1[i] == digest2[i]; + } + assertTrue("digests are not the same", flag); + } + + + /** + * test against the "void update(byte)" method; + * it checks out that if one digest is update to its forerunner + * the digests are not the same + */ + public final void testUpdatebyte() { + + boolean flag; + byte[] digest1 = null; + byte[] digest2 = null; + + for ( int j = 0; j < LENGTH ; j++) { + + byte[] bytes = new byte[j]; + + for (int i = 0; i < bytes.length; i++ ) { + bytes[i] = (byte)(i&0xFF); + } + + md.update(bytes, 0, bytes.length); + digest1 = md.digest(); + md.update(bytes, 0, bytes.length); + md.update((byte) 0); + digest2 = md.digest(); + + flag = true; + for ( int i = 0; i < digest1.length; i++ ) { + flag &= digest1[i] == digest2[i]; + } + assertFalse("digests are the same", flag); + } + } + + + /** + * test against the "void update(byte[], int, int)" method; + * it checks out throwing exceptions + */ + public final void testUpdatebyteArrayintint01() { + + // IllegalArgumentException if byte[] is null + try { + md.update(null, 0, 0); + fail("TESTCASE1 : update(null, 0, 0) :: No IllegalArgumentException"); + } catch (IllegalArgumentException e) { + } + + // ArrayIndexOutOfBoundsException if len>0 && offset < 0 +// try { +// md.update(new byte[0], -1, 1); +// fail("update(new byte[0], -1, 1) : No ArrayIndexOutOfBoundsException"); +// } catch (ArrayIndexOutOfBoundsException e) { +// } + + // IllegalArgumentException if (offset + len) >= input.length + try { + md.update(new byte[1], 0, 2); + fail("update(new byte[1], 0, 2) : No IllegalArgumentException"); + } catch (IllegalArgumentException e) { + } + } + + + /** + * test against the "void update(byte[],int,int)" method; + * it checks out that two sequential digest, + * second is byte array update to first, + * are different, provided lenght of the byte array > 0. + */ + public final void testUpdatebyteArrayintint02() { + + boolean flag; + byte[] digest1 = null; + byte[] digest2 = null; + + for ( int j = 0; j < LENGTH ; j++) { + + byte[] bytes = new byte[j]; + + for (int i = 0; i < bytes.length; i++ ) { + bytes[i] = (byte)(i&0xFF); + } + + md.update((byte) 0); + digest1 = md.digest(); + md.update((byte) 0); + md.update(bytes, 0, bytes.length); + digest2 = md.digest(); + + flag = true; + for ( int i = 0; i < digest1.length; i++ ) { + flag &= digest1[i] == digest2[i]; + } + if ( j == 0 ) { + // no update if byte[] of zero length + assertTrue("ATTENTION: digests are not the same", flag); + } else { + assertFalse("ATTENTION: digests are the same; j=" +j, flag); + } + } + } + + + /** + * test against the "void update(byte[], int, int)" method; + * it checks that if the "len" argument <=0 the method just returns with + * no affect to MessageDigestImp object (note that such behavior complies with RI). + */ +// public final void testUpdatebyteArrayintint03() { +// +// boolean flag; +// byte[] digest1 = null; +// byte[] digest2 = null; +// +// for ( int j = 0; j < LENGTH ; j++) { +// +// byte[] bytes = new byte[j]; +// +// for (int i = 0; i < bytes.length; i++ ) { +// bytes[i] = (byte)(i&0xFF); +// } +// +// md.update(bytes, 0, bytes.length); +// digest1 = md.digest(); +// md.update(bytes, 0, bytes.length); +// md.update(new byte[1], 0, -1); +// md.update(new byte[1], 0, 0); +// digest2 = md.digest(); +// +// assertTrue("digest's lengths are different : length1=" + +// digest1.length + " length2=" + digest2.length, +// digest1.length == digest2.length ); +// +// for ( int i = 0; i < digest1.length ; i++ ) { +// assertTrue("different digests : i=" +i + +// " digest1[i]=" + digest1[i] + " digest2[i]=" + digest2[i], +// digest1[i] == digest2[i] ); +// } +// } +// } + + + public static Test suite() { + return new TestSuite(SHA1_MessageDigestTest.class); + } + + public static void main(String[] args) { + junit.textui.TestRunner.run(suite()); + } + + } Propchange: incubator/harmony/enhanced/classlib/trunk/modules/security/src/test/impl/java/org/apache/harmony/security/tests/provider/crypto/SHA1_MessageDigestTest.java ------------------------------------------------------------------------------ svn:eol-style = native Added: incubator/harmony/enhanced/classlib/trunk/modules/security/src/test/impl/java/org/apache/harmony/security/tests/provider/crypto/SHA1withDSA_SignatureTest.java URL: http://svn.apache.org/viewvc/incubator/harmony/enhanced/classlib/trunk/modules/security/src/test/impl/java/org/apache/harmony/security/tests/provider/crypto/SHA1withDSA_SignatureTest.java?view=auto&rev=470330 ============================================================================== --- incubator/harmony/enhanced/classlib/trunk/modules/security/src/test/impl/java/org/apache/harmony/security/tests/provider/crypto/SHA1withDSA_SignatureTest.java (added) +++ incubator/harmony/enhanced/classlib/trunk/modules/security/src/test/impl/java/org/apache/harmony/security/tests/provider/crypto/SHA1withDSA_SignatureTest.java Thu Nov 2 03:21:12 2006 @@ -0,0 +1,1112 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You 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. + */ + +/* + * Notes. + * 1. The class doesn't contain tests against "update(..)" methods + * invoked on a Signature objects whose state is "INIT" or "VERIFY". + * Relevant checks are in tests against MessageDigest class methods. + * + * 2. The testSignbyteArrayintint03() is commented out + * because of compatibility with RI issue in current implementation of the Signature class. + */ + + +package org.apache.harmony.security.tests.provider.crypto; + + +import java.math.BigInteger; + +import java.security.InvalidKeyException; +import java.security.KeyPair; +import java.security.KeyPairGenerator; +import java.security.PrivateKey; +import java.security.PublicKey; +import java.security.SecureRandom; +import java.security.Signature; +import java.security.SignatureException; + +import java.security.interfaces.DSAParams; +import java.security.interfaces.DSAPrivateKey; +import java.security.interfaces.DSAPublicKey; +import java.security.interfaces.RSAPrivateKey; +import java.security.interfaces.RSAPublicKey; + +import java.security.spec.DSAParameterSpec; + +import junit.framework.Test; +import junit.framework.TestCase; +import junit.framework.TestSuite; + + +public class SHA1withDSA_SignatureTest extends TestCase { + + private static final String algorithm = "SHA1withDSA"; + + private static final String provider = "Crypto"; + + private static final String provider1 = "BC"; // see testVerifybyteArray04() + + private static Signature signs[]; + private static Signature signingSigns[]; + private static Signature verifyingSign; + + private static KeyPair keys; + private static KeyPairGenerator keyPairGenerator; + + private static final BigInteger MINUS_ONE = BigInteger.valueOf((long)-1); + + private static final BigInteger params[][] = new BigInteger[][] { + { BigInteger.ZERO, BigInteger.ZERO, BigInteger.ZERO }, + { BigInteger.ZERO, BigInteger.ZERO, BigInteger.ONE }, + { BigInteger.ZERO, BigInteger.ONE, BigInteger.ONE }, + { BigInteger.ONE, BigInteger.ZERO, BigInteger.ONE }, + { BigInteger.ONE, BigInteger.ONE, BigInteger.ONE }, + { MINUS_ONE, MINUS_ONE, MINUS_ONE }, + { BigInteger.ONE, BigInteger.ONE, MINUS_ONE }, + { MINUS_ONE, BigInteger.ONE, BigInteger.ONE }, + { BigInteger.ONE, MINUS_ONE, BigInteger.ONE }, + }; + + private static PrivateKey privateKey; + private static PublicKey publicKey; + + private static PrivateKey privateKey2; + private static PublicKey publicKey2; + + private static PrivateKey myRSAPrivateKey; + private static PublicKey myRSAPublicKey; + + private static SecureRandom mySecureRandom; + + + private static byte signature[]; + + private static byte bytes1[] = new byte[1000]; + private static byte bytes2[] = new byte[10]; + + private static byte message[] = new byte[1000]; + + // offset to use in corresponding methods + private static int offset; + + private static boolean flag; + + + static { + try { + keyPairGenerator = KeyPairGenerator.getInstance("DSA"); + + keyPairGenerator.initialize(1024); + keys = keyPairGenerator.generateKeyPair(); + + privateKey = keys.getPrivate(); + publicKey = keys.getPublic(); + + privateKey2 = Predefined.getPrivateKey(); + publicKey2 = Predefined.getPublicKey(); + + myRSAPrivateKey = (PrivateKey)getRSAPrivateKey(); + myRSAPublicKey = (PublicKey)getRSAPublicKey(); + + mySecureRandom = new SecureRandom(); + + mySecureRandom.nextBytes(bytes1); + mySecureRandom.nextBytes(bytes2); + mySecureRandom.nextBytes(message); + + byte myByte[] = new byte[1]; + mySecureRandom.nextBytes(myByte); + offset = myByte[0] & 037; + + flag = true; + } catch (Exception e) { + flag = false; + } + } + + + /* + * @see TestCase#setUp() + */ + protected void setUp() throws Exception { + + if (!flag) { + throw new Exception("some problem in static initializer"); + } + + super.setUp(); + + signs = new Signature[] { Signature.getInstance(algorithm, provider) , + Signature.getInstance(algorithm, provider) , + Signature.getInstance(algorithm, provider) , + Signature.getInstance(algorithm, provider) , + Signature.getInstance(algorithm, provider) + }; + + signs[1].initSign(privateKey); + signs[2].initSign(privateKey, null ); + signs[3].initSign(privateKey, mySecureRandom ); + signs[4].initVerify(publicKey); + + signingSigns = new Signature[] { signs[1], signs[2], signs[3] }; + verifyingSign = signs[4]; + } + + + static private DSAPrivateKey getDSAPrivateKey(BigInteger p, BigInteger q, BigInteger g, + BigInteger x) { + final BigInteger pp = p; + final BigInteger qq = q; + final BigInteger gg = g; + final BigInteger xx = x; + + return new DSAPrivateKey () { + public BigInteger getX() { return xx; } + public DSAParams getParams() { + BigInteger p = pp; + BigInteger q = qq; + BigInteger g = gg; + return (DSAParams)(new DSAParameterSpec(p, q, g)) ; + } + public String getAlgorithm() { return "dummy"; } + public byte[] getEncoded() { return new byte[0]; } + public String getFormat() { return "dummy"; } + }; + } + + + static private DSAPublicKey getDSAPublicKey(BigInteger p, BigInteger q, BigInteger g, + BigInteger y) { + final BigInteger pp = p; + final BigInteger qq = q; + final BigInteger gg = g; + final BigInteger yy = y; + + return new DSAPublicKey () { + public BigInteger getY() { return yy; } + public DSAParams getParams() { + BigInteger p = pp; + BigInteger q = qq; + BigInteger g = gg; + return (DSAParams)(new DSAParameterSpec(p, q, g)) ; + } + public String getAlgorithm() { return "dummy"; } + public byte[] getEncoded() { return new byte[0]; } + public String getFormat() { return "dummy"; } + }; + } + + + static private RSAPrivateKey getRSAPrivateKey() { + + return new RSAPrivateKey () { + public BigInteger getPrivateExponent() { return BigInteger.ZERO; } + public BigInteger getModulus() { return BigInteger.ZERO; } + public String getAlgorithm() { return "RSA"; } + public byte[] getEncoded() { return new byte[] {0}; } + public String getFormat() { return "fff"; } + }; + } + + static private RSAPublicKey getRSAPublicKey() { + + return new RSAPublicKey () { + public BigInteger getPublicExponent() { return BigInteger.ZERO; } + public BigInteger getModulus() { return BigInteger.ZERO; } + public String getAlgorithm() { return "RSA"; } + public byte[] getEncoded() { return new byte[] {0}; } + public String getFormat() { return "fff"; } + }; + } + + + /** + * The test against "initSign(PrivateKey)" method. + * It checks out that regardless of a Signature object's state + * the method throws InvalidKeyException if PrivateKey is null or not DSAPrivateKey + */ + public final void testInitSignPrivateKey01() { + + for ( int i = 0; i < signs.length; i++ ) { + try { + signs[i].initSign(null); + fail("case1: no InvalidKeyException : i=" + i); + } catch (InvalidKeyException e) { + } + try { + signs[i].initSign(myRSAPrivateKey); + fail("case: no InvalidKeyException : i=" + i); + } catch (InvalidKeyException e) { + } + } + } + + + /** + * The test against "initSign(PrivateKey)" method. + * It checks out that regardless of a Signature object's state + * the method throws InvalidKeyException if + * PrivateKey is DSAPrivateKey and the key is invalid, that is, + * BigIntegers constituting the key have incorrect values. + */ + public final void testInitSignPrivateKey02() throws Exception { + + for ( int i = 0; i < signs.length; i++ ) { + for ( int j = 0; j < params.length; j++ ) { + try { + signs[i].initSign((PrivateKey)getDSAPrivateKey( + params[j][0], params[j][1], params[j][2], BigInteger.ZERO ) ); + fail("no InvalidKeyException : i =" + i + " j=" + j); + } catch (InvalidKeyException e ) { + } + } + } + } + + + /** + * The test against the "initSign(PrivateKey)" method. + * It checks out that the method negates the effect of previous call + * if it is invoked with a different argument. + * + * Note. + * In RI, negating effect of previous call includes + * discarding updates done before calling the method. + */ + public final void testInitSignPrivateKey03() throws Exception { + + // Initially all signing Signature objects are initialized with some PublicKey + // and the "verifyingSign" object with corresponding PrivateKey. + + verifyingSign.initVerify(publicKey2); + + for ( int i = 0; i < signingSigns.length; i++ ) { + + signingSigns[i].update(bytes1, 0, bytes1.length); + + signingSigns[i].initSign(privateKey2); // another PrivateKey + + signingSigns[i].update(bytes2, 0, bytes2.length); + signature = signingSigns[i].sign(); + + // it is expected that "signature" is one generated only for "bytes2" update + + verifyingSign.update(bytes2, 0, bytes2.length); + assertTrue("returned 'false' : i=" + i, verifyingSign.verify(signature) ); + } + } + + + /** + * The test against the "initSign(PrivateKey)" method. + * It checks out that the method negates the effect of previous call + * if it is invoked with the same argument. + * + * Notes. + * 1. In RI, negating effect of previous call includes + * discarding updates done before calling the method. + * 2. + * The specification for the method contains the folowing clause: + * "If this method is called again with a different argument, + * it negates the effect of this call." + * which meaning requires certainty in case of sequence + * initSign - update - initSign + * RI behavior is such that with respect to "update" + * it doesn't matter whether argument is the same or different. + */ + public final void testInitSignPrivateKey04() throws Exception { + + for ( int i = 0; i < signingSigns.length; i++ ) { + + signingSigns[i].update(bytes1, 0, bytes1.length); + + signingSigns[i].initSign(privateKey); // the same PrivateKey + + signingSigns[i].update(bytes2, 0, bytes2.length); + signature = signingSigns[i].sign(); + + // it is expected that "signature" is one generated only for "bytes2" update + + verifyingSign.update(bytes2, 0, bytes2.length); + assertTrue("returned 'false' : i=" + i, verifyingSign.verify(signature) ); + } + } + + + /** + * The test against "initVerify(PublicKey)" methods + * It checks out that regardless of a Signature object's state + * the method throws InvalidKeyException if + * PublicKey is null or is not DSAPublicKey + */ + public final void testInitVerifyPublicKey01() { + + PublicKey pk = null; + + for ( int i = 0; i < signs.length; i++ ) { + try { + signs[i].initVerify(pk); + fail("case1 : no InvalidKeyException i=" + i); + } catch (InvalidKeyException e) { + } + try { + signs[i].initVerify(myRSAPublicKey); + fail("case2 : no InvalidKeyException i=" + i); + } catch (InvalidKeyException e) { + } + } + } + + + /** + * The test against "initSign(PrivateKey)" method. + * It checks out that regardless of a Signature object's state + * the method throws InvalidKeyException if + * PublicKey is DSAPublicKey and the key is invalid, that is, + * BigIntegers constituting the key have incorrect values. + */ + public final void testInitVerifyPublicKey02() throws Exception { + + for ( int i = 0; i < signs.length; i++ ) { + for ( int j = 0; j < params.length; j++ ) { + try { + signs[i].initVerify((PublicKey)getDSAPublicKey( + params[j][0], params[j][1], params[j][2], BigInteger.ZERO ) ); + fail("no InvalidKeyException : i=" + i + " j=" + j); + } catch (InvalidKeyException e ) { + } + } + } + } + + + /** + * The test against the "initVerify(PublicKey)" method. + * It checks out that the method negates the effect of previous call + * if it is invoked with a different argument, + * that is, after initializing with PublicKey from another KeyPair + * the "verify" method returns "false". + */ + public final void testInitVerifyPublicKey03() throws Exception { + + signingSigns[0].update(bytes1, 0, bytes1.length); + signature = signingSigns[0].sign(); + + verifyingSign.initVerify(publicKey2); // another key + verifyingSign.update(bytes1, 0, bytes1.length); + assertFalse("case1: returned 'true'", verifyingSign.verify(signature) ); + } + + + /** + * The test against the "initVerify(PublicKey)" method. + * It checks out that the method negates the effect of previous call + * if it is invoked with the same argument. + * Like it is for "initSign", RI behavior is such that with respect to "update" + * it doesn't matter whether argument is the same or different. + * + * Note. + * In RI negating effect of previous call includes + * discarding updates done before calling the method. + */ + public final void testInitVerifyPublicKey04() throws Exception { + + signingSigns[0].update(bytes1, 0, bytes1.length); + signature = signingSigns[0].sign(); + + verifyingSign.update(bytes2, 0, bytes2.length); + + verifyingSign.initVerify(publicKey); // the same key + verifyingSign.update(bytes1, 0, bytes1.length); + assertTrue("case2: returned 'false'", verifyingSign.verify(signature) ); + } + + + /* + * The method returns + * - -1 if a signature's syntax is incorrect + * - length of the signature otherwise. + */ + private int checkSignature(byte sig[], int offset) { + + int n1 = sig[offset +3]; + int n2 = sig[offset +n1 +5]; + + if ( sig[offset] != 0x30 || + sig[offset +1] != (n1 + n2 +4) || + sig[offset +2] != 2 || + sig[offset +n1 +4] != 2 || + n1 > 21 || n2 > 21 ) + { + return -1; + } + return (n1 + n2 + 6) ; + } + + + /** + * The test against the "sign()" method. + * It checks out that Signature object returned by the method has correct ASN1 encoding. + */ + public final void testSign01() throws Exception { + + byte sig[]; + + for (int i = 0; i < signingSigns.length; i++) { + + signingSigns[i].update(message); + + sig = signingSigns[i].sign(); + + try { + int n = checkSignature(sig, 0); + if ( n < 0 ) { + fail("incorrect signature : i=" + i); + } + if ( n != sig.length ) { + fail("incorrect signature's length : n=" + n + + " sig.length= " + sig.length ); + } + } catch (ArrayIndexOutOfBoundsException e) { + fail("incorrect signature: " + e); + } + } + } + + + /** + * The test against the "sign(byte[], int, int)" method. + * It checks out that Signature object returned by the method has correct ASN1 encoding. + */ + public final void testSignbyteArrayintint01() throws Exception { + + byte sig[] = new byte[offset +100]; + + for (int i = 0; i < signingSigns.length; i++) { + int n1; + + signingSigns[i].update(message); + + n1 = signingSigns[i].sign(sig, offset, 50); + + try { + int n2 = checkSignature(sig, offset); + if ( n2 < 0 ) { + fail("signature bytes have invalid encoding"); + } + if ( n1 != n2 ) { + fail("incorrect signature's length : n1=" + n1 + " n2=" + n2 ); + } + } catch (ArrayIndexOutOfBoundsException e) { + fail("incorrect signature: " + e); + } + } + } + + + /** + * The test agains the "sign(byte[], int, int)" method. + * It checks out that if a Signature object's state is SIGN + * passing to the object "offset" and "len" arguments that satisfy the condition: + * "offset + len <= outbuf.length" + * but "len" < actual length of signature results in throwing SignatureException. + * + * Note. + * As signature's length varies, hence, + * in general it is impossible to detect in advance the length of signature returned, + * the test consist of two testcases: + * - first for length value of 44 which is certainly less than signature's length, + * - second for length value which is less for only 1 byte + * in this case a predefined key, message and signature are used. + */ + public final void testSignbyteArrayintint02() throws Exception { + + byte sig[] = new byte[50]; + + for ( int i = 0; i < signingSigns.length; i++ ) { + + signingSigns[i].update(message); + + try { + signingSigns[i].sign(sig, 0, 44); + fail("case1 : no SignatureExcepton : i=" + i ); + } catch (SignatureException e) { + } + + signingSigns[i].initSign(privateKey2); + signingSigns[i].update( Predefined.getMessage() ); + try { + signs[i].sign( Predefined.getSignature(), 0, + Predefined.getSignatureLength() -1 ); + fail("case2 : no SignatureExcepton : i=" + i ); + } catch (SignatureException e) { + } + } + } + + + /** + * The test agains the "sign(byte[], int, int)" method. + * It checks out that if a Signature object's state is SIGN + * passing to the object "offset" and "len" arguments that satisfy the condition: + * "offset < 0" and "len" >= actual length of signature + * results in throwing ArrayIndexOutOfBoundsException. + */ +// public final void testSignbyteArrayintint03() throws Exception { +// +// byte sig[] = new byte[50]; +// +// for ( int i = 0; i < signingSigns.length; i++ ) { +// +// signingSigns[i].update(message); +// +// // because 50 is more than length of any signature, +// // for offset==-1 and len==50 ArrayIndexOutOfBoundsException is expected +// // +// try { +// signingSigns[i].sign(sig, -1, 50); +// fail("no ArrayIndexOutOfBoundsException"); +// } catch (ArrayIndexOutOfBoundsException e) { +// } +// +// // because 40 is less than length of any signature", +// //for offset==-1 and len==40 ArrayIndexOutOfBoundsException is not expected +// // +// try { +// signingSigns[i].sign(sig, -1, 40); +// fail("no SignatureException"); +// } catch (ArrayIndexOutOfBoundsException e) { +// fail("ArrayIndexOutOfBoundsException"); +// } catch (SignatureException e) { +// } +// } +// } + + + /** + * The test against the "verify(byte[])" method. + * It checks out that for given message and signature signed with some PrivateKey + * (1) the method returns "true" if PublicKey is from the same KeyPair, + * (2) the method returns "false" otherwise. + */ + public final void testVerifybyteArray01() throws Exception { + + byte sigBytes[]; + + signingSigns[0].update(message); + sigBytes = signingSigns[0].sign(); + + verifyingSign.update(message); + assertTrue("case1: test failure", verifyingSign.verify(sigBytes) ); + + verifyingSign.initVerify(publicKey2); + + verifyingSign.update(message); + assertFalse("case2: test failure", verifyingSign.verify(sigBytes) ); + } + + + /** + * The test is against the pair "sign() - verify(byte[])" method. + * It checks out that the "verify" method returns "true" + * if a verifying Signature object was updated with the same message + * which was used to update a signing Signature object. + */ + public final void testVerifybyteArray02() throws Exception { + + byte sig1[]; + byte sig2[]; + + for (int i = 0; i < signingSigns.length; i++) { + + signingSigns[i].update(bytes1); + verifyingSign.update(bytes1); + + sig1 = signingSigns[i].sign(); + + assertTrue("case 1: test failure : i=" + i, verifyingSign.verify(sig1) ); + + signingSigns[i].update(bytes1); + signingSigns[i].update(bytes2); + verifyingSign.update(bytes1); + verifyingSign.update(bytes2); + + sig2 = signingSigns[i].sign(); + + assertTrue("case 2: test failure : i=" + i, verifyingSign.verify(sig2) ); + + verifyingSign.update(bytes1); + verifyingSign.update(bytes2); + assertFalse("case 3: test failure : i=" + i, verifyingSign.verify(sig1) ); + } + } + + + + /** + * The compatibility with RI test. + * It checks out that + * for the predefined message and signature signed with PrivateKey from RI + * the method invoked on a Signature object initiazed with corresponding PublicKey from RI + * returns "true". + */ + public final void testVerifybyteArray03() throws Exception { + + verifyingSign.initVerify(publicKey2); + verifyingSign.update( Predefined.getMessage() ); + assertTrue("not verified", verifyingSign.verify( Predefined.getSignature() ) ); + } + + + /** + * The test against the pair "sign - verify" methods. + * Its specific is that signing and verifying are performed by two providers, + * provider and provider1; + * so, the test checks up on compatibility signing-verifying between implementations. + */ + public final void testVerifybyteArray04() throws Exception { + + Signature signingSign, verifyingSign; + + byte sigBytes[]; + + byte message[] = new byte[1000]; + + // testcase1 - signing with "provider", verifying with "provider1" + + signingSign = Signature.getInstance(algorithm, provider); + verifyingSign = Signature.getInstance(algorithm, provider1); + + mySecureRandom.nextBytes(message); + + signingSign.initSign(privateKey); + signingSign.update(message); + sigBytes = signingSign.sign(); + + verifyingSign.initVerify(publicKey); + verifyingSign.update(message); + assertTrue("case1: test failure", verifyingSign.verify(sigBytes) ); + + // testcase2 - signing with "provider1", verifying with "provider" + + signingSign = Signature.getInstance(algorithm, provider1); + verifyingSign = Signature.getInstance(algorithm, provider); + + mySecureRandom.nextBytes(message); + + signingSign.initSign(privateKey); + signingSign.update(message); + sigBytes = signingSign.sign(); + + verifyingSign.initVerify(publicKey); + verifyingSign.update(message); + assertTrue("case2: test failure", verifyingSign.verify(sigBytes) ); + } + + + /** + * The test against the "verify(byte[], int, int)" method. + * It checks out that if Signature object's state is VERIFY + * the method throws IllegalArgumentException in case of the following arguments : + * outbufs == null or + * offset < 0 or + * length < 0 or + * offset+length > outbuf.length + */ + public final void testVerifybyteArrayintint01() throws Exception { + + byte bArray[] = new byte[100]; + + // case1 : null byte array + try { + verifyingSign.verify(null, 0, 48); + fail("case1 : no IllegalArgumentException"); + } catch (IllegalArgumentException e) { + } + + // case2 : len < 0 + try { + verifyingSign.verify(bArray, 0, -1); + fail("case2 : no IllegalArgumentException"); + } catch (IllegalArgumentException e) { + } + + // case3 : offset < 0 + try { + verifyingSign.verify(bArray, -1, 48); + fail("case3: no IllegalArgumentException"); + } catch (IllegalArgumentException e) { + } + + // case4 : offset+len > outbuf.length + try { + int k = bArray.length/2; + verifyingSign.verify(bArray, k, bArray.length-k+1); + fail("case4: no IllegalArgumentException"); + } catch (IllegalArgumentException e) { + } + } + + + /** + * The test against the "verify(byte[], int, int)" method. + * It checks out that if Signature object's state is VERIFY + * the method throws up SignatureException if + * (1) offset+length < 0 + * (2) offset > signature.length + * (3) SignatureException if outbuf's lentgh is correct + * whereas a signature doesn't meet ASN1 syntax. + */ + public final void testVerifybyteArrayintint02() throws Exception { + + byte sigBytes[] = new byte[100]; // wrong signature + + try { + verifyingSign.verify(sigBytes, Integer.MAX_VALUE, 2); + fail("testcase1 : no SignatureException"); + } catch (SignatureException e) { + } + + try { + verifyingSign.verify(sigBytes, 2, Integer.MAX_VALUE); + fail("testcase2 : no SignatureException"); + } catch (SignatureException e) { + } + + verifyingSign.update(message); + try { + verifyingSign.verify(sigBytes, 0, 50); + fail("testcase3 : SignatureException"); + } catch (SignatureException e) { + } + } + + + /** + * The test is against the "verify(byte[], int, int)" method. + * It checks out that in case of correct signature the method throws SignatureException + * if value of "length" is less than signature's length + */ + public final void testVerifybyteArrayintint03() throws Exception { + + byte sig[] = new byte[offset +100]; + + verifyingSign.update(message); + + for (int i = 0; i < signingSigns.length; i++) { + int n; + + signingSigns[i].update(message); + n = signingSigns[i].sign(sig, offset, 50); + + try { + verifyingSign.verify(sig, offset, n-1); + fail("test failure : i=" + i + " offset=" + offset); + } catch (SignatureException e) { + verifyingSign.verify(sig, offset, n); + } + } + } + + + /** + * The test against the "verify(byte[], int, int)" method. + * It check out that if a call to the method returns normally + * a Signature object resets itself. + */ + public final void testVerifybyteArrayintint04() throws Exception { + + byte sig[] = new byte[100]; + int n = 0;; + + byte sigBytes[] = new byte[100]; // bytes for correct signature + + // the signature has correct ASN1 syntax but its value is negative; + // so, the "verify(...)" methods should return "false" without throwing an exception + sig[0] = 48; + sig[1] = 44; + sig[2] = 2; + sig[3] = 20; + sig[4] = (byte)0x8f; // negative value + sig[24] = 2; + sig[25] = 20; + sig[26] = (byte)0x8f; // negative value + + signingSigns[0].update(message); + n = signingSigns[0].sign(sigBytes, 0, 50); + + // testcase1: first call returns true, + // second returns false though signature is the same + + verifyingSign.update(message); + + assertTrue("case1: test failure", verifyingSign.verify(sigBytes, 0, n) ); + assertFalse("case2: test failure", verifyingSign.verify(sigBytes, 0, n) ); + + + // tastcase2: first call returns false (incorrect signature), + // second returns false too, in spite of correct signature (!), + // because Signature object was reset in first call + + verifyingSign.update(message); + + assertFalse("case3: test failure", verifyingSign.verify(sig, 0, 46) ); + assertFalse("case4: test failure", verifyingSign.verify(sigBytes, 0, n) ); + } + + + /** + * The test against the "verify(byte[], int, int)" method. + * It check out that a Signature object doesn't reset itself if + * the method throws up an exception. + */ + public final void testVerifybyteArrayintint05() throws Exception { + + byte sig[] = new byte[100]; //incorrect signature + + byte sigBytes[] = new byte[100]; + int n = 0; + + signingSigns[0].update(message); + n = signingSigns[0].sign(sigBytes, 0, 50); + + verifyingSign.update(message); + + try { + verifyingSign.verify(null, 0, n); + } catch (IllegalArgumentException e) { + } + + try { + verifyingSign.verify(sigBytes, -1, n); + } catch (IllegalArgumentException e) { + } + + try { + verifyingSign.verify(sigBytes, 0, -1); + } catch (IllegalArgumentException e) { + } + + try { + verifyingSign.verify(sigBytes, sigBytes.length-10, 30); + } catch (IllegalArgumentException e) { + } + + try { + verifyingSign.verify(sigBytes, Integer.MAX_VALUE, n); + } catch (SignatureException e) { + } + + try { + verifyingSign.verify(sig, 0, n); + } catch (SignatureException e) { + } + + // if the method doesn't reset the expected result of verificaton is "true" + + assertTrue("test failure : n=" +n, verifyingSign.verify(sigBytes, 0, n) ); + } + + + /** + * The test is against the pair "sign(byte[],int,int) - verify(byte[],int,int)" method. + * It checks out that the "verify" method returns "true" + * if a verifying Signature object was updated with the same message + * which was used to update a signing Signature object. + */ + public final void testVerifybyteArrayintint06() throws Exception { + + byte sig1[] = new byte[offset +100]; + byte sig2[] = new byte[offset +100]; + + int n1, n2; + + for (int i = 0; i < signingSigns.length; i++) { + + signingSigns[i].update(bytes1); + verifyingSign.update(bytes1); + + n1 = signingSigns[i].sign(sig1, offset, 50); + + assertTrue("case 1: test failure : i=" + i + " offset=" + offset, + verifyingSign.verify(sig1, offset, n1) ); + + signingSigns[i].update(bytes1); + signingSigns[i].update(bytes2); + verifyingSign.update(bytes1); + verifyingSign.update(bytes2); + + n2 = signingSigns[i].sign(sig2, offset, 50); + + assertTrue("case 2: test failure : i=" + i + " offset=" + offset, + verifyingSign.verify(sig2, offset, n2) ); + + verifyingSign.update(bytes1); + verifyingSign.update(bytes2); + assertFalse("case 3: test failure : i=" + i + " offset=" + offset, + verifyingSign.verify(sig1, offset, n1) ); + } + } + + + public static Test suite() { + return new TestSuite(SHA1withDSA_SignatureTest.class); + } + + + public static void main(String[] args) { + junit.textui.TestRunner.run(suite()); + } +} + + +class Predefined { + + static DSAPublicKey publicKey = new DSAPublicKey() { + + byte yb[] = new byte[] { + 91, 91, -5, 113, -35, 61, -111, -29, -59, -5, -53, -72, 93, 38, 81, 10, -75, + 122, -60, -88, -74, -91, -108, 88, 55, -57, 119, -2, -104, -71, 83, 45, -55, + -111, 46, -23, -113, -34, 105, 18, -36, -33, 3, 21, 23, 93, -128, -52, 42, -11, + 55, 50, -27, 51, 49, 50, -20, -92, -120, -56, 28, -114, -30, 36, -91, -102, 39, + -50, -104, -73, -94, -34, -99, -25, 76, -40, 4, -89, 1, -107, -66, -87, -112, + 22, -40, -118, 59, -26, 90, -90, -103, -75, -104, 26, -31, 54, -95, 105, 67, + -4, -44, 35, -75, 0, -69, 60, 65, -78, 49, 5, 1, 111, -122, 83, 22, -35, -65, + 122, 120, -104, -78, -25, -35, 12, -106, 101, 21, 33 }; + + byte pb[] = new byte[] { + 0, -3, 127, 83, -127, 29, 117, 18, 41, 82, -33, 74, -100, 46, -20, -28, -25, + -10, 17, -73, 82, 60, -17, 68, 0, -61, 30, 63, -128, -74, 81, 38, 105, 69, 93, + 64, 34, 81, -5, 89, 61, -115, 88, -6, -65, -59, -11, -70, 48, -10, -53, -101, + 85, 108, -41, -127, 59, -128, 29, 52, 111, -14, 102, 96, -73, 107, -103, 80, + -91, -92, -97, -97, -24, 4, 123, 16, 34, -62, 79, -69, -87, -41, -2, -73, -58, + 27, -8, 59, 87, -25, -58, -88, -90, 21, 15, 4, -5, -125, -10, -45, -59, 30, + -61, 2, 53, 84, 19, 90, 22, -111, 50, -10, 117, -13, -82, 43, 97, -41, 42, -17, + -14, 34, 3, 25, -99, -47, 72, 1, -57 }; + + byte qb[] = new byte[] { + 0, -105, 96, 80, -113, 21, 35, 11, -52, -78, -110, -71, -126, -94, -21, -124, + 11, -16, 88, 28, -11 }; + + byte gb[] = new byte[] { + 0, -9, -31, -96, -123, -42, -101, 61, -34, -53, -68, -85, 92, 54, -72, 87, -71, + 121, -108, -81, -69, -6, 58, -22, -126, -7, 87, 76, 11, 61, 7, -126, 103, 81, + 89, 87, -114, -70, -44, 89, 79, -26, 113, 7, 16, -127, -128, -76, 73, 22, 113, + 35, -24, 76, 40, 22, 19, -73, -49, 9, 50, -116, -56, -90, -31, 60, 22, 122, + -117, 84, 124, -115, 40, -32, -93, -82, 30, 43, -77, -90, 117, -111, 110, -93, + 127, 11, -6, 33, 53, 98, -15, -5, 98, 122, 1, 36, 59, -52, -92, -15, -66, -88, + 81, -112, -119, -88, -125, -33, -31, 90, -27, -97, 6, -110, -117, 102, 94, -128, + 123, 85, 37, 100, 1, 76, 59, -2, -49, 73, 42 }; + + public BigInteger getY() { return new BigInteger(yb); } + public DSAParams getParams() { + BigInteger p = new BigInteger(pb); + BigInteger q = new BigInteger(qb); + BigInteger g = new BigInteger(gb); + return (DSAParams)(new DSAParameterSpec(p, q, g)) ; + } + public String getAlgorithm() { return "DSA"; } + public byte[] getEncoded() { return null; } + public String getFormat() { return null; } + } ; + + + static DSAPrivateKey privateKey = new DSAPrivateKey() { + + byte xb[] = new byte[] { + 12, 31, -39, 65, -61, -54, -91, 37, -93, -115, 81, 122, -24, -104, + -31, -106, 113, -39, -69, 34 }; + + byte pb[] = new byte[] { + 0, -3, 127, 83, -127, 29, 117, 18, 41, 82, -33, 74, -100, 46, -20, -28, -25, -10, + 17, -73, 82, 60, -17, 68, 0, -61, 30, 63, -128, -74, 81, 38, 105, 69, 93, 64, 34, + 81, -5, 89, 61, -115, 88, -6, -65, -59, -11, -70, 48, -10, -53, -101, 85, 108, -41, + -127, 59, -128, 29, 52, 111, -14, 102, 96, -73, 107, -103, 80, -91, -92, -97, -97, + -24, 4, 123, 16, 34, -62, 79, -69, -87, -41, -2, -73, -58, 27, -8, 59, 87, -25, -58, + -88, -90, 21, 15, 4, -5, -125, -10, -45, -59, 30, -61, 2, 53, 84, 19, 90, 22, -111, + 50, -10, 117, -13, -82, 43, 97, -41, 42, -17, -14, 34, 3, 25, -99, -47, 72, 1, + -57 }; + + byte qb[] = new byte[] { + 0, -105, 96, 80, -113, 21, 35, 11, -52, -78, -110, -71, -126, -94, -21, -124, + 11, -16, 88, 28, -11 }; + + byte gb[] = new byte[] { + 0, -9, -31, -96, -123, -42, -101, 61, -34, -53, -68, -85, 92, 54, -72, 87, -71, + 121, -108, -81, -69, -6, 58, -22, -126, -7, 87, 76, 11, 61, 7, -126, 103, 81, 89, + 87, -114, -70, -44, 89, 79, -26, 113, 7, 16, -127, -128, -76, 73, 22, 113, 35, -24, + 76, 40, 22, 19, -73, -49, 9, 50, -116, -56, -90, -31, 60, 22, 122, -117, 84, 124, + -115, 40, -32, -93, -82, 30, 43, -77, -90, 117, -111, 110, -93, 127, 11, -6, 33, + 53, 98, -15, -5, 98, 122, 1, 36, 59, -52, -92, -15, -66, -88, 81, -112, -119, + -88, -125, -33, -31, 90, -27, -97, 6, -110, -117, 102, 94, -128, 123, 85, 37, 100, + 1, 76, 59, -2, -49, 73, 42 }; + + public BigInteger getX() { return new BigInteger(xb); } + public DSAParams getParams() { + BigInteger p = new BigInteger(pb); + BigInteger q = new BigInteger(qb); + BigInteger g = new BigInteger(gb); + return (DSAParams)(new DSAParameterSpec(p, q, g)) ; + } + public String getAlgorithm() { return "DSA"; } + public byte[] getEncoded() { return null; } + public String getFormat() { return null; } + }; + + + static byte msg[] = new byte[] { -126, -74, -45, -105, 31, 30, 76, -78, 56, 31, + -67, -7, 40, 36, -59, -1, -41, -46, -63, -98, + -10, -56, 18, 69, 107, -118, -70, -9, -32, 49, + -48, 11, -73, 98, -67, 82, 96, 126, 24, -40, + -15, 20, 81, 103, 119, -114, -9, -85, 56, 20, + -98, 89, -37, 34, -44, 19, -19, -126, -87, -40, + -102, -96, 102, -30, 30, 115, -68, -108, -44, 88, + -65, 35, 85, 123, -1, -82, 110, 67, 99, 84, + -32, 44, 67, 75, -121, 28, -128, 49, -54, 52, + 53, 119, -114, -99, -61, -58, -119, -97, 91, 66 }; + + + static byte sig[] = new byte[] { 48, 44, 2, 20, 33, -6, -66, -52, 17, -91, -90, 83, + -128, 73, -114, 49, 118, 82, -65, 123, -19, 94, -26, + 106, 2, 20, 59, 75, -86, -115, 94, -125, 80, -91, + -57, 61, -73, -5, -109, -93, 103, -10, -73, -21, 99, 81 }; + + static byte[] getMessage() { + return msg; + } + + + static byte[] getSignature() { + return sig; + } + + + static int getSignatureLength() { + return sig.length; + } + + + static DSAPublicKey getPublicKey() { + return publicKey; + } + + + static DSAPrivateKey getPrivateKey() { + return privateKey; + } +} Propchange: incubator/harmony/enhanced/classlib/trunk/modules/security/src/test/impl/java/org/apache/harmony/security/tests/provider/crypto/SHA1withDSA_SignatureTest.java ------------------------------------------------------------------------------ svn:eol-style = native