Files
auth-jwt/signer_rsa.go
T

58 lines
1.6 KiB
Go
Raw Normal View History

package authjwt
import (
"crypto/rsa"
"crypto/x509"
"encoding/pem"
"fmt"
"github.com/golang-jwt/jwt/v5"
)
var _ Signer = (*rsaSigner)(nil)
type rsaSigner struct {
private *rsa.PrivateKey
public *rsa.PublicKey
}
// NewRSASigner returns a Signer backed by RSA-SHA256 (RS256).
// The public key is derived from the private key — no separate argument needed.
func NewRSASigner(privateKey *rsa.PrivateKey) Signer {
return &rsaSigner{private: privateKey, public: &privateKey.PublicKey}
}
// NewRSASignerFromPEM parses a PKCS#8 or PKCS#1 PEM-encoded RSA private key.
func NewRSASignerFromPEM(pemKey []byte) (Signer, error) {
block, _ := pem.Decode(pemKey)
if block == nil {
return nil, fmt.Errorf("no PEM block found")
}
key, err := x509.ParsePKCS8PrivateKey(block.Bytes)
if err != nil {
rsaKey, err2 := x509.ParsePKCS1PrivateKey(block.Bytes)
if err2 != nil {
return nil, fmt.Errorf("parse RSA private key: %w", err)
}
return NewRSASigner(rsaKey), nil
}
rsaKey, ok := key.(*rsa.PrivateKey)
if !ok {
return nil, fmt.Errorf("PEM key is not an RSA private key")
}
return NewRSASigner(rsaKey), nil
}
func (s *rsaSigner) Sign(claims jwt.Claims) (string, error) {
return jwt.NewWithClaims(jwt.SigningMethodRS256, claims).SignedString(s.private)
}
func (s *rsaSigner) Verify(tokenString string) (*jwt.Token, error) {
return jwt.Parse(tokenString, func(t *jwt.Token) (any, error) {
if _, ok := t.Method.(*jwt.SigningMethodRSA); !ok {
return nil, fmt.Errorf("unexpected signing method %q", t.Header["alg"])
}
return s.public, nil
}, jwt.WithJSONNumber())
}