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 "crypto/rsa" 21 "errors" 22 "fmt" 23 "math/big" 24 25 "google.golang.org/protobuf/proto" 26 "github.com/google/tink/go/core/registry" 27 "github.com/google/tink/go/internal/signature" 28 "github.com/google/tink/go/keyset" 29 jrsppb "github.com/google/tink/go/proto/jwt_rsa_ssa_pss_go_proto" 30 tinkpb "github.com/google/tink/go/proto/tink_go_proto" 31) 32 33const ( 34 jwtPSVerifierKeyVersion = 0 35 jwtPSVerifierTypeURL = "type.googleapis.com/google.crypto.tink.JwtRsaSsaPssPublicKey" 36) 37 38var errJWTPSVerifierNotImplemented = errors.New("not supported on verifier key manager") 39 40// jwtPSVerifierKeyManager implements the KeyManager interface 41// for JWT Verifier using the 'PS256', 'PS384', and 'PS512' JSON Web Algorithms (JWA). 42type jwtPSVerifierKeyManager struct{} 43 44var _ registry.KeyManager = (*jwtPSVerifierKeyManager)(nil) 45 46// adding to this map will automatically add to the list of 47// "accepted" algorithms that will construct valid primitives. 48var validPSAlgToHash = map[jrsppb.JwtRsaSsaPssAlgorithm]string{ 49 jrsppb.JwtRsaSsaPssAlgorithm_PS256: "SHA256", 50 jrsppb.JwtRsaSsaPssAlgorithm_PS384: "SHA384", 51 jrsppb.JwtRsaSsaPssAlgorithm_PS512: "SHA512", 52} 53 54var psAlgToSaltLen = map[jrsppb.JwtRsaSsaPssAlgorithm]int{ 55 jrsppb.JwtRsaSsaPssAlgorithm_PS256: 32, 56 jrsppb.JwtRsaSsaPssAlgorithm_PS384: 48, 57 jrsppb.JwtRsaSsaPssAlgorithm_PS512: 64, 58} 59 60func (km *jwtPSVerifierKeyManager) Primitive(serializedKey []byte) (interface{}, error) { 61 if serializedKey == nil || len(serializedKey) == 0 { 62 return nil, fmt.Errorf("invalid key") 63 } 64 pubKey := &jrsppb.JwtRsaSsaPssPublicKey{} 65 if err := proto.Unmarshal(serializedKey, pubKey); err != nil { 66 return nil, err 67 } 68 if err := validatePSPublicKey(pubKey); err != nil { 69 return nil, err 70 } 71 e := new(big.Int).SetBytes(pubKey.GetE()) 72 if !e.IsInt64() { 73 return nil, fmt.Errorf("public exponent can't fit in a 64 bit integer") 74 } 75 rsaPubKey := &rsa.PublicKey{ 76 N: new(big.Int).SetBytes(pubKey.GetN()), 77 E: int(e.Int64()), 78 } 79 algorithm := pubKey.GetAlgorithm() 80 v, err := signature.New_RSA_SSA_PSS_Verifier(validPSAlgToHash[algorithm], psAlgToSaltLen[algorithm], rsaPubKey) 81 if err != nil { 82 return nil, err 83 } 84 return newVerifierWithKID(v, algorithm.String(), psCustomKID(pubKey)) 85} 86 87func (km *jwtPSVerifierKeyManager) NewKey(serializedKeyFormat []byte) (proto.Message, error) { 88 return nil, errJWTPSVerifierNotImplemented 89} 90 91func (km *jwtPSVerifierKeyManager) NewKeyData(serializedKeyFormat []byte) (*tinkpb.KeyData, error) { 92 return nil, errJWTPSVerifierNotImplemented 93} 94 95func (km *jwtPSVerifierKeyManager) DoesSupport(typeURL string) bool { 96 return typeURL == jwtPSVerifierTypeURL 97} 98 99func (km *jwtPSVerifierKeyManager) TypeURL() string { 100 return jwtPSVerifierTypeURL 101} 102 103func validatePSPublicKey(pubKey *jrsppb.JwtRsaSsaPssPublicKey) error { 104 if pubKey == nil { 105 return fmt.Errorf("nil public key") 106 } 107 if err := keyset.ValidateKeyVersion(pubKey.Version, jwtPSVerifierKeyVersion); err != nil { 108 return err 109 } 110 if _, ok := validPSAlgToHash[pubKey.GetAlgorithm()]; !ok { 111 return fmt.Errorf("invalid algorithm") 112 } 113 e := new(big.Int).SetBytes(pubKey.GetE()) 114 if !e.IsInt64() { 115 return fmt.Errorf("public exponent can't fit in a 64 bit integer") 116 } 117 if err := signature.RSAValidPublicExponent(int(e.Int64())); err != nil { 118 return err 119 } 120 return signature.RSAValidModulusSizeInBits(new(big.Int).SetBytes(pubKey.GetN()).BitLen()) 121} 122 123func psCustomKID(pk *jrsppb.JwtRsaSsaPssPublicKey) *string { 124 // nil is an acceptable value for a custom kid. 125 if pk.GetCustomKid() == nil { 126 return nil 127 } 128 k := pk.GetCustomKid().GetValue() 129 return &k 130} 131