• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 // Copyright 2018 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 com.google.common.truth.Truth.assertThat;
20 import static org.junit.Assert.assertThrows;
21 
22 import com.google.crypto.tink.InsecureSecretKeyAccess;
23 import com.google.crypto.tink.PublicKeySign;
24 import com.google.crypto.tink.PublicKeyVerify;
25 import com.google.crypto.tink.internal.Util;
26 import com.google.crypto.tink.signature.RsaSsaPssParameters;
27 import com.google.crypto.tink.signature.RsaSsaPssPrivateKey;
28 import com.google.crypto.tink.signature.RsaSsaPssPublicKey;
29 import com.google.crypto.tink.signature.internal.testing.RsaSsaPssTestUtil;
30 import com.google.crypto.tink.signature.internal.testing.SignatureTestVector;
31 import com.google.crypto.tink.subtle.Enums.HashType;
32 import java.security.GeneralSecurityException;
33 import java.security.KeyFactory;
34 import java.security.Provider;
35 import java.security.Security;
36 import java.security.interfaces.RSAPrivateCrtKey;
37 import java.security.spec.RSAPrivateCrtKeySpec;
38 import org.conscrypt.Conscrypt;
39 import org.junit.Assume;
40 import org.junit.Test;
41 import org.junit.experimental.theories.DataPoints;
42 import org.junit.experimental.theories.FromDataPoints;
43 import org.junit.experimental.theories.Theories;
44 import org.junit.experimental.theories.Theory;
45 import org.junit.runner.RunWith;
46 
47 /** Unit tests for RsaSsaPssSignJce. */
48 @RunWith(Theories.class)
49 public class RsaSsaPssSignJceTest {
50 
toRsaPrivateCrtKey(RsaSsaPssPrivateKey key)51   private final RSAPrivateCrtKey toRsaPrivateCrtKey(RsaSsaPssPrivateKey key) throws Exception {
52     KeyFactory keyFactory = EngineFactory.KEY_FACTORY.getInstance("RSA");
53     return (RSAPrivateCrtKey)
54         keyFactory.generatePrivate(
55             new RSAPrivateCrtKeySpec(
56                 key.getPublicKey().getModulus(),
57                 key.getParameters().getPublicExponent(),
58                 key.getPrivateExponent().getBigInteger(InsecureSecretKeyAccess.get()),
59                 key.getPrimeP().getBigInteger(InsecureSecretKeyAccess.get()),
60                 key.getPrimeQ().getBigInteger(InsecureSecretKeyAccess.get()),
61                 key.getPrimeExponentP().getBigInteger(InsecureSecretKeyAccess.get()),
62                 key.getPrimeExponentQ().getBigInteger(InsecureSecretKeyAccess.get()),
63                 key.getCrtCoefficient().getBigInteger(InsecureSecretKeyAccess.get())));
64   }
65 
toEnumHashType(RsaSsaPssParameters.HashType hash)66   private static HashType toEnumHashType(RsaSsaPssParameters.HashType hash) {
67     if (hash == RsaSsaPssParameters.HashType.SHA256) {
68       return HashType.SHA256;
69     } else if (hash == RsaSsaPssParameters.HashType.SHA384) {
70       return HashType.SHA384;
71     } else if (hash == RsaSsaPssParameters.HashType.SHA512) {
72       return HashType.SHA512;
73     } else {
74       throw new IllegalArgumentException("Unsupported hash: " + hash);
75     }
76   }
77 
78   @Test
constructorValidatesHashType()79   public void constructorValidatesHashType() throws Exception {
80     SignatureTestVector testVector = SIGNATURE_TEST_VECTORS[0];
81     RsaSsaPssPrivateKey key = (RsaSsaPssPrivateKey) testVector.getPrivateKey();
82     RSAPrivateCrtKey priv = toRsaPrivateCrtKey(key);
83 
84     assertThrows(
85         GeneralSecurityException.class,
86         () -> new RsaSsaPssSignJce(priv, HashType.SHA1, HashType.SHA1, 20));
87     assertThrows(
88         GeneralSecurityException.class,
89         () -> new RsaSsaPssSignJce(priv, HashType.SHA256, HashType.SHA1, 32));
90     assertThrows(
91         GeneralSecurityException.class,
92         () -> new RsaSsaPssSignJce(priv, HashType.SHA256, HashType.SHA384, 32));
93   }
94 
95   /**
96    * Tests that the verifier can verify a newly generated signature for the message and key in the
97    * test vector.
98    */
99   @Theory
createAndSign_works(@romDataPoints"testVectors") SignatureTestVector testVector)100   public void createAndSign_works(@FromDataPoints("testVectors") SignatureTestVector testVector)
101       throws Exception {
102     RsaSsaPssPrivateKey key = (RsaSsaPssPrivateKey) testVector.getPrivateKey();
103     PublicKeySign signer = RsaSsaPssSignJce.create(key);
104     byte[] signature = signer.sign(testVector.getMessage());
105 
106     // Test that the verifier can verify the signature.
107     PublicKeyVerify verifier = RsaSsaPssVerifyJce.create(key.getPublicKey());
108     verifier.verify(signature, testVector.getMessage());
109   }
110 
111   @Theory
constructorAndSign_works( @romDataPoints"testVectors") SignatureTestVector testVector)112   public void constructorAndSign_works(
113       @FromDataPoints("testVectors") SignatureTestVector testVector) throws Exception {
114     RsaSsaPssPrivateKey testPrivateKey = (RsaSsaPssPrivateKey) testVector.getPrivateKey();
115     RsaSsaPssPublicKey testPublicKey = testPrivateKey.getPublicKey();
116     RsaSsaPssParameters testParameters = testPublicKey.getParameters();
117     if (!testParameters.getVariant().equals(RsaSsaPssParameters.Variant.NO_PREFIX)) {
118       // Constructor doesn't support output prefix.
119       return;
120     }
121     RsaSsaPssSignJce signer =
122         new RsaSsaPssSignJce(
123             toRsaPrivateCrtKey(testPrivateKey),
124             toEnumHashType(testParameters.getSigHashType()),
125             toEnumHashType(testParameters.getMgf1HashType()),
126             testParameters.getSaltLengthBytes());
127     byte[] signature = signer.sign(testVector.getMessage());
128 
129     // Test that the verifier can verify the signature.
130     PublicKeyVerify verifier = RsaSsaPssVerifyJce.create(testPublicKey);
131     verifier.verify(signature, testVector.getMessage());
132   }
133 
134   @DataPoints("testVectors")
135   public static final SignatureTestVector[] SIGNATURE_TEST_VECTORS =
136       RsaSsaPssTestUtil.createRsaPssTestVectors();
137 
138   @Test
usesConscryptImplementationIfInstalled()139   public void usesConscryptImplementationIfInstalled() throws Exception {
140     Assume.assumeFalse(Util.isAndroid());
141 
142     SignatureTestVector testVector = SIGNATURE_TEST_VECTORS[0];
143     RsaSsaPssPrivateKey key = (RsaSsaPssPrivateKey) testVector.getPrivateKey();
144 
145     PublicKeySign signer = RsaSsaPssSignJce.create(key);
146     assertThat(signer.getClass().getSimpleName()).isEqualTo("InternalImpl");
147 
148     Provider conscrypt = Conscrypt.newProvider();
149     Security.addProvider(conscrypt);
150 
151     PublicKeySign signer2 = RsaSsaPssSignJce.create(key);
152     assertThat(signer2.getClass().getSimpleName()).isEqualTo("RsaSsaPssSignConscrypt");
153 
154     Security.removeProvider(conscrypt.getName());
155   }
156 }
157