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