package auth import ( "crypto/rsa" "crypto/sha256" "crypto/x509" "encoding/base64" "encoding/pem" "errors" "math/big" "os" ) type JWK struct { KeyType string `json:"kty"` Use string `json:"use"` KeyID string `json:"kid"` Algorithm string `json:"alg"` Modulus string `json:"n"` Exponent string `json:"e"` } func LoadRSAPrivateKey(path string) (*rsa.PrivateKey, error) { if path == "" { return nil, errors.New("rsa private key file is required") } data, err := os.ReadFile(path) if err != nil { return nil, err } block, _ := pem.Decode(data) if block == nil { return nil, errors.New("rsa private key file has no PEM block") } if key, err := x509.ParsePKCS1PrivateKey(block.Bytes); err == nil { return key, nil } parsed, err := x509.ParsePKCS8PrivateKey(block.Bytes) if err != nil { return nil, err } key, ok := parsed.(*rsa.PrivateKey) if !ok { return nil, errors.New("private key is not an RSA private key") } return key, nil } func PublicJWKFromKey(key *rsa.PrivateKey) JWK { publicKey := key.PublicKey return JWK{ KeyType: "RSA", Use: "sig", KeyID: RSAKeyID(&publicKey), Algorithm: "RS256", Modulus: base64.RawURLEncoding.EncodeToString(publicKey.N.Bytes()), Exponent: base64.RawURLEncoding.EncodeToString(big.NewInt(int64(publicKey.E)).Bytes()), } } func RSAKeyID(publicKey *rsa.PublicKey) string { hash := sha256.Sum256(publicKey.N.Bytes()) return base64.RawURLEncoding.EncodeToString(hash[:8]) }