• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 // Copyright 2022 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;
18 
19 import static java.nio.charset.StandardCharsets.UTF_8;
20 import static org.junit.Assert.assertThrows;
21 
22 import com.google.crypto.tink.DeterministicAead;
23 import com.google.crypto.tink.InsecureSecretKeyAccess;
24 import com.google.crypto.tink.KeyTemplates;
25 import com.google.crypto.tink.KeysetHandle;
26 import com.google.crypto.tink.PublicKeySign;
27 import com.google.crypto.tink.PublicKeyVerify;
28 import com.google.crypto.tink.RegistryConfiguration;
29 import com.google.crypto.tink.TinkJsonProtoKeysetFormat;
30 import com.google.crypto.tink.daead.DeterministicAeadConfig;
31 import com.google.crypto.tink.testing.TestUtil;
32 import java.security.GeneralSecurityException;
33 import org.junit.BeforeClass;
34 import org.junit.experimental.theories.DataPoints;
35 import org.junit.experimental.theories.FromDataPoints;
36 import org.junit.experimental.theories.Theories;
37 import org.junit.experimental.theories.Theory;
38 import org.junit.runner.RunWith;
39 
40 /** Unit tests for the Signature package. Uses only the public API. */
41 @RunWith(Theories.class)
42 public final class SignatureTest {
43 
44   @BeforeClass
setUp()45   public static void setUp() throws Exception {
46     SignatureConfig.register();
47     DeterministicAeadConfig.register(); // Needed for getPrimitiveFromNonSignatureKeyset_throws.
48   }
49 
50   @DataPoints("templates")
51   public static final String[] TEMPLATES =
52       new String[] {
53         // Only use one key template from the RSA key managers because key generation is slow.
54         "RSA_SSA_PKCS1_3072_SHA256_F4",
55         "RSA_SSA_PSS_3072_SHA256_F4",
56         "ECDSA_P256",
57         "ECDSA_P256_RAW",
58         "ECDSA_P384_SHA384",
59         "ECDSA_P384_SHA512",
60         "ECDSA_P521",
61         "ED25519",
62         "ED25519_RAW",
63       };
64 
65   @Theory
createSignVerify(@romDataPoints"templates") String templateName)66   public void createSignVerify(@FromDataPoints("templates") String templateName)
67       throws Exception {
68     if (TestUtil.isTsan()) {
69       // KeysetHandle.generateNew is too slow in Tsan.
70       return;
71     }
72     KeysetHandle privateHandle = KeysetHandle.generateNew(KeyTemplates.get(templateName));
73     KeysetHandle publicHandle = privateHandle.getPublicKeysetHandle();
74 
75     PublicKeySign signer =
76         privateHandle.getPrimitive(RegistryConfiguration.get(), PublicKeySign.class);
77     PublicKeyVerify verifier =
78         publicHandle.getPrimitive(RegistryConfiguration.get(), PublicKeyVerify.class);
79 
80     byte[] data = "data".getBytes(UTF_8);
81     byte[] sig = signer.sign(data);
82     verifier.verify(sig, data);
83 
84     KeysetHandle otherPrivateHandle = KeysetHandle.generateNew(KeyTemplates.get(templateName));
85     PublicKeyVerify otherVerifier =
86         otherPrivateHandle
87             .getPublicKeysetHandle()
88             .getPrimitive(RegistryConfiguration.get(), PublicKeyVerify.class);
89     assertThrows(
90         GeneralSecurityException.class, () -> otherVerifier.verify(sig, data));
91 
92     byte[] invalid = "invalid".getBytes(UTF_8);
93     byte[] empty = "".getBytes(UTF_8);
94     assertThrows(GeneralSecurityException.class, () -> verifier.verify(sig, invalid));
95     assertThrows(GeneralSecurityException.class, () -> verifier.verify(invalid, data));
96     assertThrows(GeneralSecurityException.class, () -> verifier.verify(empty, data));
97     verifier.verify(signer.sign(empty), empty);
98   }
99 
100   // Keyset with one private key for PublicKeySign, serialized in Tink's JSON format.
101   private static final String JSON_PRIVATE_KEYSET = ""
102       + "{"
103       + "  \"primaryKeyId\": 775870498,"
104       + "  \"key\": ["
105       + "    {"
106       + "      \"keyData\": {"
107       + "        \"typeUrl\": \"type.googleapis.com/google.crypto.tink.EcdsaPrivateKey\","
108       + "        \"value\": \"GiA/E6s6KksNXrEd9hLdStvhsmdsONgpSODH/rZsBbBDehJMIiApA+NmYiv"
109       + "xRfhMuvTKZAwqETmn+WagBP/reucEjEvXkRog1AJ5GBzf+n27xnj9KcoGllF9NIFfQrDEP99FNH+Cne4"
110       + "SBhgCEAIIAw==\","
111       + "        \"keyMaterialType\": \"ASYMMETRIC_PRIVATE\""
112       + "      },"
113       + "      \"status\": \"ENABLED\","
114       + "      \"keyId\": 775870498,"
115       + "      \"outputPrefixType\": \"TINK\""
116       + "    }"
117       + "  ]"
118       + "}";
119 
120   // Keyset with the corresponding public key for PublicKeyVerify, serialized in Tink's JSON format.
121   private static final String JSON_PUBLIC_KEYSET = ""
122       + "{"
123       + "  \"primaryKeyId\": 775870498,"
124       + "  \"key\": ["
125       + "    {"
126       + "      \"keyData\": {"
127       + "        \"typeUrl\": \"type.googleapis.com/google.crypto.tink.EcdsaPublicKey\","
128       + "        \"value\": \"IiApA+NmYivxRfhMuvTKZAwqETmn+WagBP/reucEjEvXkRog1AJ5GBzf+n2"
129       + "7xnj9KcoGllF9NIFfQrDEP99FNH+Cne4SBhgCEAIIAw==\","
130       + "        \"keyMaterialType\": \"ASYMMETRIC_PUBLIC\""
131       + "      },"
132       + "      \"status\": \"ENABLED\","
133       + "      \"keyId\": 775870498,"
134       + "      \"outputPrefixType\": \"TINK\""
135       + "    }"
136       + "  ]"
137       + "}";
138 
139   @Theory
readKeysetEncryptDecrypt()140   public void readKeysetEncryptDecrypt()
141       throws Exception {
142     KeysetHandle privateHandle =
143         TinkJsonProtoKeysetFormat.parseKeyset(JSON_PRIVATE_KEYSET, InsecureSecretKeyAccess.get());
144     KeysetHandle publicHandle =
145         TinkJsonProtoKeysetFormat.parseKeyset(JSON_PUBLIC_KEYSET, InsecureSecretKeyAccess.get());
146 
147     PublicKeySign signer =
148         privateHandle.getPrimitive(RegistryConfiguration.get(), PublicKeySign.class);
149     PublicKeyVerify verifier =
150         publicHandle.getPrimitive(RegistryConfiguration.get(), PublicKeyVerify.class);
151 
152     byte[] data = "data".getBytes(UTF_8);
153     byte[] sig = signer.sign(data);
154     verifier.verify(sig, data);
155   }
156 
157   // Keyset with multiple keys. The first key is the same as in JSON_PRIVATE_KEYSET. The second
158   // key is the primary key and will be used for signing.
159   private static final String JSON_PRIVATE_KEYSET_WITH_MULTIPLE_KEYS =
160       ""
161           + "{"
162           + "  \"primaryKeyId\": 1641152230,"
163           + "  \"key\": ["
164           + "    {"
165           + "      \"keyData\": {"
166           + "        \"typeUrl\": \"type.googleapis.com/google.crypto.tink.EcdsaPrivateKey\","
167           + "        \"value\": \"GiA/E6s6KksNXrEd9hLdStvhsmdsONgpSODH/rZsBbBDehJMIiApA+NmYiv"
168           + "xRfhMuvTKZAwqETmn+WagBP/reucEjEvXkRog1AJ5GBzf+n27xnj9KcoGllF9NIFfQrDEP99FNH+Cne4"
169           + "SBhgCEAIIAw==\","
170           + "        \"keyMaterialType\": \"ASYMMETRIC_PRIVATE\""
171           + "      },"
172           + "      \"status\": \"ENABLED\","
173           + "      \"keyId\": 775870498,"
174           + "      \"outputPrefixType\": \"TINK\""
175           + "    },"
176           + "    {"
177           + "      \"keyData\": {"
178           + "        \"typeUrl\":"
179           + "\"type.googleapis.com/google.crypto.tink.RsaSsaPkcs1PrivateKey\","
180           + "        \"value\": \"QoACGwosE5u2kgqsgur5eBYUTK8slJ4zjjmXBI2xCKIixqtULDfgXh2ILuZ"
181           + "7y7Myt/fmjvA4QajmKMZOHFuf6h+Z1kQN+IpKxM64RhbCoaAEc+yH5Xr75V3/qzsPW1IxcM3WVmbLn+b"
182           + "gObk3snAB9sYS8ryL1YsexZcCoshmH3ImZ/egFx6c4opPUw1jYBdMon4V+RukubFm2RRgROZRw7CZh/N"
183           + "CqYEwzbdTvPgR+g/Kbruo6yLLY4Dksq9zsM8hlhNSPaGpCjzbmBsAwT6ayEyjusGWcVB79kDaI34Y3+7"
184           + "EZ2J/4nn1D07bJGCvWz60SIVRF58beeUrc+LONKAHllx00TqAAha2k6mwibOpjfrmGpgqMTKiYsqPmJX"
185           + "w+I8MaOprCzEovsnEyLrrWFpZytoaJEEZ7SBRKavV0S/B+mSc2fTfvsF2NynbHKB62z6A5ODl6YWeF0n"
186           + "yjM7NCcxNAce/iMUdZ1qcyOGsjTWDQnp0G2cgtU3AqDjKlvodrx87DxdJB8T/cLKPpEZMbtG4TDHw2zl"
187           + "jFtdrDj38JjDN6gR3zUKhtdz8qjPD5x5K5ePQ2oakI72AuXIqCZNjGSa7rs/T8Mnv+5Uqqh2SuSQ2KvR"
188           + "Fmts6it3WSMTrQZGQdhMB7rW1h5+LqioVjc1EQyMibFHUshSvjyKfw0Pvv7YKbvv606AoIgEygAKXsLn"
189           + "L7TxNSYbgG65K3g+4LVmkbwyTp4R6XM6ilZS8S2Ypqin5P3+xZefva2vu223pC9+yULO1FUU14zZR96+"
190           + "/BpGTt3O1Psi105hi0a/ATCz4RWTeydKzxu4WP4bNZ3KJ7KsbpRVjRxIOGer38t1Igl5MnVlOZSHmWHH"
191           + "nkYBqRiu+af2xWr+fJpvHF6MyoKZ7fZwFYVE8k6BiA7mjxf87IqRzLtKSHWxR75/Rxr74rErGvAdksGU"
192           + "b5YDtaoH2XRHA4pwPNPayvls0hKsdph9XsypYfM8VCTbBoR5eJWs9N0hCkE5Q74CHfzyi1y5jhXeeFn7"
193           + "Vb7CPcJJrqLUdlGpnKoAC7wKQXuC8RIg0zAwQXubmYng/q0IPrtdTsKAkc+neoZ79oxX4bK8TeJts10P"
194           + "WXvWRmlGiKG0NN9432C36ew4f8mSmZQvwsTjgpuQF/iRFh6Eq6jU4c39y+9clMI68nXAnIeA/Es16P3w"
195           + "iw0V2BW4tpSgzB4OwnWA8YRjCHEj2jA1jOg3DaMOKM0MpXHJRpNe6D4iJKwL3fUqZAeIllmaeHgczexJ"
196           + "ed3Nt8XrArZJEIwpQrxWxTU305RHSG2gaOENPTA3IG34ObNEbOrhxJ4SbjkT/o27rpVMEQMgA+MaCGXS"
197           + "kp7IPkkDMLuxpZyHd25ECjldiT1+tXvUwxGPzTEfGgSKAAv3LCIvMyivCnsG2257pZdE57CgvN/sPUDw"
198           + "ib2zmzSjyCWepLkYOecLgvJHDLUkzClKUm5w4KnCWBD4W6iWKJqRoY1qOKxlraOeKMYPnyIpDcOcb3jn"
199           + "bNxWs+QjM/BCxczjs00D7syvw2LJq4z/sD9Z8DE5e65nn9uzmLhnjukCS9MhPSesM3JIYSrK9m7jJ7Sp"
200           + "vbRpJq+1khyns9BUldhH8Fs680g4uj7XV25tRj4wbz68BQx4AuwvhAFAsVRjjHuEzaE+ic3QLM5BY+/g"
201           + "+dY73WplALotge0A/yTO2rmwS1OyCKmxUlAjO6cKoN6W7QSl7MVKUK/BL0sa2Cxy1CCMagAQQP/mjdL4"
202           + "LePycC+amQFUv3uIimL0YQ612IbaOAeJ50VM89293EQglGPB/PNBSV8BQVEe+TiTGAifI/5uFnzVBOjH"
203           + "oOoiRI/bmP3mX6HFGd81mWX6rV8BCSkelyRhwD96OLTiPv/57xIxYT/bvPmrCIADsGTqzQ2qQtVWAq60"
204           + "KnsTQtRIhcXQ0gDPuW4iJGqMQeOAm03ewcZkul68UmJjToyziP1Dcr2KLlGGVPghs3DzfHQnvm1xwIOE"
205           + "Tzv3JWXh0PCtKeTluoXILD7RDLp0mb5ieaMRCPBYMwI23BsMd6yWWf6KfPKOOOWNCzGVL+bC+VTvjueK"
206           + "Q/5tTcUvXIIeMXtgu6nWDOX3FQfMGDvSRcM7xoLe3P40vnYWHFUdpAEbRFhTRMpoDPgRXJCd8TLRSEHi"
207           + "eedCcOSMMghehAKdzxvoRM31DuPBSKYe1Qys0ApnSs51vZLHDGkOYGbcD6Q+NdmfoE3kY0k3r+vTKDVh"
208           + "+IE0QtY2HlXHOCs7VAR5HDsKIK2x/KtD6Cvf3R667bRItIZgdA6Bf+naAoxpcWwxDXSCWsmB26wa4hrC"
209           + "1qSSRsp0zB2p6vgqDkFz7e9tCR89kzWo+oRyVdAZk5gllPA6iBVsQ6xLdoN0FoPTAbKYXHricSMGYb5K"
210           + "mbHb6sAvpw147w0aOealtndgkuu1SS0XEgRKMBCIDAQABGoAE7PMXsNlwa3uE6iDnmhmoArzugzmnJRh"
211           + "ytBzcL4dGhrIOMwQncaHNfDPsTWyfjLha6Q0TfBPiDGm0Bq+/IygQM3WKofVHuH2J7+bt4WpS0ARSQbl"
212           + "fXiXazvYAD4j4LVtBE+TuBybGB/na2ui/G48452ip+FG5V7G6sEfkxis3ETgZtyTB6oDDXXaymMoGlic"
213           + "Gsuc66BWPRiko4OvnS8PRpi0yobdw65gtggDrrD/GS4H+FVq1kEOrVKFC4UZZYyaimYnl5IS1O9Pz1vm"
214           + "5epicWptFodAFo5N0CzK/hwwcocb02CuUgxONrS3Zypw+GxyMdgRI2P/Cpihm7USCOzNxjHEmNgt7Wuw"
215           + "tQChc4ZEdlZ1KXFXXEBZf6hwLNKk5Jh7MOmJfMSU9L9J1Tqkrfls268T0FEUmD0nciLRHoeqjaD9cWxa"
216           + "h89F6r1UuCo+LVsQp4y7g/qXmxUvLvFR6JPZwHx9iyTbVEe54/P2bcgbttEIYjqgs5FLt1cG6dqjKiFx"
217           + "lC8SLZJsMg1xpZNTVe7jpzX1Ot0nK8yY/UmLUrgq0AHH31N3L9a7vg6v/uI5kdWZZoASjBlVzLNgeBCo"
218           + "QGXwFdTNENeDYCAWXEgO65K1huq3UcoJjjvCTD0tlrdTNX7q915TS3e49xgJT3lB4TynAo2Fgs9OdZta"
219           + "ovVFKpiE5K6MSAggE\","
220           + "        \"keyMaterialType\": \"ASYMMETRIC_PRIVATE\""
221           + "      },"
222           + "      \"status\": \"ENABLED\","
223           + "      \"keyId\": 1641152230,"
224           + "      \"outputPrefixType\": \"RAW\""
225           + "    },"
226           + "    {"
227           + "      \"keyData\": {"
228           + "        \"typeUrl\": \"type.googleapis.com/google.crypto.tink.EcdsaPrivateKey\","
229           + "        \"value\": \"GiBCX+pnT5vwku4z7jfD4OTgvRtft3S4KuYHovWsQrlTPhJMIiAzcsfCVUz"
230           + "GZ13oTmMLxBYd8wFM5G+dgCXMeF8tYXayrRogGOzqO4xtS0H4wl/5M/QUkLDnpnmt2TqIiQlFk0vAdck"
231           + "SBhgCEAIIAw==\","
232           + "        \"keyMaterialType\": \"ASYMMETRIC_PRIVATE\""
233           + "      },"
234           + "      \"status\": \"ENABLED\","
235           + "      \"keyId\": 857170602,"
236           + "      \"outputPrefixType\": \"LEGACY\""
237           + "    }"
238           + "  ]"
239           + "}";
240 
241   // Keyset with the public keys of the keys from JSON_PRIVATE_KEYSET_WITH_MULTIPLE_KEYS.
242   private static final String JSON_PUBLIC_KEYSET_WITH_MULTIPLE_KEYS = ""
243       + "{"
244       + "  \"primaryKeyId\": 1641152230,"
245       + "  \"key\": ["
246       + "    {"
247       + "      \"keyData\": {"
248       + "        \"typeUrl\": \"type.googleapis.com/google.crypto.tink.EcdsaPublicKey\","
249       + "        \"value\": \"IiApA+NmYivxRfhMuvTKZAwqETmn+WagBP/reucEjEvXkRog1AJ5GBzf+n2"
250       + "7xnj9KcoGllF9NIFfQrDEP99FNH+Cne4SBhgCEAIIAw==\","
251       + "        \"keyMaterialType\": \"ASYMMETRIC_PUBLIC\""
252       + "      },"
253       + "      \"status\": \"ENABLED\","
254       + "      \"keyId\": 775870498,"
255       + "      \"outputPrefixType\": \"TINK\""
256       + "    },"
257       + "    {"
258       + "      \"keyData\": {"
259       + "        \"typeUrl\":"
260       + "\"type.googleapis.com/google.crypto.tink.RsaSsaPkcs1PublicKey\","
261       + "        \"value\": \"IgMBAAEagATs8xew2XBre4TqIOeaGagCvO6DOaclGHK0HNwvh0aGsg4zBCd"
262       + "xoc18M+xNbJ+MuFrpDRN8E+IMabQGr78jKBAzdYqh9Ue4fYnv5u3halLQBFJBuV9eJdrO9gAPiPgtW0E"
263       + "T5O4HJsYH+dra6L8bjzjnaKn4UblXsbqwR+TGKzcROBm3JMHqgMNddrKYygaWJway5zroFY9GKSjg6+d"
264       + "Lw9GmLTKht3DrmC2CAOusP8ZLgf4VWrWQQ6tUoULhRlljJqKZieXkhLU70/PW+bl6mJxam0Wh0AWjk3Q"
265       + "LMr+HDByhxvTYK5SDE42tLdnKnD4bHIx2BEjY/8KmKGbtRII7M3GMcSY2C3ta7C1AKFzhkR2VnUpcVdc"
266       + "QFl/qHAs0qTkmHsw6Yl8xJT0v0nVOqSt+WzbrxPQURSYPSdyItEeh6qNoP1xbFqHz0XqvVS4Kj4tWxCn"
267       + "jLuD+pebFS8u8VHok9nAfH2LJNtUR7nj8/ZtyBu20QhiOqCzkUu3Vwbp2qMqIXGULxItkmwyDXGlk1NV"
268       + "7uOnNfU63ScrzJj9SYtSuCrQAcffU3cv1ru+Dq/+4jmR1ZlmgBKMGVXMs2B4EKhAZfAV1M0Q14NgIBZc"
269       + "SA7rkrWG6rdRygmOO8JMPS2Wt1M1fur3XlNLd7j3GAlPeUHhPKcCjYWCz051m1qi9UUqmITkroxICCAQ"
270       + "=\","
271       + "        \"keyMaterialType\": \"ASYMMETRIC_PUBLIC\""
272       + "      },"
273       + "      \"status\": \"ENABLED\","
274       + "      \"keyId\": 1641152230,"
275       + "      \"outputPrefixType\": \"RAW\""
276       + "    },"
277       + "    {"
278       + "      \"keyData\": {"
279       + "        \"typeUrl\": \"type.googleapis.com/google.crypto.tink.EcdsaPublicKey\","
280       + "        \"value\": \"IiAzcsfCVUzGZ13oTmMLxBYd8wFM5G+dgCXMeF8tYXayrRogGOzqO4xtS0H"
281       + "4wl/5M/QUkLDnpnmt2TqIiQlFk0vAdckSBhgCEAIIAw==\","
282       + "        \"keyMaterialType\": \"ASYMMETRIC_PUBLIC\""
283       + "      },"
284       + "      \"status\": \"ENABLED\","
285       + "      \"keyId\": 857170602,"
286       + "      \"outputPrefixType\": \"LEGACY\""
287       + "    }"
288       + "  ]"
289       + "}";
290 
291   @Theory
multipleKeysReadKeysetWithEncryptDecrypt()292   public void multipleKeysReadKeysetWithEncryptDecrypt()
293       throws Exception {
294     KeysetHandle privateHandle =
295         TinkJsonProtoKeysetFormat.parseKeyset(
296             JSON_PRIVATE_KEYSET_WITH_MULTIPLE_KEYS, InsecureSecretKeyAccess.get());
297     KeysetHandle publicHandle =
298         TinkJsonProtoKeysetFormat.parseKeyset(
299             JSON_PUBLIC_KEYSET_WITH_MULTIPLE_KEYS, InsecureSecretKeyAccess.get());
300 
301     PublicKeySign signer =
302         privateHandle.getPrimitive(RegistryConfiguration.get(), PublicKeySign.class);
303     PublicKeyVerify verifier =
304         publicHandle.getPrimitive(RegistryConfiguration.get(), PublicKeyVerify.class);
305 
306     byte[] data = "data".getBytes(UTF_8);
307     byte[] sig = signer.sign(data);
308     verifier.verify(sig, data);
309 
310     // Also test that verifier can verify signatures of a non-primary key. We use
311     // JSON_PRIVATE_KEYSET to sign with the first key.
312     KeysetHandle privateHandle1 =
313         TinkJsonProtoKeysetFormat.parseKeyset(JSON_PRIVATE_KEYSET, InsecureSecretKeyAccess.get());
314     PublicKeySign signer1 =
315         privateHandle1.getPrimitive(RegistryConfiguration.get(), PublicKeySign.class);
316 
317     byte[] data1 = "data1".getBytes(UTF_8);
318     byte[] sig1 = signer1.sign(data1);
319     verifier.verify(sig1, data1);
320   }
321 
322   // A keyset with a valid DeterministicAead key. This keyset can't be used with the PublicKeySign
323   // or PublicKeyVerify.
324   private static final String JSON_DAEAD_KEYSET =
325       ""
326           + "{"
327           + "  \"primaryKeyId\": 961932622,"
328           + "  \"key\": ["
329           + "    {"
330           + "      \"keyData\": {"
331           + "        \"typeUrl\": \"type.googleapis.com/google.crypto.tink.AesSivKey\","
332           + "        \"keyMaterialType\": \"SYMMETRIC\","
333           + "        \"value\": \"EkCJ9r5iwc5uxq5ugFyrHXh5dijTa7qalWUgZ8Gf08RxNd545FjtLMYL7ObcaFtCS"
334           + "kvV2+7u6F2DN+kqUjAfkf2W\""
335           + "      },"
336           + "      \"outputPrefixType\": \"TINK\","
337           + "      \"keyId\": 961932622,"
338           + "      \"status\": \"ENABLED\""
339           + "    }"
340           + "  ]"
341           + "}";
342 
343   @Theory
getPrimitiveFromNonSignatureKeyset_throws()344   public void getPrimitiveFromNonSignatureKeyset_throws()
345       throws Exception {
346     KeysetHandle handle =
347         TinkJsonProtoKeysetFormat.parseKeyset(
348             JSON_DAEAD_KEYSET, InsecureSecretKeyAccess.get());
349 
350     // Test that the keyset can create a DeterministicAead primitive, but neither PublicKeySign
351     // nor PublicKeyVerify primitives.
352     Object unused = handle.getPrimitive(RegistryConfiguration.get(), DeterministicAead.class);
353     assertThrows(
354         GeneralSecurityException.class,
355         () -> handle.getPrimitive(RegistryConfiguration.get(), PublicKeySign.class));
356     assertThrows(
357         GeneralSecurityException.class,
358         () -> handle.getPrimitive(RegistryConfiguration.get(), PublicKeyVerify.class));
359   }
360 }
361