use of com.google.crypto.tink.proto.JwtEcdsaAlgorithm in project tink by google.
the class JwkSetConverter method convertToEcdsaKey.
private static KeyData convertToEcdsaKey(JsonObject jsonKey) throws IOException {
JwtEcdsaAlgorithm algorithm;
switch(getStringItem(jsonKey, "alg")) {
case "ES256":
expectStringItem(jsonKey, "crv", "P-256");
algorithm = JwtEcdsaAlgorithm.ES256;
break;
case "ES384":
expectStringItem(jsonKey, "crv", "P-384");
algorithm = JwtEcdsaAlgorithm.ES384;
break;
case "ES512":
expectStringItem(jsonKey, "crv", "P-521");
algorithm = JwtEcdsaAlgorithm.ES512;
break;
default:
throw new IOException("Unknown Ecdsa Algorithm: " + getStringItem(jsonKey, "alg"));
}
if (jsonKey.has("d")) {
throw new UnsupportedOperationException("importing ECDSA private keys is not implemented");
}
expectStringItem(jsonKey, "kty", "EC");
validateUseIsSig(jsonKey);
validateKeyOpsIsVerify(jsonKey);
JwtEcdsaPublicKey.Builder ecdsaPubKeyBuilder = JwtEcdsaPublicKey.newBuilder().setVersion(0).setAlgorithm(algorithm).setX(ByteString.copyFrom(Base64.urlSafeDecode(getStringItem(jsonKey, "x")))).setY(ByteString.copyFrom(Base64.urlSafeDecode(getStringItem(jsonKey, "y"))));
if (jsonKey.has("kid")) {
ecdsaPubKeyBuilder.setCustomKid(JwtEcdsaPublicKey.CustomKid.newBuilder().setValue(getStringItem(jsonKey, "kid")).build());
}
return KeyData.newBuilder().setTypeUrl(JWT_ECDSA_PUBLIC_KEY_URL).setValue(ecdsaPubKeyBuilder.build().toByteString()).setKeyMaterialType(KeyMaterialType.ASYMMETRIC_PUBLIC).build();
}
use of com.google.crypto.tink.proto.JwtEcdsaAlgorithm in project tink by google.
the class JwtEcdsaSignKeyManagerTest method createSignVerifyTink_withDifferentHeaders.
@Test
public void createSignVerifyTink_withDifferentHeaders() throws Exception {
// KeysetHandle.generateNew is too slow in Tsan.
assumeFalse(TestUtil.isTsan());
KeyTemplate template = KeyTemplates.get("JWT_ES256");
KeysetHandle handle = KeysetHandle.generateNew(template);
Keyset keyset = CleartextKeysetHandle.getKeyset(handle);
JwtEcdsaPrivateKey keyProto = JwtEcdsaPrivateKey.parseFrom(keyset.getKey(0).getKeyData().getValue(), ExtensionRegistryLite.getEmptyRegistry());
ECPrivateKey privateKey = EllipticCurves.getEcPrivateKey(JwtEcdsaVerifyKeyManager.getCurve(keyProto.getPublicKey().getAlgorithm()), keyProto.getKeyValue().toByteArray());
JwtEcdsaAlgorithm algorithm = keyProto.getPublicKey().getAlgorithm();
Enums.HashType hash = JwtEcdsaVerifyKeyManager.hashForEcdsaAlgorithm(algorithm);
EcdsaSignJce rawSigner = new EcdsaSignJce(privateKey, hash, EcdsaEncoding.IEEE_P1363);
String kid = JwtFormat.getKid(keyset.getKey(0).getKeyId(), keyset.getKey(0).getOutputPrefixType()).get();
JsonObject payload = new JsonObject();
payload.addProperty("jti", "jwtId");
JwtValidator validator = JwtValidator.newBuilder().allowMissingExpiration().build();
JwtPublicKeyVerify verifier = handle.getPublicKeysetHandle().getPrimitive(JwtPublicKeyVerify.class);
// Normal, valid signed token.
JsonObject normalHeader = new JsonObject();
normalHeader.addProperty("alg", "ES256");
normalHeader.addProperty("kid", kid);
String normalToken = generateSignedCompact(rawSigner, normalHeader, payload);
verifier.verifyAndDecode(normalToken, validator);
// token without kid are rejected, even if they are valid.
JsonObject headerWithoutKid = new JsonObject();
headerWithoutKid.addProperty("alg", "ES256");
String tokenWithoutKid = generateSignedCompact(rawSigner, headerWithoutKid, payload);
assertThrows(GeneralSecurityException.class, () -> verifier.verifyAndDecode(tokenWithoutKid, validator));
// token without algorithm in the header
JsonObject headerWithoutAlg = new JsonObject();
headerWithoutAlg.addProperty("kid", kid);
String tokenWithoutAlg = generateSignedCompact(rawSigner, headerWithoutAlg, payload);
assertThrows(GeneralSecurityException.class, () -> verifier.verifyAndDecode(tokenWithoutAlg, validator));
// token with an incorrect algorithm in the header
JsonObject headerWithBadAlg = new JsonObject();
headerWithBadAlg.addProperty("kid", kid);
headerWithBadAlg.addProperty("alg", "RS256");
String badAlgToken = generateSignedCompact(rawSigner, headerWithBadAlg, payload);
assertThrows(GeneralSecurityException.class, () -> verifier.verifyAndDecode(badAlgToken, validator));
// token with an unknown kid header
JsonObject unknownKidHeader = new JsonObject();
unknownKidHeader.addProperty("alg", "ES256");
unknownKidHeader.addProperty("kid", "unknown");
String unknownKidSignedCompact = generateSignedCompact(rawSigner, unknownKidHeader, payload);
assertThrows(GeneralSecurityException.class, () -> verifier.verifyAndDecode(unknownKidSignedCompact, validator));
}
use of com.google.crypto.tink.proto.JwtEcdsaAlgorithm in project tink by google.
the class JwtEcdsaSignKeyManagerTest method createSignVerifyRaw_withDifferentHeaders.
@Test
public void createSignVerifyRaw_withDifferentHeaders() throws Exception {
// KeysetHandle.generateNew is too slow in Tsan.
assumeFalse(TestUtil.isTsan());
KeyTemplate template = KeyTemplates.get("JWT_ES256_RAW");
KeysetHandle handle = KeysetHandle.generateNew(template);
Keyset keyset = CleartextKeysetHandle.getKeyset(handle);
JwtEcdsaPrivateKey keyProto = JwtEcdsaPrivateKey.parseFrom(keyset.getKey(0).getKeyData().getValue(), ExtensionRegistryLite.getEmptyRegistry());
ECPrivateKey privateKey = EllipticCurves.getEcPrivateKey(JwtEcdsaVerifyKeyManager.getCurve(keyProto.getPublicKey().getAlgorithm()), keyProto.getKeyValue().toByteArray());
JwtEcdsaAlgorithm algorithm = keyProto.getPublicKey().getAlgorithm();
Enums.HashType hash = JwtEcdsaVerifyKeyManager.hashForEcdsaAlgorithm(algorithm);
EcdsaSignJce rawSigner = new EcdsaSignJce(privateKey, hash, EcdsaEncoding.IEEE_P1363);
JsonObject payload = new JsonObject();
payload.addProperty("jid", "jwtId");
JwtValidator validator = JwtValidator.newBuilder().allowMissingExpiration().build();
JwtPublicKeyVerify verifier = handle.getPublicKeysetHandle().getPrimitive(JwtPublicKeyVerify.class);
// Normal, valid signed compact.
JsonObject normalHeader = new JsonObject();
normalHeader.addProperty("alg", "ES256");
String normalSignedCompact = generateSignedCompact(rawSigner, normalHeader, payload);
verifier.verifyAndDecode(normalSignedCompact, validator);
// valid token, with "typ" set in the header
JsonObject goodHeader = new JsonObject();
goodHeader.addProperty("alg", "ES256");
goodHeader.addProperty("typ", "typeHeader");
String goodSignedCompact = generateSignedCompact(rawSigner, goodHeader, payload);
verifier.verifyAndDecode(goodSignedCompact, JwtValidator.newBuilder().expectTypeHeader("typeHeader").allowMissingExpiration().build());
// invalid token with an empty header
JsonObject emptyHeader = new JsonObject();
String emptyHeaderSignedCompact = generateSignedCompact(rawSigner, emptyHeader, payload);
assertThrows(GeneralSecurityException.class, () -> verifier.verifyAndDecode(emptyHeaderSignedCompact, validator));
// invalid token with a valid but incorrect algorithm in the header
JsonObject badAlgoHeader = new JsonObject();
badAlgoHeader.addProperty("alg", "RS256");
String badAlgoSignedCompact = generateSignedCompact(rawSigner, badAlgoHeader, payload);
assertThrows(GeneralSecurityException.class, () -> verifier.verifyAndDecode(badAlgoSignedCompact, validator));
// for raw keys, the validation should work even if a "kid" header is present.
JsonObject unknownKidHeader = new JsonObject();
unknownKidHeader.addProperty("alg", "ES256");
unknownKidHeader.addProperty("kid", "unknown");
String unknownKidSignedCompact = generateSignedCompact(rawSigner, unknownKidHeader, payload);
verifier.verifyAndDecode(unknownKidSignedCompact, validator);
}
use of com.google.crypto.tink.proto.JwtEcdsaAlgorithm in project tink by google.
the class JwtEcdsaSignKeyManager method keyFactory.
@Override
public KeyFactory<JwtEcdsaKeyFormat, JwtEcdsaPrivateKey> keyFactory() {
return new KeyFactory<JwtEcdsaKeyFormat, JwtEcdsaPrivateKey>(JwtEcdsaKeyFormat.class) {
@Override
public void validateKeyFormat(JwtEcdsaKeyFormat format) throws GeneralSecurityException {
JwtEcdsaVerifyKeyManager.validateEcdsaAlgorithm(format.getAlgorithm());
}
@Override
public JwtEcdsaKeyFormat parseKeyFormat(ByteString byteString) throws InvalidProtocolBufferException {
return JwtEcdsaKeyFormat.parseFrom(byteString, ExtensionRegistryLite.getEmptyRegistry());
}
@Override
public JwtEcdsaPrivateKey deriveKey(JwtEcdsaKeyFormat format, InputStream inputStream) {
throw new UnsupportedOperationException();
}
@Override
public JwtEcdsaPrivateKey createKey(JwtEcdsaKeyFormat format) throws GeneralSecurityException {
JwtEcdsaAlgorithm ecdsaAlgorithm = format.getAlgorithm();
KeyPair keyPair = EllipticCurves.generateKeyPair(JwtEcdsaVerifyKeyManager.getCurve(format.getAlgorithm()));
ECPublicKey pubKey = (ECPublicKey) keyPair.getPublic();
ECPrivateKey privKey = (ECPrivateKey) keyPair.getPrivate();
ECPoint w = pubKey.getW();
// Creates JwtEcdsaPublicKey.
JwtEcdsaPublicKey ecdsaPubKey = JwtEcdsaPublicKey.newBuilder().setVersion(getVersion()).setAlgorithm(ecdsaAlgorithm).setX(ByteString.copyFrom(w.getAffineX().toByteArray())).setY(ByteString.copyFrom(w.getAffineY().toByteArray())).build();
// Creates JwtEcdsaPrivateKey.
return JwtEcdsaPrivateKey.newBuilder().setVersion(getVersion()).setPublicKey(ecdsaPubKey).setKeyValue(ByteString.copyFrom(privKey.getS().toByteArray())).build();
}
/**
* List of default templates to generate tokens with algorithms "ES256", "ES384" or "ES512".
* Use the template with the "_RAW" suffix if you want to generate tokens without a "kid"
* header.
*/
@Override
public Map<String, KeyFactory.KeyFormat<JwtEcdsaKeyFormat>> keyFormats() {
Map<String, KeyFactory.KeyFormat<JwtEcdsaKeyFormat>> result = new HashMap<>();
result.put("JWT_ES256_RAW", createKeyFormat(JwtEcdsaAlgorithm.ES256, KeyTemplate.OutputPrefixType.RAW));
result.put("JWT_ES256", createKeyFormat(JwtEcdsaAlgorithm.ES256, KeyTemplate.OutputPrefixType.TINK));
result.put("JWT_ES384_RAW", createKeyFormat(JwtEcdsaAlgorithm.ES384, KeyTemplate.OutputPrefixType.RAW));
result.put("JWT_ES384", createKeyFormat(JwtEcdsaAlgorithm.ES384, KeyTemplate.OutputPrefixType.TINK));
result.put("JWT_ES512_RAW", createKeyFormat(JwtEcdsaAlgorithm.ES512, KeyTemplate.OutputPrefixType.RAW));
result.put("JWT_ES512", createKeyFormat(JwtEcdsaAlgorithm.ES512, KeyTemplate.OutputPrefixType.TINK));
return Collections.unmodifiableMap(result);
}
};
}
Aggregations