Skip to content

Commit 7c789e4

Browse files
juergwcopybara-github
authored andcommitted
Copy tests to internal ECDSA signer and verifier.
The implementation has been moved to internal, but we kept the subtle API. I think it's best to simply run the same tests for both. PiperOrigin-RevId: 736082365 Change-Id: Ib9ab55ded649982aeccbc3b58ea70b7fcfd1b492
1 parent b6612ae commit 7c789e4

File tree

4 files changed

+713
-0
lines changed

4 files changed

+713
-0
lines changed

src/test/java/com/google/crypto/tink/signature/internal/BUILD.bazel

+66
Original file line numberDiff line numberDiff line change
@@ -339,3 +339,69 @@ java_test(
339339
"@maven//:org_conscrypt_conscrypt_openjdk_uber",
340340
],
341341
)
342+
343+
java_test(
344+
name = "EcdsaSignJceTest",
345+
size = "small",
346+
srcs = ["EcdsaSignJceTest.java"],
347+
deps = [
348+
"//src/main/java/com/google/crypto/tink:public_key_sign",
349+
"//src/main/java/com/google/crypto/tink:public_key_verify",
350+
"//src/main/java/com/google/crypto/tink/signature:ecdsa_private_key",
351+
"//src/main/java/com/google/crypto/tink/signature:ecdsa_public_key",
352+
"//src/main/java/com/google/crypto/tink/signature/internal:ecdsa_sign_jce",
353+
"//src/main/java/com/google/crypto/tink/signature/internal:ecdsa_verify_jce",
354+
"//src/main/java/com/google/crypto/tink/signature/internal/testing:ecdsa_test_util",
355+
"//src/main/java/com/google/crypto/tink/signature/internal/testing:signature_test_vector",
356+
"//src/main/java/com/google/crypto/tink/subtle:bytes",
357+
"//src/main/java/com/google/crypto/tink/subtle:elliptic_curves",
358+
"//src/main/java/com/google/crypto/tink/subtle:enums",
359+
"//src/main/java/com/google/crypto/tink/testing:test_util",
360+
"@maven//:junit_junit",
361+
],
362+
)
363+
364+
java_test(
365+
name = "EcdsaSignVerifyFipsTest",
366+
size = "small",
367+
srcs = ["EcdsaSignVerifyFipsTest.java"],
368+
tags = ["fips"],
369+
deps = [
370+
"//src/main/java/com/google/crypto/tink:public_key_sign",
371+
"//src/main/java/com/google/crypto/tink:public_key_verify",
372+
"//src/main/java/com/google/crypto/tink/config:tink_fips",
373+
"//src/main/java/com/google/crypto/tink/config/internal:tink_fips_util",
374+
"//src/main/java/com/google/crypto/tink/signature:ecdsa_private_key",
375+
"//src/main/java/com/google/crypto/tink/signature:ecdsa_public_key",
376+
"//src/main/java/com/google/crypto/tink/signature/internal:ecdsa_sign_jce",
377+
"//src/main/java/com/google/crypto/tink/signature/internal:ecdsa_verify_jce",
378+
"//src/main/java/com/google/crypto/tink/signature/internal/testing:ecdsa_test_util",
379+
"//src/main/java/com/google/crypto/tink/signature/internal/testing:signature_test_vector",
380+
"//src/main/java/com/google/crypto/tink/subtle:elliptic_curves",
381+
"//src/main/java/com/google/crypto/tink/subtle:enums",
382+
"@maven//:junit_junit",
383+
"@maven//:org_conscrypt_conscrypt_openjdk_uber",
384+
],
385+
)
386+
387+
java_test(
388+
name = "EcdsaVerifyJceTest",
389+
size = "small",
390+
srcs = ["EcdsaVerifyJceTest.java"],
391+
data = ["@wycheproof//testvectors:all"],
392+
tags = ["notsan"],
393+
deps = [
394+
"//src/main/java/com/google/crypto/tink/config:tink_fips",
395+
"//src/main/java/com/google/crypto/tink/signature/internal:ecdsa_sign_jce",
396+
"//src/main/java/com/google/crypto/tink/signature/internal:ecdsa_verify_jce",
397+
"//src/main/java/com/google/crypto/tink/subtle:elliptic_curves",
398+
"//src/main/java/com/google/crypto/tink/subtle:enums",
399+
"//src/main/java/com/google/crypto/tink/subtle:hex",
400+
"//src/main/java/com/google/crypto/tink/subtle:subtle_util_cluster",
401+
"//src/main/java/com/google/crypto/tink/testing:test_util",
402+
"//src/main/java/com/google/crypto/tink/testing:wycheproof_test_util",
403+
"@maven//:com_google_code_gson_gson",
404+
"@maven//:junit_junit",
405+
"@maven//:org_conscrypt_conscrypt_openjdk_uber",
406+
],
407+
)
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,119 @@
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.signature.internal;
18+
19+
import static java.nio.charset.StandardCharsets.UTF_8;
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.signature.EcdsaPrivateKey;
26+
import com.google.crypto.tink.signature.EcdsaPublicKey;
27+
import com.google.crypto.tink.signature.internal.testing.EcdsaTestUtil;
28+
import com.google.crypto.tink.signature.internal.testing.SignatureTestVector;
29+
import com.google.crypto.tink.subtle.Bytes;
30+
import com.google.crypto.tink.subtle.EllipticCurves;
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.Signature;
38+
import java.security.interfaces.ECPrivateKey;
39+
import java.security.interfaces.ECPublicKey;
40+
import java.security.spec.ECParameterSpec;
41+
import org.junit.Test;
42+
import org.junit.experimental.theories.DataPoints;
43+
import org.junit.experimental.theories.FromDataPoints;
44+
import org.junit.experimental.theories.Theories;
45+
import org.junit.experimental.theories.Theory;
46+
import org.junit.runner.RunWith;
47+
48+
/** Unit tests for EcdsaSignJce. */
49+
@RunWith(Theories.class)
50+
public class EcdsaSignJceTest {
51+
52+
@Test
53+
public void testBasic() throws Exception {
54+
ECParameterSpec ecParams = EllipticCurves.getNistP256Params();
55+
KeyPairGenerator keyGen = KeyPairGenerator.getInstance("EC");
56+
keyGen.initialize(ecParams);
57+
KeyPair keyPair = keyGen.generateKeyPair();
58+
ECPublicKey pub = (ECPublicKey) keyPair.getPublic();
59+
ECPrivateKey priv = (ECPrivateKey) keyPair.getPrivate();
60+
61+
// Sign with EcdsaSign.
62+
String message = "Hello";
63+
EcdsaSignJce signer = new EcdsaSignJce(priv, HashType.SHA256, EcdsaEncoding.DER);
64+
byte[] signature = signer.sign(message.getBytes(UTF_8));
65+
66+
// Verify with JCE's Signature.
67+
Signature verifier = Signature.getInstance("SHA256WithECDSA");
68+
verifier.initVerify(pub);
69+
verifier.update(message.getBytes(UTF_8));
70+
assertTrue(verifier.verify(signature));
71+
}
72+
73+
@Test
74+
public void testConstructorExceptions() throws Exception {
75+
ECParameterSpec ecParams = EllipticCurves.getNistP256Params();
76+
KeyPairGenerator keyGen = KeyPairGenerator.getInstance("EC");
77+
keyGen.initialize(ecParams);
78+
KeyPair keyPair = keyGen.generateKeyPair();
79+
ECPrivateKey priv = (ECPrivateKey) keyPair.getPrivate();
80+
81+
GeneralSecurityException e =
82+
assertThrows(
83+
GeneralSecurityException.class,
84+
() -> new EcdsaSignJce(priv, HashType.SHA1, EcdsaEncoding.DER));
85+
TestUtil.assertExceptionContains(e, "Unsupported hash: SHA1");
86+
}
87+
88+
@Theory
89+
public void test_validateSignatureInTestVector(
90+
@FromDataPoints("allTests") SignatureTestVector testVector) throws Exception {
91+
PublicKeyVerify verifier =
92+
EcdsaVerifyJce.create((EcdsaPublicKey) testVector.getPrivateKey().getPublicKey());
93+
verifier.verify(testVector.getSignature(), testVector.getMessage());
94+
}
95+
96+
@Theory
97+
public void test_computeAndValidateFreshSignatureWithTestVector(
98+
@FromDataPoints("allTests") SignatureTestVector testVector) throws Exception {
99+
PublicKeySign signer = EcdsaSignJce.create((EcdsaPrivateKey) testVector.getPrivateKey());
100+
byte[] signature = signer.sign(testVector.getMessage());
101+
PublicKeyVerify verifier =
102+
EcdsaVerifyJce.create((EcdsaPublicKey) testVector.getPrivateKey().getPublicKey());
103+
verifier.verify(signature, testVector.getMessage());
104+
}
105+
106+
@Theory
107+
public void test_validateSignatureInTestVectorWithWrongMessage_throws(
108+
@FromDataPoints("allTests") SignatureTestVector testVector) throws Exception {
109+
PublicKeyVerify verifier =
110+
EcdsaVerifyJce.create((EcdsaPublicKey) testVector.getPrivateKey().getPublicKey());
111+
byte[] modifiedMessage = Bytes.concat(testVector.getMessage(), new byte[] {0x01});
112+
assertThrows(
113+
GeneralSecurityException.class,
114+
() -> verifier.verify(testVector.getSignature(), modifiedMessage));
115+
}
116+
117+
@DataPoints("allTests")
118+
public static final SignatureTestVector[] testVectors = EcdsaTestUtil.createEcdsaTestVectors();
119+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,147 @@
1+
// Copyright 2025 Google LLC
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.signature.internal;
18+
19+
import static java.nio.charset.StandardCharsets.UTF_8;
20+
import static org.junit.Assert.assertThrows;
21+
22+
import com.google.crypto.tink.PublicKeySign;
23+
import com.google.crypto.tink.PublicKeyVerify;
24+
import com.google.crypto.tink.config.TinkFips;
25+
import com.google.crypto.tink.config.internal.TinkFipsUtil;
26+
import com.google.crypto.tink.signature.EcdsaPrivateKey;
27+
import com.google.crypto.tink.signature.EcdsaPublicKey;
28+
import com.google.crypto.tink.signature.internal.testing.EcdsaTestUtil;
29+
import com.google.crypto.tink.signature.internal.testing.SignatureTestVector;
30+
import com.google.crypto.tink.subtle.EllipticCurves;
31+
import com.google.crypto.tink.subtle.EllipticCurves.EcdsaEncoding;
32+
import com.google.crypto.tink.subtle.Enums.HashType;
33+
import java.security.GeneralSecurityException;
34+
import java.security.KeyPair;
35+
import java.security.KeyPairGenerator;
36+
import java.security.Security;
37+
import java.security.interfaces.ECPrivateKey;
38+
import java.security.interfaces.ECPublicKey;
39+
import org.conscrypt.Conscrypt;
40+
import org.junit.Assume;
41+
import org.junit.Before;
42+
import org.junit.Test;
43+
import org.junit.runner.RunWith;
44+
import org.junit.runners.JUnit4;
45+
46+
/**
47+
* Unit tests for EcdsaSignJce and EcdsaVerifyJce in FIPS mode.
48+
*
49+
* <p>This test should be run with the <code>--use_only_fips=true</code>, both with the BoringCrypto
50+
* FIPS module enabled and disabled with <code>--define=BORINGSSL_FIPS=0</code>.
51+
*/
52+
@RunWith(JUnit4.class)
53+
public final class EcdsaSignVerifyFipsTest {
54+
55+
@Before
56+
public void useConscrypt() throws Exception {
57+
Assume.assumeTrue(TinkFips.useOnlyFips());
58+
Conscrypt.checkAvailability();
59+
Security.addProvider(Conscrypt.newProvider());
60+
}
61+
62+
private static final SignatureTestVector[] testVectors = EcdsaTestUtil.createEcdsaTestVectors();
63+
64+
@Test
65+
public void createWorksIfFipsModuleAvailable() throws Exception {
66+
Assume.assumeTrue(TinkFipsUtil.fipsModuleAvailable());
67+
for (SignatureTestVector testVector : testVectors) {
68+
PublicKeySign signer = EcdsaSignJce.create((EcdsaPrivateKey) testVector.getPrivateKey());
69+
byte[] signature = signer.sign(testVector.getMessage());
70+
PublicKeyVerify verifier =
71+
EcdsaVerifyJce.create((EcdsaPublicKey) testVector.getPrivateKey().getPublicKey());
72+
verifier.verify(signature, testVector.getMessage());
73+
}
74+
}
75+
76+
@Test
77+
public void createThrowsIfFipsModuleNotAvailable() throws Exception {
78+
Assume.assumeFalse(TinkFipsUtil.fipsModuleAvailable());
79+
for (SignatureTestVector testVector : testVectors) {
80+
assertThrows(
81+
GeneralSecurityException.class,
82+
() -> EcdsaSignJce.create((EcdsaPrivateKey) testVector.getPrivateKey()));
83+
assertThrows(
84+
GeneralSecurityException.class,
85+
() -> EcdsaVerifyJce.create((EcdsaPublicKey) testVector.getPrivateKey().getPublicKey()));
86+
}
87+
}
88+
89+
@Test
90+
public void constructorsWorkIfFipsModuleAvailable() throws Exception {
91+
Assume.assumeTrue(TinkFipsUtil.fipsModuleAvailable());
92+
93+
KeyPairGenerator keyGen = KeyPairGenerator.getInstance("EC");
94+
keyGen.initialize(EllipticCurves.getNistP256Params());
95+
KeyPair keyPair = keyGen.generateKeyPair();
96+
ECPublicKey pub = (ECPublicKey) keyPair.getPublic();
97+
ECPrivateKey priv = (ECPrivateKey) keyPair.getPrivate();
98+
99+
byte[] message = "Hello".getBytes(UTF_8);
100+
101+
EcdsaSignJce signer = new EcdsaSignJce(priv, HashType.SHA256, EcdsaEncoding.DER);
102+
byte[] signature = signer.sign(message);
103+
104+
EcdsaVerifyJce verifier = new EcdsaVerifyJce(pub, HashType.SHA256, EcdsaEncoding.DER);
105+
verifier.verify(signature, message);
106+
}
107+
108+
@Test
109+
public void constructorsDontValidateHashFunctionType() throws Exception {
110+
Assume.assumeTrue(TinkFipsUtil.fipsModuleAvailable());
111+
// Using Curve P521 with SHA256 is not allowed by the FIPS 140-2, see
112+
// https://nvlpubs.nist.gov/nistpubs/FIPS/NIST.FIPS.186-5.pdf Page 21.
113+
//
114+
// This is currently not enforced.
115+
KeyPairGenerator keyGen = KeyPairGenerator.getInstance("EC");
116+
keyGen.initialize(EllipticCurves.getNistP521Params());
117+
KeyPair keyPair = keyGen.generateKeyPair();
118+
ECPublicKey pub = (ECPublicKey) keyPair.getPublic();
119+
ECPrivateKey priv = (ECPrivateKey) keyPair.getPrivate();
120+
121+
byte[] message = "Hello".getBytes(UTF_8);
122+
123+
EcdsaSignJce signer = new EcdsaSignJce(priv, HashType.SHA256, EcdsaEncoding.DER);
124+
byte[] signature = signer.sign(message);
125+
126+
EcdsaVerifyJce verifier = new EcdsaVerifyJce(pub, HashType.SHA256, EcdsaEncoding.DER);
127+
verifier.verify(signature, message);
128+
}
129+
130+
@Test
131+
public void constructorThrowsIfFipsModuleNotAvailable() throws Exception {
132+
Assume.assumeFalse(TinkFipsUtil.fipsModuleAvailable());
133+
134+
KeyPairGenerator keyGen = KeyPairGenerator.getInstance("EC");
135+
keyGen.initialize(EllipticCurves.getNistP256Params());
136+
KeyPair keyPair = keyGen.generateKeyPair();
137+
ECPublicKey pub = (ECPublicKey) keyPair.getPublic();
138+
ECPrivateKey priv = (ECPrivateKey) keyPair.getPrivate();
139+
140+
assertThrows(
141+
GeneralSecurityException.class,
142+
() -> new EcdsaSignJce(priv, HashType.SHA256, EcdsaEncoding.DER));
143+
assertThrows(
144+
GeneralSecurityException.class,
145+
() -> new EcdsaVerifyJce(pub, HashType.SHA256, EcdsaEncoding.DER));
146+
}
147+
}

0 commit comments

Comments
 (0)