Documentation
¶
Overview ¶
Package cryptoutil provides extensible cryptographic utilities for certificate parsing, signature verification, key management, and algorithm mapping.
The core type is Extensions, which holds pluggable parsers, verifiers, and algorithm mappers. The standard library functions are always tried first; registered extensions act as fallbacks for algorithm families that Go's crypto/x509 does not support (e.g. Brainpool curves, PQ algorithms).
Index ¶
- Variables
- func ECDSAASN1ToRaw(der []byte, componentSize int) ([]byte, error)
- func ECDSAComponentSize(curve elliptic.Curve) int
- func ECDSARawToASN1(raw []byte) ([]byte, error)
- func IsECDSAKey(pub crypto.PublicKey) bool
- func IsEdDSAKey(pub crypto.PublicKey) bool
- func IsRSAKey(pub crypto.PublicKey) bool
- func NormalizeECDSASignature(sig []byte) ([]byte, error)
- func PublicKeyFromSigner(s crypto.Signer) crypto.PublicKey
- type Algorithm
- type AlgorithmRegistry
- func (r *AlgorithmRegistry) ByXMLDSIG(uri string) *Algorithm
- func (r *AlgorithmRegistry) COSEAlgorithm(pub crypto.PublicKey) (int, error)
- func (r *AlgorithmRegistry) CurveName(pub *ecdsa.PublicKey) (string, error)
- func (r *AlgorithmRegistry) ForKey(pub crypto.PublicKey) (*Algorithm, error)
- func (r *AlgorithmRegistry) JWSAlgorithm(pub crypto.PublicKey) (string, error)
- func (r *AlgorithmRegistry) Register(a *Algorithm)
- func (r *AlgorithmRegistry) XMLDSIGAlgorithm(pub crypto.PublicKey) (string, error)
- type CertificateParser
- type Extensions
- func (ext *Extensions) CheckSignature(cert *x509.Certificate, algo x509.SignatureAlgorithm, signed, signature []byte) error
- func (ext *Extensions) CheckSignatureXMLDSIG(cert *x509.Certificate, xmldsigURI string, signed, signature []byte) error
- func (ext *Extensions) ParseCertificate(der []byte) (*x509.Certificate, error)
- func (ext *Extensions) ParseCertificatesPEM(pemData []byte) ([]*x509.Certificate, error)
- func (ext *Extensions) ParsePrivateKey(der []byte) (crypto.PrivateKey, error)
- func (ext *Extensions) ParsePrivateKeyPEM(pemData []byte) (crypto.PrivateKey, error)
- type PrivateKeyParser
- type SignatureVerifier
Constants ¶
This section is empty.
Variables ¶
var ErrNotHandled = errors.New("cryptoutil: not handled by this extension")
ErrNotHandled signals that an extension does not handle this input. Extensions should return this (not nil) when declining to process.
Functions ¶
func ECDSAASN1ToRaw ¶
ECDSAASN1ToRaw converts an ASN.1 DER-encoded ECDSA signature to IEEE P1363 raw (r||s) format with the given byte size per component (typically key size in bytes: 32 for P-256, 48 for P-384, 66 for P-521).
Each component is zero-padded on the left to exactly componentSize bytes.
func ECDSAComponentSize ¶
ECDSAComponentSize returns the expected byte size of each r/s component for the given curve. This is useful when converting between ASN.1 DER and raw r||s ECDSA signatures.
func ECDSARawToASN1 ¶
ECDSARawToASN1 converts an IEEE P1363 raw (r||s) ECDSA signature to ASN.1 DER encoding. This format conversion is required by XML-DSIG (RFC 4050), JWS (RFC 7518), COSE (RFC 9053), and WebAuthn, all of which use the raw concatenation format, while Go's crypto/ecdsa expects ASN.1 DER.
The input must be an even number of bytes with r and s each occupying exactly half the total length.
func IsECDSAKey ¶
IsECDSAKey returns true if the public key is an ECDSA key.
func IsEdDSAKey ¶
IsEdDSAKey returns true if the public key is an Ed25519 key.
func NormalizeECDSASignature ¶ added in v0.4.0
NormalizeECDSASignature takes an ECDSA signature that may be BER-encoded (with unnecessary leading zeros, wrong padding, etc.) and returns a strictly DER-encoded signature. This is needed because some authenticators (notably YubiKey 5.8 firmware) produce BER-encoded signatures that Go's strict DER parser in crypto/x509 rejects.
BER (Basic Encoding Rules) is more permissive than DER (Distinguished Encoding Rules). While both are valid ASN.1, X.509 signatures should use DER. This function normalizes BER to DER by: 1. Leniently parsing the BER-encoded ASN.1 SEQUENCE 2. Extracting the raw r and s integer values 3. Re-encoding as strict DER
Returns the original signature unchanged if it's already valid DER, or an error if it cannot be parsed as an ECDSA signature at all.
Types ¶
type Algorithm ¶
type Algorithm struct {
Name string // Canonical name: "P-256", "RS256", etc.
JWS string // JWS/JWA identifier (RFC 7518)
XMLDSIG string // XML-DSIG algorithm URI
COSE int // COSE algorithm number (RFC 9053), 0 if not assigned
Hash crypto.Hash // Hash function for this algorithm
KeyType string // "EC", "RSA", "OKP", etc.
}
Algorithm describes a cryptographic algorithm across multiple protocol domains.
type AlgorithmRegistry ¶
type AlgorithmRegistry struct {
// CurveAlgorithms maps elliptic curve Params().Name to Algorithm.
CurveAlgorithms map[string]*Algorithm
// All is the full list of registered algorithms.
All []*Algorithm
// contains filtered or unexported fields
}
AlgorithmRegistry maps public keys to algorithms across protocol domains.
func NewAlgorithmRegistry ¶
func NewAlgorithmRegistry() *AlgorithmRegistry
NewAlgorithmRegistry returns a registry pre-populated with standard NIST algorithms.
func (*AlgorithmRegistry) ByXMLDSIG ¶ added in v0.3.0
func (r *AlgorithmRegistry) ByXMLDSIG(uri string) *Algorithm
ByXMLDSIG returns the Algorithm registered for the given XML-DSIG URI, or nil if the URI is not recognized.
func (*AlgorithmRegistry) COSEAlgorithm ¶
func (r *AlgorithmRegistry) COSEAlgorithm(pub crypto.PublicKey) (int, error)
COSEAlgorithm returns the COSE algorithm number for the given public key.
func (*AlgorithmRegistry) CurveName ¶
func (r *AlgorithmRegistry) CurveName(pub *ecdsa.PublicKey) (string, error)
CurveName returns the JWK curve name (e.g. "P-256") for an elliptic curve key.
func (*AlgorithmRegistry) ForKey ¶
func (r *AlgorithmRegistry) ForKey(pub crypto.PublicKey) (*Algorithm, error)
ForKey returns the Algorithm for the given public key, or an error if the key type or curve is not recognized.
func (*AlgorithmRegistry) JWSAlgorithm ¶
func (r *AlgorithmRegistry) JWSAlgorithm(pub crypto.PublicKey) (string, error)
JWSAlgorithm returns the JWS/JWA algorithm name for the given public key.
func (*AlgorithmRegistry) Register ¶
func (r *AlgorithmRegistry) Register(a *Algorithm)
Register adds an algorithm to the registry. If the algorithm has KeyType "EC", it is also indexed by its Name in CurveAlgorithms.
func (*AlgorithmRegistry) XMLDSIGAlgorithm ¶
func (r *AlgorithmRegistry) XMLDSIGAlgorithm(pub crypto.PublicKey) (string, error)
XMLDSIGAlgorithm returns the XML-DSIG algorithm URI for the given public key.
type CertificateParser ¶
type CertificateParser func(der []byte) (*x509.Certificate, error)
CertificateParser tries to parse a DER-encoded certificate that the standard library rejected. Return the certificate on success, or ErrNotHandled if the parser does not recognize this certificate type.
type Extensions ¶
type Extensions struct {
Parsers []CertificateParser
Verifiers []SignatureVerifier
Algorithms *AlgorithmRegistry
KeyParsers []PrivateKeyParser
}
Extensions holds registered crypto extensions. Pass an instance through your application's configuration; use New to create one with defaults.
func New ¶
func New() *Extensions
New returns an Extensions with an empty AlgorithmRegistry initialized.
func (*Extensions) CheckSignature ¶
func (ext *Extensions) CheckSignature(cert *x509.Certificate, algo x509.SignatureAlgorithm, signed, signature []byte) error
CheckSignature tries the standard cert.CheckSignature first, then each registered SignatureVerifier. Returns nil on the first successful verification.
func (*Extensions) CheckSignatureXMLDSIG ¶ added in v0.3.0
func (ext *Extensions) CheckSignatureXMLDSIG(cert *x509.Certificate, xmldsigURI string, signed, signature []byte) error
CheckSignatureXMLDSIG verifies a signature using an XML-DSIG algorithm URI (e.g. "http://www.w3.org/2001/04/xmldsig-more#ecdsa-sha256"). It resolves the URI via the AlgorithmRegistry, tries the standard x509.Certificate.CheckSignature if possible, and falls back to registered SignatureVerifiers. This enables verification of non-standard algorithms (e.g. brainpool) that have registered XML-DSIG URIs.
func (*Extensions) ParseCertificate ¶
func (ext *Extensions) ParseCertificate(der []byte) (*x509.Certificate, error)
ParseCertificate tries Go's x509.ParseCertificate first, then each registered CertificateParser in order. Returns the first successful result. If stdlib parses the certificate but cannot extract the public key (PublicKey is nil), extension parsers are also tried.
func (*Extensions) ParseCertificatesPEM ¶
func (ext *Extensions) ParseCertificatesPEM(pemData []byte) ([]*x509.Certificate, error)
ParseCertificatesPEM parses all certificates from PEM-encoded data, using ext.ParseCertificate for each block so that extended algorithms (brainpool, PQ, etc.) are supported. Non-CERTIFICATE blocks are skipped.
func (*Extensions) ParsePrivateKey ¶
func (ext *Extensions) ParsePrivateKey(der []byte) (crypto.PrivateKey, error)
ParsePrivateKey parses a DER-encoded private key, trying Go's standard parsers (PKCS#8, EC, PKCS#1) first, then registered KeyParsers.
func (*Extensions) ParsePrivateKeyPEM ¶
func (ext *Extensions) ParsePrivateKeyPEM(pemData []byte) (crypto.PrivateKey, error)
ParsePrivateKeyPEM parses a PEM-encoded private key. Supports RSA PRIVATE KEY, EC PRIVATE KEY, and PRIVATE KEY block types, plus registered extension parsers.
type PrivateKeyParser ¶
type PrivateKeyParser func(der []byte) (crypto.PrivateKey, error)
PrivateKeyParser tries to parse a DER-encoded private key that the standard library cannot handle. Return the key on success, or ErrNotHandled if the parser does not recognize this key type.
type SignatureVerifier ¶
type SignatureVerifier func(cert *x509.Certificate, algo x509.SignatureAlgorithm, signed, signature []byte) error
SignatureVerifier verifies a signature on signed data using a certificate whose key type the standard library cannot handle. Return nil on success, ErrNotHandled if not applicable, or an error describing the failure.
func BERTolerantECDSAVerifier ¶ added in v0.4.0
func BERTolerantECDSAVerifier() SignatureVerifier
BERTolerantECDSAVerifier returns a SignatureVerifier that handles ECDSA signatures with BER encoding. It normalizes the signature to DER before verification. This is useful as a fallback when the standard x509 CheckSignature fails due to BER-encoded signatures.
Usage:
ext := cryptoutil.New() ext.Verifiers = append(ext.Verifiers, cryptoutil.BERTolerantECDSAVerifier())