crypto: allow to select the hashing algorithm for sign/verify
This commit is contained in:
@@ -3,6 +3,7 @@ package ed25519
|
||||
import (
|
||||
"testing"
|
||||
|
||||
"github.com/INFURA/go-did/crypto"
|
||||
"github.com/INFURA/go-did/crypto/_testsuite"
|
||||
)
|
||||
|
||||
@@ -17,6 +18,8 @@ var harness = testsuite.TestHarness[PublicKey, PrivateKey]{
|
||||
PrivateKeyFromPKCS8DER: PrivateKeyFromPKCS8DER,
|
||||
PrivateKeyFromPKCS8PEM: PrivateKeyFromPKCS8PEM,
|
||||
MultibaseCode: MultibaseCode,
|
||||
DefaultHash: crypto.SHA512,
|
||||
OtherHashes: nil,
|
||||
PublicKeyBytesSize: PublicKeyBytesSize,
|
||||
PrivateKeyBytesSize: PrivateKeyBytesSize,
|
||||
SignatureBytesSize: SignatureBytesSize,
|
||||
|
||||
@@ -68,13 +68,21 @@ func (p PrivateKey) Public() crypto.PublicKey {
|
||||
return PublicKey{k: p.k.Public().(ed25519.PublicKey)}
|
||||
}
|
||||
|
||||
func (p PrivateKey) SignToBytes(message []byte) ([]byte, error) {
|
||||
func (p PrivateKey) SignToBytes(message []byte, opts ...crypto.SigningOption) ([]byte, error) {
|
||||
params := crypto.CollectSigningOptions(opts)
|
||||
if params.Hash != crypto.Hash(0) && params.Hash != crypto.SHA512 {
|
||||
return nil, fmt.Errorf("ed25519 does not support custom hash functions")
|
||||
}
|
||||
return ed25519.Sign(p.k, message), nil
|
||||
}
|
||||
|
||||
// SignToASN1 creates a signature with ASN.1 encoding.
|
||||
// This ASN.1 encoding uses a BIT STRING, which would be correct for an X.509 certificate.
|
||||
func (p PrivateKey) SignToASN1(message []byte) ([]byte, error) {
|
||||
func (p PrivateKey) SignToASN1(message []byte, opts ...crypto.SigningOption) ([]byte, error) {
|
||||
params := crypto.CollectSigningOptions(opts)
|
||||
if params.Hash != crypto.Hash(0) && params.Hash != crypto.SHA512 {
|
||||
return nil, fmt.Errorf("ed25519 does not support custom hash functions")
|
||||
}
|
||||
sig := ed25519.Sign(p.k, message)
|
||||
var b cryptobyte.Builder
|
||||
b.AddASN1BitString(sig)
|
||||
|
||||
@@ -98,13 +98,23 @@ func (p PublicKey) Equal(other crypto.PublicKey) bool {
|
||||
return false
|
||||
}
|
||||
|
||||
func (p PublicKey) VerifyBytes(message, signature []byte) bool {
|
||||
func (p PublicKey) VerifyBytes(message, signature []byte, opts ...crypto.SigningOption) bool {
|
||||
params := crypto.CollectSigningOptions(opts)
|
||||
if params.Hash != crypto.Hash(0) && params.Hash != crypto.SHA512 {
|
||||
// ed25519 does not support custom hash functions
|
||||
return false
|
||||
}
|
||||
return ed25519.Verify(p.k, message, signature)
|
||||
}
|
||||
|
||||
// VerifyASN1 verifies a signature with ASN.1 encoding.
|
||||
// This ASN.1 encoding uses a BIT STRING, which would be correct for an X.509 certificate.
|
||||
func (p PublicKey) VerifyASN1(message, signature []byte) bool {
|
||||
func (p PublicKey) VerifyASN1(message, signature []byte, opts ...crypto.SigningOption) bool {
|
||||
params := crypto.CollectSigningOptions(opts)
|
||||
if params.Hash != crypto.Hash(0) && params.Hash != crypto.SHA512 {
|
||||
// ed25519 does not support custom hash functions
|
||||
return false
|
||||
}
|
||||
var s cryptobyte.String = signature
|
||||
var bitString asn1.BitString
|
||||
|
||||
|
||||
102
crypto/hash.go
Normal file
102
crypto/hash.go
Normal file
@@ -0,0 +1,102 @@
|
||||
package crypto
|
||||
|
||||
import (
|
||||
stdcrypto "crypto"
|
||||
"hash"
|
||||
"strconv"
|
||||
|
||||
"golang.org/x/crypto/sha3"
|
||||
)
|
||||
|
||||
// As the standard crypto library prohibits from registering additional hash algorithm (like keccak),
|
||||
// below is essentially an extension of that mechanism to allow it.
|
||||
|
||||
func init() {
|
||||
RegisterHash(KECCAK_256, sha3.NewLegacyKeccak256)
|
||||
RegisterHash(KECCAK_512, sha3.NewLegacyKeccak512)
|
||||
}
|
||||
|
||||
type Hash uint
|
||||
|
||||
// HashFunc simply returns the value of h so that [Hash] implements [SignerOpts].
|
||||
func (h Hash) HashFunc() Hash {
|
||||
return h
|
||||
}
|
||||
|
||||
func (h Hash) String() string {
|
||||
if h < maxStdHash {
|
||||
return stdcrypto.Hash(h).String()
|
||||
}
|
||||
|
||||
// Extensions
|
||||
switch h {
|
||||
case KECCAK_256:
|
||||
return "Keccak-256"
|
||||
case KECCAK_512:
|
||||
return "Keccak-512"
|
||||
|
||||
default:
|
||||
return "unknown hash value " + strconv.Itoa(int(h))
|
||||
}
|
||||
}
|
||||
|
||||
const (
|
||||
// From "crypto"
|
||||
MD4 Hash = 1 + iota // import golang.org/x/crypto/md4
|
||||
MD5 // import crypto/md5
|
||||
SHA1 // import crypto/sha1
|
||||
SHA224 // import crypto/sha256
|
||||
SHA256 // import crypto/sha256
|
||||
SHA384 // import crypto/sha512
|
||||
SHA512 // import crypto/sha512
|
||||
MD5SHA1 // no implementation; MD5+SHA1 used for TLS RSA
|
||||
RIPEMD160 // import golang.org/x/crypto/ripemd160
|
||||
SHA3_224 // import golang.org/x/crypto/sha3
|
||||
SHA3_256 // import golang.org/x/crypto/sha3
|
||||
SHA3_384 // import golang.org/x/crypto/sha3
|
||||
SHA3_512 // import golang.org/x/crypto/sha3
|
||||
SHA512_224 // import crypto/sha512
|
||||
SHA512_256 // import crypto/sha512
|
||||
BLAKE2s_256 // import golang.org/x/crypto/blake2s
|
||||
BLAKE2b_256 // import golang.org/x/crypto/blake2b
|
||||
BLAKE2b_384 // import golang.org/x/crypto/blake2b
|
||||
BLAKE2b_512 // import golang.org/x/crypto/blake2b
|
||||
|
||||
maxStdHash
|
||||
|
||||
// Extensions
|
||||
KECCAK_256
|
||||
KECCAK_512
|
||||
|
||||
maxHash
|
||||
)
|
||||
|
||||
var hashes = make([]func() hash.Hash, maxHash-maxStdHash-1)
|
||||
|
||||
// New returns a new hash.Hash calculating the given hash function. New panics
|
||||
// if the hash function is not linked into the binary.
|
||||
func (h Hash) New() hash.Hash {
|
||||
if h > 0 && h < maxStdHash {
|
||||
return stdcrypto.Hash(h).New()
|
||||
}
|
||||
if h > maxStdHash && h < maxHash {
|
||||
f := hashes[h-maxStdHash-1]
|
||||
if f != nil {
|
||||
return f()
|
||||
}
|
||||
}
|
||||
panic("crypto: requested hash function #" + strconv.Itoa(int(h)) + " is unavailable")
|
||||
}
|
||||
|
||||
// RegisterHash registers a function that returns a new instance of the given
|
||||
// hash function. This is intended to be called from the init function in
|
||||
// packages that implement hash functions.
|
||||
func RegisterHash(h Hash, f func() hash.Hash) {
|
||||
if h >= maxHash {
|
||||
panic("crypto: RegisterHash of unknown hash function")
|
||||
}
|
||||
if h <= maxStdHash {
|
||||
panic("crypto: RegisterHash of standard hash function")
|
||||
}
|
||||
hashes[h-maxStdHash-1] = f
|
||||
}
|
||||
@@ -32,10 +32,10 @@ type PublicKeySigning interface {
|
||||
// VerifyBytes checks a signature in the "raw bytes" format.
|
||||
// This format can make some assumptions and may not be what you expect.
|
||||
// Ideally, this format is defined by the same specification as the underlying crypto scheme.
|
||||
VerifyBytes(message, signature []byte) bool
|
||||
VerifyBytes(message, signature []byte, opts ...SigningOption) bool
|
||||
|
||||
// VerifyASN1 checks a signature in the ASN.1 format.
|
||||
VerifyASN1(message, signature []byte) bool
|
||||
VerifyASN1(message, signature []byte, opts ...SigningOption) bool
|
||||
}
|
||||
|
||||
// Private Key
|
||||
@@ -69,10 +69,10 @@ type PrivateKeySigning interface {
|
||||
// SignToBytes creates a signature in the "raw bytes" format.
|
||||
// This format can make some assumptions and may not be what you expect.
|
||||
// Ideally, this format is defined by the same specification as the underlying crypto scheme.
|
||||
SignToBytes(message []byte) ([]byte, error)
|
||||
SignToBytes(message []byte, opts ...SigningOption) ([]byte, error)
|
||||
|
||||
// SignToASN1 creates a signature in the ASN.1 format.
|
||||
SignToASN1(message []byte) ([]byte, error)
|
||||
SignToASN1(message []byte, opts ...SigningOption) ([]byte, error)
|
||||
}
|
||||
|
||||
type PrivateKeyKeyExchange interface {
|
||||
|
||||
29
crypto/options.go
Normal file
29
crypto/options.go
Normal file
@@ -0,0 +1,29 @@
|
||||
package crypto
|
||||
|
||||
type SigningOpts struct {
|
||||
Hash Hash
|
||||
}
|
||||
|
||||
func CollectSigningOptions(opts []SigningOption) SigningOpts {
|
||||
res := SigningOpts{}
|
||||
for _, opt := range opts {
|
||||
opt(&res)
|
||||
}
|
||||
return res
|
||||
}
|
||||
|
||||
func (opts SigningOpts) HashOrDefault(_default Hash) Hash {
|
||||
if opts.Hash == 0 {
|
||||
return _default
|
||||
}
|
||||
return opts.Hash
|
||||
}
|
||||
|
||||
type SigningOption func(opts *SigningOpts)
|
||||
|
||||
// WithSigningHash specify the hash algorithm to be used for signatures
|
||||
func WithSigningHash(hash Hash) SigningOption {
|
||||
return func(opts *SigningOpts) {
|
||||
opts.Hash = hash
|
||||
}
|
||||
}
|
||||
@@ -3,6 +3,7 @@ package p256
|
||||
import (
|
||||
"testing"
|
||||
|
||||
"github.com/INFURA/go-did/crypto"
|
||||
"github.com/INFURA/go-did/crypto/_testsuite"
|
||||
)
|
||||
|
||||
@@ -17,6 +18,8 @@ var harness = testsuite.TestHarness[*PublicKey, *PrivateKey]{
|
||||
PrivateKeyFromPKCS8DER: PrivateKeyFromPKCS8DER,
|
||||
PrivateKeyFromPKCS8PEM: PrivateKeyFromPKCS8PEM,
|
||||
MultibaseCode: MultibaseCode,
|
||||
DefaultHash: crypto.SHA256,
|
||||
OtherHashes: []crypto.Hash{crypto.SHA224, crypto.SHA384, crypto.SHA512},
|
||||
PublicKeyBytesSize: PublicKeyBytesSize,
|
||||
PrivateKeyBytesSize: PrivateKeyBytesSize,
|
||||
SignatureBytesSize: SignatureBytesSize,
|
||||
|
||||
@@ -4,7 +4,6 @@ import (
|
||||
"crypto/ecdsa"
|
||||
"crypto/elliptic"
|
||||
"crypto/rand"
|
||||
"crypto/sha256"
|
||||
"crypto/x509"
|
||||
"encoding/pem"
|
||||
"fmt"
|
||||
@@ -96,15 +95,13 @@ func (p *PrivateKey) ToPKCS8PEM() string {
|
||||
}))
|
||||
}
|
||||
|
||||
/*
|
||||
Note: signatures for the crypto.PrivateKeySigning interface assumes SHA256,
|
||||
which should be correct almost always. If there is a need to use a different
|
||||
hash function, we can add separate functions that have that flexibility.
|
||||
*/
|
||||
// The default signing hash is SHA-256.
|
||||
func (p *PrivateKey) SignToBytes(message []byte, opts ...crypto.SigningOption) ([]byte, error) {
|
||||
params := crypto.CollectSigningOptions(opts)
|
||||
|
||||
func (p *PrivateKey) SignToBytes(message []byte) ([]byte, error) {
|
||||
// Hash the message with SHA-256
|
||||
hash := sha256.Sum256(message)
|
||||
hasher := params.HashOrDefault(crypto.SHA256).New()
|
||||
hasher.Write(message)
|
||||
hash := hasher.Sum(nil)
|
||||
|
||||
r, s, err := ecdsa.Sign(rand.Reader, p.k, hash[:])
|
||||
if err != nil {
|
||||
@@ -118,9 +115,13 @@ func (p *PrivateKey) SignToBytes(message []byte) ([]byte, error) {
|
||||
return sig, nil
|
||||
}
|
||||
|
||||
func (p *PrivateKey) SignToASN1(message []byte) ([]byte, error) {
|
||||
// Hash the message with SHA-256
|
||||
hash := sha256.Sum256(message)
|
||||
// The default signing hash is SHA-256.
|
||||
func (p *PrivateKey) SignToASN1(message []byte, opts ...crypto.SigningOption) ([]byte, error) {
|
||||
params := crypto.CollectSigningOptions(opts)
|
||||
|
||||
hasher := params.HashOrDefault(crypto.SHA256).New()
|
||||
hasher.Write(message)
|
||||
hash := hasher.Sum(nil)
|
||||
|
||||
return ecdsa.SignASN1(rand.Reader, p.k, hash[:])
|
||||
}
|
||||
|
||||
@@ -3,7 +3,6 @@ package p256
|
||||
import (
|
||||
"crypto/ecdsa"
|
||||
"crypto/elliptic"
|
||||
"crypto/sha256"
|
||||
"crypto/x509"
|
||||
"encoding/pem"
|
||||
"fmt"
|
||||
@@ -124,13 +123,8 @@ func (p *PublicKey) ToX509PEM() string {
|
||||
}))
|
||||
}
|
||||
|
||||
/*
|
||||
Note: signatures for the crypto.PrivateKeySigning interface assumes SHA256,
|
||||
which should be correct almost always. If there is a need to use a different
|
||||
hash function, we can add separate functions that have that flexibility.
|
||||
*/
|
||||
|
||||
func (p *PublicKey) VerifyBytes(message, signature []byte) bool {
|
||||
// The default signing hash is SHA-256.
|
||||
func (p *PublicKey) VerifyBytes(message, signature []byte, opts ...crypto.SigningOption) bool {
|
||||
if len(signature) != SignatureBytesSize {
|
||||
return false
|
||||
}
|
||||
@@ -142,12 +136,16 @@ func (p *PublicKey) VerifyBytes(message, signature []byte) bool {
|
||||
return false
|
||||
}
|
||||
|
||||
return p.VerifyASN1(message, sigAsn1)
|
||||
return p.VerifyASN1(message, sigAsn1, opts...)
|
||||
}
|
||||
|
||||
func (p *PublicKey) VerifyASN1(message, signature []byte) bool {
|
||||
// Hash the message with SHA-256
|
||||
hash := sha256.Sum256(message)
|
||||
// The default signing hash is SHA-256.
|
||||
func (p *PublicKey) VerifyASN1(message, signature []byte, opts ...crypto.SigningOption) bool {
|
||||
params := crypto.CollectSigningOptions(opts)
|
||||
|
||||
hasher := params.HashOrDefault(crypto.SHA256).New()
|
||||
hasher.Write(message)
|
||||
hash := hasher.Sum(nil)
|
||||
|
||||
return ecdsa.VerifyASN1(p.k, hash[:], signature)
|
||||
}
|
||||
|
||||
@@ -3,6 +3,7 @@ package p384
|
||||
import (
|
||||
"testing"
|
||||
|
||||
"github.com/INFURA/go-did/crypto"
|
||||
"github.com/INFURA/go-did/crypto/_testsuite"
|
||||
)
|
||||
|
||||
@@ -17,6 +18,8 @@ var harness = testsuite.TestHarness[*PublicKey, *PrivateKey]{
|
||||
PrivateKeyFromPKCS8DER: PrivateKeyFromPKCS8DER,
|
||||
PrivateKeyFromPKCS8PEM: PrivateKeyFromPKCS8PEM,
|
||||
MultibaseCode: MultibaseCode,
|
||||
DefaultHash: crypto.SHA384,
|
||||
OtherHashes: []crypto.Hash{crypto.SHA256, crypto.SHA512},
|
||||
PublicKeyBytesSize: PublicKeyBytesSize,
|
||||
PrivateKeyBytesSize: PrivateKeyBytesSize,
|
||||
SignatureBytesSize: SignatureBytesSize,
|
||||
|
||||
@@ -4,7 +4,6 @@ import (
|
||||
"crypto/ecdsa"
|
||||
"crypto/elliptic"
|
||||
"crypto/rand"
|
||||
"crypto/sha512"
|
||||
"crypto/x509"
|
||||
"encoding/pem"
|
||||
"fmt"
|
||||
@@ -96,15 +95,13 @@ func (p *PrivateKey) ToPKCS8PEM() string {
|
||||
}))
|
||||
}
|
||||
|
||||
/*
|
||||
Note: signatures for the crypto.PrivateKeySigning interface assumes SHA384,
|
||||
which should be correct almost always. If there is a need to use a different
|
||||
hash function, we can add separate functions that have that flexibility.
|
||||
*/
|
||||
// The default signing hash is SHA-384.
|
||||
func (p *PrivateKey) SignToBytes(message []byte, opts ...crypto.SigningOption) ([]byte, error) {
|
||||
params := crypto.CollectSigningOptions(opts)
|
||||
|
||||
func (p *PrivateKey) SignToBytes(message []byte) ([]byte, error) {
|
||||
// Hash the message with SHA-384
|
||||
hash := sha512.Sum384(message)
|
||||
hasher := params.HashOrDefault(crypto.SHA384).New()
|
||||
hasher.Write(message)
|
||||
hash := hasher.Sum(nil)
|
||||
|
||||
r, s, err := ecdsa.Sign(rand.Reader, p.k, hash[:])
|
||||
if err != nil {
|
||||
@@ -118,9 +115,13 @@ func (p *PrivateKey) SignToBytes(message []byte) ([]byte, error) {
|
||||
return sig, nil
|
||||
}
|
||||
|
||||
func (p *PrivateKey) SignToASN1(message []byte) ([]byte, error) {
|
||||
// Hash the message with SHA-384
|
||||
hash := sha512.Sum384(message)
|
||||
// The default signing hash is SHA-384.
|
||||
func (p *PrivateKey) SignToASN1(message []byte, opts ...crypto.SigningOption) ([]byte, error) {
|
||||
params := crypto.CollectSigningOptions(opts)
|
||||
|
||||
hasher := params.HashOrDefault(crypto.SHA384).New()
|
||||
hasher.Write(message)
|
||||
hash := hasher.Sum(nil)
|
||||
|
||||
return ecdsa.SignASN1(rand.Reader, p.k, hash[:])
|
||||
}
|
||||
|
||||
@@ -3,7 +3,6 @@ package p384
|
||||
import (
|
||||
"crypto/ecdsa"
|
||||
"crypto/elliptic"
|
||||
"crypto/sha512"
|
||||
"crypto/x509"
|
||||
"encoding/pem"
|
||||
"fmt"
|
||||
@@ -124,13 +123,8 @@ func (p *PublicKey) ToX509PEM() string {
|
||||
}))
|
||||
}
|
||||
|
||||
/*
|
||||
Note: signatures for the crypto.PrivateKeySigning interface assumes SHA384,
|
||||
which should be correct almost always. If there is a need to use a different
|
||||
hash function, we can add separate functions that have that flexibility.
|
||||
*/
|
||||
|
||||
func (p *PublicKey) VerifyBytes(message, signature []byte) bool {
|
||||
// The default signing hash is SHA-384.
|
||||
func (p *PublicKey) VerifyBytes(message, signature []byte, opts ...crypto.SigningOption) bool {
|
||||
if len(signature) != SignatureBytesSize {
|
||||
return false
|
||||
}
|
||||
@@ -142,12 +136,16 @@ func (p *PublicKey) VerifyBytes(message, signature []byte) bool {
|
||||
return false
|
||||
}
|
||||
|
||||
return p.VerifyASN1(message, sigAsn1)
|
||||
return p.VerifyASN1(message, sigAsn1, opts...)
|
||||
}
|
||||
|
||||
func (p *PublicKey) VerifyASN1(message, signature []byte) bool {
|
||||
// Hash the message with SHA-384
|
||||
hash := sha512.Sum384(message)
|
||||
// The default signing hash is SHA-384.
|
||||
func (p *PublicKey) VerifyASN1(message, signature []byte, opts ...crypto.SigningOption) bool {
|
||||
params := crypto.CollectSigningOptions(opts)
|
||||
|
||||
hasher := params.HashOrDefault(crypto.SHA384).New()
|
||||
hasher.Write(message)
|
||||
hash := hasher.Sum(nil)
|
||||
|
||||
return ecdsa.VerifyASN1(p.k, hash[:], signature)
|
||||
}
|
||||
|
||||
@@ -3,6 +3,7 @@ package p521
|
||||
import (
|
||||
"testing"
|
||||
|
||||
"github.com/INFURA/go-did/crypto"
|
||||
"github.com/INFURA/go-did/crypto/_testsuite"
|
||||
)
|
||||
|
||||
@@ -17,6 +18,8 @@ var harness = testsuite.TestHarness[*PublicKey, *PrivateKey]{
|
||||
PrivateKeyFromPKCS8DER: PrivateKeyFromPKCS8DER,
|
||||
PrivateKeyFromPKCS8PEM: PrivateKeyFromPKCS8PEM,
|
||||
MultibaseCode: MultibaseCode,
|
||||
DefaultHash: crypto.SHA512,
|
||||
OtherHashes: []crypto.Hash{crypto.SHA384},
|
||||
PublicKeyBytesSize: PublicKeyBytesSize,
|
||||
PrivateKeyBytesSize: PrivateKeyBytesSize,
|
||||
SignatureBytesSize: SignatureBytesSize,
|
||||
|
||||
@@ -4,7 +4,6 @@ import (
|
||||
"crypto/ecdsa"
|
||||
"crypto/elliptic"
|
||||
"crypto/rand"
|
||||
"crypto/sha512"
|
||||
"crypto/x509"
|
||||
"encoding/pem"
|
||||
"fmt"
|
||||
@@ -96,15 +95,13 @@ func (p *PrivateKey) ToPKCS8PEM() string {
|
||||
}))
|
||||
}
|
||||
|
||||
/*
|
||||
Note: signatures for the crypto.PrivateKeySigning interface assumes SHA512,
|
||||
which should be correct almost always. If there is a need to use a different
|
||||
hash function, we can add separate functions that have that flexibility.
|
||||
*/
|
||||
// The default signing hash is SHA-512.
|
||||
func (p *PrivateKey) SignToBytes(message []byte, opts ...crypto.SigningOption) ([]byte, error) {
|
||||
params := crypto.CollectSigningOptions(opts)
|
||||
|
||||
func (p *PrivateKey) SignToBytes(message []byte) ([]byte, error) {
|
||||
// Hash the message with SHA-512
|
||||
hash := sha512.Sum512(message)
|
||||
hasher := params.HashOrDefault(crypto.SHA512).New()
|
||||
hasher.Write(message)
|
||||
hash := hasher.Sum(nil)
|
||||
|
||||
r, s, err := ecdsa.Sign(rand.Reader, p.k, hash[:])
|
||||
if err != nil {
|
||||
@@ -118,9 +115,13 @@ func (p *PrivateKey) SignToBytes(message []byte) ([]byte, error) {
|
||||
return sig, nil
|
||||
}
|
||||
|
||||
func (p *PrivateKey) SignToASN1(message []byte) ([]byte, error) {
|
||||
// Hash the message with SHA-512
|
||||
hash := sha512.Sum512(message)
|
||||
// The default signing hash is SHA-512.
|
||||
func (p *PrivateKey) SignToASN1(message []byte, opts ...crypto.SigningOption) ([]byte, error) {
|
||||
params := crypto.CollectSigningOptions(opts)
|
||||
|
||||
hasher := params.HashOrDefault(crypto.SHA512).New()
|
||||
hasher.Write(message)
|
||||
hash := hasher.Sum(nil)
|
||||
|
||||
return ecdsa.SignASN1(rand.Reader, p.k, hash[:])
|
||||
}
|
||||
|
||||
@@ -3,7 +3,6 @@ package p521
|
||||
import (
|
||||
"crypto/ecdsa"
|
||||
"crypto/elliptic"
|
||||
"crypto/sha512"
|
||||
"crypto/x509"
|
||||
"encoding/pem"
|
||||
"fmt"
|
||||
@@ -124,13 +123,8 @@ func (p *PublicKey) ToX509PEM() string {
|
||||
}))
|
||||
}
|
||||
|
||||
/*
|
||||
Note: signatures for the crypto.PrivateKeySigning interface assumes SHA512,
|
||||
which should be correct almost always. If there is a need to use a different
|
||||
hash function, we can add separate functions that have that flexibility.
|
||||
*/
|
||||
|
||||
func (p *PublicKey) VerifyBytes(message, signature []byte) bool {
|
||||
// The default signing hash is SHA-512.
|
||||
func (p *PublicKey) VerifyBytes(message, signature []byte, opts ...crypto.SigningOption) bool {
|
||||
if len(signature) != SignatureBytesSize {
|
||||
return false
|
||||
}
|
||||
@@ -142,12 +136,16 @@ func (p *PublicKey) VerifyBytes(message, signature []byte) bool {
|
||||
return false
|
||||
}
|
||||
|
||||
return p.VerifyASN1(message, sigAsn1)
|
||||
return p.VerifyASN1(message, sigAsn1, opts...)
|
||||
}
|
||||
|
||||
func (p *PublicKey) VerifyASN1(message, signature []byte) bool {
|
||||
// Hash the message with SHA-512
|
||||
hash := sha512.Sum512(message)
|
||||
// The default signing hash is SHA-512.
|
||||
func (p *PublicKey) VerifyASN1(message, signature []byte, opts ...crypto.SigningOption) bool {
|
||||
params := crypto.CollectSigningOptions(opts)
|
||||
|
||||
hasher := params.HashOrDefault(crypto.SHA512).New()
|
||||
hasher.Write(message)
|
||||
hash := hasher.Sum(nil)
|
||||
|
||||
return ecdsa.VerifyASN1(p.k, hash[:], signature)
|
||||
}
|
||||
|
||||
4
go.mod
4
go.mod
@@ -5,6 +5,8 @@ go 1.23.0
|
||||
toolchain go1.23.1
|
||||
|
||||
require (
|
||||
github.com/decred/dcrd/dcrec/secp256k1/v4 v4.4.0
|
||||
github.com/mr-tron/base58 v1.1.0
|
||||
github.com/multiformats/go-multibase v0.2.0
|
||||
github.com/multiformats/go-varint v0.0.7
|
||||
github.com/stretchr/testify v1.10.0
|
||||
@@ -13,9 +15,9 @@ require (
|
||||
|
||||
require (
|
||||
github.com/davecgh/go-spew v1.1.1 // indirect
|
||||
github.com/mr-tron/base58 v1.1.0 // indirect
|
||||
github.com/multiformats/go-base32 v0.0.3 // indirect
|
||||
github.com/multiformats/go-base36 v0.1.0 // indirect
|
||||
github.com/pmezard/go-difflib v1.0.0 // indirect
|
||||
golang.org/x/sys v0.33.0 // indirect
|
||||
gopkg.in/yaml.v3 v3.0.1 // indirect
|
||||
)
|
||||
|
||||
6
go.sum
6
go.sum
@@ -1,5 +1,9 @@
|
||||
github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c=
|
||||
github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
|
||||
github.com/decred/dcrd/crypto/blake256 v1.1.0 h1:zPMNGQCm0g4QTY27fOCorQW7EryeQ/U0x++OzVrdms8=
|
||||
github.com/decred/dcrd/crypto/blake256 v1.1.0/go.mod h1:2OfgNZ5wDpcsFmHmCK5gZTPcCXqlm2ArzUIkw9czNJo=
|
||||
github.com/decred/dcrd/dcrec/secp256k1/v4 v4.4.0 h1:NMZiJj8QnKe1LgsbDayM4UoHwbvwDRwnI3hwNaAHRnc=
|
||||
github.com/decred/dcrd/dcrec/secp256k1/v4 v4.4.0/go.mod h1:ZXNYxsqcloTdSy/rNShjYzMhyjf0LaoftYK0p+A3h40=
|
||||
github.com/mr-tron/base58 v1.1.0 h1:Y51FGVJ91WBqCEabAi5OPUz38eAx8DakuAm5svLcsfQ=
|
||||
github.com/mr-tron/base58 v1.1.0/go.mod h1:xcD2VGqlgYjBdcBLw+TuYLr8afG+Hj8g2eTVqeSzSU8=
|
||||
github.com/multiformats/go-base32 v0.0.3 h1:tw5+NhuwaOjJCC5Pp82QuXbrmLzWg7uxlMFp8Nq/kkI=
|
||||
@@ -16,6 +20,8 @@ github.com/stretchr/testify v1.10.0 h1:Xv5erBjTwe/5IxqUQTdXv5kgmIvbHo3QQyRwhJsOf
|
||||
github.com/stretchr/testify v1.10.0/go.mod h1:r2ic/lqez/lEtzL7wO/rwa5dbSLXVDPFyf8C91i36aY=
|
||||
golang.org/x/crypto v0.39.0 h1:SHs+kF4LP+f+p14esP5jAoDpHU8Gu/v9lFRK6IT5imM=
|
||||
golang.org/x/crypto v0.39.0/go.mod h1:L+Xg3Wf6HoL4Bn4238Z6ft6KfEpN0tJGo53AAPC632U=
|
||||
golang.org/x/sys v0.33.0 h1:q3i8TbbEz+JRD9ywIRlyRAQbM0qF7hu24q3teo2hbuw=
|
||||
golang.org/x/sys v0.33.0/go.mod h1:BJP2sWEmIv4KK5OTEluFJCKSidICx8ciO85XgH3Ak8k=
|
||||
gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405 h1:yhCVgyC4o1eVCa2tZl7eS0r+SDo693bJlVdllGtEeKM=
|
||||
gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
|
||||
gopkg.in/yaml.v3 v3.0.1 h1:fxVm/GzAzEWqLHuvctI91KS9hhNmmWOoWu0XTYJS7CA=
|
||||
|
||||
Reference in New Issue
Block a user