github.com/minio/minio@v0.0.0-20240328213742-3f72439b8a27/internal/config/identity/openid/jwks.go (about) 1 // Copyright (c) 2015-2021 MinIO, Inc. 2 // 3 // This file is part of MinIO Object Storage stack 4 // 5 // This program is free software: you can redistribute it and/or modify 6 // it under the terms of the GNU Affero General Public License as published by 7 // the Free Software Foundation, either version 3 of the License, or 8 // (at your option) any later version. 9 // 10 // This program is distributed in the hope that it will be useful 11 // but WITHOUT ANY WARRANTY; without even the implied warranty of 12 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 13 // GNU Affero General Public License for more details. 14 // 15 // You should have received a copy of the GNU Affero General Public License 16 // along with this program. If not, see <http://www.gnu.org/licenses/>. 17 18 package openid 19 20 import ( 21 "crypto" 22 "crypto/ecdsa" 23 "crypto/elliptic" 24 "crypto/rsa" 25 "encoding/base64" 26 "errors" 27 "fmt" 28 "math/big" 29 ) 30 31 // JWKS - https://tools.ietf.org/html/rfc7517 32 type JWKS struct { 33 Keys []*JWKS `json:"keys,omitempty"` 34 35 Kty string `json:"kty"` 36 Use string `json:"use,omitempty"` 37 Kid string `json:"kid,omitempty"` 38 Alg string `json:"alg,omitempty"` 39 40 Crv string `json:"crv,omitempty"` 41 X string `json:"x,omitempty"` 42 Y string `json:"y,omitempty"` 43 D string `json:"d,omitempty"` 44 N string `json:"n,omitempty"` 45 E string `json:"e,omitempty"` 46 K string `json:"k,omitempty"` 47 } 48 49 var ( 50 errMalformedJWKRSAKey = errors.New("malformed JWK RSA key") 51 errMalformedJWKECKey = errors.New("malformed JWK EC key") 52 ) 53 54 // DecodePublicKey - decodes JSON Web Key (JWK) as public key 55 func (key *JWKS) DecodePublicKey() (crypto.PublicKey, error) { 56 switch key.Kty { 57 case "RSA": 58 if key.N == "" || key.E == "" { 59 return nil, errMalformedJWKRSAKey 60 } 61 62 // decode exponent 63 ebuf, err := base64.RawURLEncoding.DecodeString(key.E) 64 if err != nil { 65 return nil, errMalformedJWKRSAKey 66 } 67 68 nbuf, err := base64.RawURLEncoding.DecodeString(key.N) 69 if err != nil { 70 return nil, errMalformedJWKRSAKey 71 } 72 73 var n, e big.Int 74 n.SetBytes(nbuf) 75 e.SetBytes(ebuf) 76 77 return &rsa.PublicKey{ 78 E: int(e.Int64()), 79 N: &n, 80 }, nil 81 case "EC": 82 if key.Crv == "" || key.X == "" || key.Y == "" { 83 return nil, errMalformedJWKECKey 84 } 85 86 var curve elliptic.Curve 87 switch key.Crv { 88 case "P-224": 89 curve = elliptic.P224() 90 case "P-256": 91 curve = elliptic.P256() 92 case "P-384": 93 curve = elliptic.P384() 94 case "P-521": 95 curve = elliptic.P521() 96 default: 97 return nil, fmt.Errorf("Unknown curve type: %s", key.Crv) 98 } 99 100 xbuf, err := base64.RawURLEncoding.DecodeString(key.X) 101 if err != nil { 102 return nil, errMalformedJWKECKey 103 } 104 105 ybuf, err := base64.RawURLEncoding.DecodeString(key.Y) 106 if err != nil { 107 return nil, errMalformedJWKECKey 108 } 109 110 var x, y big.Int 111 x.SetBytes(xbuf) 112 y.SetBytes(ybuf) 113 114 return &ecdsa.PublicKey{ 115 Curve: curve, 116 X: &x, 117 Y: &y, 118 }, nil 119 default: 120 return nil, fmt.Errorf("Unknown JWK key type %s", key.Kty) 121 } 122 }