Documentation
¶
Overview ¶
Package crypto is the single cryptographic policy and primitives layer for the gmb-eudi EUDI modules. All JOSE/COSE/X.509 operations go through this package; no other module names an algorithm (ECCG Agreed Cryptographic Mechanisms v2.0, EW-PIO-01-003).
Import with an alias to avoid clashing with the standard library:
eudicrypto "github.com/gmb-eudi/go-eudi-crypto"
Index ¶
- Constants
- Variables
- func ECPublicKeyToJWK(pub stdcrypto.PublicKey) (map[string]any, error)
- func EncryptJWE(recipient stdcrypto.PublicKey, protected map[string]any, payload []byte) ([]byte, error)
- func GenerateEphemeralKey(crv string) (*ecdsa.PrivateKey, error)
- func ParseCertChain(raw []byte) ([]*x509.Certificate, error)
- func ParseECPublicKeyJWK(jwkJSON []byte) (stdcrypto.PublicKey, error)
- func SignCOSESign1(ctx context.Context, kp KeyProvider, keyID string, protected COSEHeader, ...) ([]byte, error)
- func SignJWS(ctx context.Context, kp KeyProvider, keyID string, protected map[string]any, ...) ([]byte, error)
- func VerifyChain(leaf *x509.Certificate, intermediates []*x509.Certificate, opts ChainOptions) ([][]*x509.Certificate, error)
- type COSEHeader
- type ChainOptions
- type Decrypter
- type Header
- type KeyProvider
- type Policy
- type StaticProvider
Constants ¶
const ECCGVersion = "2.0"
ECCGVersion is the pinned version of the ECCG Agreed Cryptographic Mechanisms document this policy table implements (EW-PIO-01-003).
Variables ¶
var ( ErrAlgorithmNotAllowed = errors.New("crypto: algorithm not allowed by ECCG policy") ErrCurveNotAllowed = errors.New("crypto: curve not allowed by ECCG policy") ErrKeyTypeNotAllowed = errors.New("crypto: key type not allowed by ECCG policy") ErrKeyNotFound = errors.New("crypto: key not found") ErrNoAnchors = errors.New("crypto: no trust anchors provided") ErrCritUnsupported = errors.New("crypto: unsupported critical header parameter") ErrAlgKeyMismatch = errors.New("crypto: token algorithm does not match key") ErrProtectedHeader = errors.New("crypto: forbidden protected header parameter") ErrMalformed = errors.New("crypto: malformed input") ErrVerificationFailed = errors.New("crypto: verification failed") ErrDecryptionFailed = errors.New("crypto: decryption failed") )
Sentinel errors. Callers map these to their own problem/reason codes; this library never carries HTTP semantics or framework dependencies.
Functions ¶
func ECPublicKeyToJWK ¶
ECPublicKeyToJWK serializes an EC public key to an RFC 7518 §6.2 JWK as a map (ready to embed as an SD-JWT VC `cnf.jwk` object; RFC 7800). Rejects non-EC keys and curves not on the ECCG allow-list.
func EncryptJWE ¶
func EncryptJWE(recipient stdcrypto.PublicKey, protected map[string]any, payload []byte) ([]byte, error)
EncryptJWE encrypts payload to an EC recipient key using ECDH-ES key agreement with A256GCM content encryption (RFC 7516; ECCG Agreed Mechanisms / HAIP 1.0 encrypted-response profile). Compact serialization. The protected map may carry additional header params (e.g. OID4VP Annex B.2 apu = base64url(mdocGeneratedNonce)); alg/enc/epk are set by the library from policy and must not be supplied by the caller. The pair is never taken from the caller — algorithms are policy-driven, never chosen by callers or tokens.
func GenerateEphemeralKey ¶
func GenerateEphemeralKey(crv string) (*ecdsa.PrivateKey, error)
GenerateEphemeralKey creates a fresh EC keypair for per-session response encryption (HAIP response encryption; OID4VP §8.3 direct_post.jwt). The curve must be ECCG-allowed.
func ParseCertChain ¶
func ParseCertChain(raw []byte) ([]*x509.Certificate, error)
ParseCertChain parses one or more certificates from PEM (CERTIFICATE blocks) or raw DER. Untrusted input — fuzzed (FuzzParseCertChain).
func ParseECPublicKeyJWK ¶
ParseECPublicKeyJWK parses an RFC 7518 EC public-key JWK — as carried in an SD-JWT VC `cnf.jwk` (RFC 7800) — into a *ecdsa.PublicKey. Strict and fail-closed: only kty="EC" on an ECCG-allowed curve is accepted, x/y must be fixed-size big-endian coordinates, and the point is fully validated (on-curve, non-identity) by ecdsa.ParseUncompressedPublicKey. Malformed input is rejected and never panics (fuzzed: FuzzParseECPublicKeyJWK).
func SignCOSESign1 ¶
func SignCOSESign1(ctx context.Context, kp KeyProvider, keyID string, protected COSEHeader, payload []byte) ([]byte, error)
SignCOSESign1 signs payload as COSE_Sign1 (RFC 9052 §4.2). The alg label is derived from the key; callers must not set label 1 (algorithms are derived from keys, never chosen by callers or messages).
func SignJWS ¶
func SignJWS(ctx context.Context, kp KeyProvider, keyID string, protected map[string]any, payload []byte) ([]byte, error)
SignJWS signs payload as a compact JWS (RFC 7515). The alg header is derived from the key; callers must not set it (algorithms are derived from keys, never chosen by callers or tokens).
func VerifyChain ¶
func VerifyChain(leaf *x509.Certificate, intermediates []*x509.Certificate, opts ChainOptions) ([][]*x509.Certificate, error)
VerifyChain performs RFC 5280 §6.1 path validation of leaf against the explicit anchor set. Fail closed: empty anchors is an error, never a system-pool fallback.
Types ¶
type COSEHeader ¶
COSEHeader carries integer-labeled COSE header parameters (RFC 9052 §3). EUDI profiles (ISO 18013-5 IssuerAuth/DeviceAuth) use integer labels only; string labels are not surfaced by this façade.
func VerifyCOSESign1 ¶
VerifyCOSESign1 verifies a COSE_Sign1 message (RFC 9052 §4.2) against an explicitly supplied key. The expected algorithm is derived from the key; a mismatching protected alg is rejected.
type ChainOptions ¶
type ChainOptions struct {
Anchors []*x509.Certificate
EKUs []x509.ExtKeyUsage // empty = any EKU accepted (callers pass profile EKUs)
At time.Time // required; explicitly injected clock, no hidden time.Now
}
ChainOptions configures VerifyChain. Anchors MUST come from go-eudi-trust — never the system pool, never inline PEM in services.
type Decrypter ¶
type Decrypter interface {
PrivateKey() stdcrypto.PrivateKey
}
Decrypter exposes the private key material needed for JWE ECDH-ES key agreement (RFC 7518 §4.6). In-memory implementations return the key directly; HSM-backed implementations require a native-decrypt extension of this interface — revisited when an HSM-backed provider lands.
type Header ¶
Header is a decoded JOSE protected header.
func DecryptJWE ¶
func DecryptJWE(ctx context.Context, kp KeyProvider, keyID string, token []byte) ([]byte, Header, error)
DecryptJWE decrypts a compact JWE (RFC 7516) addressed to keyID. The protected header's alg/enc pair is checked against the ECCG policy BEFORE any decryption is attempted (HAIP: ECDH-ES with AES-GCM only).
type KeyProvider ¶
type KeyProvider interface {
Signer(ctx context.Context, keyID string) (stdcrypto.Signer, error)
Decrypter(ctx context.Context, keyID string) (Decrypter, error)
Public(ctx context.Context, keyID string) (stdcrypto.PublicKey, error)
}
KeyProvider abstracts access to the operator's private keys. Planned implementations: filekeys (PEM/PKCS#8, dev), k8ssecret, pkcs11 (build tag), kms — only filekeys and the in-memory StaticProvider ship today.
type Policy ¶
type Policy interface {
AllowedJWSAlg(alg string) bool
AllowedJWEAlg(alg, enc string) bool
AllowedCOSEAlg(alg int64) bool
AllowedCurve(crv string) bool
HashForAlg(alg string) (stdcrypto.Hash, error)
AllowedHashName(name string) bool
HashForName(name string) (stdcrypto.Hash, error)
HashForMSODigestAlg(alg string) (stdcrypto.Hash, error)
}
Policy is the ECCG-pinned algorithm allow-list. Immutable; no env/config overrides for algorithms — they are derived from keys, never chosen by callers or tokens. Unknown = reject.
type StaticProvider ¶
type StaticProvider struct {
// contains filtered or unexported fields
}
StaticProvider is an in-memory KeyProvider for per-session ephemeral keys (GenerateEphemeralKey) and tests. The map is copied at construction and immutable afterwards, so concurrent use needs no locking.
func NewStaticProvider ¶
func NewStaticProvider(keys map[string]*ecdsa.PrivateKey) *StaticProvider
NewStaticProvider returns a StaticProvider serving the given keys. The map is copied, so callers may safely mutate their own copy afterwards.
func (*StaticProvider) Decrypter ¶
Decrypter returns a Decrypter wrapping the EC private key matching keyID.