go.chromium.org/luci@v0.0.0-20240309015107-7cdc2e660f33/server/auth/openid/json_web_keys_test.go (about)

     1  // Copyright 2017 The LUCI Authors.
     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  package openid
    16  
    17  import (
    18  	"context"
    19  	"crypto/rsa"
    20  	"testing"
    21  
    22  	"go.chromium.org/luci/server/auth/signing/signingtest"
    23  
    24  	. "github.com/smartystreets/goconvey/convey"
    25  	. "go.chromium.org/luci/common/testing/assertions"
    26  )
    27  
    28  func TestParseJSONWebKeySet(t *testing.T) {
    29  	t.Parallel()
    30  
    31  	Convey("Happy path", t, func() {
    32  		keys, err := NewJSONWebKeySet(&JSONWebKeySetStruct{
    33  			Keys: []JSONWebKeyStruct{
    34  				{
    35  					Kty: "RSA",
    36  					Alg: "RS256",
    37  					Use: "sig",
    38  					Kid: "key-1",
    39  					N:   "sJ46htmsgvo99FyibDKBh6zHGr2hldxfHt-6y9VTrDo3jfuFeA8xFG3Lb9LkJE4qlCvC9QRv3S0TWhQcTg9uGN2mY7B7ccIRaD2AL2hh87mFAkQzoRPxg5lvS6QisgiFQcH-oea-4iBYlBHyMemoXR8pRSwTeQKxzvZ2zohl5c-yE77vhrmDV9_n3viJH1YBYJk2weAj9Pqcfj7_cLF6tR1vd4voTL29WrWJwkO2KG6FcXrc0DQQba8nXPc-TFJd1Z9aSyzxS91rxnj8wnMbPdXPfG2jryT1Dg_LhWtDjIG7m2ZVN-_wL1hHhxC6m7yl4jSIaAO5rjKMToq5wrlgVQ",
    40  					E:   "AQAB",
    41  				},
    42  				{
    43  					Kty: "SOMETHING-ELSE",
    44  				},
    45  			},
    46  		})
    47  		So(err, ShouldBeNil)
    48  		So(len(keys.keys), ShouldEqual, 1)
    49  		So(keys.keys["key-1"].E, ShouldEqual, 65537)
    50  	})
    51  
    52  	Convey("No key ID", t, func() {
    53  		_, err := NewJSONWebKeySet(&JSONWebKeySetStruct{
    54  			Keys: []JSONWebKeyStruct{
    55  				{
    56  					Kty: "RSA",
    57  					Alg: "RS256",
    58  					Use: "sig",
    59  					N:   "sJ46htmsgvo99FyibD",
    60  					E:   "AQAB",
    61  				},
    62  			},
    63  		})
    64  		So(err, ShouldErrLike, "missing 'kid' field")
    65  	})
    66  
    67  	Convey("Bad e", t, func() {
    68  		_, err := NewJSONWebKeySet(&JSONWebKeySetStruct{
    69  			Keys: []JSONWebKeyStruct{
    70  				{
    71  					Kty: "RSA",
    72  					Alg: "RS256",
    73  					Use: "sig",
    74  					Kid: "key-1",
    75  					N:   "sJ46htmsgvo99FyibD",
    76  					E:   "????",
    77  				},
    78  			},
    79  		})
    80  		So(err, ShouldErrLike, "bad exponent encoding")
    81  	})
    82  
    83  	Convey("Bad n", t, func() {
    84  		_, err := NewJSONWebKeySet(&JSONWebKeySetStruct{
    85  			Keys: []JSONWebKeyStruct{
    86  				{
    87  					Kty: "RSA",
    88  					Alg: "RS256",
    89  					Use: "sig",
    90  					Kid: "key-1",
    91  					N:   "????",
    92  					E:   "AQAB",
    93  				},
    94  			},
    95  		})
    96  		So(err, ShouldErrLike, "bad modulus encoding")
    97  	})
    98  
    99  	Convey("No signing keys", t, func() {
   100  		_, err := NewJSONWebKeySet(&JSONWebKeySetStruct{
   101  			Keys: []JSONWebKeyStruct{
   102  				{
   103  					Kty: "RSA",
   104  					Alg: "RS256",
   105  					Use: "encrypt",
   106  					Kid: "key-1",
   107  					N:   "sJ46htmsgvo99FyibD",
   108  					E:   "AQAB",
   109  				},
   110  			},
   111  		})
   112  		So(err, ShouldErrLike, "didn't have any signing keys")
   113  	})
   114  }
   115  
   116  func TestCheckSignature(t *testing.T) {
   117  	t.Parallel()
   118  
   119  	Convey("With signed blob", t, func() {
   120  		ctx := context.Background()
   121  		signer := signingtest.NewSigner(nil)
   122  		keys := JSONWebKeySet{
   123  			keys: map[string]rsa.PublicKey{
   124  				"key-1": signer.KeyForTest().PublicKey,
   125  			},
   126  		}
   127  
   128  		var blob = []byte("blah blah")
   129  		_, sig, err := signer.SignBytes(ctx, blob)
   130  		So(err, ShouldBeNil)
   131  
   132  		Convey("Good signature", func() {
   133  			So(keys.CheckSignature("key-1", blob, sig), ShouldBeNil)
   134  		})
   135  
   136  		Convey("Bad signature", func() {
   137  			So(keys.CheckSignature("key-1", []byte("something else"), sig), ShouldErrLike, "bad signature")
   138  		})
   139  
   140  		Convey("Unknown key", func() {
   141  			So(keys.CheckSignature("unknown", blob, sig), ShouldErrLike, "unknown signing key")
   142  		})
   143  	})
   144  }