package jwtutil import ( "crypto/rand" "crypto/rsa" "crypto/x509" "encoding/pem" "os" "github.com/lestrrat-go/jwx/v2/jwa" "github.com/lestrrat-go/jwx/v2/jwk" "github.com/pkg/errors" ) func FromRSA(privateKey *rsa.PrivateKey) (jwk.Key, error) { key, err := jwk.FromRaw(privateKey) if err != nil { return nil, errors.WithStack(err) } if err := key.Set(jwk.AlgorithmKey, jwa.RS256); err != nil { return nil, errors.WithStack(err) } return key, nil } func LoadOrGenerateRSAKey(path string, size int) (*rsa.PrivateKey, error) { privateKey, err := LoadRSAKey(path) if err != nil { if !errors.Is(err, os.ErrNotExist) { return nil, errors.WithStack(err) } privateKey, err = GenerateRSAKey(size) if err != nil { return nil, errors.WithStack(err) } if err := SaveRSAKey(path, privateKey); err != nil { return nil, errors.WithStack(err) } } return privateKey, nil } func LoadRSAKey(path string) (*rsa.PrivateKey, error) { data, err := os.ReadFile(path) if err != nil { return nil, errors.WithStack(err) } block, _ := pem.Decode(data) if block == nil { return nil, errors.New("failed to parse pem block") } privateKey, err := x509.ParsePKCS1PrivateKey(block.Bytes) if err != nil { return nil, errors.WithStack(err) } return privateKey, nil } func SaveRSAKey(path string, privateKey *rsa.PrivateKey) error { data := x509.MarshalPKCS1PrivateKey(privateKey) pem := pem.EncodeToMemory( &pem.Block{ Type: "RSA PRIVATE KEY", Bytes: data, }, ) if err := os.WriteFile(path, pem, os.FileMode(0600)); err != nil { return errors.WithStack(err) } return nil } func GenerateRSAKey(size int) (*rsa.PrivateKey, error) { privateKey, err := rsa.GenerateKey(rand.Reader, size) if err != nil { return nil, errors.WithStack(err) } return privateKey, nil }