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 "fmt" 21 "testing" 22 "time" 23 24 "google.golang.org/protobuf/proto" 25 "github.com/google/tink/go/core/registry" 26 jepb "github.com/google/tink/go/proto/jwt_ecdsa_go_proto" 27) 28 29const testECDSAVerifierKeyType = "type.googleapis.com/google.crypto.tink.JwtEcdsaPublicKey" 30 31func TestECDSAVerifierNotImplemented(t *testing.T) { 32 km, err := registry.GetKeyManager(testECDSAVerifierKeyType) 33 if err != nil { 34 t.Fatalf("registry.GetKeyManager(%q) err = %v, want nil", testECDSAVerifierKeyType, err) 35 } 36 if _, err := km.NewKey(nil); err != errECDSAVerifierNotImplemented { 37 t.Fatalf("km.NewKey() err = %v, want %v", err, errECDSAVerifierNotImplemented) 38 } 39 if _, err := km.NewKeyData(nil); err != errECDSAVerifierNotImplemented { 40 t.Fatalf("km.NewKeyData() err = %v, want %v", err, errECDSAVerifierNotImplemented) 41 } 42} 43 44func TestECDSAVerifierDoesSupport(t *testing.T) { 45 km, err := registry.GetKeyManager(testECDSAVerifierKeyType) 46 if err != nil { 47 t.Fatalf("registry.GetKeyManager(%q) err = %v, want nil", testECDSAVerifierKeyType, err) 48 } 49 if !km.DoesSupport(testECDSAVerifierKeyType) { 50 t.Errorf("km.DoesSupport(%q) = false, want true", testECDSAVerifierKeyType) 51 } 52 if km.DoesSupport("not.the.actual.key.type") { 53 t.Errorf("km.DoesSupport('not.the.actual.key.type') = true, want false") 54 } 55} 56 57func TestECDSAVerifierTypeURL(t *testing.T) { 58 km, err := registry.GetKeyManager(testECDSAVerifierKeyType) 59 if err != nil { 60 t.Fatalf("registry.GetKeyManager(%q) err = %v, want nil", testECDSAVerifierKeyType, err) 61 } 62 if km.TypeURL() != testECDSAVerifierKeyType { 63 t.Errorf("km.TypeURL() = %q, want %q", km.TypeURL(), testECDSAVerifierKeyType) 64 } 65} 66 67func TestECDSAVerifierPrimitiveWithNilKey(t *testing.T) { 68 km, err := registry.GetKeyManager(testECDSAVerifierKeyType) 69 if err != nil { 70 t.Fatalf("registry.GetKeyManager(%q) err = %v, want nil", testECDSAVerifierKeyType, err) 71 } 72 if _, err := km.Primitive(nil); err == nil { 73 t.Errorf("km.Primitive(nil) err = nil, want error") 74 } 75} 76 77func createECDSAPublicKey(algorithm jepb.JwtEcdsaAlgorithm, kid *string, version uint32) (*jepb.JwtEcdsaPublicKey, error) { 78 // Public key from: https://datatracker.ietf.org/doc/html/rfc7515#appendix-A.3 79 x, err := base64Decode("f83OJ3D2xF1Bg8vub9tLe1gHMzV76e8Tus9uPHvRVEU") 80 if err != nil { 81 return nil, fmt.Errorf("base64 decoding x coordinate of public key: %v", err) 82 } 83 y, err := base64Decode("x_FEzRu9m36HLN_tue659LNpXW6pCyStikYjKIWI5a0") 84 if err != nil { 85 return nil, fmt.Errorf("base64 decoding y coordinate of public key: %v", err) 86 } 87 var customKID *jepb.JwtEcdsaPublicKey_CustomKid = nil 88 if kid != nil { 89 customKID = &jepb.JwtEcdsaPublicKey_CustomKid{Value: *kid} 90 } 91 return &jepb.JwtEcdsaPublicKey{ 92 Version: version, 93 Algorithm: algorithm, 94 X: x, 95 Y: y, 96 CustomKid: customKID, 97 }, nil 98} 99 100func createECDSASerializedPublicKey(algorithm jepb.JwtEcdsaAlgorithm, kid *string, version uint32) ([]byte, error) { 101 pubKey, err := createECDSAPublicKey(algorithm, kid, version) 102 if err != nil { 103 return nil, err 104 } 105 return proto.Marshal(pubKey) 106} 107 108func TestECDSAVerifierPrimitiveInvalidKeyVersion(t *testing.T) { 109 km, err := registry.GetKeyManager(testECDSAVerifierKeyType) 110 if err != nil { 111 t.Fatalf("registry.GetKeyManager(%q) err = %v, want nil", testECDSAVerifierKeyType, err) 112 } 113 var invalidKeyVersion uint32 = 1 114 serializedPubKey, err := createECDSASerializedPublicKey(jepb.JwtEcdsaAlgorithm_ES384, nil, invalidKeyVersion) 115 if err != nil { 116 t.Fatal(err) 117 } 118 if _, err := km.Primitive(serializedPubKey); err == nil { 119 t.Errorf("km.Primitive() err = nil, want error") 120 } 121} 122 123func TestECDSAVerifierPrimitiveWithInvalidAlgorithm(t *testing.T) { 124 km, err := registry.GetKeyManager(testECDSAVerifierKeyType) 125 if err != nil { 126 t.Fatalf("registry.GetKeyManager(%q) err = %v, want nil", testECDSAVerifierKeyType, err) 127 } 128 serializedPubKey, err := createECDSASerializedPublicKey(jepb.JwtEcdsaAlgorithm_ES_UNKNOWN, nil /*=kid*/, 0 /*=version*/) 129 if err != nil { 130 t.Fatal(err) 131 } 132 if _, err := km.Primitive(serializedPubKey); err == nil { 133 t.Errorf("km.Primitive() err = nil, want error") 134 } 135} 136 137func TestECDSAVerifierPrimitiveVerifyFixedToken(t *testing.T) { 138 km, err := registry.GetKeyManager(testECDSAVerifierKeyType) 139 if err != nil { 140 t.Fatalf("registry.GetKeyManager(%q) err = %v, want nil", testECDSAVerifierKeyType, err) 141 } 142 serializedPubKey, err := createECDSASerializedPublicKey(jepb.JwtEcdsaAlgorithm_ES256, nil /*=kid*/, 0 /*=version*/) 143 if err != nil { 144 t.Fatal(err) 145 } 146 v, err := km.Primitive(serializedPubKey) 147 if err != nil { 148 t.Fatalf("km.Primitive() err = %v, want nil", err) 149 } 150 verifier, ok := v.(*verifierWithKID) 151 if !ok { 152 t.Fatalf("primitive is not a JWT Verifier") 153 } 154 // compact from https://datatracker.ietf.org/doc/html/rfc7515#appendix-A.3 155 compact := "eyJhbGciOiJFUzI1NiJ9.eyJpc3MiOiJqb2UiLA0KICJleHAiOjEzMDA4MTkzODAsDQogImh0dHA6Ly9leGFtcGxlLmNvbS9pc19yb290Ijp0cnVlfQ.DtEhU3ljbEg8L38VWAfUAqOyKAM6-Xx-F4GawxaepmXFCgfTjDxw5djxLa8ISlSApmWQxfKTUJqPP3-Kg6NU1Q" 156 opts := &ValidatorOpts{ 157 ExpectedIssuer: refString("joe"), 158 FixedNow: time.Unix(12345, 0), 159 } 160 validator, err := NewValidator(opts) 161 if err != nil { 162 t.Fatalf("creating JWTValidator: %v", err) 163 } 164 // verification succeeds because token was valid valid on January 1, 1970 UTC. 165 if _, err := verifier.VerifyAndDecodeWithKID(compact, validator, nil); err != nil { 166 t.Errorf("verifier.VerifyAndDecodeWithKID(kid = nil) err = %v, want nil", err) 167 } 168 // verification with KID fails because token contains no KID. 169 if _, err := verifier.VerifyAndDecodeWithKID(compact, validator, refString("1234")); err == nil { 170 t.Errorf("verifier.VerifyAndDecodeWithKID(kid = '1234') err = nil, want error") 171 } 172} 173 174func TestECDSAVerifierPrimitiveFixedTokenWithKID(t *testing.T) { 175 km, err := registry.GetKeyManager(testECDSAVerifierKeyType) 176 if err != nil { 177 t.Fatalf("registry.GetKeyManager(%q) err = %v, want nil", testECDSAVerifierKeyType, err) 178 } 179 serializedPubKey, err := createECDSASerializedPublicKey(jepb.JwtEcdsaAlgorithm_ES256, refString("1234"), 0 /*=version*/) 180 if err != nil { 181 t.Fatal(err) 182 } 183 v, err := km.Primitive(serializedPubKey) 184 if err != nil { 185 t.Fatalf("km.Primitive() err = %v, want nil", err) 186 } 187 verifier, ok := v.(*verifierWithKID) 188 if !ok { 189 t.Fatalf("primitive is not a JWT Verifier") 190 } 191 // compact is the claim set '{}' with header '{"alg":"ES256", "kid":"1234"}' 192 // signed with private key as specified in https://datatracker.ietf.org/doc/html/rfc7515#appendix-A.3 193 compact := "eyJhbGciOiJFUzI1NiIsImtpZCI6IjEyMzQifQ.e30.3jdIhPC4qfXrzE8ds6tyrLoqqmwfXX-CyfP9YG0k_LFeuF5wYPsmgPeUthMFfvPIN63zQ9i-I5BQLJVwaRTTdw" 194 validator, err := NewValidator(&ValidatorOpts{AllowMissingExpiration: true}) 195 if err != nil { 196 t.Fatalf("creating JWTValidator: %v", err) 197 } 198 if _, err := verifier.VerifyAndDecodeWithKID(compact, validator, nil); err != nil { 199 t.Errorf("verifier.VerifyAndDecodeWithKID(kid = nil) err = %v, want nil ", err) 200 } 201 if _, err := verifier.VerifyAndDecodeWithKID(compact, validator, refString("1234")); err == nil { 202 t.Errorf("verifier.VerifyAndDecodeWithKID(kid = 1234) err = nil, want error ") 203 } 204} 205