storj.io/minio@v0.0.0-20230509071714-0cbc90f649b1/cmd/config/identity/openid/jwks.go (about)

     1  /*
     2   * MinIO Cloud Storage, (C) 2018 MinIO, Inc.
     3   *
     4   * Licensed under the Apache License, Version 2.0 (the "License");
     5   * you may not use this file except in compliance with the License.
     6   * You may obtain a copy of the License at
     7   *
     8   *     http://www.apache.org/licenses/LICENSE-2.0
     9   *
    10   * Unless required by applicable law or agreed to in writing, software
    11   * distributed under the License is distributed on an "AS IS" BASIS,
    12   * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
    13   * See the License for the specific language governing permissions and
    14   * limitations under the License.
    15   */
    16  
    17  package openid
    18  
    19  import (
    20  	"crypto"
    21  	"crypto/ecdsa"
    22  	"crypto/elliptic"
    23  	"crypto/rsa"
    24  	"encoding/base64"
    25  	"errors"
    26  	"fmt"
    27  	"math/big"
    28  )
    29  
    30  // JWKS - https://tools.ietf.org/html/rfc7517
    31  type JWKS struct {
    32  	Keys []*JWKS `json:"keys,omitempty"`
    33  
    34  	Kty string `json:"kty"`
    35  	Use string `json:"use,omitempty"`
    36  	Kid string `json:"kid,omitempty"`
    37  	Alg string `json:"alg,omitempty"`
    38  
    39  	Crv string `json:"crv,omitempty"`
    40  	X   string `json:"x,omitempty"`
    41  	Y   string `json:"y,omitempty"`
    42  	D   string `json:"d,omitempty"`
    43  	N   string `json:"n,omitempty"`
    44  	E   string `json:"e,omitempty"`
    45  	K   string `json:"k,omitempty"`
    46  }
    47  
    48  var (
    49  	errMalformedJWKRSAKey = errors.New("malformed JWK RSA key")
    50  	errMalformedJWKECKey  = errors.New("malformed JWK EC key")
    51  )
    52  
    53  // DecodePublicKey - decodes JSON Web Key (JWK) as public key
    54  func (key *JWKS) DecodePublicKey() (crypto.PublicKey, error) {
    55  	switch key.Kty {
    56  	case "RSA":
    57  		if key.N == "" || key.E == "" {
    58  			return nil, errMalformedJWKRSAKey
    59  		}
    60  
    61  		// decode exponent
    62  		ebuf, err := base64.RawURLEncoding.DecodeString(key.E)
    63  		if err != nil {
    64  			return nil, errMalformedJWKRSAKey
    65  		}
    66  
    67  		nbuf, err := base64.RawURLEncoding.DecodeString(key.N)
    68  		if err != nil {
    69  			return nil, errMalformedJWKRSAKey
    70  		}
    71  
    72  		var n, e big.Int
    73  		n.SetBytes(nbuf)
    74  		e.SetBytes(ebuf)
    75  
    76  		return &rsa.PublicKey{
    77  			E: int(e.Int64()),
    78  			N: &n,
    79  		}, nil
    80  	case "EC":
    81  		if key.Crv == "" || key.X == "" || key.Y == "" {
    82  			return nil, errMalformedJWKECKey
    83  		}
    84  
    85  		var curve elliptic.Curve
    86  		switch key.Crv {
    87  		case "P-224":
    88  			curve = elliptic.P224()
    89  		case "P-256":
    90  			curve = elliptic.P256()
    91  		case "P-384":
    92  			curve = elliptic.P384()
    93  		case "P-521":
    94  			curve = elliptic.P521()
    95  		default:
    96  			return nil, fmt.Errorf("Unknown curve type: %s", key.Crv)
    97  		}
    98  
    99  		xbuf, err := base64.RawURLEncoding.DecodeString(key.X)
   100  		if err != nil {
   101  			return nil, errMalformedJWKECKey
   102  		}
   103  
   104  		ybuf, err := base64.RawURLEncoding.DecodeString(key.Y)
   105  		if err != nil {
   106  			return nil, errMalformedJWKECKey
   107  		}
   108  
   109  		var x, y big.Int
   110  		x.SetBytes(xbuf)
   111  		y.SetBytes(ybuf)
   112  
   113  		return &ecdsa.PublicKey{
   114  			Curve: curve,
   115  			X:     &x,
   116  			Y:     &y,
   117  		}, nil
   118  	default:
   119  		return nil, fmt.Errorf("Unknown JWK key type %s", key.Kty)
   120  	}
   121  }