Path: blob/main/components/public-api-server/pkg/jws/rsa256.go
2506 views
// Copyright (c) 2023 Gitpod GmbH. All rights reserved.1// Licensed under the GNU Affero General Public License (AGPL).2// See License.AGPL.txt in the project root for license information.34package jws56import (7"crypto"8"crypto/rsa"9"errors"10"fmt"1112"github.com/golang-jwt/jwt/v5"13)1415func NewRSA256(keyset KeySet) (*RSA256, error) {16verifier, err := NewRSA256VerifierFromKeySet(keyset)17if err != nil {18return nil, err19}2021return &RSA256{22RSA256Signer: &RSA256Signer{23Signing: keyset.Signing,24},25RSA256Verifier: verifier,26}, nil27}2829type RSA256 struct {30*RSA256Signer31*RSA256Verifier32}3334type RSA256Signer struct {35Signing Key36}3738func (s *RSA256Signer) Sign(token *jwt.Token) (string, error) {39if token.Method != jwt.SigningMethodRS256 {40return "", errors.New("invalid signing method, token must use RSA256")41}4243token.Header[KeyIDName] = s.Signing.ID4445signed, err := token.SignedString(s.Signing.Private)46if err != nil {47return "", fmt.Errorf("failed to sign jwt: %w", err)48}4950return signed, nil51}5253func NewRSA256VerifierFromKeySet(keyset KeySet) (*RSA256Verifier, error) {54keys := map[string]*rsa.PrivateKey{55keyset.Signing.ID: keyset.Signing.Private,56}5758for _, v := range keyset.Validating {59if _, found := keys[v.ID]; found {60return nil, errors.New("duplicate keys when constructing JWT")61}6263keys[v.ID] = v.Private64}6566return &RSA256Verifier{67Keys: keys,68}, nil69}7071type RSA256Verifier struct {72// Keys by Key ID73Keys map[string]*rsa.PrivateKey74}7576func (v *RSA256Verifier) Verify(token string, claims jwt.Claims, opts ...jwt.ParserOption) (*jwt.Token, error) {77parsed, err := jwt.ParseWithClaims(token, claims, jwt.Keyfunc(func(t *jwt.Token) (interface{}, error) {78return v.getPublicKeyFromKeyID(t)79}), opts...)8081if err != nil {82return nil, fmt.Errorf("failed to parse jwt: %w", err)83}8485return parsed, nil86}8788func (v *RSA256Verifier) getPublicKeyFromKeyID(token *jwt.Token) (crypto.PublicKey, error) {89keyID, ok := token.Header[KeyIDName].(string)90if !ok {91return nil, fmt.Errorf("missing key id: %w", ErrInvalidKeyID)92}9394key, ok := v.Keys[keyID]95if !ok {96return nil, fmt.Errorf("unknown key id %s: %w", keyID, ErrInvalidKeyID)97}9899return key.Public(), nil100}101102103