2
.github/workflows/gotest.yml
vendored
2
.github/workflows/gotest.yml
vendored
@@ -24,4 +24,4 @@ jobs:
|
||||
- name: Run tests
|
||||
run: go test -v ./...
|
||||
- name: Check formatted
|
||||
run: gofmt -l .
|
||||
run: gofmt -l .
|
||||
|
||||
@@ -9,6 +9,7 @@ import (
|
||||
mbase "github.com/multiformats/go-multibase"
|
||||
"github.com/multiformats/go-varint"
|
||||
"github.com/stretchr/testify/require"
|
||||
"github.com/ucan-wg/go-varsig"
|
||||
|
||||
"github.com/MetaMask/go-did-it/crypto"
|
||||
)
|
||||
@@ -194,6 +195,7 @@ func TestSuite[PubT crypto.PublicKey, PrivT crypto.PrivateKey](t *testing.T, har
|
||||
name string
|
||||
signer func(msg []byte, opts ...crypto.SigningOption) ([]byte, error)
|
||||
verifier func(msg []byte, sig []byte, opts ...crypto.SigningOption) bool
|
||||
varsig func(opts ...crypto.SigningOption) varsig.Varsig
|
||||
expectedSize int
|
||||
stats *int
|
||||
defaultHash crypto.Hash
|
||||
@@ -210,6 +212,7 @@ func TestSuite[PubT crypto.PublicKey, PrivT crypto.PrivateKey](t *testing.T, har
|
||||
name: "Bytes signature",
|
||||
signer: spriv.SignToBytes,
|
||||
verifier: spub.VerifyBytes,
|
||||
varsig: spriv.Varsig,
|
||||
expectedSize: harness.SignatureBytesSize,
|
||||
stats: &stats.sigRawSize,
|
||||
defaultHash: harness.DefaultHash,
|
||||
@@ -227,6 +230,7 @@ func TestSuite[PubT crypto.PublicKey, PrivT crypto.PrivateKey](t *testing.T, har
|
||||
name: "ASN.1 signature",
|
||||
signer: spriv.SignToASN1,
|
||||
verifier: spub.VerifyASN1,
|
||||
varsig: spriv.Varsig,
|
||||
stats: &stats.sigAsn1Size,
|
||||
defaultHash: harness.DefaultHash,
|
||||
otherHashes: harness.OtherHashes,
|
||||
@@ -245,6 +249,9 @@ func TestSuite[PubT crypto.PublicKey, PrivT crypto.PrivateKey](t *testing.T, har
|
||||
sigDefault, err := tc.signer(msg, crypto.WithSigningHash(tc.defaultHash))
|
||||
require.NoError(t, err)
|
||||
|
||||
vsig := tc.varsig()
|
||||
require.Equal(t, harness.DefaultHash.ToVarsigHash(), vsig.Hash())
|
||||
|
||||
if tc.expectedSize > 0 {
|
||||
require.Equal(t, tc.expectedSize, len(sigNoParams))
|
||||
}
|
||||
@@ -253,13 +260,21 @@ func TestSuite[PubT crypto.PublicKey, PrivT crypto.PrivateKey](t *testing.T, har
|
||||
// signatures might be different (i.e. non-deterministic), but they should verify the same way
|
||||
valid := tc.verifier(msg, sigNoParams)
|
||||
require.True(t, valid)
|
||||
valid = tc.verifier(msg, sigNoParams, crypto.WithVarsig(vsig))
|
||||
require.True(t, valid)
|
||||
valid = tc.verifier(msg, sigDefault)
|
||||
require.True(t, valid)
|
||||
valid = tc.verifier(msg, sigDefault, crypto.WithVarsig(vsig))
|
||||
require.True(t, valid)
|
||||
|
||||
valid = tc.verifier([]byte("wrong message"), sigNoParams)
|
||||
require.False(t, valid)
|
||||
valid = tc.verifier([]byte("wrong message"), sigNoParams, crypto.WithVarsig(vsig))
|
||||
require.False(t, valid)
|
||||
valid = tc.verifier([]byte("wrong message"), sigDefault)
|
||||
require.False(t, valid)
|
||||
valid = tc.verifier([]byte("wrong message"), sigDefault, crypto.WithVarsig(vsig))
|
||||
require.False(t, valid)
|
||||
})
|
||||
for _, hash := range tc.otherHashes {
|
||||
t.Run(fmt.Sprintf("%s-%s", tc.name, hash.String()), func(t *testing.T) {
|
||||
@@ -269,11 +284,18 @@ func TestSuite[PubT crypto.PublicKey, PrivT crypto.PrivateKey](t *testing.T, har
|
||||
require.NoError(t, err)
|
||||
require.NotEmpty(t, sig)
|
||||
|
||||
vsig := tc.varsig(crypto.WithSigningHash(hash))
|
||||
require.Equal(t, hash.ToVarsigHash(), vsig.Hash())
|
||||
|
||||
valid := tc.verifier(msg, sig, crypto.WithSigningHash(hash))
|
||||
require.True(t, valid)
|
||||
valid = tc.verifier(msg, sig, crypto.WithVarsig(vsig))
|
||||
require.True(t, valid)
|
||||
|
||||
valid = tc.verifier([]byte("wrong message"), sig)
|
||||
require.False(t, valid)
|
||||
valid = tc.verifier([]byte("wrong message"), sig, crypto.WithVarsig(vsig))
|
||||
require.False(t, valid)
|
||||
})
|
||||
}
|
||||
}
|
||||
@@ -503,6 +525,29 @@ func BenchSuite[PubT crypto.PublicKey, PrivT crypto.PrivateKey](b *testing.B, ha
|
||||
}
|
||||
})
|
||||
|
||||
b.Run("Verify from varsig signature", func(b *testing.B) {
|
||||
if !pubImplements[PubT, crypto.PublicKeySigningBytes]() {
|
||||
b.Skip("Signature to bytes is not implemented")
|
||||
}
|
||||
|
||||
pub, priv, err := harness.GenerateKeyPair()
|
||||
require.NoError(b, err)
|
||||
|
||||
spub := (crypto.PublicKey(pub)).(crypto.PublicKeySigningBytes)
|
||||
spriv := (crypto.PrivateKey(priv)).(crypto.PrivateKeySigningBytes)
|
||||
|
||||
sig, err := spriv.SignToBytes([]byte("message"))
|
||||
require.NoError(b, err)
|
||||
vsig := spriv.Varsig()
|
||||
|
||||
b.ResetTimer()
|
||||
b.ReportAllocs()
|
||||
|
||||
for i := 0; i < b.N; i++ {
|
||||
spub.VerifyBytes([]byte("message"), sig, crypto.WithVarsig(vsig))
|
||||
}
|
||||
})
|
||||
|
||||
b.Run("Sign to ASN.1 signature", func(b *testing.B) {
|
||||
if !pubImplements[PubT, crypto.PublicKeySigningASN1]() {
|
||||
b.Skip("Signature to ASN.1 is not implemented")
|
||||
|
||||
@@ -6,6 +6,7 @@ import (
|
||||
"encoding/pem"
|
||||
"fmt"
|
||||
|
||||
"github.com/ucan-wg/go-varsig"
|
||||
"golang.org/x/crypto/cryptobyte"
|
||||
|
||||
"github.com/MetaMask/go-did-it/crypto"
|
||||
@@ -21,7 +22,7 @@ type PrivateKey struct {
|
||||
|
||||
// PrivateKeyFromBytes converts a serialized private key to a PrivateKey.
|
||||
// This compact serialization format is the raw key material, without metadata or structure.
|
||||
// It errors if the slice is not the right size.
|
||||
// It returns an error if the slice is not the right size.
|
||||
func PrivateKeyFromBytes(b []byte) (PrivateKey, error) {
|
||||
if len(b) != PrivateKeyBytesSize {
|
||||
return PrivateKey{}, fmt.Errorf("invalid ed25519 private key size")
|
||||
@@ -73,11 +74,19 @@ func (p PrivateKey) Public() crypto.PublicKey {
|
||||
return PublicKey{k: p.k.Public().(ed25519.PublicKey)}
|
||||
}
|
||||
|
||||
func (p PrivateKey) Varsig(opts ...crypto.SigningOption) varsig.Varsig {
|
||||
params := crypto.CollectSigningOptions(opts)
|
||||
return varsig.NewEdDSAVarsig(varsig.CurveEd25519, params.HashOrDefault(crypto.SHA512).ToVarsigHash(), params.PayloadEncoding())
|
||||
}
|
||||
|
||||
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 {
|
||||
|
||||
hash := params.HashOrDefault(crypto.SHA512)
|
||||
if hash != crypto.SHA512 {
|
||||
return nil, fmt.Errorf("ed25519 does not support custom hash functions")
|
||||
}
|
||||
|
||||
return ed25519.Sign(p.k, message), nil
|
||||
}
|
||||
|
||||
@@ -85,9 +94,12 @@ func (p PrivateKey) SignToBytes(message []byte, opts ...crypto.SigningOption) ([
|
||||
// This ASN.1 encoding uses a BIT STRING, which would be correct for an X.509 certificate.
|
||||
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 {
|
||||
|
||||
hash := params.HashOrDefault(crypto.SHA512)
|
||||
if 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)
|
||||
|
||||
@@ -7,6 +7,7 @@ import (
|
||||
"encoding/pem"
|
||||
"fmt"
|
||||
|
||||
"github.com/ucan-wg/go-varsig"
|
||||
"golang.org/x/crypto/cryptobyte"
|
||||
|
||||
"github.com/MetaMask/go-did-it/crypto"
|
||||
@@ -101,10 +102,16 @@ func (p PublicKey) Equal(other crypto.PublicKey) 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 {
|
||||
|
||||
if !params.VarsigMatch(varsig.AlgorithmEdDSA, uint64(varsig.CurveEd25519), 0) {
|
||||
return false
|
||||
}
|
||||
|
||||
if params.HashOrDefault(crypto.SHA512) != crypto.SHA512 {
|
||||
// ed25519 does not support custom hash functions
|
||||
return false
|
||||
}
|
||||
|
||||
return ed25519.Verify(p.k, message, signature)
|
||||
}
|
||||
|
||||
@@ -112,10 +119,16 @@ func (p PublicKey) VerifyBytes(message, signature []byte, opts ...crypto.Signing
|
||||
// This ASN.1 encoding uses a BIT STRING, which would be correct for an X.509 certificate.
|
||||
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 {
|
||||
|
||||
if !params.VarsigMatch(varsig.AlgorithmEdDSA, uint64(varsig.CurveEd25519), 0) {
|
||||
return false
|
||||
}
|
||||
|
||||
if params.HashOrDefault(crypto.SHA512) != crypto.SHA512 {
|
||||
// ed25519 does not support custom hash functions
|
||||
return false
|
||||
}
|
||||
|
||||
var s cryptobyte.String = signature
|
||||
var bitString asn1.BitString
|
||||
|
||||
|
||||
143
crypto/hash.go
143
crypto/hash.go
@@ -5,41 +5,15 @@ import (
|
||||
"hash"
|
||||
"strconv"
|
||||
|
||||
"github.com/ucan-wg/go-varsig"
|
||||
"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
|
||||
@@ -71,7 +45,20 @@ const (
|
||||
maxHash
|
||||
)
|
||||
|
||||
var hashes = make([]func() hash.Hash, maxHash-maxStdHash-1)
|
||||
// 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()
|
||||
}
|
||||
if h > maxStdHash && h < maxHash {
|
||||
return hashNames[h-maxStdHash-1]
|
||||
}
|
||||
panic("requested hash #" + strconv.Itoa(int(h)) + " is unavailable")
|
||||
}
|
||||
|
||||
// New returns a new hash.Hash calculating the given hash function. New panics
|
||||
// if the hash function is not linked into the binary.
|
||||
@@ -80,23 +67,101 @@ func (h Hash) New() hash.Hash {
|
||||
return stdcrypto.Hash(h).New()
|
||||
}
|
||||
if h > maxStdHash && h < maxHash {
|
||||
f := hashes[h-maxStdHash-1]
|
||||
f := hashFns[h-maxStdHash-1]
|
||||
if f != nil {
|
||||
return f()
|
||||
}
|
||||
}
|
||||
panic("crypto: requested hash function #" + strconv.Itoa(int(h)) + " is unavailable")
|
||||
panic("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")
|
||||
func (h Hash) ToVarsigHash() varsig.Hash {
|
||||
if h == MD5SHA1 {
|
||||
panic("no multihash/multicodec value exists for MD5+SHA1")
|
||||
}
|
||||
if h <= maxStdHash {
|
||||
panic("crypto: RegisterHash of standard hash function")
|
||||
if h < maxHash {
|
||||
return hashVarsigs[h]
|
||||
}
|
||||
hashes[h-maxStdHash-1] = f
|
||||
panic("requested hash #" + strconv.Itoa(int(h)) + " is unavailable")
|
||||
}
|
||||
|
||||
func FromVarsigHash(h varsig.Hash) Hash {
|
||||
switch h {
|
||||
case varsig.HashMd4:
|
||||
return MD4
|
||||
case varsig.HashMd5:
|
||||
return MD5
|
||||
case varsig.HashSha1:
|
||||
return SHA1
|
||||
case varsig.HashSha2_224:
|
||||
return SHA224
|
||||
case varsig.HashSha2_256:
|
||||
return SHA256
|
||||
case varsig.HashSha2_384:
|
||||
return SHA384
|
||||
case varsig.HashSha2_512:
|
||||
return SHA512
|
||||
case varsig.HashRipemd_160:
|
||||
return RIPEMD160
|
||||
case varsig.HashSha3_224:
|
||||
return SHA3_224
|
||||
case varsig.HashSha3_256:
|
||||
return SHA3_256
|
||||
case varsig.HashSha3_384:
|
||||
return SHA3_384
|
||||
case varsig.HashSha3_512:
|
||||
return SHA3_512
|
||||
case varsig.HashSha512_224:
|
||||
return SHA512_224
|
||||
case varsig.HashSha512_256:
|
||||
return SHA512_256
|
||||
case varsig.HashBlake2s_256:
|
||||
return BLAKE2s_256
|
||||
case varsig.HashBlake2b_256:
|
||||
return BLAKE2b_256
|
||||
case varsig.HashBlake2b_384:
|
||||
return BLAKE2b_384
|
||||
case varsig.HashBlake2b_512:
|
||||
return BLAKE2b_512
|
||||
case varsig.HashKeccak_256:
|
||||
return KECCAK_256
|
||||
case varsig.HashKeccak_512:
|
||||
return KECCAK_512
|
||||
default:
|
||||
panic("varsig " + strconv.Itoa(int(h)) + " is not supported")
|
||||
}
|
||||
}
|
||||
|
||||
var hashNames = []string{
|
||||
"Keccak-256",
|
||||
"Keccak-512",
|
||||
}
|
||||
var hashFns = []func() hash.Hash{
|
||||
sha3.NewLegacyKeccak256,
|
||||
sha3.NewLegacyKeccak512,
|
||||
}
|
||||
var hashVarsigs = []varsig.Hash{
|
||||
0, // undef
|
||||
varsig.HashMd4,
|
||||
varsig.HashMd5,
|
||||
varsig.HashSha1,
|
||||
varsig.HashSha2_224,
|
||||
varsig.HashSha2_256,
|
||||
varsig.HashSha2_384,
|
||||
varsig.HashSha2_512,
|
||||
0, // missing MD5SHA1
|
||||
varsig.HashRipemd_160,
|
||||
varsig.HashSha3_224,
|
||||
varsig.HashSha3_256,
|
||||
varsig.HashSha3_384,
|
||||
varsig.HashSha3_512,
|
||||
varsig.HashSha512_224,
|
||||
varsig.HashSha512_256,
|
||||
varsig.HashBlake2s_256,
|
||||
varsig.HashBlake2b_256,
|
||||
varsig.HashBlake2b_384,
|
||||
varsig.HashBlake2b_512,
|
||||
0, // maxStdHash
|
||||
varsig.HashKeccak_256,
|
||||
varsig.HashKeccak_512,
|
||||
}
|
||||
|
||||
@@ -1,7 +1,17 @@
|
||||
package crypto
|
||||
|
||||
import (
|
||||
"github.com/ucan-wg/go-varsig"
|
||||
)
|
||||
|
||||
type SigningOpts struct {
|
||||
Hash Hash
|
||||
hash Hash
|
||||
payloadEncoding varsig.PayloadEncoding
|
||||
|
||||
// if WithVarsig is used
|
||||
algo varsig.Algorithm
|
||||
curve uint64
|
||||
keyLen uint64
|
||||
}
|
||||
|
||||
func CollectSigningOptions(opts []SigningOption) SigningOpts {
|
||||
@@ -13,10 +23,34 @@ func CollectSigningOptions(opts []SigningOption) SigningOpts {
|
||||
}
|
||||
|
||||
func (opts SigningOpts) HashOrDefault(_default Hash) Hash {
|
||||
if opts.Hash == 0 {
|
||||
if opts.hash == 0 {
|
||||
return _default
|
||||
}
|
||||
return opts.Hash
|
||||
return opts.hash
|
||||
}
|
||||
|
||||
func (opts SigningOpts) PayloadEncoding() varsig.PayloadEncoding {
|
||||
if opts.payloadEncoding == 0 {
|
||||
return varsig.PayloadEncodingVerbatim
|
||||
}
|
||||
return opts.payloadEncoding
|
||||
}
|
||||
|
||||
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")
|
||||
}
|
||||
}
|
||||
|
||||
type SigningOption func(opts *SigningOpts)
|
||||
@@ -24,6 +58,34 @@ 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
|
||||
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")
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -9,6 +9,8 @@ import (
|
||||
"fmt"
|
||||
"math/big"
|
||||
|
||||
"github.com/ucan-wg/go-varsig"
|
||||
|
||||
"github.com/MetaMask/go-did-it/crypto"
|
||||
)
|
||||
|
||||
@@ -99,6 +101,12 @@ func (p *PrivateKey) ToPKCS8PEM() string {
|
||||
}))
|
||||
}
|
||||
|
||||
// The default signing hash is SHA-256.
|
||||
func (p *PrivateKey) Varsig(opts ...crypto.SigningOption) varsig.Varsig {
|
||||
params := crypto.CollectSigningOptions(opts)
|
||||
return varsig.NewECDSAVarsig(varsig.CurveP256, params.HashOrDefault(crypto.SHA256).ToVarsigHash(), params.PayloadEncoding())
|
||||
}
|
||||
|
||||
// The default signing hash is SHA-256.
|
||||
func (p *PrivateKey) SignToBytes(message []byte, opts ...crypto.SigningOption) ([]byte, error) {
|
||||
params := crypto.CollectSigningOptions(opts)
|
||||
|
||||
@@ -8,6 +8,8 @@ import (
|
||||
"fmt"
|
||||
"math/big"
|
||||
|
||||
"github.com/ucan-wg/go-varsig"
|
||||
|
||||
"github.com/MetaMask/go-did-it/crypto"
|
||||
helpers "github.com/MetaMask/go-did-it/crypto/internal"
|
||||
)
|
||||
@@ -148,6 +150,10 @@ func (p *PublicKey) VerifyBytes(message, signature []byte, opts ...crypto.Signin
|
||||
func (p *PublicKey) VerifyASN1(message, signature []byte, opts ...crypto.SigningOption) bool {
|
||||
params := crypto.CollectSigningOptions(opts)
|
||||
|
||||
if !params.VarsigMatch(varsig.AlgorithmECDSA, uint64(varsig.CurveP256), 0) {
|
||||
return false
|
||||
}
|
||||
|
||||
hasher := params.HashOrDefault(crypto.SHA256).New()
|
||||
hasher.Write(message)
|
||||
hash := hasher.Sum(nil)
|
||||
|
||||
@@ -9,6 +9,8 @@ import (
|
||||
"fmt"
|
||||
"math/big"
|
||||
|
||||
"github.com/ucan-wg/go-varsig"
|
||||
|
||||
"github.com/MetaMask/go-did-it/crypto"
|
||||
)
|
||||
|
||||
@@ -99,6 +101,12 @@ func (p *PrivateKey) ToPKCS8PEM() string {
|
||||
}))
|
||||
}
|
||||
|
||||
// The default signing hash is SHA-384.
|
||||
func (p *PrivateKey) Varsig(opts ...crypto.SigningOption) varsig.Varsig {
|
||||
params := crypto.CollectSigningOptions(opts)
|
||||
return varsig.NewECDSAVarsig(varsig.CurveP384, params.HashOrDefault(crypto.SHA384).ToVarsigHash(), params.PayloadEncoding())
|
||||
}
|
||||
|
||||
// The default signing hash is SHA-384.
|
||||
func (p *PrivateKey) SignToBytes(message []byte, opts ...crypto.SigningOption) ([]byte, error) {
|
||||
params := crypto.CollectSigningOptions(opts)
|
||||
|
||||
@@ -8,6 +8,8 @@ import (
|
||||
"fmt"
|
||||
"math/big"
|
||||
|
||||
"github.com/ucan-wg/go-varsig"
|
||||
|
||||
"github.com/MetaMask/go-did-it/crypto"
|
||||
helpers "github.com/MetaMask/go-did-it/crypto/internal"
|
||||
)
|
||||
@@ -148,6 +150,10 @@ func (p *PublicKey) VerifyBytes(message, signature []byte, opts ...crypto.Signin
|
||||
func (p *PublicKey) VerifyASN1(message, signature []byte, opts ...crypto.SigningOption) bool {
|
||||
params := crypto.CollectSigningOptions(opts)
|
||||
|
||||
if !params.VarsigMatch(varsig.AlgorithmECDSA, uint64(varsig.CurveP384), 0) {
|
||||
return false
|
||||
}
|
||||
|
||||
hasher := params.HashOrDefault(crypto.SHA384).New()
|
||||
hasher.Write(message)
|
||||
hash := hasher.Sum(nil)
|
||||
|
||||
@@ -9,6 +9,8 @@ import (
|
||||
"fmt"
|
||||
"math/big"
|
||||
|
||||
"github.com/ucan-wg/go-varsig"
|
||||
|
||||
"github.com/MetaMask/go-did-it/crypto"
|
||||
)
|
||||
|
||||
@@ -99,6 +101,12 @@ func (p *PrivateKey) ToPKCS8PEM() string {
|
||||
}))
|
||||
}
|
||||
|
||||
// The default signing hash is SHA-512.
|
||||
func (p *PrivateKey) Varsig(opts ...crypto.SigningOption) varsig.Varsig {
|
||||
params := crypto.CollectSigningOptions(opts)
|
||||
return varsig.NewECDSAVarsig(varsig.CurveP521, params.HashOrDefault(crypto.SHA512).ToVarsigHash(), params.PayloadEncoding())
|
||||
}
|
||||
|
||||
// The default signing hash is SHA-512.
|
||||
func (p *PrivateKey) SignToBytes(message []byte, opts ...crypto.SigningOption) ([]byte, error) {
|
||||
params := crypto.CollectSigningOptions(opts)
|
||||
|
||||
@@ -8,6 +8,8 @@ import (
|
||||
"fmt"
|
||||
"math/big"
|
||||
|
||||
"github.com/ucan-wg/go-varsig"
|
||||
|
||||
"github.com/MetaMask/go-did-it/crypto"
|
||||
helpers "github.com/MetaMask/go-did-it/crypto/internal"
|
||||
)
|
||||
@@ -148,6 +150,10 @@ func (p *PublicKey) VerifyBytes(message, signature []byte, opts ...crypto.Signin
|
||||
func (p *PublicKey) VerifyASN1(message, signature []byte, opts ...crypto.SigningOption) bool {
|
||||
params := crypto.CollectSigningOptions(opts)
|
||||
|
||||
if !params.VarsigMatch(varsig.AlgorithmECDSA, uint64(varsig.CurveP521), 0) {
|
||||
return false
|
||||
}
|
||||
|
||||
hasher := params.HashOrDefault(crypto.SHA512).New()
|
||||
hasher.Write(message)
|
||||
hash := hasher.Sum(nil)
|
||||
|
||||
@@ -1,48 +1,6 @@
|
||||
package crypto
|
||||
|
||||
// Public Key
|
||||
|
||||
type PublicKey interface {
|
||||
// Equal returns true if other is the same PublicKey
|
||||
Equal(other PublicKey) bool
|
||||
|
||||
// ToPublicKeyMultibase format the PublicKey into a string compatible with a PublicKeyMultibase field
|
||||
// in a DID Document.
|
||||
ToPublicKeyMultibase() string
|
||||
|
||||
// ToX509DER serializes the PublicKey into the X.509 DER (binary) format.
|
||||
ToX509DER() []byte
|
||||
|
||||
// ToX509PEM serializes the PublicKey into the X.509 PEM (string) format.
|
||||
ToX509PEM() string
|
||||
}
|
||||
|
||||
type PublicKeyToBytes interface {
|
||||
PublicKey
|
||||
|
||||
// ToBytes serializes the PublicKey into "raw bytes", without metadata or structure.
|
||||
// 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.
|
||||
ToBytes() []byte
|
||||
}
|
||||
|
||||
type PublicKeySigningBytes interface {
|
||||
PublicKey
|
||||
|
||||
// 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, opts ...SigningOption) bool
|
||||
}
|
||||
|
||||
type PublicKeySigningASN1 interface {
|
||||
PublicKey
|
||||
|
||||
// VerifyASN1 checks a signature in the ASN.1 format.
|
||||
VerifyASN1(message, signature []byte, opts ...SigningOption) bool
|
||||
}
|
||||
|
||||
// Private Key
|
||||
import "github.com/ucan-wg/go-varsig"
|
||||
|
||||
type PrivateKey interface {
|
||||
// Equal returns true if other is the same PrivateKey
|
||||
@@ -70,6 +28,9 @@ type PrivateKeyToBytes interface {
|
||||
type PrivateKeySigningBytes interface {
|
||||
PrivateKey
|
||||
|
||||
// Varsig returns the varsig.Varsig corresponding to the given parameters and private key.
|
||||
Varsig(opts ...SigningOption) varsig.Varsig
|
||||
|
||||
// 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.
|
||||
@@ -79,6 +40,9 @@ type PrivateKeySigningBytes interface {
|
||||
type PrivateKeySigningASN1 interface {
|
||||
PrivateKey
|
||||
|
||||
// Varsig returns the varsig.Varsig corresponding to the given parameters and private key.
|
||||
Varsig(opts ...SigningOption) varsig.Varsig
|
||||
|
||||
// SignToASN1 creates a signature in the ASN.1 format.
|
||||
SignToASN1(message []byte, opts ...SigningOption) ([]byte, error)
|
||||
}
|
||||
41
crypto/public.go
Normal file
41
crypto/public.go
Normal file
@@ -0,0 +1,41 @@
|
||||
package crypto
|
||||
|
||||
type PublicKey interface {
|
||||
// Equal returns true if other is the same PublicKey
|
||||
Equal(other PublicKey) bool
|
||||
|
||||
// ToPublicKeyMultibase format the PublicKey into a string compatible with a PublicKeyMultibase field
|
||||
// in a DID Document.
|
||||
ToPublicKeyMultibase() string
|
||||
|
||||
// ToX509DER serializes the PublicKey into the X.509 DER (binary) format.
|
||||
ToX509DER() []byte
|
||||
|
||||
// ToX509PEM serializes the PublicKey into the X.509 PEM (string) format.
|
||||
ToX509PEM() string
|
||||
}
|
||||
|
||||
type PublicKeyToBytes interface {
|
||||
PublicKey
|
||||
|
||||
// ToBytes serializes the PublicKey into "raw bytes", without metadata or structure.
|
||||
// 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.
|
||||
ToBytes() []byte
|
||||
}
|
||||
|
||||
type PublicKeySigningBytes interface {
|
||||
PublicKey
|
||||
|
||||
// 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, opts ...SigningOption) bool
|
||||
}
|
||||
|
||||
type PublicKeySigningASN1 interface {
|
||||
PublicKey
|
||||
|
||||
// VerifyASN1 checks a signature in the ASN.1 format.
|
||||
VerifyASN1(message, signature []byte, opts ...SigningOption) bool
|
||||
}
|
||||
@@ -9,6 +9,8 @@ import (
|
||||
"fmt"
|
||||
"math/big"
|
||||
|
||||
"github.com/ucan-wg/go-varsig"
|
||||
|
||||
"github.com/MetaMask/go-did-it/crypto"
|
||||
)
|
||||
|
||||
@@ -67,8 +69,8 @@ func PrivateKeyFromPKCS8PEM(str string) (*PrivateKey, error) {
|
||||
return PrivateKeyFromPKCS8DER(block.Bytes)
|
||||
}
|
||||
|
||||
func (p *PrivateKey) BitLen() int {
|
||||
return p.k.N.BitLen()
|
||||
func (p *PrivateKey) KeyLength() uint64 {
|
||||
return uint64((p.k.N.BitLen() + 7) / 8) // Round up to the nearest byte
|
||||
}
|
||||
|
||||
func (p *PrivateKey) DBytes() []byte {
|
||||
@@ -147,6 +149,16 @@ func (p *PrivateKey) ToPKCS8PEM() string {
|
||||
}))
|
||||
}
|
||||
|
||||
// The default signing hash is:
|
||||
// - SHA-256 for keys of length 2048 bits and under
|
||||
// - SHA-384 for keys of length 3072 bits and under
|
||||
// - SHA-512 for higher key length
|
||||
func (p *PrivateKey) Varsig(opts ...crypto.SigningOption) varsig.Varsig {
|
||||
params := crypto.CollectSigningOptions(opts)
|
||||
hashCode := params.HashOrDefault(defaultSigHash(p.k.N.BitLen()))
|
||||
return varsig.NewRSAVarsig(hashCode.ToVarsigHash(), uint64(p.KeyLength()), params.PayloadEncoding())
|
||||
}
|
||||
|
||||
// SignToASN1 produce a PKCS#1 v1.5 signature.
|
||||
// The default signing hash is:
|
||||
// - SHA-256 for keys of length 2048 bits and under
|
||||
|
||||
@@ -8,6 +8,8 @@ import (
|
||||
"fmt"
|
||||
"math/big"
|
||||
|
||||
"github.com/ucan-wg/go-varsig"
|
||||
|
||||
"github.com/MetaMask/go-did-it/crypto"
|
||||
helpers "github.com/MetaMask/go-did-it/crypto/internal"
|
||||
)
|
||||
@@ -93,8 +95,8 @@ func PublicKeyFromX509PEM(str string) (*PublicKey, error) {
|
||||
return PublicKeyFromX509DER(block.Bytes)
|
||||
}
|
||||
|
||||
func (p *PublicKey) BitLen() int {
|
||||
return p.k.N.BitLen()
|
||||
func (p *PublicKey) KeyLength() uint64 {
|
||||
return uint64((p.k.N.BitLen() + 7) / 8) // Round up to the nearest byte
|
||||
}
|
||||
|
||||
func (p *PublicKey) NBytes() []byte {
|
||||
@@ -138,6 +140,10 @@ func (p *PublicKey) ToX509PEM() string {
|
||||
func (p *PublicKey) VerifyASN1(message, signature []byte, opts ...crypto.SigningOption) bool {
|
||||
params := crypto.CollectSigningOptions(opts)
|
||||
|
||||
if !params.VarsigMatch(varsig.AlgorithmRSA, 0, p.KeyLength()) {
|
||||
return false
|
||||
}
|
||||
|
||||
hashCode := params.HashOrDefault(defaultSigHash(p.k.N.BitLen()))
|
||||
hasher := hashCode.New()
|
||||
hasher.Write(message)
|
||||
|
||||
@@ -8,6 +8,7 @@ import (
|
||||
|
||||
"github.com/decred/dcrd/dcrec/secp256k1/v4"
|
||||
"github.com/decred/dcrd/dcrec/secp256k1/v4/ecdsa"
|
||||
"github.com/ucan-wg/go-varsig"
|
||||
|
||||
"github.com/MetaMask/go-did-it/crypto"
|
||||
)
|
||||
@@ -172,6 +173,12 @@ func (p *PrivateKey) ToPKCS8PEM() string {
|
||||
}))
|
||||
}
|
||||
|
||||
// The default signing hash is SHA-256.
|
||||
func (p *PrivateKey) Varsig(opts ...crypto.SigningOption) varsig.Varsig {
|
||||
params := crypto.CollectSigningOptions(opts)
|
||||
return varsig.NewECDSAVarsig(varsig.CurveSecp256k1, params.HashOrDefault(crypto.SHA256).ToVarsigHash(), params.PayloadEncoding())
|
||||
}
|
||||
|
||||
// The default signing hash is SHA-256.
|
||||
func (p *PrivateKey) SignToBytes(message []byte, opts ...crypto.SigningOption) ([]byte, error) {
|
||||
params := crypto.CollectSigningOptions(opts)
|
||||
|
||||
@@ -8,6 +8,7 @@ import (
|
||||
|
||||
"github.com/decred/dcrd/dcrec/secp256k1/v4"
|
||||
"github.com/decred/dcrd/dcrec/secp256k1/v4/ecdsa"
|
||||
"github.com/ucan-wg/go-varsig"
|
||||
|
||||
"github.com/MetaMask/go-did-it/crypto"
|
||||
helpers "github.com/MetaMask/go-did-it/crypto/internal"
|
||||
@@ -176,6 +177,10 @@ func (p *PublicKey) VerifyBytes(message, signature []byte, opts ...crypto.Signin
|
||||
|
||||
params := crypto.CollectSigningOptions(opts)
|
||||
|
||||
if !params.VarsigMatch(varsig.AlgorithmECDSA, uint64(varsig.CurveSecp256k1), 0) {
|
||||
return false
|
||||
}
|
||||
|
||||
hasher := params.HashOrDefault(crypto.SHA256).New()
|
||||
hasher.Write(message)
|
||||
hash := hasher.Sum(nil)
|
||||
@@ -191,6 +196,10 @@ func (p *PublicKey) VerifyBytes(message, signature []byte, opts ...crypto.Signin
|
||||
func (p *PublicKey) VerifyASN1(message, signature []byte, opts ...crypto.SigningOption) bool {
|
||||
params := crypto.CollectSigningOptions(opts)
|
||||
|
||||
if !params.VarsigMatch(varsig.AlgorithmECDSA, uint64(varsig.CurveSecp256k1), 0) {
|
||||
return false
|
||||
}
|
||||
|
||||
hasher := params.HashOrDefault(crypto.SHA256).New()
|
||||
hasher.Write(message)
|
||||
hash := hasher.Sum(nil)
|
||||
|
||||
@@ -23,7 +23,7 @@ func Example_signature() {
|
||||
|
||||
// 3) Use the appropriate set of verification methods (ex: verify a signature for authentication purpose)
|
||||
sig, _ := base64.StdEncoding.DecodeString("nhpkr5a7juUM2eDpDRSJVdEE++0SYqaZXHtuvyafVFUx8zsOdDSrij+vHmd/ARwUOmi/ysmSD+b3K9WTBtmmBQ==")
|
||||
if ok, method := did.TryAllVerify(doc.Authentication(), []byte("message"), sig); ok {
|
||||
if ok, method := did.TryAllVerifyBytes(doc.Authentication(), []byte("message"), sig); ok {
|
||||
fmt.Println("Signature is valid, verified with method:", method.Type(), method.ID())
|
||||
} else {
|
||||
fmt.Println("Signature is invalid")
|
||||
|
||||
9
go.mod
9
go.mod
@@ -1,8 +1,8 @@
|
||||
module github.com/MetaMask/go-did-it
|
||||
|
||||
go 1.23.0
|
||||
go 1.24.4
|
||||
|
||||
toolchain go1.23.1
|
||||
toolchain go1.24.5
|
||||
|
||||
require (
|
||||
github.com/decred/dcrd/dcrec/secp256k1/v4 v4.4.0
|
||||
@@ -10,7 +10,8 @@ require (
|
||||
github.com/multiformats/go-multibase v0.2.0
|
||||
github.com/multiformats/go-varint v0.0.7
|
||||
github.com/stretchr/testify v1.10.0
|
||||
golang.org/x/crypto v0.39.0
|
||||
github.com/ucan-wg/go-varsig v1.0.0
|
||||
golang.org/x/crypto v0.40.0
|
||||
)
|
||||
|
||||
require (
|
||||
@@ -18,6 +19,6 @@ require (
|
||||
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
|
||||
golang.org/x/sys v0.34.0 // indirect
|
||||
gopkg.in/yaml.v3 v3.0.1 // indirect
|
||||
)
|
||||
|
||||
10
go.sum
10
go.sum
@@ -18,10 +18,12 @@ github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZb
|
||||
github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4=
|
||||
github.com/stretchr/testify v1.10.0 h1:Xv5erBjTwe/5IxqUQTdXv5kgmIvbHo3QQyRwhJsOfJA=
|
||||
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=
|
||||
github.com/ucan-wg/go-varsig v1.0.0 h1:Hrc437Zg+B5Eoajg+qZQZI3Q3ocPyjlnp3/Bz9ZnlWw=
|
||||
github.com/ucan-wg/go-varsig v1.0.0/go.mod h1:Sakln6IPooDPH+ClQ0VvR09TuwUhHcfLqcPiPkMZGh0=
|
||||
golang.org/x/crypto v0.40.0 h1:r4x+VvoG5Fm+eJcxMaY8CQM7Lb0l1lsmjGBQ6s8BfKM=
|
||||
golang.org/x/crypto v0.40.0/go.mod h1:Qr1vMER5WyS2dfPHAlsOj01wgLbsyWtFn/aY+5+ZdxY=
|
||||
golang.org/x/sys v0.34.0 h1:H5Y5sJ2L2JRdyv7ROF1he/lPdvFsd0mJHFw2ThKHxLA=
|
||||
golang.org/x/sys v0.34.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=
|
||||
|
||||
@@ -104,8 +104,11 @@ type VerificationMethod interface {
|
||||
type VerificationMethodSignature interface {
|
||||
VerificationMethod
|
||||
|
||||
// Verify checks that 'sig' is a valid signature of 'data'.
|
||||
Verify(data []byte, sig []byte) (bool, error)
|
||||
// VerifyBytes checks that 'sig' is a valid "raw bytes" signature of 'data'.
|
||||
VerifyBytes(data []byte, sig []byte, opts ...crypto.SigningOption) (bool, error)
|
||||
|
||||
// VerifyASN1 checks that 'sig' is a valid ASN.1 signature of 'data'.
|
||||
VerifyASN1(data []byte, sig []byte, opts ...crypto.SigningOption) (bool, error)
|
||||
}
|
||||
|
||||
// VerificationMethodKeyAgreement is a VerificationMethod implementing a shared key agreement.
|
||||
|
||||
18
utilities.go
18
utilities.go
@@ -6,12 +6,24 @@ import (
|
||||
"github.com/MetaMask/go-did-it/crypto"
|
||||
)
|
||||
|
||||
// TryAllVerify tries to verify the signature with all the methods in the slice.
|
||||
// TryAllVerifyBytes tries to verify the signature as bytes with all the methods in the slice.
|
||||
// It returns true if the signature is verified, and the method that verified it.
|
||||
// If no method verifies the signature, it returns false and nil.
|
||||
func TryAllVerify(methods []VerificationMethodSignature, data []byte, sig []byte) (bool, VerificationMethodSignature) {
|
||||
func TryAllVerifyBytes(methods []VerificationMethodSignature, data []byte, sig []byte, opts ...crypto.SigningOption) (bool, VerificationMethodSignature) {
|
||||
for _, method := range methods {
|
||||
if valid, err := method.Verify(data, sig); err == nil && valid {
|
||||
if valid, err := method.VerifyBytes(data, sig, opts...); err == nil && valid {
|
||||
return true, method
|
||||
}
|
||||
}
|
||||
return false, nil
|
||||
}
|
||||
|
||||
// TryAllVerifyASN1 tries to verify the signature as ASN.1 with all the methods in the slice.
|
||||
// It returns true if the signature is verified, and the method that verified it.
|
||||
// If no method verifies the signature, it returns false and nil.
|
||||
func TryAllVerifyASN1(methods []VerificationMethodSignature, data []byte, sig []byte, opts ...crypto.SigningOption) (bool, VerificationMethodSignature) {
|
||||
for _, method := range methods {
|
||||
if valid, err := method.VerifyASN1(data, sig, opts...); err == nil && valid {
|
||||
return true, method
|
||||
}
|
||||
}
|
||||
|
||||
@@ -8,6 +8,7 @@ import (
|
||||
"github.com/mr-tron/base58"
|
||||
|
||||
"github.com/MetaMask/go-did-it"
|
||||
"github.com/MetaMask/go-did-it/crypto"
|
||||
"github.com/MetaMask/go-did-it/crypto/ed25519"
|
||||
)
|
||||
|
||||
@@ -97,6 +98,10 @@ func (v VerificationKey2018) JsonLdContext() string {
|
||||
return JsonLdContext2018
|
||||
}
|
||||
|
||||
func (v VerificationKey2018) Verify(data []byte, sig []byte) (bool, error) {
|
||||
return v.pubkey.VerifyBytes(data, sig), nil
|
||||
func (v VerificationKey2018) VerifyBytes(data []byte, sig []byte, opts ...crypto.SigningOption) (bool, error) {
|
||||
return v.pubkey.VerifyBytes(data, sig, opts...), nil
|
||||
}
|
||||
|
||||
func (v VerificationKey2018) VerifyASN1(data []byte, sig []byte, opts ...crypto.SigningOption) (bool, error) {
|
||||
return v.pubkey.VerifyASN1(data, sig, opts...), nil
|
||||
}
|
||||
|
||||
@@ -6,6 +6,7 @@ import (
|
||||
"fmt"
|
||||
|
||||
"github.com/MetaMask/go-did-it"
|
||||
"github.com/MetaMask/go-did-it/crypto"
|
||||
"github.com/MetaMask/go-did-it/crypto/ed25519"
|
||||
)
|
||||
|
||||
@@ -91,6 +92,10 @@ func (v VerificationKey2020) JsonLdContext() string {
|
||||
return JsonLdContext2020
|
||||
}
|
||||
|
||||
func (v VerificationKey2020) Verify(data []byte, sig []byte) (bool, error) {
|
||||
return v.pubkey.VerifyBytes(data, sig), nil
|
||||
func (v VerificationKey2020) VerifyBytes(data []byte, sig []byte, opts ...crypto.SigningOption) (bool, error) {
|
||||
return v.pubkey.VerifyBytes(data, sig, opts...), nil
|
||||
}
|
||||
|
||||
func (v VerificationKey2020) VerifyASN1(data []byte, sig []byte, opts ...crypto.SigningOption) (bool, error) {
|
||||
return v.pubkey.VerifyASN1(data, sig, opts...), nil
|
||||
}
|
||||
|
||||
@@ -93,9 +93,16 @@ func (j JsonWebKey2020) JsonLdContext() string {
|
||||
return JsonLdContext
|
||||
}
|
||||
|
||||
func (j JsonWebKey2020) Verify(data []byte, sig []byte) (bool, error) {
|
||||
func (j JsonWebKey2020) VerifyBytes(data []byte, sig []byte, opts ...crypto.SigningOption) (bool, error) {
|
||||
if pub, ok := j.pubkey.(crypto.PublicKeySigningBytes); ok {
|
||||
return pub.VerifyBytes(data, sig), nil
|
||||
return pub.VerifyBytes(data, sig, opts...), nil
|
||||
}
|
||||
return false, errors.New("not a signing public key")
|
||||
}
|
||||
|
||||
func (j JsonWebKey2020) VerifyASN1(data []byte, sig []byte, opts ...crypto.SigningOption) (bool, error) {
|
||||
if pub, ok := j.pubkey.(crypto.PublicKeySigningASN1); ok {
|
||||
return pub.VerifyASN1(data, sig, opts...), nil
|
||||
}
|
||||
return false, errors.New("not a signing public key")
|
||||
}
|
||||
|
||||
@@ -96,9 +96,16 @@ func (m MultiKey) JsonLdContext() string {
|
||||
return JsonLdContext
|
||||
}
|
||||
|
||||
func (m MultiKey) Verify(data []byte, sig []byte) (bool, error) {
|
||||
func (m MultiKey) VerifyBytes(data []byte, sig []byte, opts ...crypto.SigningOption) (bool, error) {
|
||||
if pub, ok := m.pubkey.(crypto.PublicKeySigningBytes); ok {
|
||||
return pub.VerifyBytes(data, sig), nil
|
||||
return pub.VerifyBytes(data, sig, opts...), nil
|
||||
}
|
||||
return false, errors.New("not a signing public key")
|
||||
}
|
||||
|
||||
func (m MultiKey) VerifyASN1(data []byte, sig []byte, opts ...crypto.SigningOption) (bool, error) {
|
||||
if pub, ok := m.pubkey.(crypto.PublicKeySigningASN1); ok {
|
||||
return pub.VerifyASN1(data, sig, opts...), nil
|
||||
}
|
||||
return false, errors.New("not a signing public key")
|
||||
}
|
||||
|
||||
@@ -101,8 +101,12 @@ func (m Key2021) JsonLdContext() string {
|
||||
return JsonLdContext2021
|
||||
}
|
||||
|
||||
func (m Key2021) Verify(data []byte, sig []byte) (bool, error) {
|
||||
return m.pubkey.VerifyBytes(data, sig), nil
|
||||
func (m Key2021) VerifyBytes(data []byte, sig []byte, opts ...crypto.SigningOption) (bool, error) {
|
||||
return m.pubkey.VerifyBytes(data, sig, opts...), nil
|
||||
}
|
||||
|
||||
func (m Key2021) VerifyASN1(data []byte, sig []byte, opts ...crypto.SigningOption) (bool, error) {
|
||||
return m.pubkey.VerifyASN1(data, sig, opts...), nil
|
||||
}
|
||||
|
||||
func (m Key2021) PrivateKeyIsCompatible(local crypto.PrivateKeyKeyExchange) bool {
|
||||
|
||||
@@ -101,8 +101,12 @@ func (vm VerificationKey2019) JsonLdContext() string {
|
||||
return JsonLdContext
|
||||
}
|
||||
|
||||
func (vm VerificationKey2019) Verify(data []byte, sig []byte) (bool, error) {
|
||||
return vm.pubkey.VerifyBytes(data, sig), nil
|
||||
func (vm VerificationKey2019) VerifyBytes(data []byte, sig []byte, opts ...crypto.SigningOption) (bool, error) {
|
||||
return vm.pubkey.VerifyBytes(data, sig, opts...), nil
|
||||
}
|
||||
|
||||
func (vm VerificationKey2019) VerifyASN1(data []byte, sig []byte, opts ...crypto.SigningOption) (bool, error) {
|
||||
return vm.pubkey.VerifyASN1(data, sig, opts...), nil
|
||||
}
|
||||
|
||||
func (vm VerificationKey2019) PrivateKeyIsCompatible(local crypto.PrivateKeyKeyExchange) bool {
|
||||
|
||||
@@ -32,7 +32,7 @@ func ExampleGenerateKeyPair() {
|
||||
// Resolve the DID and verify a signature
|
||||
doc, err := dk.Document()
|
||||
handleErr(err)
|
||||
ok, _ := did.TryAllVerify(doc.Authentication(), msg, sig)
|
||||
ok, _ := did.TryAllVerifyBytes(doc.Authentication(), msg, sig)
|
||||
fmt.Println("Signature verified:", ok)
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user