2025-07-08 12:57:06 +02:00
|
|
|
package crypto
|
|
|
|
|
|
2025-07-30 18:32:14 +02:00
|
|
|
import (
|
|
|
|
|
"github.com/ucan-wg/go-varsig"
|
|
|
|
|
)
|
|
|
|
|
|
2026-01-05 16:33:21 +01:00
|
|
|
// SigningOpts contains the resulting signature configuration.
|
2025-07-08 12:57:06 +02:00
|
|
|
type SigningOpts struct {
|
2025-07-30 18:32:14 +02:00
|
|
|
hash Hash
|
|
|
|
|
payloadEncoding varsig.PayloadEncoding
|
|
|
|
|
|
|
|
|
|
// if WithVarsig is used
|
|
|
|
|
algo varsig.Algorithm
|
|
|
|
|
curve uint64
|
|
|
|
|
keyLen uint64
|
2025-07-08 12:57:06 +02:00
|
|
|
}
|
|
|
|
|
|
2026-01-05 16:33:21 +01:00
|
|
|
// CollectSigningOptions collects the signing options into a SigningOpts.
|
2025-07-08 12:57:06 +02:00
|
|
|
func CollectSigningOptions(opts []SigningOption) SigningOpts {
|
|
|
|
|
res := SigningOpts{}
|
|
|
|
|
for _, opt := range opts {
|
|
|
|
|
opt(&res)
|
|
|
|
|
}
|
|
|
|
|
return res
|
|
|
|
|
}
|
|
|
|
|
|
2026-01-05 16:33:21 +01:00
|
|
|
// HashOrDefault returns the hash algorithm to be used for signatures, or the default if not specified.
|
2025-07-08 12:57:06 +02:00
|
|
|
func (opts SigningOpts) HashOrDefault(_default Hash) Hash {
|
2025-07-30 18:32:14 +02:00
|
|
|
if opts.hash == 0 {
|
2025-07-08 12:57:06 +02:00
|
|
|
return _default
|
|
|
|
|
}
|
2025-07-30 18:32:14 +02:00
|
|
|
return opts.hash
|
|
|
|
|
}
|
|
|
|
|
|
2026-01-05 16:33:21 +01:00
|
|
|
// PayloadEncoding returns the encoding used on the message before signing it.
|
2025-07-30 18:32:14 +02:00
|
|
|
func (opts SigningOpts) PayloadEncoding() varsig.PayloadEncoding {
|
|
|
|
|
if opts.payloadEncoding == 0 {
|
|
|
|
|
return varsig.PayloadEncodingVerbatim
|
|
|
|
|
}
|
|
|
|
|
return opts.payloadEncoding
|
|
|
|
|
}
|
|
|
|
|
|
2026-01-05 16:33:21 +01:00
|
|
|
// VarsigMatch returns true if the given varsig parameters match the signing options.
|
2025-07-30 18:32:14 +02:00
|
|
|
func (opts SigningOpts) VarsigMatch(algo varsig.Algorithm, curve uint64, keyLength uint64) bool {
|
|
|
|
|
// This is relatively ugly, but we get cyclic import otherwise
|
|
|
|
|
switch opts.algo {
|
|
|
|
|
case 0:
|
|
|
|
|
// not varsig to compare
|
|
|
|
|
return true
|
|
|
|
|
case varsig.AlgorithmECDSA:
|
|
|
|
|
return algo == varsig.AlgorithmECDSA && opts.curve == curve
|
|
|
|
|
case varsig.AlgorithmEdDSA:
|
|
|
|
|
return algo == varsig.AlgorithmEdDSA && opts.curve == curve
|
|
|
|
|
case varsig.AlgorithmRSA:
|
|
|
|
|
return algo == varsig.AlgorithmRSA && opts.keyLen == keyLength
|
|
|
|
|
default:
|
|
|
|
|
panic("unreachable")
|
|
|
|
|
}
|
2025-07-08 12:57:06 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
type SigningOption func(opts *SigningOpts)
|
|
|
|
|
|
|
|
|
|
// WithSigningHash specify the hash algorithm to be used for signatures
|
|
|
|
|
func WithSigningHash(hash Hash) SigningOption {
|
|
|
|
|
return func(opts *SigningOpts) {
|
2025-07-30 18:32:14 +02:00
|
|
|
opts.hash = hash
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// WithPayloadEncoding specify the encoding that was used on the message before signing it.
|
|
|
|
|
// This will be included in the resulting varsig.
|
|
|
|
|
func WithPayloadEncoding(encoding varsig.PayloadEncoding) SigningOption {
|
|
|
|
|
return func(opts *SigningOpts) {
|
|
|
|
|
opts.payloadEncoding = encoding
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// WithVarsig configure the signing or verification parameters from a varsig.
|
|
|
|
|
// If you use WithVarsig, you should NOT use other options.
|
|
|
|
|
func WithVarsig(vsig varsig.Varsig) SigningOption {
|
|
|
|
|
return func(opts *SigningOpts) {
|
|
|
|
|
opts.payloadEncoding = vsig.PayloadEncoding()
|
|
|
|
|
opts.hash = FromVarsigHash(vsig.Hash())
|
|
|
|
|
opts.algo = vsig.Algorithm()
|
|
|
|
|
switch vsig := vsig.(type) {
|
|
|
|
|
case varsig.EdDSAVarsig:
|
|
|
|
|
opts.curve = uint64(vsig.Curve())
|
|
|
|
|
case varsig.ECDSAVarsig:
|
|
|
|
|
opts.curve = uint64(vsig.Curve())
|
|
|
|
|
case varsig.RSAVarsig:
|
|
|
|
|
opts.keyLen = vsig.KeyLength()
|
|
|
|
|
default:
|
|
|
|
|
panic("unreachable")
|
|
|
|
|
}
|
2025-07-08 12:57:06 +02:00
|
|
|
}
|
|
|
|
|
}
|