Initial QSfera import
This commit is contained in:
+100
@@ -0,0 +1,100 @@
|
||||
package dsig
|
||||
|
||||
import (
|
||||
"crypto"
|
||||
"crypto/rsa"
|
||||
"fmt"
|
||||
"io"
|
||||
)
|
||||
|
||||
// Sign generates a digital signature using the specified key and algorithm.
|
||||
//
|
||||
// This function loads the signer registered in the dsig package _ONLY_.
|
||||
// It does not support custom signers that the user might have registered.
|
||||
//
|
||||
// rr is an io.Reader that provides randomness for signing. If rr is nil, it defaults to rand.Reader.
|
||||
// Not all algorithms require this parameter, but it is included for consistency.
|
||||
// 99% of the time, you can pass nil for rr, and it will work fine.
|
||||
func Sign(key any, alg string, payload []byte, rr io.Reader) ([]byte, error) {
|
||||
info, ok := GetAlgorithmInfo(alg)
|
||||
if !ok {
|
||||
return nil, fmt.Errorf(`dsig.Sign: unsupported signature algorithm %q`, alg)
|
||||
}
|
||||
|
||||
switch info.Family {
|
||||
case HMAC:
|
||||
return dispatchHMACSign(key, info, payload)
|
||||
case RSA:
|
||||
return dispatchRSASign(key, info, payload, rr)
|
||||
case ECDSA:
|
||||
return dispatchECDSASign(key, info, payload, rr)
|
||||
case EdDSAFamily:
|
||||
return dispatchEdDSASign(key, info, payload, rr)
|
||||
default:
|
||||
return nil, fmt.Errorf(`dsig.Sign: unsupported signature family %q`, info.Family)
|
||||
}
|
||||
}
|
||||
|
||||
func dispatchHMACSign(key any, info AlgorithmInfo, payload []byte) ([]byte, error) {
|
||||
meta, ok := info.Meta.(HMACFamilyMeta)
|
||||
if !ok {
|
||||
return nil, fmt.Errorf(`dsig.Sign: invalid HMAC metadata`)
|
||||
}
|
||||
|
||||
var hmackey []byte
|
||||
if err := toHMACKey(&hmackey, key); err != nil {
|
||||
return nil, fmt.Errorf(`dsig.Sign: %w`, err)
|
||||
}
|
||||
return SignHMAC(hmackey, payload, meta.HashFunc)
|
||||
}
|
||||
|
||||
func dispatchRSASign(key any, info AlgorithmInfo, payload []byte, rr io.Reader) ([]byte, error) {
|
||||
meta, ok := info.Meta.(RSAFamilyMeta)
|
||||
if !ok {
|
||||
return nil, fmt.Errorf(`dsig.Sign: invalid RSA metadata`)
|
||||
}
|
||||
|
||||
cs, isCryptoSigner, err := rsaGetSignerCryptoSignerKey(key)
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf(`dsig.Sign: %w`, err)
|
||||
}
|
||||
if isCryptoSigner {
|
||||
var options crypto.SignerOpts = meta.Hash
|
||||
if meta.PSS {
|
||||
rsaopts := rsaPSSOptions(meta.Hash)
|
||||
options = &rsaopts
|
||||
}
|
||||
return SignCryptoSigner(cs, payload, meta.Hash, options, rr)
|
||||
}
|
||||
|
||||
privkey, ok := key.(*rsa.PrivateKey)
|
||||
if !ok {
|
||||
return nil, fmt.Errorf(`dsig.Sign: invalid key type %T. *rsa.PrivateKey is required`, key)
|
||||
}
|
||||
return SignRSA(privkey, payload, meta.Hash, meta.PSS, rr)
|
||||
}
|
||||
|
||||
func dispatchEdDSASign(key any, _ AlgorithmInfo, payload []byte, rr io.Reader) ([]byte, error) {
|
||||
signer, err := eddsaGetSigner(key)
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf(`dsig.Sign: %w`, err)
|
||||
}
|
||||
|
||||
return SignCryptoSigner(signer, payload, crypto.Hash(0), crypto.Hash(0), rr)
|
||||
}
|
||||
|
||||
func dispatchECDSASign(key any, info AlgorithmInfo, payload []byte, rr io.Reader) ([]byte, error) {
|
||||
meta, ok := info.Meta.(ECDSAFamilyMeta)
|
||||
if !ok {
|
||||
return nil, fmt.Errorf(`dsig.Sign: invalid ECDSA metadata`)
|
||||
}
|
||||
|
||||
privkey, cs, isCryptoSigner, err := ecdsaGetSignerKey(key)
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf(`dsig.Sign: %w`, err)
|
||||
}
|
||||
if isCryptoSigner {
|
||||
return SignECDSACryptoSigner(cs, payload, meta.Hash, rr)
|
||||
}
|
||||
return SignECDSA(privkey, payload, meta.Hash, rr)
|
||||
}
|
||||
Reference in New Issue
Block a user