xref: /aosp_15_r20/external/tink/java_src/src/main/java/com/google/crypto/tink/jwt/JwkSetConverter.java (revision e7b1675dde1b92d52ec075b0a92829627f2c52a5)
1 // Copyright 2021 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.jwt;
18 
19 import com.google.crypto.tink.KeyStatus;
20 import com.google.crypto.tink.KeysetHandle;
21 import com.google.crypto.tink.internal.BigIntegerEncoding;
22 import com.google.crypto.tink.internal.MutableSerializationRegistry;
23 import com.google.crypto.tink.internal.ProtoKeySerialization;
24 import com.google.crypto.tink.proto.JwtEcdsaAlgorithm;
25 import com.google.crypto.tink.proto.JwtEcdsaPublicKey;
26 import com.google.crypto.tink.proto.JwtRsaSsaPkcs1Algorithm;
27 import com.google.crypto.tink.proto.JwtRsaSsaPkcs1PublicKey;
28 import com.google.crypto.tink.proto.JwtRsaSsaPssAlgorithm;
29 import com.google.crypto.tink.proto.JwtRsaSsaPssPublicKey;
30 import com.google.crypto.tink.proto.KeyData.KeyMaterialType;
31 import com.google.crypto.tink.proto.OutputPrefixType;
32 import com.google.crypto.tink.subtle.Base64;
33 import com.google.crypto.tink.tinkkey.KeyAccess;
34 import com.google.errorprone.annotations.InlineMe;
35 import com.google.gson.JsonArray;
36 import com.google.gson.JsonElement;
37 import com.google.gson.JsonObject;
38 import com.google.gson.JsonParseException;
39 import com.google.gson.internal.Streams;
40 import com.google.gson.stream.JsonReader;
41 import com.google.protobuf.ByteString;
42 import com.google.protobuf.ExtensionRegistryLite;
43 import com.google.protobuf.InvalidProtocolBufferException;
44 import java.io.IOException;
45 import java.io.StringReader;
46 import java.math.BigInteger;
47 import java.nio.ByteBuffer;
48 import java.security.GeneralSecurityException;
49 import java.util.Optional;
50 import javax.annotation.Nullable;
51 
52 /**
53  * Provides functions to import and export public Json Web Key (JWK) sets.
54  *
55  * <p>The currently supported algorithms are ES256, ES384, ES512, RS256, RS384, RS512, PS256, PS384
56  * and PS512.
57  */
58 public final class JwkSetConverter {
59 
60   /**
61    * Converts a Tink KeysetHandle with JWT public keys into a Json Web Key (JWK) set.
62    *
63    * <p>The currently supported algorithms are ES256, ES384, ES512, RS256, RS384, RS512, PS256,
64    * PS384 and PS512. JWK is defined in https://www.rfc-editor.org/rfc/rfc7517.txt.
65    */
fromPublicKeysetHandle(KeysetHandle handle)66   public static String fromPublicKeysetHandle(KeysetHandle handle)
67       throws IOException, GeneralSecurityException {
68     // Check validity of the keyset handle before calling "getAt".
69     // See comments in {@link KeysetHandle#Entry#getAt}.
70     handle = KeysetHandle.newBuilder(handle).build();
71     // We never throw a IOException anymore, but keep it in the interface for compatibility.
72     JsonArray keys = new JsonArray();
73     for (int i = 0; i < handle.size(); i++) {
74       KeysetHandle.Entry entry = handle.getAt(i);
75       if (entry.getStatus() != KeyStatus.ENABLED) {
76         continue;
77       }
78       ProtoKeySerialization protoKeySerialization =
79           MutableSerializationRegistry.globalInstance()
80               .serializeKey(entry.getKey(), ProtoKeySerialization.class, /* access= */ null);
81 
82       if ((protoKeySerialization.getOutputPrefixType() != OutputPrefixType.RAW)
83           && (protoKeySerialization.getOutputPrefixType() != OutputPrefixType.TINK)) {
84         throw new GeneralSecurityException("only OutputPrefixType RAW and TINK are supported");
85       }
86       if (protoKeySerialization.getKeyMaterialType() != KeyMaterialType.ASYMMETRIC_PUBLIC) {
87         throw new GeneralSecurityException("only public keys can be converted");
88       }
89       switch (protoKeySerialization.getTypeUrl()) {
90         case JWT_ECDSA_PUBLIC_KEY_URL:
91           keys.add(convertJwtEcdsaKey(protoKeySerialization));
92           break;
93         case JWT_RSA_SSA_PKCS1_PUBLIC_KEY_URL:
94           keys.add(convertJwtRsaSsaPkcs1(protoKeySerialization));
95           break;
96         case JWT_RSA_SSA_PSS_PUBLIC_KEY_URL:
97           keys.add(convertJwtRsaSsaPss(protoKeySerialization));
98           break;
99         default:
100           throw new GeneralSecurityException(
101               String.format("key type %s is not supported", protoKeySerialization.getTypeUrl()));
102       }
103     }
104     JsonObject jwkSet = new JsonObject();
105     jwkSet.add("keys", keys);
106     return jwkSet.toString();
107   }
108 
109   /**
110    * Converts a Json Web Key (JWK) set with public keys into a Tink KeysetHandle.
111    *
112    * <p>It requires that all keys in the set have the "alg" field set. The currently supported
113    * algorithms are ES256, ES384, ES512, RS256, RS384, RS512, PS256, PS384 and PS512. JWK is defined
114    * in https://www.rfc-editor.org/rfc/rfc7517.txt.
115    */
toPublicKeysetHandle(String jwkSet)116   public static KeysetHandle toPublicKeysetHandle(String jwkSet)
117       throws IOException, GeneralSecurityException {
118     // We never throw a IOException anymore, but keep it in the interface for compatibility.
119     JsonObject jsonKeyset;
120     try {
121       JsonReader jsonReader = new JsonReader(new StringReader(jwkSet));
122       jsonReader.setLenient(false);
123       jsonKeyset = Streams.parse(jsonReader).getAsJsonObject();
124     } catch (IllegalStateException | JsonParseException | StackOverflowError ex) {
125       throw new GeneralSecurityException("JWK set is invalid JSON", ex);
126     }
127     KeysetHandle.Builder builder = KeysetHandle.newBuilder();
128     JsonArray jsonKeys = jsonKeyset.get("keys").getAsJsonArray();
129     for (JsonElement element : jsonKeys) {
130       JsonObject jsonKey = element.getAsJsonObject();
131       String algPrefix = getStringItem(jsonKey, "alg").substring(0, 2);
132       ProtoKeySerialization keySerialization;
133       switch (algPrefix) {
134         case "RS":
135           keySerialization = convertToRsaSsaPkcs1Key(jsonKey);
136           break;
137         case "PS":
138           keySerialization = convertToRsaSsaPssKey(jsonKey);
139           break;
140         case "ES":
141           keySerialization = convertToEcdsaKey(jsonKey);
142           break;
143         default:
144           throw new GeneralSecurityException(
145               "unexpected alg value: " + getStringItem(jsonKey, "alg"));
146       }
147       builder.addEntry(
148           KeysetHandle.importKey(
149                   MutableSerializationRegistry.globalInstance()
150                       .parseKeyWithLegacyFallback(keySerialization, null))
151               .withRandomId());
152     }
153     if (builder.size() <= 0) {
154       throw new GeneralSecurityException("empty keyset");
155     }
156     builder.getAt(0).makePrimary();
157     return builder.build();
158   }
159 
160   private static final String JWT_ECDSA_PUBLIC_KEY_URL =
161       "type.googleapis.com/google.crypto.tink.JwtEcdsaPublicKey";
162   private static final String JWT_RSA_SSA_PKCS1_PUBLIC_KEY_URL =
163       "type.googleapis.com/google.crypto.tink.JwtRsaSsaPkcs1PublicKey";
164   private static final String JWT_RSA_SSA_PSS_PUBLIC_KEY_URL =
165       "type.googleapis.com/google.crypto.tink.JwtRsaSsaPssPublicKey";
166 
getKid(@ullable Integer idRequirement)167   private static Optional<String> getKid(@Nullable Integer idRequirement) {
168     if (idRequirement == null) {
169       return Optional.empty();
170     }
171     byte[] bigEndianKeyId = ByteBuffer.allocate(4).putInt(idRequirement).array();
172     return Optional.of(Base64.urlSafeEncode(bigEndianKeyId));
173   }
174 
convertJwtEcdsaKey(ProtoKeySerialization protoKeySerialization)175   private static JsonObject convertJwtEcdsaKey(ProtoKeySerialization protoKeySerialization)
176       throws GeneralSecurityException {
177     JwtEcdsaPublicKey jwtEcdsaPublicKey;
178     try {
179       jwtEcdsaPublicKey =
180         JwtEcdsaPublicKey.parseFrom(
181             protoKeySerialization.getValue(), ExtensionRegistryLite.getEmptyRegistry());
182     } catch (InvalidProtocolBufferException e) {
183       throw new GeneralSecurityException("failed to parse value as JwtEcdsaPublicKey proto", e);
184     }
185     String alg;
186     String crv;
187     // We currently encode with one extra 0 byte at the beginning, to make sure
188     // that parsing is correct even if passing of a two's complement encoding is used.
189     // See also b/264525021.
190     int encLength;
191     switch (jwtEcdsaPublicKey.getAlgorithm()) {
192       case ES256:
193         alg = "ES256";
194         crv = "P-256";
195         encLength = 33;
196         break;
197       case ES384:
198         alg = "ES384";
199         crv = "P-384";
200         encLength = 49;
201         break;
202       case ES512:
203         alg = "ES512";
204         crv = "P-521";
205         encLength = 67;
206         break;
207       default:
208         throw new GeneralSecurityException("unknown algorithm");
209     }
210     JsonObject jsonKey = new JsonObject();
211     jsonKey.addProperty("kty", "EC");
212     jsonKey.addProperty("crv", crv);
213     BigInteger x =
214         BigIntegerEncoding.fromUnsignedBigEndianBytes(jwtEcdsaPublicKey.getX().toByteArray());
215     BigInteger y =
216         BigIntegerEncoding.fromUnsignedBigEndianBytes(jwtEcdsaPublicKey.getY().toByteArray());
217     jsonKey.addProperty(
218         "x", Base64.urlSafeEncode(BigIntegerEncoding.toBigEndianBytesOfFixedLength(x, encLength)));
219     jsonKey.addProperty(
220         "y", Base64.urlSafeEncode(BigIntegerEncoding.toBigEndianBytesOfFixedLength(y, encLength)));
221     jsonKey.addProperty("use", "sig");
222     jsonKey.addProperty("alg", alg);
223     JsonArray keyOps = new JsonArray();
224     keyOps.add("verify");
225     jsonKey.add("key_ops", keyOps);
226     Optional<String> kid = getKid(protoKeySerialization.getIdRequirementOrNull());
227     if (kid.isPresent()) {
228       jsonKey.addProperty("kid", kid.get());
229     } else if (jwtEcdsaPublicKey.hasCustomKid()) {
230       jsonKey.addProperty("kid", jwtEcdsaPublicKey.getCustomKid().getValue());
231     }
232     return jsonKey;
233   }
234 
convertJwtRsaSsaPkcs1(ProtoKeySerialization protoKeySerialization)235   private static JsonObject convertJwtRsaSsaPkcs1(ProtoKeySerialization protoKeySerialization)
236       throws GeneralSecurityException {
237     JwtRsaSsaPkcs1PublicKey jwtRsaSsaPkcs1PublicKey;
238     try {
239       jwtRsaSsaPkcs1PublicKey =
240         JwtRsaSsaPkcs1PublicKey.parseFrom(
241             protoKeySerialization.getValue(), ExtensionRegistryLite.getEmptyRegistry());
242     } catch (InvalidProtocolBufferException e) {
243       throw new GeneralSecurityException(
244           "failed to parse value as JwtRsaSsaPkcs1PublicKey proto", e);
245     }
246     String alg;
247     switch (jwtRsaSsaPkcs1PublicKey.getAlgorithm()) {
248       case RS256:
249         alg = "RS256";
250         break;
251       case RS384:
252         alg = "RS384";
253         break;
254       case RS512:
255         alg = "RS512";
256         break;
257       default:
258         throw new GeneralSecurityException("unknown algorithm");
259     }
260     JsonObject jsonKey = new JsonObject();
261     jsonKey.addProperty("kty", "RSA");
262     jsonKey.addProperty("n", Base64.urlSafeEncode(jwtRsaSsaPkcs1PublicKey.getN().toByteArray()));
263     jsonKey.addProperty("e", Base64.urlSafeEncode(jwtRsaSsaPkcs1PublicKey.getE().toByteArray()));
264     jsonKey.addProperty("use", "sig");
265     jsonKey.addProperty("alg", alg);
266     JsonArray keyOps = new JsonArray();
267     keyOps.add("verify");
268     jsonKey.add("key_ops", keyOps);
269     Optional<String> kid = getKid(protoKeySerialization.getIdRequirementOrNull());
270     if (kid.isPresent()) {
271       jsonKey.addProperty("kid", kid.get());
272     } else if (jwtRsaSsaPkcs1PublicKey.hasCustomKid()) {
273       jsonKey.addProperty("kid", jwtRsaSsaPkcs1PublicKey.getCustomKid().getValue());
274     }
275     return jsonKey;
276   }
277 
convertJwtRsaSsaPss(ProtoKeySerialization protoKeySerialization)278   private static JsonObject convertJwtRsaSsaPss(ProtoKeySerialization protoKeySerialization)
279       throws GeneralSecurityException {
280     JwtRsaSsaPssPublicKey jwtRsaSsaPssPublicKey;
281     try {
282       jwtRsaSsaPssPublicKey =
283         JwtRsaSsaPssPublicKey.parseFrom(
284             protoKeySerialization.getValue(), ExtensionRegistryLite.getEmptyRegistry());
285     } catch (InvalidProtocolBufferException e) {
286       throw new GeneralSecurityException("failed to parse value as JwtRsaSsaPssPublicKey proto", e);
287     }
288     String alg;
289     switch (jwtRsaSsaPssPublicKey.getAlgorithm()) {
290       case PS256:
291         alg = "PS256";
292         break;
293       case PS384:
294         alg = "PS384";
295         break;
296       case PS512:
297         alg = "PS512";
298         break;
299       default:
300         throw new GeneralSecurityException("unknown algorithm");
301     }
302     JsonObject jsonKey = new JsonObject();
303     jsonKey.addProperty("kty", "RSA");
304     jsonKey.addProperty("n", Base64.urlSafeEncode(jwtRsaSsaPssPublicKey.getN().toByteArray()));
305     jsonKey.addProperty("e", Base64.urlSafeEncode(jwtRsaSsaPssPublicKey.getE().toByteArray()));
306     jsonKey.addProperty("use", "sig");
307     jsonKey.addProperty("alg", alg);
308     JsonArray keyOps = new JsonArray();
309     keyOps.add("verify");
310     jsonKey.add("key_ops", keyOps);
311     Optional<String> kid = getKid(protoKeySerialization.getIdRequirementOrNull());
312     if (kid.isPresent()) {
313       jsonKey.addProperty("kid", kid.get());
314     } else if (jwtRsaSsaPssPublicKey.hasCustomKid()) {
315       jsonKey.addProperty("kid", jwtRsaSsaPssPublicKey.getCustomKid().getValue());
316     }
317     return jsonKey;
318   }
319 
getStringItem(JsonObject obj, String name)320   private static String getStringItem(JsonObject obj, String name) throws GeneralSecurityException {
321     if (!obj.has(name)) {
322       throw new GeneralSecurityException(name + " not found");
323     }
324     if (!obj.get(name).isJsonPrimitive() || !obj.get(name).getAsJsonPrimitive().isString()) {
325       throw new GeneralSecurityException(name + " is not a string");
326     }
327     return obj.get(name).getAsString();
328   }
329 
expectStringItem(JsonObject obj, String name, String expectedValue)330   private static void expectStringItem(JsonObject obj, String name, String expectedValue)
331       throws GeneralSecurityException {
332     String value = getStringItem(obj, name);
333     if (!value.equals(expectedValue)) {
334       throw new GeneralSecurityException("unexpected " + name + " value: " + value);
335     }
336   }
337 
validateUseIsSig(JsonObject jsonKey)338   private static void validateUseIsSig(JsonObject jsonKey) throws GeneralSecurityException {
339     if (!jsonKey.has("use")) {
340       return;
341     }
342     expectStringItem(jsonKey, "use", "sig");
343   }
344 
validateKeyOpsIsVerify(JsonObject jsonKey)345   private static void validateKeyOpsIsVerify(JsonObject jsonKey) throws GeneralSecurityException {
346     if (!jsonKey.has("key_ops")) {
347       return;
348     }
349     if (!jsonKey.get("key_ops").isJsonArray()) {
350       throw new GeneralSecurityException("key_ops is not an array");
351     }
352     JsonArray keyOps = jsonKey.get("key_ops").getAsJsonArray();
353     if (keyOps.size() != 1) {
354       throw new GeneralSecurityException("key_ops must contain exactly one element");
355     }
356     if (!keyOps.get(0).isJsonPrimitive() || !keyOps.get(0).getAsJsonPrimitive().isString()) {
357       throw new GeneralSecurityException("key_ops is not a string");
358     }
359     if (!keyOps.get(0).getAsString().equals("verify")) {
360       throw new GeneralSecurityException("unexpected keyOps value: " + keyOps.get(0).getAsString());
361     }
362   }
363 
convertToRsaSsaPkcs1Key(JsonObject jsonKey)364   private static ProtoKeySerialization convertToRsaSsaPkcs1Key(JsonObject jsonKey)
365       throws GeneralSecurityException {
366     JwtRsaSsaPkcs1Algorithm algorithm;
367     switch (getStringItem(jsonKey, "alg")) {
368       case "RS256":
369         algorithm = JwtRsaSsaPkcs1Algorithm.RS256;
370         break;
371       case "RS384":
372         algorithm = JwtRsaSsaPkcs1Algorithm.RS384;
373         break;
374       case "RS512":
375         algorithm = JwtRsaSsaPkcs1Algorithm.RS512;
376         break;
377       default:
378         throw new GeneralSecurityException(
379             "Unknown Rsa Algorithm: " + getStringItem(jsonKey, "alg"));
380     }
381     if (jsonKey.has("p")
382         || jsonKey.has("q")
383         || jsonKey.has("dp")
384         || jsonKey.has("dq")
385         || jsonKey.has("d")
386         || jsonKey.has("qi")) {
387       throw new UnsupportedOperationException("importing RSA private keys is not implemented");
388     }
389     expectStringItem(jsonKey, "kty", "RSA");
390     validateUseIsSig(jsonKey);
391     validateKeyOpsIsVerify(jsonKey);
392     JwtRsaSsaPkcs1PublicKey.Builder pkcs1PubKeyBuilder =
393         JwtRsaSsaPkcs1PublicKey.newBuilder()
394             .setVersion(0)
395             .setAlgorithm(algorithm)
396             .setE(ByteString.copyFrom(Base64.urlSafeDecode(getStringItem(jsonKey, "e"))))
397             .setN(ByteString.copyFrom(Base64.urlSafeDecode(getStringItem(jsonKey, "n"))));
398     if (jsonKey.has("kid")) {
399       pkcs1PubKeyBuilder.setCustomKid(
400           JwtRsaSsaPkcs1PublicKey.CustomKid.newBuilder()
401               .setValue(getStringItem(jsonKey, "kid"))
402               .build());
403     }
404     return ProtoKeySerialization.create(
405         JWT_RSA_SSA_PKCS1_PUBLIC_KEY_URL,
406         pkcs1PubKeyBuilder.build().toByteString(),
407         KeyMaterialType.ASYMMETRIC_PUBLIC,
408         OutputPrefixType.RAW,
409         null);
410   }
411 
convertToRsaSsaPssKey(JsonObject jsonKey)412   private static ProtoKeySerialization convertToRsaSsaPssKey(JsonObject jsonKey)
413       throws GeneralSecurityException {
414     JwtRsaSsaPssAlgorithm algorithm;
415     switch (getStringItem(jsonKey, "alg")) {
416       case "PS256":
417         algorithm = JwtRsaSsaPssAlgorithm.PS256;
418         break;
419       case "PS384":
420         algorithm = JwtRsaSsaPssAlgorithm.PS384;
421         break;
422       case "PS512":
423         algorithm = JwtRsaSsaPssAlgorithm.PS512;
424         break;
425       default:
426         throw new GeneralSecurityException(
427             "Unknown Rsa Algorithm: " + getStringItem(jsonKey, "alg"));
428     }
429     if (jsonKey.has("p")
430         || jsonKey.has("q")
431         || jsonKey.has("dq")
432         || jsonKey.has("dq")
433         || jsonKey.has("d")
434         || jsonKey.has("qi")) {
435       throw new UnsupportedOperationException("importing RSA private keys is not implemented");
436     }
437     expectStringItem(jsonKey, "kty", "RSA");
438     validateUseIsSig(jsonKey);
439     validateKeyOpsIsVerify(jsonKey);
440     JwtRsaSsaPssPublicKey.Builder pssPubKeyBuilder =
441         JwtRsaSsaPssPublicKey.newBuilder()
442             .setVersion(0)
443             .setAlgorithm(algorithm)
444             .setE(ByteString.copyFrom(Base64.urlSafeDecode(getStringItem(jsonKey, "e"))))
445             .setN(ByteString.copyFrom(Base64.urlSafeDecode(getStringItem(jsonKey, "n"))));
446     if (jsonKey.has("kid")) {
447       pssPubKeyBuilder.setCustomKid(
448           JwtRsaSsaPssPublicKey.CustomKid.newBuilder()
449               .setValue(getStringItem(jsonKey, "kid"))
450               .build());
451     }
452     return ProtoKeySerialization.create(
453         JWT_RSA_SSA_PSS_PUBLIC_KEY_URL,
454         pssPubKeyBuilder.build().toByteString(),
455         KeyMaterialType.ASYMMETRIC_PUBLIC,
456         OutputPrefixType.RAW,
457         null);
458   }
459 
convertToEcdsaKey(JsonObject jsonKey)460   private static ProtoKeySerialization convertToEcdsaKey(JsonObject jsonKey)
461       throws GeneralSecurityException {
462     JwtEcdsaAlgorithm algorithm;
463     switch (getStringItem(jsonKey, "alg")) {
464       case "ES256":
465         expectStringItem(jsonKey, "crv", "P-256");
466         algorithm = JwtEcdsaAlgorithm.ES256;
467         break;
468       case "ES384":
469         expectStringItem(jsonKey, "crv", "P-384");
470         algorithm = JwtEcdsaAlgorithm.ES384;
471         break;
472       case "ES512":
473         expectStringItem(jsonKey, "crv", "P-521");
474         algorithm = JwtEcdsaAlgorithm.ES512;
475         break;
476       default:
477         throw new GeneralSecurityException(
478             "Unknown Ecdsa Algorithm: " + getStringItem(jsonKey, "alg"));
479     }
480     if (jsonKey.has("d")) {
481       throw new UnsupportedOperationException("importing ECDSA private keys is not implemented");
482     }
483     expectStringItem(jsonKey, "kty", "EC");
484     validateUseIsSig(jsonKey);
485     validateKeyOpsIsVerify(jsonKey);
486     JwtEcdsaPublicKey.Builder ecdsaPubKeyBuilder =
487         JwtEcdsaPublicKey.newBuilder()
488             .setVersion(0)
489             .setAlgorithm(algorithm)
490             .setX(ByteString.copyFrom(Base64.urlSafeDecode(getStringItem(jsonKey, "x"))))
491             .setY(ByteString.copyFrom(Base64.urlSafeDecode(getStringItem(jsonKey, "y"))));
492     if (jsonKey.has("kid")) {
493       ecdsaPubKeyBuilder.setCustomKid(
494           JwtEcdsaPublicKey.CustomKid.newBuilder().setValue(getStringItem(jsonKey, "kid")).build());
495     }
496     return ProtoKeySerialization.create(
497         JWT_ECDSA_PUBLIC_KEY_URL,
498         ecdsaPubKeyBuilder.build().toByteString(),
499         KeyMaterialType.ASYMMETRIC_PUBLIC,
500         OutputPrefixType.RAW,
501         null);
502   }
503 
504   /**
505    * @deprecated Use JwkSetConverter.fromPublicKeysetHandle(handle) instead.
506    */
507   @InlineMe(
508       replacement = "JwkSetConverter.fromPublicKeysetHandle(handle)",
509       imports = "com.google.crypto.tink.jwt.JwkSetConverter")
510   @Deprecated
fromKeysetHandle(KeysetHandle handle, KeyAccess keyAccess)511   public static String fromKeysetHandle(KeysetHandle handle, KeyAccess keyAccess)
512       throws IOException, GeneralSecurityException {
513     return fromPublicKeysetHandle(handle);
514   }
515 
516   /**
517    * @deprecated Use JwkSetConverter.toPublicKeysetHandle(jwkSet) instead.
518    */
519   @InlineMe(
520       replacement = "JwkSetConverter.toPublicKeysetHandle(jwkSet)",
521       imports = "com.google.crypto.tink.jwt.JwkSetConverter")
522   @Deprecated
toKeysetHandle(String jwkSet, KeyAccess keyAccess)523   public static KeysetHandle toKeysetHandle(String jwkSet, KeyAccess keyAccess)
524       throws IOException, GeneralSecurityException {
525     return toPublicKeysetHandle(jwkSet);
526   }
527 
JwkSetConverter()528   private JwkSetConverter() {}
529 }
530