2
.github/workflows/gotest.yml
vendored
2
.github/workflows/gotest.yml
vendored
@@ -24,4 +24,4 @@ jobs:
|
|||||||
- name: Run tests
|
- name: Run tests
|
||||||
run: go test -v ./...
|
run: go test -v ./...
|
||||||
- name: Check formatted
|
- name: Check formatted
|
||||||
run: gofmt -l .
|
run: gofmt -l .
|
||||||
|
|||||||
@@ -9,6 +9,7 @@ import (
|
|||||||
mbase "github.com/multiformats/go-multibase"
|
mbase "github.com/multiformats/go-multibase"
|
||||||
"github.com/multiformats/go-varint"
|
"github.com/multiformats/go-varint"
|
||||||
"github.com/stretchr/testify/require"
|
"github.com/stretchr/testify/require"
|
||||||
|
"github.com/ucan-wg/go-varsig"
|
||||||
|
|
||||||
"github.com/MetaMask/go-did-it/crypto"
|
"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
|
name string
|
||||||
signer func(msg []byte, opts ...crypto.SigningOption) ([]byte, error)
|
signer func(msg []byte, opts ...crypto.SigningOption) ([]byte, error)
|
||||||
verifier func(msg []byte, sig []byte, opts ...crypto.SigningOption) bool
|
verifier func(msg []byte, sig []byte, opts ...crypto.SigningOption) bool
|
||||||
|
varsig func(opts ...crypto.SigningOption) varsig.Varsig
|
||||||
expectedSize int
|
expectedSize int
|
||||||
stats *int
|
stats *int
|
||||||
defaultHash crypto.Hash
|
defaultHash crypto.Hash
|
||||||
@@ -210,6 +212,7 @@ func TestSuite[PubT crypto.PublicKey, PrivT crypto.PrivateKey](t *testing.T, har
|
|||||||
name: "Bytes signature",
|
name: "Bytes signature",
|
||||||
signer: spriv.SignToBytes,
|
signer: spriv.SignToBytes,
|
||||||
verifier: spub.VerifyBytes,
|
verifier: spub.VerifyBytes,
|
||||||
|
varsig: spriv.Varsig,
|
||||||
expectedSize: harness.SignatureBytesSize,
|
expectedSize: harness.SignatureBytesSize,
|
||||||
stats: &stats.sigRawSize,
|
stats: &stats.sigRawSize,
|
||||||
defaultHash: harness.DefaultHash,
|
defaultHash: harness.DefaultHash,
|
||||||
@@ -227,6 +230,7 @@ func TestSuite[PubT crypto.PublicKey, PrivT crypto.PrivateKey](t *testing.T, har
|
|||||||
name: "ASN.1 signature",
|
name: "ASN.1 signature",
|
||||||
signer: spriv.SignToASN1,
|
signer: spriv.SignToASN1,
|
||||||
verifier: spub.VerifyASN1,
|
verifier: spub.VerifyASN1,
|
||||||
|
varsig: spriv.Varsig,
|
||||||
stats: &stats.sigAsn1Size,
|
stats: &stats.sigAsn1Size,
|
||||||
defaultHash: harness.DefaultHash,
|
defaultHash: harness.DefaultHash,
|
||||||
otherHashes: harness.OtherHashes,
|
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))
|
sigDefault, err := tc.signer(msg, crypto.WithSigningHash(tc.defaultHash))
|
||||||
require.NoError(t, err)
|
require.NoError(t, err)
|
||||||
|
|
||||||
|
vsig := tc.varsig()
|
||||||
|
require.Equal(t, harness.DefaultHash.ToVarsigHash(), vsig.Hash())
|
||||||
|
|
||||||
if tc.expectedSize > 0 {
|
if tc.expectedSize > 0 {
|
||||||
require.Equal(t, tc.expectedSize, len(sigNoParams))
|
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
|
// signatures might be different (i.e. non-deterministic), but they should verify the same way
|
||||||
valid := tc.verifier(msg, sigNoParams)
|
valid := tc.verifier(msg, sigNoParams)
|
||||||
require.True(t, valid)
|
require.True(t, valid)
|
||||||
|
valid = tc.verifier(msg, sigNoParams, crypto.WithVarsig(vsig))
|
||||||
|
require.True(t, valid)
|
||||||
valid = tc.verifier(msg, sigDefault)
|
valid = tc.verifier(msg, sigDefault)
|
||||||
require.True(t, valid)
|
require.True(t, valid)
|
||||||
|
valid = tc.verifier(msg, sigDefault, crypto.WithVarsig(vsig))
|
||||||
|
require.True(t, valid)
|
||||||
|
|
||||||
valid = tc.verifier([]byte("wrong message"), sigNoParams)
|
valid = tc.verifier([]byte("wrong message"), sigNoParams)
|
||||||
require.False(t, valid)
|
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)
|
valid = tc.verifier([]byte("wrong message"), sigDefault)
|
||||||
require.False(t, valid)
|
require.False(t, valid)
|
||||||
|
valid = tc.verifier([]byte("wrong message"), sigDefault, crypto.WithVarsig(vsig))
|
||||||
|
require.False(t, valid)
|
||||||
})
|
})
|
||||||
for _, hash := range tc.otherHashes {
|
for _, hash := range tc.otherHashes {
|
||||||
t.Run(fmt.Sprintf("%s-%s", tc.name, hash.String()), func(t *testing.T) {
|
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.NoError(t, err)
|
||||||
require.NotEmpty(t, sig)
|
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))
|
valid := tc.verifier(msg, sig, crypto.WithSigningHash(hash))
|
||||||
require.True(t, valid)
|
require.True(t, valid)
|
||||||
|
valid = tc.verifier(msg, sig, crypto.WithVarsig(vsig))
|
||||||
|
require.True(t, valid)
|
||||||
|
|
||||||
valid = tc.verifier([]byte("wrong message"), sig)
|
valid = tc.verifier([]byte("wrong message"), sig)
|
||||||
require.False(t, valid)
|
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) {
|
b.Run("Sign to ASN.1 signature", func(b *testing.B) {
|
||||||
if !pubImplements[PubT, crypto.PublicKeySigningASN1]() {
|
if !pubImplements[PubT, crypto.PublicKeySigningASN1]() {
|
||||||
b.Skip("Signature to ASN.1 is not implemented")
|
b.Skip("Signature to ASN.1 is not implemented")
|
||||||
|
|||||||
@@ -6,6 +6,7 @@ import (
|
|||||||
"encoding/pem"
|
"encoding/pem"
|
||||||
"fmt"
|
"fmt"
|
||||||
|
|
||||||
|
"github.com/ucan-wg/go-varsig"
|
||||||
"golang.org/x/crypto/cryptobyte"
|
"golang.org/x/crypto/cryptobyte"
|
||||||
|
|
||||||
"github.com/MetaMask/go-did-it/crypto"
|
"github.com/MetaMask/go-did-it/crypto"
|
||||||
@@ -21,7 +22,7 @@ type PrivateKey struct {
|
|||||||
|
|
||||||
// PrivateKeyFromBytes converts a serialized private key to a PrivateKey.
|
// PrivateKeyFromBytes converts a serialized private key to a PrivateKey.
|
||||||
// This compact serialization format is the raw key material, without metadata or structure.
|
// 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) {
|
func PrivateKeyFromBytes(b []byte) (PrivateKey, error) {
|
||||||
if len(b) != PrivateKeyBytesSize {
|
if len(b) != PrivateKeyBytesSize {
|
||||||
return PrivateKey{}, fmt.Errorf("invalid ed25519 private key size")
|
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)}
|
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) {
|
func (p PrivateKey) SignToBytes(message []byte, opts ...crypto.SigningOption) ([]byte, error) {
|
||||||
params := crypto.CollectSigningOptions(opts)
|
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 nil, fmt.Errorf("ed25519 does not support custom hash functions")
|
||||||
}
|
}
|
||||||
|
|
||||||
return ed25519.Sign(p.k, message), nil
|
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.
|
// 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) {
|
func (p PrivateKey) SignToASN1(message []byte, opts ...crypto.SigningOption) ([]byte, error) {
|
||||||
params := crypto.CollectSigningOptions(opts)
|
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 nil, fmt.Errorf("ed25519 does not support custom hash functions")
|
||||||
}
|
}
|
||||||
|
|
||||||
sig := ed25519.Sign(p.k, message)
|
sig := ed25519.Sign(p.k, message)
|
||||||
var b cryptobyte.Builder
|
var b cryptobyte.Builder
|
||||||
b.AddASN1BitString(sig)
|
b.AddASN1BitString(sig)
|
||||||
|
|||||||
@@ -7,6 +7,7 @@ import (
|
|||||||
"encoding/pem"
|
"encoding/pem"
|
||||||
"fmt"
|
"fmt"
|
||||||
|
|
||||||
|
"github.com/ucan-wg/go-varsig"
|
||||||
"golang.org/x/crypto/cryptobyte"
|
"golang.org/x/crypto/cryptobyte"
|
||||||
|
|
||||||
"github.com/MetaMask/go-did-it/crypto"
|
"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 {
|
func (p PublicKey) VerifyBytes(message, signature []byte, opts ...crypto.SigningOption) bool {
|
||||||
params := crypto.CollectSigningOptions(opts)
|
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
|
// ed25519 does not support custom hash functions
|
||||||
return false
|
return false
|
||||||
}
|
}
|
||||||
|
|
||||||
return ed25519.Verify(p.k, message, signature)
|
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.
|
// 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 {
|
func (p PublicKey) VerifyASN1(message, signature []byte, opts ...crypto.SigningOption) bool {
|
||||||
params := crypto.CollectSigningOptions(opts)
|
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
|
// ed25519 does not support custom hash functions
|
||||||
return false
|
return false
|
||||||
}
|
}
|
||||||
|
|
||||||
var s cryptobyte.String = signature
|
var s cryptobyte.String = signature
|
||||||
var bitString asn1.BitString
|
var bitString asn1.BitString
|
||||||
|
|
||||||
|
|||||||
143
crypto/hash.go
143
crypto/hash.go
@@ -5,41 +5,15 @@ import (
|
|||||||
"hash"
|
"hash"
|
||||||
"strconv"
|
"strconv"
|
||||||
|
|
||||||
|
"github.com/ucan-wg/go-varsig"
|
||||||
"golang.org/x/crypto/sha3"
|
"golang.org/x/crypto/sha3"
|
||||||
)
|
)
|
||||||
|
|
||||||
// As the standard crypto library prohibits from registering additional hash algorithm (like keccak),
|
// As the standard crypto library prohibits from registering additional hash algorithm (like keccak),
|
||||||
// below is essentially an extension of that mechanism to allow it.
|
// 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
|
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 (
|
const (
|
||||||
// From "crypto"
|
// From "crypto"
|
||||||
MD4 Hash = 1 + iota // import golang.org/x/crypto/md4
|
MD4 Hash = 1 + iota // import golang.org/x/crypto/md4
|
||||||
@@ -71,7 +45,20 @@ const (
|
|||||||
maxHash
|
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
|
// New returns a new hash.Hash calculating the given hash function. New panics
|
||||||
// if the hash function is not linked into the binary.
|
// 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()
|
return stdcrypto.Hash(h).New()
|
||||||
}
|
}
|
||||||
if h > maxStdHash && h < maxHash {
|
if h > maxStdHash && h < maxHash {
|
||||||
f := hashes[h-maxStdHash-1]
|
f := hashFns[h-maxStdHash-1]
|
||||||
if f != nil {
|
if f != nil {
|
||||||
return f()
|
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
|
func (h Hash) ToVarsigHash() varsig.Hash {
|
||||||
// hash function. This is intended to be called from the init function in
|
if h == MD5SHA1 {
|
||||||
// packages that implement hash functions.
|
panic("no multihash/multicodec value exists for MD5+SHA1")
|
||||||
func RegisterHash(h Hash, f func() hash.Hash) {
|
|
||||||
if h >= maxHash {
|
|
||||||
panic("crypto: RegisterHash of unknown hash function")
|
|
||||||
}
|
}
|
||||||
if h <= maxStdHash {
|
if h < maxHash {
|
||||||
panic("crypto: RegisterHash of standard hash function")
|
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
|
package crypto
|
||||||
|
|
||||||
|
import (
|
||||||
|
"github.com/ucan-wg/go-varsig"
|
||||||
|
)
|
||||||
|
|
||||||
type SigningOpts struct {
|
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 {
|
func CollectSigningOptions(opts []SigningOption) SigningOpts {
|
||||||
@@ -13,10 +23,34 @@ func CollectSigningOptions(opts []SigningOption) SigningOpts {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func (opts SigningOpts) HashOrDefault(_default Hash) Hash {
|
func (opts SigningOpts) HashOrDefault(_default Hash) Hash {
|
||||||
if opts.Hash == 0 {
|
if opts.hash == 0 {
|
||||||
return _default
|
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)
|
type SigningOption func(opts *SigningOpts)
|
||||||
@@ -24,6 +58,34 @@ type SigningOption func(opts *SigningOpts)
|
|||||||
// WithSigningHash specify the hash algorithm to be used for signatures
|
// WithSigningHash specify the hash algorithm to be used for signatures
|
||||||
func WithSigningHash(hash Hash) SigningOption {
|
func WithSigningHash(hash Hash) SigningOption {
|
||||||
return func(opts *SigningOpts) {
|
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"
|
"fmt"
|
||||||
"math/big"
|
"math/big"
|
||||||
|
|
||||||
|
"github.com/ucan-wg/go-varsig"
|
||||||
|
|
||||||
"github.com/MetaMask/go-did-it/crypto"
|
"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.
|
// The default signing hash is SHA-256.
|
||||||
func (p *PrivateKey) SignToBytes(message []byte, opts ...crypto.SigningOption) ([]byte, error) {
|
func (p *PrivateKey) SignToBytes(message []byte, opts ...crypto.SigningOption) ([]byte, error) {
|
||||||
params := crypto.CollectSigningOptions(opts)
|
params := crypto.CollectSigningOptions(opts)
|
||||||
|
|||||||
@@ -8,6 +8,8 @@ import (
|
|||||||
"fmt"
|
"fmt"
|
||||||
"math/big"
|
"math/big"
|
||||||
|
|
||||||
|
"github.com/ucan-wg/go-varsig"
|
||||||
|
|
||||||
"github.com/MetaMask/go-did-it/crypto"
|
"github.com/MetaMask/go-did-it/crypto"
|
||||||
helpers "github.com/MetaMask/go-did-it/crypto/internal"
|
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 {
|
func (p *PublicKey) VerifyASN1(message, signature []byte, opts ...crypto.SigningOption) bool {
|
||||||
params := crypto.CollectSigningOptions(opts)
|
params := crypto.CollectSigningOptions(opts)
|
||||||
|
|
||||||
|
if !params.VarsigMatch(varsig.AlgorithmECDSA, uint64(varsig.CurveP256), 0) {
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
|
||||||
hasher := params.HashOrDefault(crypto.SHA256).New()
|
hasher := params.HashOrDefault(crypto.SHA256).New()
|
||||||
hasher.Write(message)
|
hasher.Write(message)
|
||||||
hash := hasher.Sum(nil)
|
hash := hasher.Sum(nil)
|
||||||
|
|||||||
@@ -9,6 +9,8 @@ import (
|
|||||||
"fmt"
|
"fmt"
|
||||||
"math/big"
|
"math/big"
|
||||||
|
|
||||||
|
"github.com/ucan-wg/go-varsig"
|
||||||
|
|
||||||
"github.com/MetaMask/go-did-it/crypto"
|
"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.
|
// The default signing hash is SHA-384.
|
||||||
func (p *PrivateKey) SignToBytes(message []byte, opts ...crypto.SigningOption) ([]byte, error) {
|
func (p *PrivateKey) SignToBytes(message []byte, opts ...crypto.SigningOption) ([]byte, error) {
|
||||||
params := crypto.CollectSigningOptions(opts)
|
params := crypto.CollectSigningOptions(opts)
|
||||||
|
|||||||
@@ -8,6 +8,8 @@ import (
|
|||||||
"fmt"
|
"fmt"
|
||||||
"math/big"
|
"math/big"
|
||||||
|
|
||||||
|
"github.com/ucan-wg/go-varsig"
|
||||||
|
|
||||||
"github.com/MetaMask/go-did-it/crypto"
|
"github.com/MetaMask/go-did-it/crypto"
|
||||||
helpers "github.com/MetaMask/go-did-it/crypto/internal"
|
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 {
|
func (p *PublicKey) VerifyASN1(message, signature []byte, opts ...crypto.SigningOption) bool {
|
||||||
params := crypto.CollectSigningOptions(opts)
|
params := crypto.CollectSigningOptions(opts)
|
||||||
|
|
||||||
|
if !params.VarsigMatch(varsig.AlgorithmECDSA, uint64(varsig.CurveP384), 0) {
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
|
||||||
hasher := params.HashOrDefault(crypto.SHA384).New()
|
hasher := params.HashOrDefault(crypto.SHA384).New()
|
||||||
hasher.Write(message)
|
hasher.Write(message)
|
||||||
hash := hasher.Sum(nil)
|
hash := hasher.Sum(nil)
|
||||||
|
|||||||
@@ -9,6 +9,8 @@ import (
|
|||||||
"fmt"
|
"fmt"
|
||||||
"math/big"
|
"math/big"
|
||||||
|
|
||||||
|
"github.com/ucan-wg/go-varsig"
|
||||||
|
|
||||||
"github.com/MetaMask/go-did-it/crypto"
|
"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.
|
// The default signing hash is SHA-512.
|
||||||
func (p *PrivateKey) SignToBytes(message []byte, opts ...crypto.SigningOption) ([]byte, error) {
|
func (p *PrivateKey) SignToBytes(message []byte, opts ...crypto.SigningOption) ([]byte, error) {
|
||||||
params := crypto.CollectSigningOptions(opts)
|
params := crypto.CollectSigningOptions(opts)
|
||||||
|
|||||||
@@ -8,6 +8,8 @@ import (
|
|||||||
"fmt"
|
"fmt"
|
||||||
"math/big"
|
"math/big"
|
||||||
|
|
||||||
|
"github.com/ucan-wg/go-varsig"
|
||||||
|
|
||||||
"github.com/MetaMask/go-did-it/crypto"
|
"github.com/MetaMask/go-did-it/crypto"
|
||||||
helpers "github.com/MetaMask/go-did-it/crypto/internal"
|
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 {
|
func (p *PublicKey) VerifyASN1(message, signature []byte, opts ...crypto.SigningOption) bool {
|
||||||
params := crypto.CollectSigningOptions(opts)
|
params := crypto.CollectSigningOptions(opts)
|
||||||
|
|
||||||
|
if !params.VarsigMatch(varsig.AlgorithmECDSA, uint64(varsig.CurveP521), 0) {
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
|
||||||
hasher := params.HashOrDefault(crypto.SHA512).New()
|
hasher := params.HashOrDefault(crypto.SHA512).New()
|
||||||
hasher.Write(message)
|
hasher.Write(message)
|
||||||
hash := hasher.Sum(nil)
|
hash := hasher.Sum(nil)
|
||||||
|
|||||||
@@ -1,48 +1,6 @@
|
|||||||
package crypto
|
package crypto
|
||||||
|
|
||||||
// Public Key
|
import "github.com/ucan-wg/go-varsig"
|
||||||
|
|
||||||
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
|
|
||||||
|
|
||||||
type PrivateKey interface {
|
type PrivateKey interface {
|
||||||
// Equal returns true if other is the same PrivateKey
|
// Equal returns true if other is the same PrivateKey
|
||||||
@@ -70,6 +28,9 @@ type PrivateKeyToBytes interface {
|
|||||||
type PrivateKeySigningBytes interface {
|
type PrivateKeySigningBytes interface {
|
||||||
PrivateKey
|
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.
|
// SignToBytes creates a signature in the "raw bytes" format.
|
||||||
// This format can make some assumptions and may not be what you expect.
|
// 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.
|
// Ideally, this format is defined by the same specification as the underlying crypto scheme.
|
||||||
@@ -79,6 +40,9 @@ type PrivateKeySigningBytes interface {
|
|||||||
type PrivateKeySigningASN1 interface {
|
type PrivateKeySigningASN1 interface {
|
||||||
PrivateKey
|
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 creates a signature in the ASN.1 format.
|
||||||
SignToASN1(message []byte, opts ...SigningOption) ([]byte, error)
|
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"
|
"fmt"
|
||||||
"math/big"
|
"math/big"
|
||||||
|
|
||||||
|
"github.com/ucan-wg/go-varsig"
|
||||||
|
|
||||||
"github.com/MetaMask/go-did-it/crypto"
|
"github.com/MetaMask/go-did-it/crypto"
|
||||||
)
|
)
|
||||||
|
|
||||||
@@ -67,8 +69,8 @@ func PrivateKeyFromPKCS8PEM(str string) (*PrivateKey, error) {
|
|||||||
return PrivateKeyFromPKCS8DER(block.Bytes)
|
return PrivateKeyFromPKCS8DER(block.Bytes)
|
||||||
}
|
}
|
||||||
|
|
||||||
func (p *PrivateKey) BitLen() int {
|
func (p *PrivateKey) KeyLength() uint64 {
|
||||||
return p.k.N.BitLen()
|
return uint64((p.k.N.BitLen() + 7) / 8) // Round up to the nearest byte
|
||||||
}
|
}
|
||||||
|
|
||||||
func (p *PrivateKey) DBytes() []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.
|
// SignToASN1 produce a PKCS#1 v1.5 signature.
|
||||||
// The default signing hash is:
|
// The default signing hash is:
|
||||||
// - SHA-256 for keys of length 2048 bits and under
|
// - SHA-256 for keys of length 2048 bits and under
|
||||||
|
|||||||
@@ -8,6 +8,8 @@ import (
|
|||||||
"fmt"
|
"fmt"
|
||||||
"math/big"
|
"math/big"
|
||||||
|
|
||||||
|
"github.com/ucan-wg/go-varsig"
|
||||||
|
|
||||||
"github.com/MetaMask/go-did-it/crypto"
|
"github.com/MetaMask/go-did-it/crypto"
|
||||||
helpers "github.com/MetaMask/go-did-it/crypto/internal"
|
helpers "github.com/MetaMask/go-did-it/crypto/internal"
|
||||||
)
|
)
|
||||||
@@ -93,8 +95,8 @@ func PublicKeyFromX509PEM(str string) (*PublicKey, error) {
|
|||||||
return PublicKeyFromX509DER(block.Bytes)
|
return PublicKeyFromX509DER(block.Bytes)
|
||||||
}
|
}
|
||||||
|
|
||||||
func (p *PublicKey) BitLen() int {
|
func (p *PublicKey) KeyLength() uint64 {
|
||||||
return p.k.N.BitLen()
|
return uint64((p.k.N.BitLen() + 7) / 8) // Round up to the nearest byte
|
||||||
}
|
}
|
||||||
|
|
||||||
func (p *PublicKey) NBytes() []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 {
|
func (p *PublicKey) VerifyASN1(message, signature []byte, opts ...crypto.SigningOption) bool {
|
||||||
params := crypto.CollectSigningOptions(opts)
|
params := crypto.CollectSigningOptions(opts)
|
||||||
|
|
||||||
|
if !params.VarsigMatch(varsig.AlgorithmRSA, 0, p.KeyLength()) {
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
|
||||||
hashCode := params.HashOrDefault(defaultSigHash(p.k.N.BitLen()))
|
hashCode := params.HashOrDefault(defaultSigHash(p.k.N.BitLen()))
|
||||||
hasher := hashCode.New()
|
hasher := hashCode.New()
|
||||||
hasher.Write(message)
|
hasher.Write(message)
|
||||||
|
|||||||
@@ -8,6 +8,7 @@ import (
|
|||||||
|
|
||||||
"github.com/decred/dcrd/dcrec/secp256k1/v4"
|
"github.com/decred/dcrd/dcrec/secp256k1/v4"
|
||||||
"github.com/decred/dcrd/dcrec/secp256k1/v4/ecdsa"
|
"github.com/decred/dcrd/dcrec/secp256k1/v4/ecdsa"
|
||||||
|
"github.com/ucan-wg/go-varsig"
|
||||||
|
|
||||||
"github.com/MetaMask/go-did-it/crypto"
|
"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.
|
// The default signing hash is SHA-256.
|
||||||
func (p *PrivateKey) SignToBytes(message []byte, opts ...crypto.SigningOption) ([]byte, error) {
|
func (p *PrivateKey) SignToBytes(message []byte, opts ...crypto.SigningOption) ([]byte, error) {
|
||||||
params := crypto.CollectSigningOptions(opts)
|
params := crypto.CollectSigningOptions(opts)
|
||||||
|
|||||||
@@ -8,6 +8,7 @@ import (
|
|||||||
|
|
||||||
"github.com/decred/dcrd/dcrec/secp256k1/v4"
|
"github.com/decred/dcrd/dcrec/secp256k1/v4"
|
||||||
"github.com/decred/dcrd/dcrec/secp256k1/v4/ecdsa"
|
"github.com/decred/dcrd/dcrec/secp256k1/v4/ecdsa"
|
||||||
|
"github.com/ucan-wg/go-varsig"
|
||||||
|
|
||||||
"github.com/MetaMask/go-did-it/crypto"
|
"github.com/MetaMask/go-did-it/crypto"
|
||||||
helpers "github.com/MetaMask/go-did-it/crypto/internal"
|
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)
|
params := crypto.CollectSigningOptions(opts)
|
||||||
|
|
||||||
|
if !params.VarsigMatch(varsig.AlgorithmECDSA, uint64(varsig.CurveSecp256k1), 0) {
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
|
||||||
hasher := params.HashOrDefault(crypto.SHA256).New()
|
hasher := params.HashOrDefault(crypto.SHA256).New()
|
||||||
hasher.Write(message)
|
hasher.Write(message)
|
||||||
hash := hasher.Sum(nil)
|
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 {
|
func (p *PublicKey) VerifyASN1(message, signature []byte, opts ...crypto.SigningOption) bool {
|
||||||
params := crypto.CollectSigningOptions(opts)
|
params := crypto.CollectSigningOptions(opts)
|
||||||
|
|
||||||
|
if !params.VarsigMatch(varsig.AlgorithmECDSA, uint64(varsig.CurveSecp256k1), 0) {
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
|
||||||
hasher := params.HashOrDefault(crypto.SHA256).New()
|
hasher := params.HashOrDefault(crypto.SHA256).New()
|
||||||
hasher.Write(message)
|
hasher.Write(message)
|
||||||
hash := hasher.Sum(nil)
|
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)
|
// 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==")
|
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())
|
fmt.Println("Signature is valid, verified with method:", method.Type(), method.ID())
|
||||||
} else {
|
} else {
|
||||||
fmt.Println("Signature is invalid")
|
fmt.Println("Signature is invalid")
|
||||||
|
|||||||
9
go.mod
9
go.mod
@@ -1,8 +1,8 @@
|
|||||||
module github.com/MetaMask/go-did-it
|
module github.com/MetaMask/go-did-it
|
||||||
|
|
||||||
go 1.23.0
|
go 1.24.4
|
||||||
|
|
||||||
toolchain go1.23.1
|
toolchain go1.24.5
|
||||||
|
|
||||||
require (
|
require (
|
||||||
github.com/decred/dcrd/dcrec/secp256k1/v4 v4.4.0
|
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-multibase v0.2.0
|
||||||
github.com/multiformats/go-varint v0.0.7
|
github.com/multiformats/go-varint v0.0.7
|
||||||
github.com/stretchr/testify v1.10.0
|
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 (
|
require (
|
||||||
@@ -18,6 +19,6 @@ require (
|
|||||||
github.com/multiformats/go-base32 v0.0.3 // indirect
|
github.com/multiformats/go-base32 v0.0.3 // indirect
|
||||||
github.com/multiformats/go-base36 v0.1.0 // indirect
|
github.com/multiformats/go-base36 v0.1.0 // indirect
|
||||||
github.com/pmezard/go-difflib v1.0.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
|
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/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 h1:Xv5erBjTwe/5IxqUQTdXv5kgmIvbHo3QQyRwhJsOfJA=
|
||||||
github.com/stretchr/testify v1.10.0/go.mod h1:r2ic/lqez/lEtzL7wO/rwa5dbSLXVDPFyf8C91i36aY=
|
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=
|
github.com/ucan-wg/go-varsig v1.0.0 h1:Hrc437Zg+B5Eoajg+qZQZI3Q3ocPyjlnp3/Bz9ZnlWw=
|
||||||
golang.org/x/crypto v0.39.0/go.mod h1:L+Xg3Wf6HoL4Bn4238Z6ft6KfEpN0tJGo53AAPC632U=
|
github.com/ucan-wg/go-varsig v1.0.0/go.mod h1:Sakln6IPooDPH+ClQ0VvR09TuwUhHcfLqcPiPkMZGh0=
|
||||||
golang.org/x/sys v0.33.0 h1:q3i8TbbEz+JRD9ywIRlyRAQbM0qF7hu24q3teo2hbuw=
|
golang.org/x/crypto v0.40.0 h1:r4x+VvoG5Fm+eJcxMaY8CQM7Lb0l1lsmjGBQ6s8BfKM=
|
||||||
golang.org/x/sys v0.33.0/go.mod h1:BJP2sWEmIv4KK5OTEluFJCKSidICx8ciO85XgH3Ak8k=
|
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 h1:yhCVgyC4o1eVCa2tZl7eS0r+SDo693bJlVdllGtEeKM=
|
||||||
gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
|
gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
|
||||||
gopkg.in/yaml.v3 v3.0.1 h1:fxVm/GzAzEWqLHuvctI91KS9hhNmmWOoWu0XTYJS7CA=
|
gopkg.in/yaml.v3 v3.0.1 h1:fxVm/GzAzEWqLHuvctI91KS9hhNmmWOoWu0XTYJS7CA=
|
||||||
|
|||||||
@@ -104,8 +104,11 @@ type VerificationMethod interface {
|
|||||||
type VerificationMethodSignature interface {
|
type VerificationMethodSignature interface {
|
||||||
VerificationMethod
|
VerificationMethod
|
||||||
|
|
||||||
// Verify checks that 'sig' is a valid signature of 'data'.
|
// VerifyBytes checks that 'sig' is a valid "raw bytes" signature of 'data'.
|
||||||
Verify(data []byte, sig []byte) (bool, error)
|
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.
|
// 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"
|
"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.
|
// 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.
|
// 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 {
|
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
|
return true, method
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -8,6 +8,7 @@ import (
|
|||||||
"github.com/mr-tron/base58"
|
"github.com/mr-tron/base58"
|
||||||
|
|
||||||
"github.com/MetaMask/go-did-it"
|
"github.com/MetaMask/go-did-it"
|
||||||
|
"github.com/MetaMask/go-did-it/crypto"
|
||||||
"github.com/MetaMask/go-did-it/crypto/ed25519"
|
"github.com/MetaMask/go-did-it/crypto/ed25519"
|
||||||
)
|
)
|
||||||
|
|
||||||
@@ -97,6 +98,10 @@ func (v VerificationKey2018) JsonLdContext() string {
|
|||||||
return JsonLdContext2018
|
return JsonLdContext2018
|
||||||
}
|
}
|
||||||
|
|
||||||
func (v VerificationKey2018) Verify(data []byte, sig []byte) (bool, error) {
|
func (v VerificationKey2018) VerifyBytes(data []byte, sig []byte, opts ...crypto.SigningOption) (bool, error) {
|
||||||
return v.pubkey.VerifyBytes(data, sig), nil
|
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"
|
"fmt"
|
||||||
|
|
||||||
"github.com/MetaMask/go-did-it"
|
"github.com/MetaMask/go-did-it"
|
||||||
|
"github.com/MetaMask/go-did-it/crypto"
|
||||||
"github.com/MetaMask/go-did-it/crypto/ed25519"
|
"github.com/MetaMask/go-did-it/crypto/ed25519"
|
||||||
)
|
)
|
||||||
|
|
||||||
@@ -91,6 +92,10 @@ func (v VerificationKey2020) JsonLdContext() string {
|
|||||||
return JsonLdContext2020
|
return JsonLdContext2020
|
||||||
}
|
}
|
||||||
|
|
||||||
func (v VerificationKey2020) Verify(data []byte, sig []byte) (bool, error) {
|
func (v VerificationKey2020) VerifyBytes(data []byte, sig []byte, opts ...crypto.SigningOption) (bool, error) {
|
||||||
return v.pubkey.VerifyBytes(data, sig), nil
|
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
|
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 {
|
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")
|
return false, errors.New("not a signing public key")
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -96,9 +96,16 @@ func (m MultiKey) JsonLdContext() string {
|
|||||||
return JsonLdContext
|
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 {
|
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")
|
return false, errors.New("not a signing public key")
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -101,8 +101,12 @@ func (m Key2021) JsonLdContext() string {
|
|||||||
return JsonLdContext2021
|
return JsonLdContext2021
|
||||||
}
|
}
|
||||||
|
|
||||||
func (m Key2021) Verify(data []byte, sig []byte) (bool, error) {
|
func (m Key2021) VerifyBytes(data []byte, sig []byte, opts ...crypto.SigningOption) (bool, error) {
|
||||||
return m.pubkey.VerifyBytes(data, sig), nil
|
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 {
|
func (m Key2021) PrivateKeyIsCompatible(local crypto.PrivateKeyKeyExchange) bool {
|
||||||
|
|||||||
@@ -101,8 +101,12 @@ func (vm VerificationKey2019) JsonLdContext() string {
|
|||||||
return JsonLdContext
|
return JsonLdContext
|
||||||
}
|
}
|
||||||
|
|
||||||
func (vm VerificationKey2019) Verify(data []byte, sig []byte) (bool, error) {
|
func (vm VerificationKey2019) VerifyBytes(data []byte, sig []byte, opts ...crypto.SigningOption) (bool, error) {
|
||||||
return vm.pubkey.VerifyBytes(data, sig), nil
|
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 {
|
func (vm VerificationKey2019) PrivateKeyIsCompatible(local crypto.PrivateKeyKeyExchange) bool {
|
||||||
|
|||||||
@@ -32,7 +32,7 @@ func ExampleGenerateKeyPair() {
|
|||||||
// Resolve the DID and verify a signature
|
// Resolve the DID and verify a signature
|
||||||
doc, err := dk.Document()
|
doc, err := dk.Document()
|
||||||
handleErr(err)
|
handleErr(err)
|
||||||
ok, _ := did.TryAllVerify(doc.Authentication(), msg, sig)
|
ok, _ := did.TryAllVerifyBytes(doc.Authentication(), msg, sig)
|
||||||
fmt.Println("Signature verified:", ok)
|
fmt.Println("Signature verified:", ok)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user