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 17package jwt 18 19import ( 20 "errors" 21 "fmt" 22 23 "google.golang.org/protobuf/proto" 24 "github.com/google/tink/go/core/registry" 25 "github.com/google/tink/go/keyset" 26 "github.com/google/tink/go/signature/subtle" 27 jepb "github.com/google/tink/go/proto/jwt_ecdsa_go_proto" 28 tinkpb "github.com/google/tink/go/proto/tink_go_proto" 29) 30 31const ( 32 jwtECDSAVerifierKeyVersion = 0 33 jwtECDSAVerifierTypeURL = "type.googleapis.com/google.crypto.tink.JwtEcdsaPublicKey" 34 jwtECDSAEncoding = "IEEE_P1363" 35) 36 37var ( 38 errECDSAInvalidAlgorithm = errors.New("invalid algorithm") 39 errECDSAVerifierNotImplemented = errors.New("not supported on verifier key manager") 40) 41 42// jwtECDSAVerifierKeyManager implements the KeyManager interface 43// for JWT Verifier using the 'ES256', 'ES384', and 'ES512' JWA algorithm. 44type jwtECDSAVerifierKeyManager struct{} 45 46var _ registry.KeyManager = (*jwtECDSAVerifierKeyManager)(nil) 47 48type ecdsaParams struct { 49 Curve string 50 Hash string 51} 52 53var esAlgToParams = map[jepb.JwtEcdsaAlgorithm]ecdsaParams{ 54 jepb.JwtEcdsaAlgorithm_ES256: {Curve: "NIST_P256", Hash: "SHA256"}, 55 jepb.JwtEcdsaAlgorithm_ES384: {Curve: "NIST_P384", Hash: "SHA384"}, 56 jepb.JwtEcdsaAlgorithm_ES512: {Curve: "NIST_P521", Hash: "SHA512"}, 57} 58 59func (km *jwtECDSAVerifierKeyManager) Primitive(serializedKey []byte) (interface{}, error) { 60 if serializedKey == nil || len(serializedKey) == 0 { 61 return nil, fmt.Errorf("invalid key") 62 } 63 pubKey := &jepb.JwtEcdsaPublicKey{} 64 if err := proto.Unmarshal(serializedKey, pubKey); err != nil { 65 return nil, err 66 } 67 if err := keyset.ValidateKeyVersion(pubKey.Version, jwtECDSAVerifierKeyVersion); err != nil { 68 return nil, fmt.Errorf("invalid key: %v", err) 69 } 70 params, ok := esAlgToParams[pubKey.GetAlgorithm()] 71 if !ok { 72 return nil, errECDSAInvalidAlgorithm 73 } 74 tv, err := subtle.NewECDSAVerifier(params.Hash, params.Curve, jwtECDSAEncoding, pubKey.GetX(), pubKey.GetY()) 75 if err != nil { 76 return nil, err 77 } 78 return newVerifierWithKID(tv, pubKey.GetAlgorithm().String(), ecdsaCustomKID(pubKey)) 79} 80 81func (km *jwtECDSAVerifierKeyManager) NewKey(serializedKeyFormat []byte) (proto.Message, error) { 82 return nil, errECDSAVerifierNotImplemented 83} 84 85func (km *jwtECDSAVerifierKeyManager) NewKeyData(serializedKeyFormat []byte) (*tinkpb.KeyData, error) { 86 return nil, errECDSAVerifierNotImplemented 87} 88 89func (km *jwtECDSAVerifierKeyManager) DoesSupport(typeURL string) bool { 90 return typeURL == jwtECDSAVerifierTypeURL 91} 92 93func (km *jwtECDSAVerifierKeyManager) TypeURL() string { 94 return jwtECDSAVerifierTypeURL 95} 96 97func ecdsaCustomKID(pk *jepb.JwtEcdsaPublicKey) *string { 98 if pk.GetCustomKid() == nil { 99 return nil 100 } 101 k := pk.GetCustomKid().GetValue() 102 return &k 103} 104