• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 // Copyright 2017 Google Inc.
2 //
3 // Licensed under the Apache License, Version 2.0 (the "License");
4 // you may not use this file except in compliance with the License.
5 // You may obtain a copy of the License at
6 //
7 //      http://www.apache.org/licenses/LICENSE-2.0
8 //
9 // Unless required by applicable law or agreed to in writing, software
10 // distributed under the License is distributed on an "AS IS" BASIS,
11 // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 // See the License for the specific language governing permissions and
13 // limitations under the License.
14 //
15 ////////////////////////////////////////////////////////////////////////////////
16 
17 package com.google.crypto.tink.subtle;
18 
19 import static org.junit.Assert.assertFalse;
20 import static org.junit.Assert.assertThrows;
21 import static org.junit.Assert.assertTrue;
22 
23 import com.google.crypto.tink.PublicKeySign;
24 import com.google.crypto.tink.PublicKeyVerify;
25 import com.google.crypto.tink.config.TinkFips;
26 import com.google.crypto.tink.config.internal.TinkFipsUtil;
27 import com.google.crypto.tink.signature.EcdsaPrivateKey;
28 import com.google.crypto.tink.signature.EcdsaPublicKey;
29 import com.google.crypto.tink.signature.internal.testing.EcdsaTestUtil;
30 import com.google.crypto.tink.signature.internal.testing.SignatureTestVector;
31 import com.google.crypto.tink.subtle.EllipticCurves.EcdsaEncoding;
32 import com.google.crypto.tink.subtle.Enums.HashType;
33 import com.google.crypto.tink.testing.TestUtil;
34 import java.security.GeneralSecurityException;
35 import java.security.KeyPair;
36 import java.security.KeyPairGenerator;
37 import java.security.Security;
38 import java.security.Signature;
39 import java.security.interfaces.ECPrivateKey;
40 import java.security.interfaces.ECPublicKey;
41 import java.security.spec.ECParameterSpec;
42 import org.conscrypt.Conscrypt;
43 import org.junit.Assume;
44 import org.junit.Before;
45 import org.junit.Test;
46 import org.junit.experimental.theories.DataPoints;
47 import org.junit.experimental.theories.FromDataPoints;
48 import org.junit.experimental.theories.Theories;
49 import org.junit.experimental.theories.Theory;
50 import org.junit.runner.RunWith;
51 
52 /** Unit tests for EcdsaSignJce. */
53 @RunWith(Theories.class)
54 public class EcdsaSignJceTest {
55 
56   @Before
useConscrypt()57   public void useConscrypt() throws Exception {
58     // If Tink is build in FIPS-only mode, then we register Conscrypt for the tests.
59     if (TinkFips.useOnlyFips()) {
60       try {
61         Conscrypt.checkAvailability();
62         Security.addProvider(Conscrypt.newProvider());
63       } catch (Throwable cause) {
64         throw new IllegalStateException(
65             "Cannot test ECDSA sign in FIPS-mode without Conscrypt Provider", cause);
66       }
67     }
68   }
69 
70   @Test
testBasic()71   public void testBasic() throws Exception {
72     Assume.assumeTrue(!TinkFips.useOnlyFips() || TinkFipsUtil.fipsModuleAvailable());
73 
74     ECParameterSpec ecParams = EllipticCurves.getNistP256Params();
75     KeyPairGenerator keyGen = KeyPairGenerator.getInstance("EC");
76     keyGen.initialize(ecParams);
77     KeyPair keyPair = keyGen.generateKeyPair();
78     ECPublicKey pub = (ECPublicKey) keyPair.getPublic();
79     ECPrivateKey priv = (ECPrivateKey) keyPair.getPrivate();
80 
81     // Sign with EcdsaSign.
82     String message = "Hello";
83     EcdsaSignJce signer = new EcdsaSignJce(priv, HashType.SHA256, EcdsaEncoding.DER);
84     byte[] signature = signer.sign(message.getBytes("UTF-8"));
85 
86     // Verify with JCE's Signature.
87     Signature verifier = Signature.getInstance("SHA256WithECDSA");
88     verifier.initVerify(pub);
89     verifier.update(message.getBytes("UTF-8"));
90     assertTrue(verifier.verify(signature));
91   }
92 
93   @Test
testConstructorExceptions()94   public void testConstructorExceptions() throws Exception {
95     Assume.assumeTrue(!TinkFips.useOnlyFips() || TinkFipsUtil.fipsModuleAvailable());
96 
97     ECParameterSpec ecParams = EllipticCurves.getNistP256Params();
98     KeyPairGenerator keyGen = KeyPairGenerator.getInstance("EC");
99     keyGen.initialize(ecParams);
100     KeyPair keyPair = keyGen.generateKeyPair();
101     ECPrivateKey priv = (ECPrivateKey) keyPair.getPrivate();
102 
103     GeneralSecurityException e =
104         assertThrows(
105             GeneralSecurityException.class,
106             () -> new EcdsaSignJce(priv, HashType.SHA1, EcdsaEncoding.DER));
107     TestUtil.assertExceptionContains(e, "Unsupported hash: SHA1");
108   }
109 
110   @Test
testBitFlipAgainstSignatureInstance()111   public void testBitFlipAgainstSignatureInstance() throws Exception {
112     Assume.assumeTrue(!TinkFips.useOnlyFips() || TinkFipsUtil.fipsModuleAvailable());
113 
114     ECParameterSpec ecParams = EllipticCurves.getNistP256Params();
115     KeyPairGenerator keyGen = KeyPairGenerator.getInstance("EC");
116     keyGen.initialize(ecParams);
117     KeyPair keyPair = keyGen.generateKeyPair();
118     ECPublicKey pub = (ECPublicKey) keyPair.getPublic();
119     ECPrivateKey priv = (ECPrivateKey) keyPair.getPrivate();
120 
121     // Sign with EcdsaSign.
122     String message = "Hello";
123     EcdsaSignJce signer = new EcdsaSignJce(priv, HashType.SHA256, EcdsaEncoding.DER);
124     byte[] signature = signer.sign(message.getBytes("UTF-8"));
125 
126     for (int i = 0; i < signature.length; i++) {
127       for (int j = 0; j < 8; j++) {
128         signature[i] = (byte) (signature[i] ^ (1 << j));
129         // Verify with JCE's Signature.
130         Signature verifier = Signature.getInstance("SHA256WithECDSA");
131         verifier.initVerify(pub);
132         verifier.update(message.getBytes("UTF-8"));
133         boolean verified = true;
134         try {
135           verified = verifier.verify(signature);
136         } catch (GeneralSecurityException expected) {
137           verified = false;
138         }
139         assertFalse(verified);
140         signature[i] = (byte) (signature[i] ^ (1 << j));
141       }
142     }
143   }
144 
145   @Test
testFailIfFipsModuleNotAvailable()146   public void testFailIfFipsModuleNotAvailable() throws Exception {
147     Assume.assumeTrue(TinkFips.useOnlyFips() && !TinkFipsUtil.fipsModuleAvailable());
148 
149     ECParameterSpec ecParams = EllipticCurves.getNistP256Params();
150     KeyPairGenerator keyGen = KeyPairGenerator.getInstance("EC");
151     keyGen.initialize(ecParams);
152     KeyPair keyPair = keyGen.generateKeyPair();
153 
154     assertThrows(
155         GeneralSecurityException.class,
156         () ->
157             new EcdsaSignJce(
158                 (ECPrivateKey) keyPair.getPrivate(), HashType.SHA256, EcdsaEncoding.DER));
159   }
160 
161   @Theory
test_validateSignatureInTestVector( @romDataPoints"allTests") SignatureTestVector testVector)162   public void test_validateSignatureInTestVector(
163       @FromDataPoints("allTests") SignatureTestVector testVector) throws Exception {
164     PublicKeyVerify verifier =
165         EcdsaVerifyJce.create((EcdsaPublicKey) testVector.getPrivateKey().getPublicKey());
166     verifier.verify(testVector.getSignature(), testVector.getMessage());
167   }
168 
169   @Theory
test_computeAndValidateFreshSignatureWithTestVector( @romDataPoints"allTests") SignatureTestVector testVector)170   public void test_computeAndValidateFreshSignatureWithTestVector(
171       @FromDataPoints("allTests") SignatureTestVector testVector) throws Exception {
172     PublicKeySign signer = EcdsaSignJce.create((EcdsaPrivateKey) testVector.getPrivateKey());
173     byte[] signature = signer.sign(testVector.getMessage());
174     PublicKeyVerify verifier =
175         EcdsaVerifyJce.create((EcdsaPublicKey) testVector.getPrivateKey().getPublicKey());
176     verifier.verify(signature, testVector.getMessage());
177   }
178 
179   @Theory
test_validateSignatureInTestVectorWithWrongMessage_throws( @romDataPoints"allTests") SignatureTestVector testVector)180   public void test_validateSignatureInTestVectorWithWrongMessage_throws(
181       @FromDataPoints("allTests") SignatureTestVector testVector) throws Exception {
182     PublicKeyVerify verifier =
183         EcdsaVerifyJce.create((EcdsaPublicKey) testVector.getPrivateKey().getPublicKey());
184     byte[] modifiedMessage = Bytes.concat(testVector.getMessage(), new byte[] {0x01});
185     assertThrows(
186         GeneralSecurityException.class,
187         () -> verifier.verify(testVector.getSignature(), modifiedMessage));
188   }
189 
190   @DataPoints("allTests")
191   public static final SignatureTestVector[] ALL_TEST_VECTORS =
192       EcdsaTestUtil.createEcdsaTestVectors();
193 }
194