1 // Copyright 2018 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 package com.google.crypto.tink.signature; 17 18 import static com.google.common.truth.Truth.assertThat; 19 import static org.junit.Assert.fail; 20 21 import com.google.crypto.tink.KeysetHandle; 22 import com.google.crypto.tink.PublicKeyVerify; 23 import com.google.crypto.tink.RegistryConfiguration; 24 import com.google.crypto.tink.TinkProtoKeysetFormat; 25 import com.google.crypto.tink.internal.KeyManagerRegistry; 26 import com.google.crypto.tink.signature.internal.testing.RsaSsaPssTestUtil; 27 import com.google.crypto.tink.signature.internal.testing.SignatureTestVector; 28 import com.google.crypto.tink.subtle.Hex; 29 import java.math.BigInteger; 30 import java.security.GeneralSecurityException; 31 import org.junit.BeforeClass; 32 import org.junit.Test; 33 import org.junit.runner.RunWith; 34 import org.junit.runners.JUnit4; 35 36 /** Unit tests for RsaSsaPssVerifyKeyManager. */ 37 @RunWith(JUnit4.class) 38 public class RsaSsaPssVerifyKeyManagerTest { 39 @BeforeClass beforeClass()40 public static void beforeClass() throws Exception { 41 RsaSsaPssSignKeyManager.registerPair(/* newKeyAllowed= */ true); 42 PublicKeySignWrapper.register(); 43 PublicKeyVerifyWrapper.register(); 44 } 45 46 static class NistTestVector { 47 byte[] msg; 48 byte[] sig; 49 RsaSsaPssPublicKey publicKey; 50 NistTestVector( String modulusHex, String exponentHex, String msg, String sig, RsaSsaPssParameters.HashType sigHash, RsaSsaPssParameters.HashType mgf1Hash, int saltLength)51 public NistTestVector( 52 String modulusHex, 53 String exponentHex, 54 String msg, 55 String sig, 56 RsaSsaPssParameters.HashType sigHash, 57 RsaSsaPssParameters.HashType mgf1Hash, 58 int saltLength) 59 throws Exception { 60 this.msg = Hex.decode(msg); 61 this.sig = Hex.decode(sig); 62 BigInteger modulus = new BigInteger(modulusHex, 16); 63 BigInteger exponent = new BigInteger(exponentHex, 16); 64 RsaSsaPssParameters parameters = 65 RsaSsaPssParameters.builder() 66 .setModulusSizeBits(modulus.bitLength()) 67 .setPublicExponent(exponent) 68 .setVariant(RsaSsaPssParameters.Variant.NO_PREFIX) 69 .setMgf1HashType(mgf1Hash) 70 .setSigHashType(sigHash) 71 .setSaltLengthBytes(saltLength) 72 .build(); 73 this.publicKey = 74 RsaSsaPssPublicKey.builder().setParameters(parameters).setModulus(modulus).build(); 75 } 76 } 77 78 // Test vector from 79 // https://csrc.nist.gov/Projects/Cryptographic-Algorithm-Validation-Program/Digital-Signatures 80 static NistTestVector[] nistTestVectors; 81 82 @BeforeClass setUpNistTestVectors()83 public static void setUpNistTestVectors() throws Exception { 84 nistTestVectors = 85 new NistTestVector[] { 86 new NistTestVector( 87 "a47d04e7cacdba4ea26eca8a4c6e14563c2ce03b623b768c0d49868a57121301dbf783d82f4c055e73960e70550187d0af62ac3496f0a3d9103c2eb7919a72752fa7ce8c688d81e3aee99468887a15288afbb7acb845b7c522b5c64e678fcd3d22feb84b44272700be527d2b2025a3f83c2383bf6a39cf5b4e48b3cf2f56eef0dfff18555e31037b915248694876f3047814415164f2c660881e694b58c28038a032ad25634aad7b39171dee368e3d59bfb7299e4601d4587e68caaf8db457b75af42fc0cf1ae7caced286d77fac6cedb03ad94f1433d2c94d08e60bc1fdef0543cd2951e765b38230fdd18de5d2ca627ddc032fe05bbd2ff21e2db1c2f94d8b", 88 "0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000010e43f", 89 "e002377affb04f0fe4598de9d92d31d6c786040d5776976556a2cfc55e54a1dcb3cb1b126bd6a4bed2a184990ccea773fcc79d246553e6c64f686d21ad4152673cafec22aeb40f6a084e8a5b4991f4c64cf8a927effd0fd775e71e8329e41fdd4457b3911173187b4f09a817d79ea2397fc12dfe3d9c9a0290c8ead31b6690a6", 90 "4f9b425c2058460e4ab2f5c96384da2327fd29150f01955a76b4efe956af06dc08779a374ee4607eab61a93adc5608f4ec36e47f2a0f754e8ff839a8a19b1db1e884ea4cf348cd455069eb87afd53645b44e28a0a56808f5031da5ba9112768dfbfca44ebe63a0c0572b731d66122fb71609be1480faa4e4f75e43955159d70f081e2a32fbb19a48b9f162cf6b2fb445d2d6994bc58910a26b5943477803cdaaa1bd74b0da0a5d053d8b1dc593091db5388383c26079f344e2aea600d0e324164b450f7b9b465111b7265f3b1b063089ae7e2623fc0fda8052cf4bf3379102fbf71d7c98e8258664ceed637d20f95ff0111881e650ce61f251d9c3a629ef222d", 91 RsaSsaPssParameters.HashType.SHA256, 92 RsaSsaPssParameters.HashType.SHA256, 93 32), 94 new NistTestVector( 95 "99a5c8d094a5f917034667a0408b7ecfcaacc3f9784444e21773c3461ec355f0d0f52a5db0568a71d388696788ef66ae7340c6b28dbf925fe83557986575f79cca69217221397ed5808a26f7e7e714c93235f914d45c4a9af4619b20f511ad644bd3412dfdf0ff717f7aac746f310bfa9a141ac3dbf01c1fc74febd197938419c262293505c35f402f9053ad13c51a5960ecde55ec829e953f941af733e58705913767e7a7200d1d09e7e7e2d269fa29a558bb16304b059f13f4ca560a8101fe3720b4a779ec126427326caa132a3d3611d7dbc50336fac789ec406b397e1e36d7daf9b624bf639c82b859288747690c730c980b2f5a239dd95ad5389a2ec90c5778604713710383ae55d4d28c06d4ac26f0d1231f1d6762c8e0d918118156bc637760daea184746b8dcf6f61db274a7ddceaa074937ababad4549b97ab992494a807208abd789823f5d75c4b994089c8072cfc254e0d8202fd896476e96ad9d309a0e8e7301282f07eb2ae8edefb7dbbe13b96e8b4024c6b84de0a05e150285", 96 "00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000008a649", 97 "cc21593a6a0f737e2970b7c07984b070d761726296a07e24e056e68ff846b29cc1548179843d74dcee86479858b2c16e4cb84f2544b4ecdcb4dd43a04bb7183a768ae44a2712bf9ad47883acc2812f958306890ebea408c92eb4f001ed7dbf55f3a9c8d6d9f61e5fe32eb3253e59c18e863169478cd69b9155c335db66016f96", 98 "0aa572a6845b870b8909a683bb7e6e7616f77beff28746116d8bc4b7335546b51e8006ed0fc9a0d66f63ce0b9ebf792d7efd4305d7624d545400a5fd6a06b78f174b86803f7cd1cc93e3a97286f0ea590e40ff26195aa219fe1510a016785223606d9311a16c59a8fe4a6da6ecd0c1d7775039290c2aaa17ed1eb1b54374f7e572db13cca3a638575f8004aa54a2fa98422fc07e43ad3a20dd93001493442677d883914dc74ec1cbebbbd3d2b6bad4666d91457b69b46a1a61f21298f1a67942ec86c876322dd366ed167814e9c8fc9040c5b4b7a859bbd880cb6bc241b9e327ce779e0783b1cf445e0b2f5771b3f5822a1364391c154dc506fff1fb9d9a35f80199a6b30b4b92b92619a40e21aea19284015863c44866c61ed904a7ad19ee04d966c0aae390636243565581ff20bd6e3cfb6e31f5afba964b311dc2d023a21998c8dd50ca453699190bd467429e2f88ace29c4d1da4da61aac1eda2380230aa8dbb63c75a3c1ec04da3a1f880c9c747acdb74a8395af58f5f044015ccaf6e94", 99 RsaSsaPssParameters.HashType.SHA512, 100 RsaSsaPssParameters.HashType.SHA512, 101 0), 102 }; 103 } 104 105 @Test testNistTestVector()106 public void testNistTestVector() throws Exception { 107 for (NistTestVector t : nistTestVectors) { 108 KeysetHandle handle = 109 KeysetHandle.newBuilder() 110 .addEntry(KeysetHandle.importKey(t.publicKey).withRandomId().makePrimary()) 111 .build(); 112 PublicKeyVerify verifier = 113 handle.getPrimitive(RegistryConfiguration.get(), PublicKeyVerify.class); 114 try { 115 verifier.verify(t.sig, t.msg); 116 } catch (GeneralSecurityException e) { 117 fail("Valid signature, should not throw exception" + e); 118 } 119 } 120 } 121 122 @Test test_serializeAndParse_works()123 public void test_serializeAndParse_works() throws Exception { 124 SignatureTestVector testVector = RsaSsaPssTestUtil.createRsaPssTestVectors()[0]; 125 RsaSsaPssPublicKey key = (RsaSsaPssPublicKey) testVector.getPrivateKey().getPublicKey(); 126 KeysetHandle.Builder.Entry entry = KeysetHandle.importKey(key).withFixedId(1951).makePrimary(); 127 KeysetHandle handle = KeysetHandle.newBuilder().addEntry(entry).build(); 128 129 byte[] serializedHandle = TinkProtoKeysetFormat.serializeKeysetWithoutSecret(handle); 130 KeysetHandle parsedHandle = TinkProtoKeysetFormat.parseKeysetWithoutSecret(serializedHandle); 131 assertThat(parsedHandle.equalsKeyset(handle)).isTrue(); 132 } 133 134 @Test testKeyManagerRegistered()135 public void testKeyManagerRegistered() throws Exception { 136 assertThat( 137 KeyManagerRegistry.globalInstance() 138 .getKeyManager( 139 "type.googleapis.com/google.crypto.tink.RsaSsaPssPublicKey", 140 PublicKeyVerify.class)) 141 .isNotNull(); 142 } 143 } 144