dumb-jose/jwk/jwk.go

79 lines
1.7 KiB
Go

package jwk
import (
"crypto"
"encoding/json"
"fmt"
"io"
"mercan.dev/dumb-jose/internal/publickey"
)
type JWK struct {
KeyID string `json:"kid"`
KeyType string `json:"kty"`
Algorithm string `json:"alg"`
UseCase string `json:"use"`
PublicKey crypto.PublicKey `json:"-"`
}
type jwkHeader struct {
Keys []json.RawMessage `json:"keys"`
}
func ParseKeysFromSet(r io.Reader) ([]JWK, error) {
dec := json.NewDecoder(r)
keys := jwkHeader{}
err := dec.Decode(&keys)
if err != nil {
return nil, err
}
var set []JWK
for _, key := range keys.Keys {
var jwk JWK
err := json.Unmarshal(key, &jwk)
if err != nil {
return nil, err
}
if jwk.UseCase != "sig" {
return nil, fmt.Errorf("Non-signing use case %s", jwk.UseCase)
}
switch jwk.Algorithm {
case "ES256", "ES384", "ES512":
if jwk.KeyType != "EC" {
return nil, fmt.Errorf("Insuitable key type %s for algorithm %s", jwk.KeyType, jwk.Algorithm)
}
jwk.PublicKey, err = publickey.ParseECDSAPublicKey(key)
case "RS256", "RS384", "RS512", "PS256", "PS384", "PS512":
if jwk.KeyType != "RSA" {
return nil, fmt.Errorf("Insuitable key type %s for algorithm %s", jwk.KeyType, jwk.Algorithm)
}
jwk.PublicKey, err = publickey.ParseRSAPublicKey(key)
case "EdDSA":
if jwk.KeyType != "OKP" {
return nil, fmt.Errorf("Insuitable key type %s for algorithm %s", jwk.KeyType, jwk.Algorithm)
}
jwk.PublicKey, err = publickey.ParseEdDSAPublicKey(key)
default:
return nil, fmt.Errorf("Invalid/Unsupported JWK Algorithm %s", jwk.Algorithm)
}
if err != nil {
return nil, err
}
set = append(set, jwk)
}
return set, nil
}