Files
autoglue/internal/auth/jwks_export.go
2025-11-02 13:19:30 +00:00

72 lines
1.6 KiB
Go

package auth
import (
"crypto/ed25519"
"crypto/rsa"
"encoding/base64"
"fmt"
"math/big"
)
// base64url (no padding)
func b64url(b []byte) string {
return base64.RawURLEncoding.EncodeToString(b)
}
// convert small int (RSA exponent) to big-endian bytes
func fromInt(i int) []byte {
var x big.Int
x.SetInt64(int64(i))
return x.Bytes()
}
// --- public accessors for JWKS ---
// KeyMeta is a minimal metadata view exposed for JWKS rendering.
type KeyMeta struct {
Alg string
}
// MetaFor returns minimal metadata (currently the alg) for a given kid.
// If not found, returns zero value (Alg == "").
func MetaFor(kid string) KeyMeta {
kc.mu.RLock()
defer kc.mu.RUnlock()
if m, ok := kc.meta[kid]; ok {
return KeyMeta{Alg: m.Alg}
}
return KeyMeta{}
}
// KcCopy invokes fn with a shallow copy of the public key map (kid -> public key instance).
// Useful to iterate without holding the lock during JSON building.
func KcCopy(fn func(map[string]interface{})) {
kc.mu.RLock()
defer kc.mu.RUnlock()
out := make(map[string]interface{}, len(kc.pub))
for kid, pk := range kc.pub {
out[kid] = pk
}
fmt.Println(out)
fn(out)
}
// PubToJWK converts a parsed public key into bare JWK parameters + kty.
// - RSA: returns n/e (base64url) and kty="RSA"
// - Ed25519: returns x (base64url) and kty="OKP"
func PubToJWK(_kid, _alg string, pub any) (map[string]string, string) {
switch k := pub.(type) {
case *rsa.PublicKey:
return map[string]string{
"n": b64url(k.N.Bytes()),
"e": b64url(fromInt(k.E)),
}, "RSA"
case ed25519.PublicKey:
return map[string]string{
"x": b64url([]byte(k)),
}, "OKP"
default:
return nil, ""
}
}