From f8b5fa3a327ece51a9aaa3fde68e975ca652b38c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Michael=20Mur=C3=A9?= Date: Mon, 14 Oct 2024 15:16:38 +0200 Subject: [PATCH 01/11] did: simplify public API, add missing required algorithm --- did/crypto.go | 46 +++++++++++++-- did/crypto_test.go | 1 + did/did.go | 137 ++++++++++++++++----------------------------- did/did_test.go | 76 +++++-------------------- 4 files changed, 104 insertions(+), 156 deletions(-) diff --git a/did/crypto.go b/did/crypto.go index 172065d..c79d5ef 100644 --- a/did/crypto.go +++ b/did/crypto.go @@ -1,6 +1,7 @@ package did import ( + "crypto/rand" "errors" crypto "github.com/libp2p/go-libp2p/core/crypto" @@ -9,6 +10,42 @@ import ( "github.com/multiformats/go-varint" ) +// GenerateEd25519 generates an Ed25519 private key and the matching DID. +// This is the RECOMMENDED algorithm. +func GenerateEd25519() (crypto.PrivKey, DID, error) { + priv, pub, err := crypto.GenerateEd25519Key(rand.Reader) + if err != nil { + return nil, Undef, nil + } + did, err := FromPubKey(pub) + return priv, did, err +} + +// GenerateRSA generates a RSA private key and the matching DID. +func GenerateSecp256k1() (crypto.PrivKey, DID, error) { + // NIST Special Publication 800-57 Part 1 Revision 5 + // Section 5.6.1.1 (Table 2) + // Paraphrased: 2048-bit RSA keys are secure until 2030 and 3072-bit keys are recommended for longer-term security. + const keyLength = 3072 + + priv, pub, err := crypto.GenerateRSAKeyPair(keyLength, rand.Reader) + if err != nil { + return nil, Undef, nil + } + did, err := FromPubKey(pub) + return priv, did, err +} + +// GenerateEd25519 generates a Secp256k1 private key and the matching DID. +func GenerateRSA() (crypto.PrivKey, DID, error) { + priv, pub, err := crypto.GenerateSecp256k1Key(rand.Reader) + if err != nil { + return nil, Undef, nil + } + did, err := FromPubKey(pub) + return priv, did, err +} + func FromPrivKey(privKey crypto.PrivKey) (DID, error) { return FromPubKey(privKey.GetPublic()) } @@ -21,20 +58,17 @@ func FromPubKey(pubKey crypto.PubKey) (DID, error) { pb.KeyType_ECDSA: multicodec.Es256, }[pubKey.Type()] if !ok { - return Undef, errors.New("Blah") + return Undef, errors.New("unsupported key type") } - buf := varint.ToUvarint(uint64(code)) - pubBytes, err := pubKey.Raw() if err != nil { return Undef, err } return DID{ - str: string(append(buf, pubBytes...)), - code: uint64(code), - key: true, + code: code, + bytes: string(append(varint.ToUvarint(uint64(code)), pubBytes...)), }, nil } diff --git a/did/crypto_test.go b/did/crypto_test.go index 64723bd..6ee6fcb 100644 --- a/did/crypto_test.go +++ b/did/crypto_test.go @@ -5,6 +5,7 @@ import ( "github.com/libp2p/go-libp2p/core/crypto" "github.com/stretchr/testify/require" + "github.com/ucan-wg/go-ucan/did" ) diff --git a/did/did.go b/did/did.go index 68f7219..9711178 100644 --- a/did/did.go +++ b/did/did.go @@ -10,111 +10,46 @@ import ( varint "github.com/multiformats/go-varint" ) -const Prefix = "did:" -const KeyPrefix = "did:key:" - -const DIDCore = 0x0d1d -const Ed25519 = 0xed -const RSA = uint64(multicodec.RsaPub) - -var MethodOffset = varint.UvarintSize(uint64(DIDCore)) - -// -// [did:key format]: https://w3c-ccg.github.io/did-method-key/ -type DID struct { - key bool - code uint64 - str string -} +const Ed25519 = multicodec.Ed25519Pub // recommended +const P256 = multicodec.P256Pub +const Secp256k1 = multicodec.Secp256k1Pub +const RSA = multicodec.RsaPub // Undef can be used to represent a nil or undefined DID, using DID{} // directly is also acceptable. var Undef = DID{} -func (d DID) Defined() bool { - return d.str != "" +// DID is a Decentralized Identifier of the did:key type, directly holding a cryptographic public key. +// [did:key format]: https://w3c-ccg.github.io/did-method-key/ +type DID struct { + code multicodec.Code + bytes string // as string instead of []byte to allow the == operator } -func (d DID) Bytes() []byte { - if !d.Defined() { - return nil - } - return []byte(d.str) -} +func Parse(str string) (DID, error) { + const keyPrefix = "did:key:" -func (d DID) Code() uint64 { - return d.code -} - -func (d DID) DID() DID { - return d -} - -func (d DID) Key() bool { - return d.key -} - -func (d DID) PubKey() (crypto.PubKey, error) { - if !d.key { - return nil, fmt.Errorf("unsupported did type: %s", d.String()) + if !strings.HasPrefix(str, keyPrefix) { + return Undef, fmt.Errorf("must start with 'did:key'") } - unmarshaler, ok := map[multicodec.Code]crypto.PubKeyUnmarshaller{ - multicodec.Ed25519Pub: crypto.UnmarshalEd25519PublicKey, - multicodec.RsaPub: crypto.UnmarshalRsaPublicKey, - multicodec.Secp256k1Pub: crypto.UnmarshalSecp256k1PublicKey, - multicodec.Es256: crypto.UnmarshalECDSAPublicKey, - }[multicodec.Code(d.code)] - if !ok { - return nil, fmt.Errorf("unsupported multicodec: %d", d.code) + baseCodec, bytes, err := mbase.Decode(str[len(keyPrefix):]) + if err != nil { + return Undef, err } - - return unmarshaler(d.Bytes()[varint.UvarintSize(d.code):]) -} - -// String formats the decentralized identity document (DID) as a string. -func (d DID) String() string { - if d.key { - key, _ := mbase.Encode(mbase.Base58BTC, []byte(d.str)) - return "did:key:" + key + if baseCodec != mbase.Base58BTC { + return Undef, fmt.Errorf("not Base58BTC encoded") } - return "did:" + d.str[MethodOffset:] -} - -func Decode(bytes []byte) (DID, error) { code, _, err := varint.FromUvarint(bytes) if err != nil { return Undef, err } - if code == Ed25519 || code == RSA { - return DID{str: string(bytes), code: code, key: true}, nil - } else if code == DIDCore { - return DID{str: string(bytes)}, nil + switch multicodec.Code(code) { + case Ed25519, P256, Secp256k1, RSA: + return DID{bytes: string(bytes), code: multicodec.Code(code)}, nil + default: + return Undef, fmt.Errorf("unsupported did:key multicodec: 0x%x", code) } - return Undef, fmt.Errorf("unsupported DID encoding: 0x%x", code) -} - -func Parse(str string) (DID, error) { - if !strings.HasPrefix(str, Prefix) { - return Undef, fmt.Errorf("must start with 'did:'") - } - - if strings.HasPrefix(str, KeyPrefix) { - code, bytes, err := mbase.Decode(str[len(KeyPrefix):]) - if err != nil { - return Undef, err - } - if code != mbase.Base58BTC { - return Undef, fmt.Errorf("not Base58BTC encoded") - } - return Decode(bytes) - } - - buf := make([]byte, MethodOffset) - varint.PutUvarint(buf, DIDCore) - suffix, _ := strings.CutPrefix(str, Prefix) - buf = append(buf, suffix...) - return DID{str: string(buf), code: DIDCore}, nil } func MustParse(str string) DID { @@ -124,3 +59,29 @@ func MustParse(str string) DID { } return did } + +// Defined tells if the DID is defined, not equal to Undef. +func (d DID) Defined() bool { + return d.code == 0 || len(d.bytes) > 0 +} + +func (d DID) PubKey() (crypto.PubKey, error) { + unmarshaler, ok := map[multicodec.Code]crypto.PubKeyUnmarshaller{ + Ed25519: crypto.UnmarshalEd25519PublicKey, + P256: crypto.UnmarshalECDSAPublicKey, + Secp256k1: crypto.UnmarshalSecp256k1PublicKey, + RSA: crypto.UnmarshalRsaPublicKey, + }[d.code] + if !ok { + return nil, fmt.Errorf("unsupported multicodec: %d", d.code) + } + + codeSize := varint.UvarintSize(uint64(d.code)) + return unmarshaler([]byte(d.bytes)[codeSize:]) +} + +// String formats the decentralized identity document (DID) as a string. +func (d DID) String() string { + key, _ := mbase.Encode(mbase.Base58BTC, []byte(d.bytes)) + return "did:key:" + key +} diff --git a/did/did_test.go b/did/did_test.go index 6ee0b81..f536c32 100644 --- a/did/did_test.go +++ b/did/did_test.go @@ -9,12 +9,8 @@ import ( func TestParseDIDKey(t *testing.T) { str := "did:key:z6Mkod5Jr3yd5SC7UDueqK4dAAw5xYJYjksy722tA9Boxc4z" d, err := Parse(str) - if err != nil { - t.Fatalf("%v", err) - } - if d.String() != str { - t.Fatalf("expected %v to equal %v", d.String(), str) - } + require.NoError(t, err) + require.Equal(t, str, d.String()) } func TestMustParseDIDKey(t *testing.T) { @@ -29,65 +25,21 @@ func TestMustParseDIDKey(t *testing.T) { }) } -func TestDecodeDIDKey(t *testing.T) { - str := "did:key:z6Mkod5Jr3yd5SC7UDueqK4dAAw5xYJYjksy722tA9Boxc4z" - d0, err := Parse(str) - if err != nil { - t.Fatalf("%v", err) - } - d1, err := Decode(d0.Bytes()) - if err != nil { - t.Fatalf("%v", err) - } - if d1.String() != str { - t.Fatalf("expected %v to equal %v", d1.String(), str) - } -} - -func TestParseDIDWeb(t *testing.T) { - str := "did:web:up.web3.storage" - d, err := Parse(str) - if err != nil { - t.Fatalf("%v", err) - } - if d.String() != str { - t.Fatalf("expected %v to equal %v", d.String(), str) - } -} - -func TestDecodeDIDWeb(t *testing.T) { - str := "did:web:up.web3.storage" - d0, err := Parse(str) - if err != nil { - t.Fatalf("%v", err) - } - d1, err := Decode(d0.Bytes()) - if err != nil { - t.Fatalf("%v", err) - } - if d1.String() != str { - t.Fatalf("expected %v to equal %v", d1.String(), str) - } +func TestRoundTrip(t *testing.T) { + // TODO: round-trip pubkey-->did-->pubkey for all supported types } func TestEquivalence(t *testing.T) { - u0 := DID{} - u1 := Undef - if u0 != u1 { - t.Fatalf("undef DID not equivalent") - } + undef0 := DID{} + undef1 := Undef - d0, err := Parse("did:key:z6Mkod5Jr3yd5SC7UDueqK4dAAw5xYJYjksy722tA9Boxc4z") - if err != nil { - t.Fatalf("%v", err) - } + did0, err := Parse("did:key:z6Mkod5Jr3yd5SC7UDueqK4dAAw5xYJYjksy722tA9Boxc4z") + require.NoError(t, err) + did1, err := Parse("did:key:z6Mkod5Jr3yd5SC7UDueqK4dAAw5xYJYjksy722tA9Boxc4z") + require.NoError(t, err) - d1, err := Parse("did:key:z6Mkod5Jr3yd5SC7UDueqK4dAAw5xYJYjksy722tA9Boxc4z") - if err != nil { - t.Fatalf("%v", err) - } - - if d0 != d1 { - t.Fatalf("two equivalent DID not equivalent") - } + require.True(t, undef0 == undef1) + require.False(t, undef0 == did0) + require.True(t, did0 == did1) + require.False(t, undef1 == did1) } From da1310b78a7d0eda024ae21b2fca16ad09a97293 Mon Sep 17 00:00:00 2001 From: Steve Moyer Date: Thu, 17 Oct 2024 07:42:40 -0400 Subject: [PATCH 02/11] feat(did): strengthens crypto for public key handliing --- did/crypto.go | 118 ++++++++++++++++++++++++++++++++++++++++++--- did/crypto_test.go | 32 ++++++++++++ did/did.go | 20 ++++++-- go.mod | 4 +- 4 files changed, 161 insertions(+), 13 deletions(-) diff --git a/did/crypto.go b/did/crypto.go index c79d5ef..d723f5e 100644 --- a/did/crypto.go +++ b/did/crypto.go @@ -1,9 +1,13 @@ package did import ( + "crypto/ecdsa" + "crypto/elliptic" "crypto/rand" "errors" + "fmt" + "github.com/decred/dcrd/dcrec/secp256k1/v4" crypto "github.com/libp2p/go-libp2p/core/crypto" "github.com/libp2p/go-libp2p/core/crypto/pb" "github.com/multiformats/go-multicodec" @@ -46,21 +50,73 @@ func GenerateRSA() (crypto.PrivKey, DID, error) { return priv, did, err } +// GenerateECDSA generates an ECDSA private key and the matching DID +// for the default P256 curve. +func GenerateECDSA() (crypto.PrivKey, DID, error) { + return GenerateECDSAWithCurve(P256) +} + +// GenerateECDSAWithCurve generates an ECDSA private key and matching +// DID for the user-supplied curve +func GenerateECDSAWithCurve(code multicodec.Code) (crypto.PrivKey, DID, error) { + var curve elliptic.Curve + + switch code { + case P256: + curve = elliptic.P256() + case P384: + curve = elliptic.P384() + case P521: + curve = elliptic.P521() + default: + return nil, Undef, errors.New("unsupported ECDSA curve") + } + + priv, pub, err := crypto.GenerateECDSAKeyPairWithCurve(curve, rand.Reader) + if err != nil { + return nil, Undef, err + } + + _ = priv + _ = pub + + return nil, Undef, nil // TODO + +} + func FromPrivKey(privKey crypto.PrivKey) (DID, error) { return FromPubKey(privKey.GetPublic()) } +// FromPubKey returns a did:key constructed from the provided public key. func FromPubKey(pubKey crypto.PubKey) (DID, error) { - code, ok := map[pb.KeyType]multicodec.Code{ - pb.KeyType_Ed25519: multicodec.Ed25519Pub, - pb.KeyType_RSA: multicodec.RsaPub, - pb.KeyType_Secp256k1: multicodec.Secp256k1Pub, - pb.KeyType_ECDSA: multicodec.Es256, - }[pubKey.Type()] - if !ok { + var code multicodec.Code + + switch pubKey.Type() { + case pb.KeyType_Ed25519: + code = multicodec.Ed25519Pub + case pb.KeyType_RSA: + code = RSA + case pb.KeyType_Secp256k1: + code = Secp256k1 + case pb.KeyType_ECDSA: + var err error + if code, err = codeForCurve(pubKey); err != nil { + return Undef, err + } + default: return Undef, errors.New("unsupported key type") } + if pubKey.Type() == pb.KeyType_ECDSA && code == Secp256k1 { + var err error + + pubKey, err = coerceECDSAToSecp256k1(pubKey) + if err != nil { + return Undef, err + } + } + pubBytes, err := pubKey.Raw() if err != nil { return Undef, err @@ -80,3 +136,51 @@ func ToPubKey(s string) (crypto.PubKey, error) { return id.PubKey() } + +func codeForCurve(pubKey crypto.PubKey) (multicodec.Code, error) { + stdPub, err := crypto.PubKeyToStdKey(pubKey) + if err != nil { + return multicodec.Identity, err + } + + ecdsaPub, ok := stdPub.(*ecdsa.PublicKey) + if !ok { + return multicodec.Identity, errors.New("failed to assert type for code to curve") + } + + switch ecdsaPub.Curve { + case elliptic.P256(): + return P256, nil + case elliptic.P384(): + return P384, nil + case elliptic.P521(): + return P521, nil + case secp256k1.S256(): + return Secp256k1, nil + default: + return multicodec.Identity, fmt.Errorf("unsupported ECDSA curve: %s", ecdsaPub.Curve.Params().Name) + } +} + +func coerceECDSAToSecp256k1(pubKey crypto.PubKey) (crypto.PubKey, error) { + stdPub, err := crypto.PubKeyToStdKey(pubKey) + if err != nil { + return nil, err + } + + ecdsaPub, ok := stdPub.(*ecdsa.PublicKey) + if !ok { + return nil, errors.New("failed to assert type for secp256k1 coersion") + } + + ecdsaPubBytes := append([]byte{0x04}, append(ecdsaPub.X.Bytes(), ecdsaPub.Y.Bytes()...)...) + + secp256k1Pub, err := secp256k1.ParsePubKey(ecdsaPubBytes) + if err != nil { + return nil, err + } + + cryptoPub := crypto.Secp256k1PublicKey(*secp256k1Pub) + + return &cryptoPub, nil +} diff --git a/did/crypto_test.go b/did/crypto_test.go index 6ee6fcb..6395811 100644 --- a/did/crypto_test.go +++ b/did/crypto_test.go @@ -1,9 +1,13 @@ package did_test import ( + "crypto/elliptic" + "crypto/rand" "testing" "github.com/libp2p/go-libp2p/core/crypto" + "github.com/multiformats/go-multicodec" + "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" "github.com/ucan-wg/go-ucan/did" @@ -17,6 +21,34 @@ const ( func TestFromPubKey(t *testing.T) { t.Parallel() + _, ecdsaP256, err := crypto.GenerateECDSAKeyPairWithCurve(elliptic.P256(), rand.Reader) + require.NoError(t, err) + _, ecdsaP384, err := crypto.GenerateECDSAKeyPairWithCurve(elliptic.P384(), rand.Reader) + require.NoError(t, err) + _, ecdsaP521, err := crypto.GenerateECDSAKeyPairWithCurve(elliptic.P521(), rand.Reader) + require.NoError(t, err) + _, secp256k1PubKey1, err := crypto.GenerateSecp256k1Key(rand.Reader) + require.NoError(t, err) + + test := func(pub crypto.PubKey, code multicodec.Code) func(t *testing.T) { + t.Helper() + + return func(t *testing.T) { + t.Parallel() + + id, err := did.FromPubKey(pub) + require.NoError(t, err) + p, err := id.PubKey() + require.NoError(t, err) + assert.Equal(t, pub, p) + } + } + + t.Run("ECDSA with P256 curve", test(ecdsaP256, did.P256)) + t.Run("ECDSA with P384 curve", test(ecdsaP384, did.P384)) + t.Run("ECDSA with P521 curve", test(ecdsaP521, did.P521)) + t.Run("With secp256k1 (secp256k1)", test(secp256k1PubKey1, did.Secp256k1)) + id, err := did.FromPubKey(examplePubKey(t)) require.NoError(t, err) require.Equal(t, exampleDID(t), id) diff --git a/did/did.go b/did/did.go index 9711178..111f210 100644 --- a/did/did.go +++ b/did/did.go @@ -10,10 +10,18 @@ import ( varint "github.com/multiformats/go-varint" ) -const Ed25519 = multicodec.Ed25519Pub // recommended -const P256 = multicodec.P256Pub -const Secp256k1 = multicodec.Secp256k1Pub -const RSA = multicodec.RsaPub +// Signature algorithms from the [did:key specification] +// +// [did:key specification]: https://w3c-ccg.github.io/did-method-key/#signature-method-creation-algorithm +const ( + X25519 = multicodec.X25519Pub + Ed25519 = multicodec.Ed25519Pub // UCAN required/recommended + P256 = multicodec.P256Pub // UCAN required + P384 = multicodec.P384Pub + P521 = multicodec.P521Pub + Secp256k1 = multicodec.Secp256k1Pub // UCAN required + RSA = multicodec.RsaPub +) // Undef can be used to represent a nil or undefined DID, using DID{} // directly is also acceptable. @@ -65,10 +73,14 @@ func (d DID) Defined() bool { return d.code == 0 || len(d.bytes) > 0 } +// PubKey returns the public key encapsulated in the did:key. func (d DID) PubKey() (crypto.PubKey, error) { unmarshaler, ok := map[multicodec.Code]crypto.PubKeyUnmarshaller{ + X25519: crypto.UnmarshalEd25519PublicKey, Ed25519: crypto.UnmarshalEd25519PublicKey, P256: crypto.UnmarshalECDSAPublicKey, + P384: crypto.UnmarshalECDSAPublicKey, + P521: crypto.UnmarshalECDSAPublicKey, Secp256k1: crypto.UnmarshalSecp256k1PublicKey, RSA: crypto.UnmarshalRsaPublicKey, }[d.code] diff --git a/go.mod b/go.mod index 28cd9c6..d5ad0f9 100644 --- a/go.mod +++ b/go.mod @@ -3,9 +3,11 @@ module github.com/ucan-wg/go-ucan go 1.23 require ( + github.com/decred/dcrd/dcrec/secp256k1/v4 v4.3.0 github.com/ipfs/go-cid v0.4.1 github.com/ipld/go-ipld-prime v0.21.0 github.com/libp2p/go-libp2p v0.36.3 + github.com/mr-tron/base58 v1.2.0 github.com/multiformats/go-multibase v0.2.0 github.com/multiformats/go-multicodec v0.9.0 github.com/multiformats/go-multihash v0.2.3 @@ -16,11 +18,9 @@ require ( require ( github.com/davecgh/go-spew v1.1.1 // indirect - github.com/decred/dcrd/dcrec/secp256k1/v4 v4.3.0 // indirect github.com/google/go-cmp v0.5.9 // indirect github.com/klauspost/cpuid/v2 v2.2.8 // indirect github.com/minio/sha256-simd v1.0.1 // indirect - github.com/mr-tron/base58 v1.2.0 // indirect github.com/multiformats/go-base32 v0.1.0 // indirect github.com/multiformats/go-base36 v0.2.0 // indirect github.com/pmezard/go-difflib v1.0.0 // indirect From fb978ee5742a9e637a7be395d23bb27740f30aa6 Mon Sep 17 00:00:00 2001 From: Steve Moyer Date: Thu, 17 Oct 2024 15:18:31 -0400 Subject: [PATCH 03/11] feat(did): strengthen DID crypto --- did/crypto.go | 48 +++++++++++++++++++++++++++++++++++++++---- did/crypto_test.go | 8 +++++++- did/did.go | 51 +++++++++++++++++++++++++++++++++++++++++----- go.mod | 8 ++++++++ go.sum | 21 +++++++++++++++++++ 5 files changed, 126 insertions(+), 10 deletions(-) diff --git a/did/crypto.go b/did/crypto.go index d723f5e..9b11d75 100644 --- a/did/crypto.go +++ b/did/crypto.go @@ -4,6 +4,8 @@ import ( "crypto/ecdsa" "crypto/elliptic" "crypto/rand" + "crypto/rsa" + "crypto/x509" "errors" "fmt" @@ -84,6 +86,8 @@ func GenerateECDSAWithCurve(code multicodec.Code) (crypto.PrivKey, DID, error) { } +// FromPrivKey is a convenience function that returns the DID associated +// with the public key associated with the provided private key. func FromPrivKey(privKey crypto.PrivKey) (DID, error) { return FromPubKey(privKey.GetPublic()) } @@ -117,17 +121,53 @@ func FromPubKey(pubKey crypto.PubKey) (DID, error) { } } - pubBytes, err := pubKey.Raw() - if err != nil { - return Undef, err + var bytes []byte + + switch pubKey.Type() { + case pb.KeyType_ECDSA: + pkix, err := pubKey.Raw() + if err != nil { + return Undef, err + } + + publicKey, err := x509.ParsePKIXPublicKey(pkix) + if err != nil { + return Undef, err + } + + ecdsaPublicKey := publicKey.(*ecdsa.PublicKey) + + bytes = elliptic.MarshalCompressed(ecdsaPublicKey.Curve, ecdsaPublicKey.X, ecdsaPublicKey.Y) + case pb.KeyType_Ed25519, pb.KeyType_Secp256k1: + var err error + + if bytes, err = pubKey.Raw(); err != nil { + return Undef, err + } + case pb.KeyType_RSA: + var err error + + pkix, err := pubKey.Raw() + if err != nil { + return Undef, err + } + + publicKey, err := x509.ParsePKIXPublicKey(pkix) + if err != nil { + return Undef, err + } + + bytes = x509.MarshalPKCS1PublicKey(publicKey.(*rsa.PublicKey)) } return DID{ code: code, - bytes: string(append(varint.ToUvarint(uint64(code)), pubBytes...)), + bytes: string(append(varint.ToUvarint(uint64(code)), bytes...)), }, nil } +// ToPubKey returns the crypto.PubKey encapsulated in the DID formed by +// parsing the provided string. func ToPubKey(s string) (crypto.PubKey, error) { id, err := Parse(s) if err != nil { diff --git a/did/crypto_test.go b/did/crypto_test.go index 6395811..43d0bea 100644 --- a/did/crypto_test.go +++ b/did/crypto_test.go @@ -27,6 +27,10 @@ func TestFromPubKey(t *testing.T) { require.NoError(t, err) _, ecdsaP521, err := crypto.GenerateECDSAKeyPairWithCurve(elliptic.P521(), rand.Reader) require.NoError(t, err) + _, ed25519, err := crypto.GenerateEd25519Key(rand.Reader) + require.NoError(t, err) + _, rsa, err := crypto.GenerateRSAKeyPair(2048, rand.Reader) + require.NoError(t, err) _, secp256k1PubKey1, err := crypto.GenerateSecp256k1Key(rand.Reader) require.NoError(t, err) @@ -47,7 +51,9 @@ func TestFromPubKey(t *testing.T) { t.Run("ECDSA with P256 curve", test(ecdsaP256, did.P256)) t.Run("ECDSA with P384 curve", test(ecdsaP384, did.P384)) t.Run("ECDSA with P521 curve", test(ecdsaP521, did.P521)) - t.Run("With secp256k1 (secp256k1)", test(secp256k1PubKey1, did.Secp256k1)) + t.Run("Ed25519", test(ed25519, did.Ed25519)) + t.Run("RSA", test(rsa, did.RSA)) + t.Run("secp256k1", test(secp256k1PubKey1, did.Secp256k1)) id, err := did.FromPubKey(examplePubKey(t)) require.NoError(t, err) diff --git a/did/did.go b/did/did.go index 111f210..bf92946 100644 --- a/did/did.go +++ b/did/did.go @@ -1,6 +1,9 @@ package did import ( + "crypto/ecdsa" + "crypto/elliptic" + "crypto/x509" "fmt" "strings" @@ -34,6 +37,10 @@ type DID struct { bytes string // as string instead of []byte to allow the == operator } +// Parse returns the DID from the string representation or an error if +// the prefix and method are incorrect, if an unknown encryption algorithm +// is specified or if the method-specific-identifier's bytes don't +// represent a public key for the specified encryption algorithm. func Parse(str string) (DID, error) { const keyPrefix = "did:key:" @@ -60,6 +67,7 @@ func Parse(str string) (DID, error) { } } +// MustParse is like Parse but panics instead of returning an error. func MustParse(str string) DID { did, err := Parse(str) if err != nil { @@ -73,16 +81,16 @@ func (d DID) Defined() bool { return d.code == 0 || len(d.bytes) > 0 } -// PubKey returns the public key encapsulated in the did:key. +// PubKey returns the public key encapsulated by the did:key. func (d DID) PubKey() (crypto.PubKey, error) { unmarshaler, ok := map[multicodec.Code]crypto.PubKeyUnmarshaller{ X25519: crypto.UnmarshalEd25519PublicKey, Ed25519: crypto.UnmarshalEd25519PublicKey, - P256: crypto.UnmarshalECDSAPublicKey, - P384: crypto.UnmarshalECDSAPublicKey, - P521: crypto.UnmarshalECDSAPublicKey, + P256: ecdsaPubKeyUnmarshaler(elliptic.P256()), + P384: ecdsaPubKeyUnmarshaler(elliptic.P384()), + P521: ecdsaPubKeyUnmarshaler(elliptic.P521()), Secp256k1: crypto.UnmarshalSecp256k1PublicKey, - RSA: crypto.UnmarshalRsaPublicKey, + RSA: rsaPubKeyUnmarshaller, }[d.code] if !ok { return nil, fmt.Errorf("unsupported multicodec: %d", d.code) @@ -97,3 +105,36 @@ func (d DID) String() string { key, _ := mbase.Encode(mbase.Base58BTC, []byte(d.bytes)) return "did:key:" + key } + +func ecdsaPubKeyUnmarshaler(curve elliptic.Curve) crypto.PubKeyUnmarshaller { + return func(data []byte) (crypto.PubKey, error) { + x, y := elliptic.UnmarshalCompressed(curve, data) + + ecdsaPublicKey := &ecdsa.PublicKey{ + Curve: curve, + X: x, + Y: y, + } + + pkix, err := x509.MarshalPKIXPublicKey(ecdsaPublicKey) + if err != nil { + return nil, err + } + + return crypto.UnmarshalECDSAPublicKey(pkix) + } +} + +func rsaPubKeyUnmarshaller(data []byte) (crypto.PubKey, error) { + rsaPublicKey, err := x509.ParsePKCS1PublicKey(data) + if err != nil { + return nil, err + } + + pkix, err := x509.MarshalPKIXPublicKey(rsaPublicKey) + if err != nil { + return nil, err + } + + return crypto.UnmarshalRsaPublicKey(pkix) +} diff --git a/go.mod b/go.mod index d5ad0f9..2193ff4 100644 --- a/go.mod +++ b/go.mod @@ -6,6 +6,7 @@ require ( github.com/decred/dcrd/dcrec/secp256k1/v4 v4.3.0 github.com/ipfs/go-cid v0.4.1 github.com/ipld/go-ipld-prime v0.21.0 + github.com/lestrrat-go/jwx/v2 v2.1.1 github.com/libp2p/go-libp2p v0.36.3 github.com/mr-tron/base58 v1.2.0 github.com/multiformats/go-multibase v0.2.0 @@ -18,13 +19,20 @@ require ( require ( github.com/davecgh/go-spew v1.1.1 // indirect + github.com/goccy/go-json v0.10.3 // indirect github.com/google/go-cmp v0.5.9 // indirect github.com/klauspost/cpuid/v2 v2.2.8 // indirect + github.com/lestrrat-go/blackmagic v1.0.2 // indirect + github.com/lestrrat-go/httpcc v1.0.1 // indirect + github.com/lestrrat-go/httprc v1.0.6 // indirect + github.com/lestrrat-go/iter v1.0.2 // indirect + github.com/lestrrat-go/option v1.0.1 // indirect github.com/minio/sha256-simd v1.0.1 // indirect github.com/multiformats/go-base32 v0.1.0 // indirect github.com/multiformats/go-base36 v0.2.0 // indirect github.com/pmezard/go-difflib v1.0.0 // indirect github.com/polydawn/refmt v0.89.0 // indirect + github.com/segmentio/asm v1.2.0 // indirect github.com/spaolacci/murmur3 v1.1.0 // indirect golang.org/x/crypto v0.25.0 // indirect golang.org/x/sys v0.22.0 // indirect diff --git a/go.sum b/go.sum index 1d69a3a..82932d5 100644 --- a/go.sum +++ b/go.sum @@ -1,5 +1,6 @@ github.com/BurntSushi/toml v0.3.1/go.mod h1:xHWCNGjB5oqiDr8zfno3MHue2Ht5sIBksp03qcyfWMU= github.com/cpuguy83/go-md2man/v2 v2.0.0-20190314233015-f79a8a8ca69d/go.mod h1:maD7wRr/U5Z6m/iR4s+kqSMx2CaBsrgA7czyZG/E6dU= +github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c= github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= github.com/decred/dcrd/crypto/blake256 v1.0.1 h1:7PltbUIQB7u/FfZ39+DGa/ShuMyJ5ilcvdfma9wOH6Y= @@ -9,6 +10,8 @@ github.com/decred/dcrd/dcrec/secp256k1/v4 v4.3.0/go.mod h1:v57UDF4pDQJcEfFUCRop3 github.com/frankban/quicktest v1.14.6 h1:7Xjx+VpznH+oBnejlPUj8oUpdxnVs4f8XU8WnHkI4W8= github.com/frankban/quicktest v1.14.6/go.mod h1:4ptaffx2x8+WTWXmUCuVU6aPUX1/Mz7zb5vbUoiM6w0= github.com/go-yaml/yaml v2.1.0+incompatible/go.mod h1:w2MrLa16VYP0jy6N7M5kHaCkaLENm+P+Tv+MfurjSw0= +github.com/goccy/go-json v0.10.3 h1:KZ5WoDbxAIgm2HNbYckL0se1fHD6rz5j4ywS6ebzDqA= +github.com/goccy/go-json v0.10.3/go.mod h1:oq7eo15ShAhp70Anwd5lgX2pLfOS3QCiwU/PULtXL6M= github.com/google/go-cmp v0.5.9 h1:O2Tfq5qg4qc4AmwVlvv0oLiVAGB7enBSJ2x2DqQFi38= github.com/google/go-cmp v0.5.9/go.mod h1:17dUlkBOakJ0+DkrSSNjCkIjxS6bF9zb3elmeNGIjoY= github.com/gopherjs/gopherjs v0.0.0-20181017120253-0766667cb4d1 h1:EGx4pi6eqNxGaHF6qqu48+N2wcFQ5qg5FXgOdqsJ5d8= @@ -25,6 +28,18 @@ github.com/kr/pretty v0.3.1 h1:flRD4NNwYAUpkphVc1HcthR4KEIFJ65n8Mw5qdRn3LE= github.com/kr/pretty v0.3.1/go.mod h1:hoEshYVHaxMs3cyo3Yncou5ZscifuDolrwPKZanG3xk= github.com/kr/text v0.2.0 h1:5Nx0Ya0ZqY2ygV366QzturHI13Jq95ApcVaJBhpS+AY= github.com/kr/text v0.2.0/go.mod h1:eLer722TekiGuMkidMxC/pM04lWEeraHUUmBw8l2grE= +github.com/lestrrat-go/blackmagic v1.0.2 h1:Cg2gVSc9h7sz9NOByczrbUvLopQmXrfFx//N+AkAr5k= +github.com/lestrrat-go/blackmagic v1.0.2/go.mod h1:UrEqBzIR2U6CnzVyUtfM6oZNMt/7O7Vohk2J0OGSAtU= +github.com/lestrrat-go/httpcc v1.0.1 h1:ydWCStUeJLkpYyjLDHihupbn2tYmZ7m22BGkcvZZrIE= +github.com/lestrrat-go/httpcc v1.0.1/go.mod h1:qiltp3Mt56+55GPVCbTdM9MlqhvzyuL6W/NMDA8vA5E= +github.com/lestrrat-go/httprc v1.0.6 h1:qgmgIRhpvBqexMJjA/PmwSvhNk679oqD1RbovdCGW8k= +github.com/lestrrat-go/httprc v1.0.6/go.mod h1:mwwz3JMTPBjHUkkDv/IGJ39aALInZLrhBp0X7KGUZlo= +github.com/lestrrat-go/iter v1.0.2 h1:gMXo1q4c2pHmC3dn8LzRhJfP1ceCbgSiT9lUydIzltI= +github.com/lestrrat-go/iter v1.0.2/go.mod h1:Momfcq3AnRlRjI5b5O8/G5/BvpzrhoFTZcn06fEOPt4= +github.com/lestrrat-go/jwx/v2 v2.1.1 h1:Y2ltVl8J6izLYFs54BVcpXLv5msSW4o8eXwnzZLI32E= +github.com/lestrrat-go/jwx/v2 v2.1.1/go.mod h1:4LvZg7oxu6Q5VJwn7Mk/UwooNRnTHUpXBj2C4j3HNx0= +github.com/lestrrat-go/option v1.0.1 h1:oAzP2fvZGQKWkvHa1/SAcFolBEca1oN+mQ7eooNBEYU= +github.com/lestrrat-go/option v1.0.1/go.mod h1:5ZHFbivi4xwXxhxY9XHDe2FHo6/Z7WWmtT7T5nBBp3I= github.com/libp2p/go-buffer-pool v0.1.0 h1:oK4mSFcQz7cTQIfqbe4MIj9gLW+mnanjyFtc6cdF0Y8= github.com/libp2p/go-buffer-pool v0.1.0/go.mod h1:N+vh8gMqimBzdKkSMVuydVDq+UV5QTWy5HSiZacSbPg= github.com/libp2p/go-libp2p v0.36.3 h1:NHz30+G7D8Y8YmznrVZZla0ofVANrvBl2c+oARfMeDQ= @@ -54,6 +69,8 @@ github.com/polydawn/refmt v0.89.0/go.mod h1:/zvteZs/GwLtCgZ4BL6CBsk9IKIlexP43ObX github.com/rogpeppe/go-internal v1.9.0 h1:73kH8U+JUqXU8lRuOHeVHaa/SZPifC7BkcraZVejAe8= github.com/rogpeppe/go-internal v1.9.0/go.mod h1:WtVeX8xhTBvf0smdhujwtBcq4Qrzq/fJaraNFVN+nFs= github.com/russross/blackfriday/v2 v2.0.1/go.mod h1:+Rmxgy9KzJVeS9/2gXHxylqXiyQDYRxCVz55jmeOWTM= +github.com/segmentio/asm v1.2.0 h1:9BQrFxC+YOHJlTlHGkTrFWf59nbL3XnCoFLTwDCI7ys= +github.com/segmentio/asm v1.2.0/go.mod h1:BqMnlJP91P8d+4ibuonYZw9mfnzI9HfxselHZr5aAcs= github.com/shurcooL/sanitized_anchor_name v1.0.0/go.mod h1:1NzhyTcUVG4SuEtjjoZeVRXNmyL/1OwPU0+IJeTBvfc= github.com/smartystreets/assertions v1.2.0 h1:42S6lae5dvLc7BrLu/0ugRtcFVjoJNMC/N3yZFZkDFs= github.com/smartystreets/assertions v1.2.0/go.mod h1:tcbTF8ujkAEcZ8TElKY+i30BzYlVhC/LOxJk7iOWnoo= @@ -61,6 +78,9 @@ github.com/smartystreets/goconvey v1.7.2 h1:9RBaZCeXEQ3UselpuwUQHltGVXvdwm6cv1hg github.com/smartystreets/goconvey v1.7.2/go.mod h1:Vw0tHAZW6lzCRk3xgdin6fKYcG+G3Pg9vgXWeJpQFMM= github.com/spaolacci/murmur3 v1.1.0 h1:7c1g84S4BPRrfL5Xrdp6fOJ206sU9y293DDHaoy0bLI= github.com/spaolacci/murmur3 v1.1.0/go.mod h1:JwIasOWyU6f++ZhiEuf87xNszmSA2myDM2Kzu9HwQUA= +github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME= +github.com/stretchr/testify v1.6.1/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg= +github.com/stretchr/testify v1.7.1/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg= github.com/stretchr/testify v1.9.0 h1:HtqpIVDClZ4nwg75+f6Lvsy/wHu+3BoSGCbBAcpTsTg= github.com/stretchr/testify v1.9.0/go.mod h1:r2ic/lqez/lEtzL7wO/rwa5dbSLXVDPFyf8C91i36aY= github.com/urfave/cli v1.22.10/go.mod h1:Gos4lmkARVdJ6EkW0WaNv/tZAAMe9V7XWyB60NtXRu0= @@ -86,6 +106,7 @@ gopkg.in/check.v1 v1.0.0-20190902080502-41f04d3bba15/go.mod h1:Co6ibVJAznAaIkqp8 gopkg.in/yaml.v2 v2.2.2/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= gopkg.in/yaml.v2 v2.4.0 h1:D8xgwECY7CYvx+Y2n4sBz93Jn9JRvxdiyyo8CTfuKaY= gopkg.in/yaml.v2 v2.4.0/go.mod h1:RDklbk79AGWmwhnvt/jBztapEOGDOx6ZbXqjP6csGnQ= +gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= gopkg.in/yaml.v3 v3.0.1 h1:fxVm/GzAzEWqLHuvctI91KS9hhNmmWOoWu0XTYJS7CA= gopkg.in/yaml.v3 v3.0.1/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= gotest.tools/v3 v3.5.1 h1:EENdUnS3pdur5nybKYIh2Vfgc8IUNBjxDPSjtiJcOzU= From abda49061d19c4e5eb6d0e288d2024f771c2c5a8 Mon Sep 17 00:00:00 2001 From: Steve Moyer Date: Thu, 17 Oct 2024 15:19:49 -0400 Subject: [PATCH 04/11] test(did): add test vectors from did:key specification --- .github/workflows/gotest.yml | 4 +- did/README.md | 31 +++ did/key_spec_test.go | 243 ++++++++++++++++++++ did/testdata/bls12381.json | 231 +++++++++++++++++++ did/testdata/ed25519-x25519.json | 293 ++++++++++++++++++++++++ did/testdata/nist-curves.json | 371 +++++++++++++++++++++++++++++++ did/testdata/rsa.json | 106 +++++++++ did/testdata/secp256k1.json | 257 +++++++++++++++++++++ did/testdata/x25519.json | 80 +++++++ 9 files changed, 1614 insertions(+), 2 deletions(-) create mode 100644 did/README.md create mode 100644 did/key_spec_test.go create mode 100644 did/testdata/bls12381.json create mode 100644 did/testdata/ed25519-x25519.json create mode 100644 did/testdata/nist-curves.json create mode 100644 did/testdata/rsa.json create mode 100644 did/testdata/secp256k1.json create mode 100644 did/testdata/x25519.json diff --git a/.github/workflows/gotest.yml b/.github/workflows/gotest.yml index 7632e29..cdcce2a 100644 --- a/.github/workflows/gotest.yml +++ b/.github/workflows/gotest.yml @@ -7,7 +7,7 @@ jobs: fail-fast: false matrix: os: [ "ubuntu" ] - go: [ "1.21.x", "1.22.x", "1.23.x", ] + go: [ "1.22.x", "1.23.x", ] env: COVERAGES: "" runs-on: ${{ matrix.os }}-latest @@ -22,6 +22,6 @@ jobs: go version go env - name: Run tests - run: go test -v ./... + run: go test -v ./... -tags jwx_es256k - name: Check formatted run: gofmt -l . \ No newline at end of file diff --git a/did/README.md b/did/README.md new file mode 100644 index 0000000..6a35934 --- /dev/null +++ b/did/README.md @@ -0,0 +1,31 @@ +## did + +### Testing + +The test suite for this package includes test vectors provided by the +authors of the [`did:key` method specification](https://w3c-ccg.github.io/did-method-key/). +Some of these tests provide the public key associated with a `did:key` +as JWKs and an extra (test-only) dependency has been added to unmarshal +the JWK into a Go `struct`. Support for the `secp256k1` encryption +algorithm is experimental (but stable in my experience) and requires the +addition of the following build tag to properly run: + +``` +// go:build jwx_es256k +``` + +WARNING: These tests will not run by default! + +To include these tests from the CLI, execute the following command: + +``` +go test -v ./did -tags jwx_es256k +``` + +It should also be possible to configure your IDE to run these tests. For +instance, in Codium, add the following JSON snippet to your local project +configuration: + +``` +"go.testTags": "jwx_es256k", +``` \ No newline at end of file diff --git a/did/key_spec_test.go b/did/key_spec_test.go new file mode 100644 index 0000000..bcc5098 --- /dev/null +++ b/did/key_spec_test.go @@ -0,0 +1,243 @@ +// go:build jwx_es256k + +package did_test + +import ( + "crypto/ecdsa" + "crypto/ed25519" + "crypto/elliptic" + "crypto/rsa" + "crypto/x509" + "encoding/json" + "errors" + "os" + "path/filepath" + "testing" + + "github.com/decred/dcrd/dcrec/secp256k1/v4" + "github.com/lestrrat-go/jwx/v2/jwk" + "github.com/libp2p/go-libp2p/core/crypto" + "github.com/mr-tron/base58" + "github.com/stretchr/testify/assert" + "github.com/stretchr/testify/require" + "github.com/ucan-wg/go-ucan/did" +) + +// TestDidKeyVectors executes tests read from the [test vector files] provided +// as part of the DID Key method's [specification]. +// +// [test vector files]: https://github.com/w3c-ccg/did-method-key/tree/main/test-vectors +// [specification]: https://w3c-ccg.github.io/did-method-key +func TestDidKeyVectors(t *testing.T) { + t.Parallel() + + for _, f := range []string{ + // TODO: These test vectors are not supported by go-libp2p/core/crypto + // "bls12381.json", + "ed25519-x25519.json", + "nist-curves.json", + "rsa.json", + "secp256k1.json", + // This test vector only contains a DID Document + // "x25519.json", + } { + vs := loadTestVectors(t, f) + + t.Run(f, func(t *testing.T) { + t.Parallel() + + for k, v := range vs { + f := f + + t.Run(k, func(t *testing.T) { + t.Parallel() + + exp := vectorPubKey(t, v) + + id, err := did.FromPubKey(exp) + require.NoError(t, err, f, k) + act, err := id.PubKey() + require.NoError(t, err) + + assert.Equal(t, k, id.String(), f, k) + assert.Equal(t, exp, act) + }) + } + }) + } +} + +func loadTestVectors(t *testing.T, filename string) vectors { + t.Helper() + + data, err := os.ReadFile(filepath.Join("testdata", filename)) + require.NoError(t, err) + + var vs vectors + + require.NoError(t, json.Unmarshal(data, &vs)) + + return vs +} + +func vectorPubKey(t *testing.T, v vector) crypto.PubKey { + t.Helper() + + pubKey, err := v.pubKey() + require.NoError(t, err) + require.NotZero(t, pubKey) + + return pubKey +} + +func vectorType(t *testing.T, v vector) string { + vectorType, err := v.pubKeyType() + require.NoError(t, err) + + return vectorType +} + +type vectors map[string]vector + +// This is pretty gross but the structure allows the repeated verifier, +// PublicKeyJwk and PublicKeyBase58 account for the fact that the test +// files are very inconsistent. +type vector struct { + VerificationKeyPair verifier + VerificationMethod verifier + PublicKeyJwk json.RawMessage + DidDocument json.RawMessage // TODO: if we start producing DID documents, we should test this too +} + +type verifier struct { + ID string + Type string + PublicKeyBase58 string + PublicKeyJwk json.RawMessage +} + +func (v vector) pubKey() (crypto.PubKey, error) { + // If the public key is in base58 + if pubB58 := v.pubKeyBase58(); len(pubB58) > 0 { + pubBytes, err := base58.Decode(pubB58) + if err != nil { + return nil, err + } + + t, err := v.pubKeyType() + if err != nil { + return nil, err + } + + var unmarshaler crypto.PubKeyUnmarshaller + + switch t { + case "Ed25519VerificationKey2018": + unmarshaler = crypto.UnmarshalEd25519PublicKey + case "EcdsaSecp256k1VerificationKey2019": + unmarshaler = crypto.UnmarshalSecp256k1PublicKey + // This is weak as it assumes the P256 curve - that's all the vectors contain (for now) + case "P256Key2021": + unmarshaler = compressedEcdsaPublicKeyUnmarshaler + default: + return nil, errors.New("failed to resolve unmarshaler") + } + + return unmarshaler(pubBytes) + } + + // If the public key is in a JWK + if pubJwk := v.pubKeyJwk(); len(pubJwk) > 0 { + key, err := jwk.ParseKey(pubJwk) + if err != nil { + return nil, err + } + + var a any + + if err := key.Raw(&a); err != nil { + return nil, err + } + + switch a.(type) { + case *ecdsa.PublicKey: + epub := a.(*ecdsa.PublicKey) + + if epub.Curve == secp256k1.S256() { + bytes := append([]byte{0x04}, append(epub.X.Bytes(), epub.Y.Bytes()...)...) + + return crypto.UnmarshalSecp256k1PublicKey(bytes) + } + + asn1, err := x509.MarshalPKIXPublicKey(epub) + if err != nil { + return nil, err + } + + return crypto.UnmarshalECDSAPublicKey(asn1) + case ed25519.PublicKey: + return crypto.UnmarshalEd25519PublicKey(a.(ed25519.PublicKey)) + case *rsa.PublicKey: + asn1, err := x509.MarshalPKIXPublicKey(a.(*rsa.PublicKey)) + if err != nil { + return nil, err + } + + return crypto.UnmarshalRsaPublicKey(asn1) + default: + return nil, errors.New("unsupported key type") + } + } + + // If we don't find a public key at all + return nil, errors.New("vector's public key not found") +} + +func (v vector) pubKeyBase58() string { + if len(v.VerificationKeyPair.PublicKeyBase58) > 0 { + return v.VerificationKeyPair.PublicKeyBase58 + } + + return v.VerificationMethod.PublicKeyBase58 +} + +func (v vector) pubKeyJwk() json.RawMessage { + if len(v.VerificationKeyPair.PublicKeyJwk) > 0 { + return v.VerificationKeyPair.PublicKeyJwk + } + + if len(v.VerificationMethod.PublicKeyJwk) > 0 { + return v.VerificationMethod.PublicKeyJwk + } + + return v.PublicKeyJwk +} + +func (v vector) pubKeyType() (string, error) { + if len(v.VerificationKeyPair.Type) > 0 { + return v.VerificationKeyPair.Type, nil + } + + if len(v.VerificationMethod.Type) > 0 { + return v.VerificationMethod.Type, nil + } + + return "", errors.New("vector's type not found") +} + +func compressedEcdsaPublicKeyUnmarshaler(data []byte) (crypto.PubKey, error) { + x, y := elliptic.UnmarshalCompressed(elliptic.P256(), data) + + ecdsaPublicKey := ecdsa.PublicKey{ + Curve: elliptic.P256(), + X: x, + Y: y, + } + + asn1, err := x509.MarshalPKIXPublicKey(&ecdsaPublicKey) + if err != nil { + return nil, err + } + + return crypto.UnmarshalECDSAPublicKey(asn1) +} diff --git a/did/testdata/bls12381.json b/did/testdata/bls12381.json new file mode 100644 index 0000000..1731da6 --- /dev/null +++ b/did/testdata/bls12381.json @@ -0,0 +1,231 @@ +{ + "did:key:zUC7K4ndUaGZgV7Cp2yJy6JtMoUHY6u7tkcSYUvPrEidqBmLCTLmi6d5WvwnUqejscAkERJ3bfjEiSYtdPkRSE8kSa11hFBr4sTgnbZ95SJj19PN2jdvJjyzpSZgxkyyxNnBNnY": { + "verificationKeyPair": { + "id": "#zUC7K4ndUaGZgV7Cp2yJy6JtMoUHY6u7tkcSYUvPrEidqBmLCTLmi6d5WvwnUqejscAkERJ3bfjEiSYtdPkRSE8kSa11hFBr4sTgnbZ95SJj19PN2jdvJjyzpSZgxkyyxNnBNnY", + "type": "Bls12381G2Key2020", + "controller": "did:key:zUC7K4ndUaGZgV7Cp2yJy6JtMoUHY6u7tkcSYUvPrEidqBmLCTLmi6d5WvwnUqejscAkERJ3bfjEiSYtdPkRSE8kSa11hFBr4sTgnbZ95SJj19PN2jdvJjyzpSZgxkyyxNnBNnY", + "publicKeyBase58": "25EEkQtcLKsEzQ6JTo9cg4W7NHpaurn4Wg6LaNPFq6JQXnrP91SDviUz7KrJVMJd76CtAZFsRLYzvgX2JGxo2ccUHtuHk7ELCWwrkBDfrXCFVfqJKDootee9iVaF6NpdJtBE", + "privateKeyBase58": "8TXrPTbhefHvcz2vkGsDLBZT2UMeemveLKbdh5JZCvvn" + }, + "didDocument": { + "@context": [ + "https://www.w3.org/ns/did/v1", + "https://w3id.org/security/suites/bls12381-2020/v1" + ], + "id": "did:key:zUC7K4ndUaGZgV7Cp2yJy6JtMoUHY6u7tkcSYUvPrEidqBmLCTLmi6d5WvwnUqejscAkERJ3bfjEiSYtdPkRSE8kSa11hFBr4sTgnbZ95SJj19PN2jdvJjyzpSZgxkyyxNnBNnY", + "verificationMethod": [ + { + "id": "did:key:zUC7K4ndUaGZgV7Cp2yJy6JtMoUHY6u7tkcSYUvPrEidqBmLCTLmi6d5WvwnUqejscAkERJ3bfjEiSYtdPkRSE8kSa11hFBr4sTgnbZ95SJj19PN2jdvJjyzpSZgxkyyxNnBNnY#zUC7K4ndUaGZgV7Cp2yJy6JtMoUHY6u7tkcSYUvPrEidqBmLCTLmi6d5WvwnUqejscAkERJ3bfjEiSYtdPkRSE8kSa11hFBr4sTgnbZ95SJj19PN2jdvJjyzpSZgxkyyxNnBNnY", + "type": "Bls12381G2Key2020", + "controller": "did:key:zUC7K4ndUaGZgV7Cp2yJy6JtMoUHY6u7tkcSYUvPrEidqBmLCTLmi6d5WvwnUqejscAkERJ3bfjEiSYtdPkRSE8kSa11hFBr4sTgnbZ95SJj19PN2jdvJjyzpSZgxkyyxNnBNnY", + "publicKeyBase58": "25EEkQtcLKsEzQ6JTo9cg4W7NHpaurn4Wg6LaNPFq6JQXnrP91SDviUz7KrJVMJd76CtAZFsRLYzvgX2JGxo2ccUHtuHk7ELCWwrkBDfrXCFVfqJKDootee9iVaF6NpdJtBE" + } + ], + "assertionMethod": [ + "did:key:zUC7K4ndUaGZgV7Cp2yJy6JtMoUHY6u7tkcSYUvPrEidqBmLCTLmi6d5WvwnUqejscAkERJ3bfjEiSYtdPkRSE8kSa11hFBr4sTgnbZ95SJj19PN2jdvJjyzpSZgxkyyxNnBNnY#zUC7K4ndUaGZgV7Cp2yJy6JtMoUHY6u7tkcSYUvPrEidqBmLCTLmi6d5WvwnUqejscAkERJ3bfjEiSYtdPkRSE8kSa11hFBr4sTgnbZ95SJj19PN2jdvJjyzpSZgxkyyxNnBNnY" + ], + "authentication": [ + "did:key:zUC7K4ndUaGZgV7Cp2yJy6JtMoUHY6u7tkcSYUvPrEidqBmLCTLmi6d5WvwnUqejscAkERJ3bfjEiSYtdPkRSE8kSa11hFBr4sTgnbZ95SJj19PN2jdvJjyzpSZgxkyyxNnBNnY#zUC7K4ndUaGZgV7Cp2yJy6JtMoUHY6u7tkcSYUvPrEidqBmLCTLmi6d5WvwnUqejscAkERJ3bfjEiSYtdPkRSE8kSa11hFBr4sTgnbZ95SJj19PN2jdvJjyzpSZgxkyyxNnBNnY" + ], + "capabilityInvocation": [ + "did:key:zUC7K4ndUaGZgV7Cp2yJy6JtMoUHY6u7tkcSYUvPrEidqBmLCTLmi6d5WvwnUqejscAkERJ3bfjEiSYtdPkRSE8kSa11hFBr4sTgnbZ95SJj19PN2jdvJjyzpSZgxkyyxNnBNnY#zUC7K4ndUaGZgV7Cp2yJy6JtMoUHY6u7tkcSYUvPrEidqBmLCTLmi6d5WvwnUqejscAkERJ3bfjEiSYtdPkRSE8kSa11hFBr4sTgnbZ95SJj19PN2jdvJjyzpSZgxkyyxNnBNnY" + ], + "capabilityDelegation": [ + "did:key:zUC7K4ndUaGZgV7Cp2yJy6JtMoUHY6u7tkcSYUvPrEidqBmLCTLmi6d5WvwnUqejscAkERJ3bfjEiSYtdPkRSE8kSa11hFBr4sTgnbZ95SJj19PN2jdvJjyzpSZgxkyyxNnBNnY#zUC7K4ndUaGZgV7Cp2yJy6JtMoUHY6u7tkcSYUvPrEidqBmLCTLmi6d5WvwnUqejscAkERJ3bfjEiSYtdPkRSE8kSa11hFBr4sTgnbZ95SJj19PN2jdvJjyzpSZgxkyyxNnBNnY" + ] + } + }, + "did:key:zUC77uxiMKceQoxciSy1xgk3nvP8c8NZXDnaY1xsXZaU5UmsZdnwStUke8Ca8zAdPX3MQTHEMhDTCgfdGU7UrY4RRdVhqZp8FaAaoaXFEVp2ZAM7oj3P45BuTCfc3t9FEGBAEQY": { + "verificationKeyPair": { + "id": "#zUC77uxiMKceQoxciSy1xgk3nvP8c8NZXDnaY1xsXZaU5UmsZdnwStUke8Ca8zAdPX3MQTHEMhDTCgfdGU7UrY4RRdVhqZp8FaAaoaXFEVp2ZAM7oj3P45BuTCfc3t9FEGBAEQY", + "type": "Bls12381G2Key2020", + "controller": "did:key:zUC77uxiMKceQoxciSy1xgk3nvP8c8NZXDnaY1xsXZaU5UmsZdnwStUke8Ca8zAdPX3MQTHEMhDTCgfdGU7UrY4RRdVhqZp8FaAaoaXFEVp2ZAM7oj3P45BuTCfc3t9FEGBAEQY", + "publicKeyBase58": "t5QqHdxR4C6QJWJAnk3qVd2DMr4MVFEefdP43i7fLbR5A2qJkE5bqgEtyzpNsDViGEsMKHMdpo7fKbPMhGihbfxz3Dv2Hw36XvprLHBA5DDFSphmy91oHQFdahQMei2HjoE", + "privateKeyBase58": "URWBZN9g2ZfKVdAz1L8pvVwEBqCbGBozt4p8Cootb35" + }, + "didDocument": { + "@context": [ + "https://www.w3.org/ns/did/v1", + "https://w3id.org/security/suites/bls12381-2020/v1" + ], + "id": "did:key:zUC77uxiMKceQoxciSy1xgk3nvP8c8NZXDnaY1xsXZaU5UmsZdnwStUke8Ca8zAdPX3MQTHEMhDTCgfdGU7UrY4RRdVhqZp8FaAaoaXFEVp2ZAM7oj3P45BuTCfc3t9FEGBAEQY", + "verificationMethod": [ + { + "id": "did:key:zUC77uxiMKceQoxciSy1xgk3nvP8c8NZXDnaY1xsXZaU5UmsZdnwStUke8Ca8zAdPX3MQTHEMhDTCgfdGU7UrY4RRdVhqZp8FaAaoaXFEVp2ZAM7oj3P45BuTCfc3t9FEGBAEQY#zUC77uxiMKceQoxciSy1xgk3nvP8c8NZXDnaY1xsXZaU5UmsZdnwStUke8Ca8zAdPX3MQTHEMhDTCgfdGU7UrY4RRdVhqZp8FaAaoaXFEVp2ZAM7oj3P45BuTCfc3t9FEGBAEQY", + "type": "Bls12381G2Key2020", + "controller": "did:key:zUC77uxiMKceQoxciSy1xgk3nvP8c8NZXDnaY1xsXZaU5UmsZdnwStUke8Ca8zAdPX3MQTHEMhDTCgfdGU7UrY4RRdVhqZp8FaAaoaXFEVp2ZAM7oj3P45BuTCfc3t9FEGBAEQY", + "publicKeyBase58": "t5QqHdxR4C6QJWJAnk3qVd2DMr4MVFEefdP43i7fLbR5A2qJkE5bqgEtyzpNsDViGEsMKHMdpo7fKbPMhGihbfxz3Dv2Hw36XvprLHBA5DDFSphmy91oHQFdahQMei2HjoE" + } + ], + "assertionMethod": [ + "did:key:zUC77uxiMKceQoxciSy1xgk3nvP8c8NZXDnaY1xsXZaU5UmsZdnwStUke8Ca8zAdPX3MQTHEMhDTCgfdGU7UrY4RRdVhqZp8FaAaoaXFEVp2ZAM7oj3P45BuTCfc3t9FEGBAEQY#zUC77uxiMKceQoxciSy1xgk3nvP8c8NZXDnaY1xsXZaU5UmsZdnwStUke8Ca8zAdPX3MQTHEMhDTCgfdGU7UrY4RRdVhqZp8FaAaoaXFEVp2ZAM7oj3P45BuTCfc3t9FEGBAEQY" + ], + "authentication": [ + "did:key:zUC77uxiMKceQoxciSy1xgk3nvP8c8NZXDnaY1xsXZaU5UmsZdnwStUke8Ca8zAdPX3MQTHEMhDTCgfdGU7UrY4RRdVhqZp8FaAaoaXFEVp2ZAM7oj3P45BuTCfc3t9FEGBAEQY#zUC77uxiMKceQoxciSy1xgk3nvP8c8NZXDnaY1xsXZaU5UmsZdnwStUke8Ca8zAdPX3MQTHEMhDTCgfdGU7UrY4RRdVhqZp8FaAaoaXFEVp2ZAM7oj3P45BuTCfc3t9FEGBAEQY" + ], + "capabilityInvocation": [ + "did:key:zUC77uxiMKceQoxciSy1xgk3nvP8c8NZXDnaY1xsXZaU5UmsZdnwStUke8Ca8zAdPX3MQTHEMhDTCgfdGU7UrY4RRdVhqZp8FaAaoaXFEVp2ZAM7oj3P45BuTCfc3t9FEGBAEQY#zUC77uxiMKceQoxciSy1xgk3nvP8c8NZXDnaY1xsXZaU5UmsZdnwStUke8Ca8zAdPX3MQTHEMhDTCgfdGU7UrY4RRdVhqZp8FaAaoaXFEVp2ZAM7oj3P45BuTCfc3t9FEGBAEQY" + ], + "capabilityDelegation": [ + "did:key:zUC77uxiMKceQoxciSy1xgk3nvP8c8NZXDnaY1xsXZaU5UmsZdnwStUke8Ca8zAdPX3MQTHEMhDTCgfdGU7UrY4RRdVhqZp8FaAaoaXFEVp2ZAM7oj3P45BuTCfc3t9FEGBAEQY#zUC77uxiMKceQoxciSy1xgk3nvP8c8NZXDnaY1xsXZaU5UmsZdnwStUke8Ca8zAdPX3MQTHEMhDTCgfdGU7UrY4RRdVhqZp8FaAaoaXFEVp2ZAM7oj3P45BuTCfc3t9FEGBAEQY" + ] + } + }, + "did:key:zUC7KKoJk5ttwuuc8pmQDiUmtckEPTwcaFVZe4DSFV7fURuoRnD17D3xkBK3A9tZqdADkTTMKSwNkhjo9Hs6HfgNUXo48TNRaxU6XPLSPdRgMc15jCD5DfN34ixjoVemY62JxnW": { + "verificationKeyPair": { + "id": "#zUC7KKoJk5ttwuuc8pmQDiUmtckEPTwcaFVZe4DSFV7fURuoRnD17D3xkBK3A9tZqdADkTTMKSwNkhjo9Hs6HfgNUXo48TNRaxU6XPLSPdRgMc15jCD5DfN34ixjoVemY62JxnW", + "type": "Bls12381G2Key2020", + "controller": "did:key:zUC7KKoJk5ttwuuc8pmQDiUmtckEPTwcaFVZe4DSFV7fURuoRnD17D3xkBK3A9tZqdADkTTMKSwNkhjo9Hs6HfgNUXo48TNRaxU6XPLSPdRgMc15jCD5DfN34ixjoVemY62JxnW", + "publicKeyBase58": "25VFRgQEfbJ3Pit6Z3mnZbKPK9BdQYGwdmfdcmderjYZ12BFNQYeowjMN1AYKKKcacF3UH35ZNpBqCR8y8QLeeaGLL7UKdKLcFje3VQnosesDNHsU8jBvtvYmLJusxXsSUBC", + "privateKeyBase58": "48FTGTBBhezV7Ldk5g392NSxP2hwgEgWiSZQkMoNri7E" + }, + "didDocument": { + "@context": [ + "https://www.w3.org/ns/did/v1", + "https://w3id.org/security/suites/bls12381-2020/v1" + ], + "id": "did:key:zUC7KKoJk5ttwuuc8pmQDiUmtckEPTwcaFVZe4DSFV7fURuoRnD17D3xkBK3A9tZqdADkTTMKSwNkhjo9Hs6HfgNUXo48TNRaxU6XPLSPdRgMc15jCD5DfN34ixjoVemY62JxnW", + "verificationMethod": [ + { + "id": "did:key:zUC7KKoJk5ttwuuc8pmQDiUmtckEPTwcaFVZe4DSFV7fURuoRnD17D3xkBK3A9tZqdADkTTMKSwNkhjo9Hs6HfgNUXo48TNRaxU6XPLSPdRgMc15jCD5DfN34ixjoVemY62JxnW#zUC7KKoJk5ttwuuc8pmQDiUmtckEPTwcaFVZe4DSFV7fURuoRnD17D3xkBK3A9tZqdADkTTMKSwNkhjo9Hs6HfgNUXo48TNRaxU6XPLSPdRgMc15jCD5DfN34ixjoVemY62JxnW", + "type": "Bls12381G2Key2020", + "controller": "did:key:zUC7KKoJk5ttwuuc8pmQDiUmtckEPTwcaFVZe4DSFV7fURuoRnD17D3xkBK3A9tZqdADkTTMKSwNkhjo9Hs6HfgNUXo48TNRaxU6XPLSPdRgMc15jCD5DfN34ixjoVemY62JxnW", + "publicKeyBase58": "25VFRgQEfbJ3Pit6Z3mnZbKPK9BdQYGwdmfdcmderjYZ12BFNQYeowjMN1AYKKKcacF3UH35ZNpBqCR8y8QLeeaGLL7UKdKLcFje3VQnosesDNHsU8jBvtvYmLJusxXsSUBC" + } + ], + "assertionMethod": [ + "did:key:zUC7KKoJk5ttwuuc8pmQDiUmtckEPTwcaFVZe4DSFV7fURuoRnD17D3xkBK3A9tZqdADkTTMKSwNkhjo9Hs6HfgNUXo48TNRaxU6XPLSPdRgMc15jCD5DfN34ixjoVemY62JxnW#zUC7KKoJk5ttwuuc8pmQDiUmtckEPTwcaFVZe4DSFV7fURuoRnD17D3xkBK3A9tZqdADkTTMKSwNkhjo9Hs6HfgNUXo48TNRaxU6XPLSPdRgMc15jCD5DfN34ixjoVemY62JxnW" + ], + "authentication": [ + "did:key:zUC7KKoJk5ttwuuc8pmQDiUmtckEPTwcaFVZe4DSFV7fURuoRnD17D3xkBK3A9tZqdADkTTMKSwNkhjo9Hs6HfgNUXo48TNRaxU6XPLSPdRgMc15jCD5DfN34ixjoVemY62JxnW#zUC7KKoJk5ttwuuc8pmQDiUmtckEPTwcaFVZe4DSFV7fURuoRnD17D3xkBK3A9tZqdADkTTMKSwNkhjo9Hs6HfgNUXo48TNRaxU6XPLSPdRgMc15jCD5DfN34ixjoVemY62JxnW" + ], + "capabilityInvocation": [ + "did:key:zUC7KKoJk5ttwuuc8pmQDiUmtckEPTwcaFVZe4DSFV7fURuoRnD17D3xkBK3A9tZqdADkTTMKSwNkhjo9Hs6HfgNUXo48TNRaxU6XPLSPdRgMc15jCD5DfN34ixjoVemY62JxnW#zUC7KKoJk5ttwuuc8pmQDiUmtckEPTwcaFVZe4DSFV7fURuoRnD17D3xkBK3A9tZqdADkTTMKSwNkhjo9Hs6HfgNUXo48TNRaxU6XPLSPdRgMc15jCD5DfN34ixjoVemY62JxnW" + ], + "capabilityDelegation": [ + "did:key:zUC7KKoJk5ttwuuc8pmQDiUmtckEPTwcaFVZe4DSFV7fURuoRnD17D3xkBK3A9tZqdADkTTMKSwNkhjo9Hs6HfgNUXo48TNRaxU6XPLSPdRgMc15jCD5DfN34ixjoVemY62JxnW#zUC7KKoJk5ttwuuc8pmQDiUmtckEPTwcaFVZe4DSFV7fURuoRnD17D3xkBK3A9tZqdADkTTMKSwNkhjo9Hs6HfgNUXo48TNRaxU6XPLSPdRgMc15jCD5DfN34ixjoVemY62JxnW" + ] + } + }, + "did:key:zUC7FB43ErjeTPiBLZ8wWT3aBTL7QnJ6AAZh9opgV5dKkw291mC23yTnKQ2pTcSgLbdKnVJ1ARn6XrwxWqvFg5dRFzCjwSg1j35nRgs5c2nbqkJ4auPTyPtkJ3xcABRNWaDX6QU": { + "verificationKeyPair": { + "id": "#zUC7FB43ErjeTPiBLZ8wWT3aBTL7QnJ6AAZh9opgV5dKkw291mC23yTnKQ2pTcSgLbdKnVJ1ARn6XrwxWqvFg5dRFzCjwSg1j35nRgs5c2nbqkJ4auPTyPtkJ3xcABRNWaDX6QU", + "type": "Bls12381G2Key2020", + "controller": "did:key:zUC7FB43ErjeTPiBLZ8wWT3aBTL7QnJ6AAZh9opgV5dKkw291mC23yTnKQ2pTcSgLbdKnVJ1ARn6XrwxWqvFg5dRFzCjwSg1j35nRgs5c2nbqkJ4auPTyPtkJ3xcABRNWaDX6QU", + "publicKeyBase58": "21LWABB5R6mqxvcU6LWMMt9yCAVyt8C1mHREs1EAX23fLcAEPMK4dWx59Jd6RpJ5geGt881vH9yPzZyC8WpHhS2g296mumPxJA3Aghp9jMoACE13rtTie8FYdgzgUw24eboA", + "privateKeyBase58": "86rp8w6Q7zgDdKqYxZsdTyhZogzwbcR7wf3VQrhV3xLG" + }, + "didDocument": { + "@context": [ + "https://www.w3.org/ns/did/v1", + "https://w3id.org/security/suites/bls12381-2020/v1" + ], + "id": "did:key:zUC7FB43ErjeTPiBLZ8wWT3aBTL7QnJ6AAZh9opgV5dKkw291mC23yTnKQ2pTcSgLbdKnVJ1ARn6XrwxWqvFg5dRFzCjwSg1j35nRgs5c2nbqkJ4auPTyPtkJ3xcABRNWaDX6QU", + "verificationMethod": [ + { + "id": "did:key:zUC7FB43ErjeTPiBLZ8wWT3aBTL7QnJ6AAZh9opgV5dKkw291mC23yTnKQ2pTcSgLbdKnVJ1ARn6XrwxWqvFg5dRFzCjwSg1j35nRgs5c2nbqkJ4auPTyPtkJ3xcABRNWaDX6QU#zUC7FB43ErjeTPiBLZ8wWT3aBTL7QnJ6AAZh9opgV5dKkw291mC23yTnKQ2pTcSgLbdKnVJ1ARn6XrwxWqvFg5dRFzCjwSg1j35nRgs5c2nbqkJ4auPTyPtkJ3xcABRNWaDX6QU", + "type": "Bls12381G2Key2020", + "controller": "did:key:zUC7FB43ErjeTPiBLZ8wWT3aBTL7QnJ6AAZh9opgV5dKkw291mC23yTnKQ2pTcSgLbdKnVJ1ARn6XrwxWqvFg5dRFzCjwSg1j35nRgs5c2nbqkJ4auPTyPtkJ3xcABRNWaDX6QU", + "publicKeyBase58": "21LWABB5R6mqxvcU6LWMMt9yCAVyt8C1mHREs1EAX23fLcAEPMK4dWx59Jd6RpJ5geGt881vH9yPzZyC8WpHhS2g296mumPxJA3Aghp9jMoACE13rtTie8FYdgzgUw24eboA" + } + ], + "assertionMethod": [ + "did:key:zUC7FB43ErjeTPiBLZ8wWT3aBTL7QnJ6AAZh9opgV5dKkw291mC23yTnKQ2pTcSgLbdKnVJ1ARn6XrwxWqvFg5dRFzCjwSg1j35nRgs5c2nbqkJ4auPTyPtkJ3xcABRNWaDX6QU#zUC7FB43ErjeTPiBLZ8wWT3aBTL7QnJ6AAZh9opgV5dKkw291mC23yTnKQ2pTcSgLbdKnVJ1ARn6XrwxWqvFg5dRFzCjwSg1j35nRgs5c2nbqkJ4auPTyPtkJ3xcABRNWaDX6QU" + ], + "authentication": [ + "did:key:zUC7FB43ErjeTPiBLZ8wWT3aBTL7QnJ6AAZh9opgV5dKkw291mC23yTnKQ2pTcSgLbdKnVJ1ARn6XrwxWqvFg5dRFzCjwSg1j35nRgs5c2nbqkJ4auPTyPtkJ3xcABRNWaDX6QU#zUC7FB43ErjeTPiBLZ8wWT3aBTL7QnJ6AAZh9opgV5dKkw291mC23yTnKQ2pTcSgLbdKnVJ1ARn6XrwxWqvFg5dRFzCjwSg1j35nRgs5c2nbqkJ4auPTyPtkJ3xcABRNWaDX6QU" + ], + "capabilityInvocation": [ + "did:key:zUC7FB43ErjeTPiBLZ8wWT3aBTL7QnJ6AAZh9opgV5dKkw291mC23yTnKQ2pTcSgLbdKnVJ1ARn6XrwxWqvFg5dRFzCjwSg1j35nRgs5c2nbqkJ4auPTyPtkJ3xcABRNWaDX6QU#zUC7FB43ErjeTPiBLZ8wWT3aBTL7QnJ6AAZh9opgV5dKkw291mC23yTnKQ2pTcSgLbdKnVJ1ARn6XrwxWqvFg5dRFzCjwSg1j35nRgs5c2nbqkJ4auPTyPtkJ3xcABRNWaDX6QU" + ], + "capabilityDelegation": [ + "did:key:zUC7FB43ErjeTPiBLZ8wWT3aBTL7QnJ6AAZh9opgV5dKkw291mC23yTnKQ2pTcSgLbdKnVJ1ARn6XrwxWqvFg5dRFzCjwSg1j35nRgs5c2nbqkJ4auPTyPtkJ3xcABRNWaDX6QU#zUC7FB43ErjeTPiBLZ8wWT3aBTL7QnJ6AAZh9opgV5dKkw291mC23yTnKQ2pTcSgLbdKnVJ1ARn6XrwxWqvFg5dRFzCjwSg1j35nRgs5c2nbqkJ4auPTyPtkJ3xcABRNWaDX6QU" + ] + } + }, + "did:key:zUC7FNFB7UinoJ5tqkeEELWLsytHBdHpwQ7wLVFAYRT6vqdr5uC3JPK6BVNNByj4KxvVKXoirT7VuqptSznjRCgvr7Ksuk42zyFw1GJSYNQSKCpjVcrZXoPUbR1P6zHmr97mVdA": { + "verificationKeyPair": { + "id": "#zUC7FNFB7UinoJ5tqkeEELWLsytHBdHpwQ7wLVFAYRT6vqdr5uC3JPK6BVNNByj4KxvVKXoirT7VuqptSznjRCgvr7Ksuk42zyFw1GJSYNQSKCpjVcrZXoPUbR1P6zHmr97mVdA", + "type": "Bls12381G2Key2020", + "controller": "did:key:zUC7FNFB7UinoJ5tqkeEELWLsytHBdHpwQ7wLVFAYRT6vqdr5uC3JPK6BVNNByj4KxvVKXoirT7VuqptSznjRCgvr7Ksuk42zyFw1GJSYNQSKCpjVcrZXoPUbR1P6zHmr97mVdA", + "publicKeyBase58": "21XhJ3o4ZSgDgRoyP4Pp8agXMwLycuRa1U6fM4ZzJBxH3gJEQbiuwP3Qh2zNoofNrBKPqp3FgXxGvW84cFwMD29oA7Q9w3L8Sjcc3e9mZqFgs8iWxSsDNRcbQdoYtGaxu11r", + "privateKeyBase58": "5LjJ3yibKGP4zKbNgqeiQ284g8LJYnbF7ZBve7Ke9qZ5" + }, + "didDocument": { + "@context": [ + "https://www.w3.org/ns/did/v1", + "https://w3id.org/security/suites/bls12381-2020/v1" + ], + "id": "did:key:zUC7FNFB7UinoJ5tqkeEELWLsytHBdHpwQ7wLVFAYRT6vqdr5uC3JPK6BVNNByj4KxvVKXoirT7VuqptSznjRCgvr7Ksuk42zyFw1GJSYNQSKCpjVcrZXoPUbR1P6zHmr97mVdA", + "verificationMethod": [ + { + "id": "did:key:zUC7FNFB7UinoJ5tqkeEELWLsytHBdHpwQ7wLVFAYRT6vqdr5uC3JPK6BVNNByj4KxvVKXoirT7VuqptSznjRCgvr7Ksuk42zyFw1GJSYNQSKCpjVcrZXoPUbR1P6zHmr97mVdA#zUC7FNFB7UinoJ5tqkeEELWLsytHBdHpwQ7wLVFAYRT6vqdr5uC3JPK6BVNNByj4KxvVKXoirT7VuqptSznjRCgvr7Ksuk42zyFw1GJSYNQSKCpjVcrZXoPUbR1P6zHmr97mVdA", + "type": "Bls12381G2Key2020", + "controller": "did:key:zUC7FNFB7UinoJ5tqkeEELWLsytHBdHpwQ7wLVFAYRT6vqdr5uC3JPK6BVNNByj4KxvVKXoirT7VuqptSznjRCgvr7Ksuk42zyFw1GJSYNQSKCpjVcrZXoPUbR1P6zHmr97mVdA", + "publicKeyBase58": "21XhJ3o4ZSgDgRoyP4Pp8agXMwLycuRa1U6fM4ZzJBxH3gJEQbiuwP3Qh2zNoofNrBKPqp3FgXxGvW84cFwMD29oA7Q9w3L8Sjcc3e9mZqFgs8iWxSsDNRcbQdoYtGaxu11r" + } + ], + "assertionMethod": [ + "did:key:zUC7FNFB7UinoJ5tqkeEELWLsytHBdHpwQ7wLVFAYRT6vqdr5uC3JPK6BVNNByj4KxvVKXoirT7VuqptSznjRCgvr7Ksuk42zyFw1GJSYNQSKCpjVcrZXoPUbR1P6zHmr97mVdA#zUC7FNFB7UinoJ5tqkeEELWLsytHBdHpwQ7wLVFAYRT6vqdr5uC3JPK6BVNNByj4KxvVKXoirT7VuqptSznjRCgvr7Ksuk42zyFw1GJSYNQSKCpjVcrZXoPUbR1P6zHmr97mVdA" + ], + "authentication": [ + "did:key:zUC7FNFB7UinoJ5tqkeEELWLsytHBdHpwQ7wLVFAYRT6vqdr5uC3JPK6BVNNByj4KxvVKXoirT7VuqptSznjRCgvr7Ksuk42zyFw1GJSYNQSKCpjVcrZXoPUbR1P6zHmr97mVdA#zUC7FNFB7UinoJ5tqkeEELWLsytHBdHpwQ7wLVFAYRT6vqdr5uC3JPK6BVNNByj4KxvVKXoirT7VuqptSznjRCgvr7Ksuk42zyFw1GJSYNQSKCpjVcrZXoPUbR1P6zHmr97mVdA" + ], + "capabilityInvocation": [ + "did:key:zUC7FNFB7UinoJ5tqkeEELWLsytHBdHpwQ7wLVFAYRT6vqdr5uC3JPK6BVNNByj4KxvVKXoirT7VuqptSznjRCgvr7Ksuk42zyFw1GJSYNQSKCpjVcrZXoPUbR1P6zHmr97mVdA#zUC7FNFB7UinoJ5tqkeEELWLsytHBdHpwQ7wLVFAYRT6vqdr5uC3JPK6BVNNByj4KxvVKXoirT7VuqptSznjRCgvr7Ksuk42zyFw1GJSYNQSKCpjVcrZXoPUbR1P6zHmr97mVdA" + ], + "capabilityDelegation": [ + "did:key:zUC7FNFB7UinoJ5tqkeEELWLsytHBdHpwQ7wLVFAYRT6vqdr5uC3JPK6BVNNByj4KxvVKXoirT7VuqptSznjRCgvr7Ksuk42zyFw1GJSYNQSKCpjVcrZXoPUbR1P6zHmr97mVdA#zUC7FNFB7UinoJ5tqkeEELWLsytHBdHpwQ7wLVFAYRT6vqdr5uC3JPK6BVNNByj4KxvVKXoirT7VuqptSznjRCgvr7Ksuk42zyFw1GJSYNQSKCpjVcrZXoPUbR1P6zHmr97mVdA" + ] + } + }, + "did:key:z5TcCmGLu7HrkT5FTnejDTKcH11LPMQLXMPHTRyzY4KdRvqpPLprH7s1ddWFD38cAkZoiDtofUmJVZyEweUTfwjG5H3znk3ir4tzmuDBUSNbNQ7U6jJqj5bkQLKRaQB1bpFJKGLEq3EBwsfPutL5D7p78kFeLNHznqbf5oGpik7ScaDbGLaTLh1Jtadi6VmPNNd44Cojk": { + "verificationKeyPair": { + "id": "did:key:z5TcCmGLu7HrkT5FTnejDTKcH11LPMQLXMPHTRyzY4KdRvqpPLprH7s1ddWFD38cAkZoiDtofUmJVZyEweUTfwjG5H3znk3ir4tzmuDBUSNbNQ7U6jJqj5bkQLKRaQB1bpFJKGLEq3EBwsfPutL5D7p78kFeLNHznqbf5oGpik7ScaDbGLaTLh1Jtadi6VmPNNd44Cojk#z3tEEysHYz5kkgpfDAByfDVgAuvtSFLHSqoMWmmSZBU1LZtN2sDsAS6RVQSevfxv39kyty", + "type": "JsonWebKey2020", + "controller": "did:key:z5TcCmGLu7HrkT5FTnejDTKcH11LPMQLXMPHTRyzY4KdRvqpPLprH7s1ddWFD38cAkZoiDtofUmJVZyEweUTfwjG5H3znk3ir4tzmuDBUSNbNQ7U6jJqj5bkQLKRaQB1bpFJKGLEq3EBwsfPutL5D7p78kFeLNHznqbf5oGpik7ScaDbGLaTLh1Jtadi6VmPNNd44Cojk", + "publicKeyJwk": { + "kty": "EC", + "crv": "BLS12381_G1", + "x": "im0OQGMTkh4YEhAl16hQwUQTcOaRqIqThqtSwksFK7WaH6Qywypmc3VIDyydmYTe" + }, + "privateKeyJwk": { + "kty": "EC", + "crv": "BLS12381_G1", + "x": "im0OQGMTkh4YEhAl16hQwUQTcOaRqIqThqtSwksFK7WaH6Qywypmc3VIDyydmYTe", + "d": "S7Z1TuL05WHge8od0_mW8b3sRM747caCffsLwS6JZ-c" + } + }, + "didDocument": { + "@context": [ + "https://www.w3.org/ns/did/v1", + "https://w3id.org/security/suites/jws-2020/v1" + ], + "id": "did:key:z5TcCmGLu7HrkT5FTnejDTKcH11LPMQLXMPHTRyzY4KdRvqpPLprH7s1ddWFD38cAkZoiDtofUmJVZyEweUTfwjG5H3znk3ir4tzmuDBUSNbNQ7U6jJqj5bkQLKRaQB1bpFJKGLEq3EBwsfPutL5D7p78kFeLNHznqbf5oGpik7ScaDbGLaTLh1Jtadi6VmPNNd44Cojk", + "verificationMethod": [ + { + "id": "did:key:z5TcCmGLu7HrkT5FTnejDTKcH11LPMQLXMPHTRyzY4KdRvqpPLprH7s1ddWFD38cAkZoiDtofUmJVZyEweUTfwjG5H3znk3ir4tzmuDBUSNbNQ7U6jJqj5bkQLKRaQB1bpFJKGLEq3EBwsfPutL5D7p78kFeLNHznqbf5oGpik7ScaDbGLaTLh1Jtadi6VmPNNd44Cojk#z3tEEysHYz5kkgpfDAByfDVgAuvtSFLHSqoMWmmSZBU1LZtN2sDsAS6RVQSevfxv39kyty", + "type": "JsonWebKey2020", + "controller": "did:key:z5TcCmGLu7HrkT5FTnejDTKcH11LPMQLXMPHTRyzY4KdRvqpPLprH7s1ddWFD38cAkZoiDtofUmJVZyEweUTfwjG5H3znk3ir4tzmuDBUSNbNQ7U6jJqj5bkQLKRaQB1bpFJKGLEq3EBwsfPutL5D7p78kFeLNHznqbf5oGpik7ScaDbGLaTLh1Jtadi6VmPNNd44Cojk", + "publicKeyJwk": { + "kty": "EC", + "crv": "BLS12381_G1", + "x": "im0OQGMTkh4YEhAl16hQwUQTcOaRqIqThqtSwksFK7WaH6Qywypmc3VIDyydmYTe" + } + } + ], + "assertionMethod": [ + "did:key:z5TcCmGLu7HrkT5FTnejDTKcH11LPMQLXMPHTRyzY4KdRvqpPLprH7s1ddWFD38cAkZoiDtofUmJVZyEweUTfwjG5H3znk3ir4tzmuDBUSNbNQ7U6jJqj5bkQLKRaQB1bpFJKGLEq3EBwsfPutL5D7p78kFeLNHznqbf5oGpik7ScaDbGLaTLh1Jtadi6VmPNNd44Cojk#z3tEEysHYz5kkgpfDAByfDVgAuvtSFLHSqoMWmmSZBU1LZtN2sDsAS6RVQSevfxv39kyty" + ], + "authentication": [ + "did:key:z5TcCmGLu7HrkT5FTnejDTKcH11LPMQLXMPHTRyzY4KdRvqpPLprH7s1ddWFD38cAkZoiDtofUmJVZyEweUTfwjG5H3znk3ir4tzmuDBUSNbNQ7U6jJqj5bkQLKRaQB1bpFJKGLEq3EBwsfPutL5D7p78kFeLNHznqbf5oGpik7ScaDbGLaTLh1Jtadi6VmPNNd44Cojk#z3tEEysHYz5kkgpfDAByfDVgAuvtSFLHSqoMWmmSZBU1LZtN2sDsAS6RVQSevfxv39kyty" + ], + "capabilityInvocation": [ + "did:key:z5TcCmGLu7HrkT5FTnejDTKcH11LPMQLXMPHTRyzY4KdRvqpPLprH7s1ddWFD38cAkZoiDtofUmJVZyEweUTfwjG5H3znk3ir4tzmuDBUSNbNQ7U6jJqj5bkQLKRaQB1bpFJKGLEq3EBwsfPutL5D7p78kFeLNHznqbf5oGpik7ScaDbGLaTLh1Jtadi6VmPNNd44Cojk#z3tEEysHYz5kkgpfDAByfDVgAuvtSFLHSqoMWmmSZBU1LZtN2sDsAS6RVQSevfxv39kyty" + ], + "capabilityDelegation": [ + "did:key:z5TcCmGLu7HrkT5FTnejDTKcH11LPMQLXMPHTRyzY4KdRvqpPLprH7s1ddWFD38cAkZoiDtofUmJVZyEweUTfwjG5H3znk3ir4tzmuDBUSNbNQ7U6jJqj5bkQLKRaQB1bpFJKGLEq3EBwsfPutL5D7p78kFeLNHznqbf5oGpik7ScaDbGLaTLh1Jtadi6VmPNNd44Cojk#z3tEEysHYz5kkgpfDAByfDVgAuvtSFLHSqoMWmmSZBU1LZtN2sDsAS6RVQSevfxv39kyty" + ] + } + } +} diff --git a/did/testdata/ed25519-x25519.json b/did/testdata/ed25519-x25519.json new file mode 100644 index 0000000..f403ce1 --- /dev/null +++ b/did/testdata/ed25519-x25519.json @@ -0,0 +1,293 @@ +{ + "did:key:z6MkiTBz1ymuepAQ4HEHYSF1H8quG5GLVVQR3djdX3mDooWp": { + "seed": "0000000000000000000000000000000000000000000000000000000000000000", + "verificationKeyPair": { + "id": "#z6MkiTBz1ymuepAQ4HEHYSF1H8quG5GLVVQR3djdX3mDooWp", + "type": "Ed25519VerificationKey2018", + "controller": "did:key:z6MkiTBz1ymuepAQ4HEHYSF1H8quG5GLVVQR3djdX3mDooWp", + "publicKeyBase58": "4zvwRjXUKGfvwnParsHAS3HuSVzV5cA4McphgmoCtajS" + }, + "keyAgreementKeyPair": { + "id": "#z6LShs9GGnqk85isEBzzshkuVWrVKsRp24GnDuHk8QWkARMW", + "type": "X25519KeyAgreementKey2019", + "controller": "did:key:z6MkiTBz1ymuepAQ4HEHYSF1H8quG5GLVVQR3djdX3mDooWp", + "publicKeyBase58": "7By6kV2t2d188odEM4ExAve1UithKT6dLva4dwsDT3ak", + "privateKeyBase58": "6QN8DfuN9hjgHgPvLXqgzqYE3jRRGRrmJQZkd5tL8paR" + }, + "didDocument": { + "@context": [ + "https://www.w3.org/ns/did/v1", + "https://w3id.org/security/suites/ed25519-2018/v1", + "https://w3id.org/security/suites/x25519-2019/v1" + ], + "id": "did:key:z6MkiTBz1ymuepAQ4HEHYSF1H8quG5GLVVQR3djdX3mDooWp", + "verificationMethod": [ + { + "id": "did:key:z6MkiTBz1ymuepAQ4HEHYSF1H8quG5GLVVQR3djdX3mDooWp#z6MkiTBz1ymuepAQ4HEHYSF1H8quG5GLVVQR3djdX3mDooWp", + "type": "Ed25519VerificationKey2018", + "controller": "did:key:z6MkiTBz1ymuepAQ4HEHYSF1H8quG5GLVVQR3djdX3mDooWp", + "publicKeyBase58": "4zvwRjXUKGfvwnParsHAS3HuSVzV5cA4McphgmoCtajS" + }, + { + "id": "did:key:z6MkiTBz1ymuepAQ4HEHYSF1H8quG5GLVVQR3djdX3mDooWp#z6LShs9GGnqk85isEBzzshkuVWrVKsRp24GnDuHk8QWkARMW", + "type": "X25519KeyAgreementKey2019", + "controller": "did:key:z6MkiTBz1ymuepAQ4HEHYSF1H8quG5GLVVQR3djdX3mDooWp", + "publicKeyBase58": "7By6kV2t2d188odEM4ExAve1UithKT6dLva4dwsDT3ak" + } + ], + "assertionMethod": [ + "did:key:z6MkiTBz1ymuepAQ4HEHYSF1H8quG5GLVVQR3djdX3mDooWp#z6MkiTBz1ymuepAQ4HEHYSF1H8quG5GLVVQR3djdX3mDooWp" + ], + "authentication": [ + "did:key:z6MkiTBz1ymuepAQ4HEHYSF1H8quG5GLVVQR3djdX3mDooWp#z6MkiTBz1ymuepAQ4HEHYSF1H8quG5GLVVQR3djdX3mDooWp" + ], + "capabilityInvocation": [ + "did:key:z6MkiTBz1ymuepAQ4HEHYSF1H8quG5GLVVQR3djdX3mDooWp#z6MkiTBz1ymuepAQ4HEHYSF1H8quG5GLVVQR3djdX3mDooWp" + ], + "capabilityDelegation": [ + "did:key:z6MkiTBz1ymuepAQ4HEHYSF1H8quG5GLVVQR3djdX3mDooWp#z6MkiTBz1ymuepAQ4HEHYSF1H8quG5GLVVQR3djdX3mDooWp" + ], + "keyAgreement": [ + "did:key:z6MkiTBz1ymuepAQ4HEHYSF1H8quG5GLVVQR3djdX3mDooWp#z6LShs9GGnqk85isEBzzshkuVWrVKsRp24GnDuHk8QWkARMW" + ] + } + }, + "did:key:z6MkjchhfUsD6mmvni8mCdXHw216Xrm9bQe2mBH1P5RDjVJG": { + "seed": "0000000000000000000000000000000000000000000000000000000000000001", + "verificationKeyPair": { + "id": "#z6MkjchhfUsD6mmvni8mCdXHw216Xrm9bQe2mBH1P5RDjVJG", + "type": "Ed25519VerificationKey2018", + "controller": "did:key:z6MkjchhfUsD6mmvni8mCdXHw216Xrm9bQe2mBH1P5RDjVJG", + "publicKeyBase58": "6ASf5EcmmEHTgDJ4X4ZT5vT6iHVJBXPg5AN5YoTCpGWt" + }, + "keyAgreementKeyPair": { + "id": "#z6LSrHyXiPBhUbvPUtyUCdf32sniiMGPTAesgHrtEa4FePtr", + "type": "X25519KeyAgreementKey2019", + "controller": "did:key:z6MkjchhfUsD6mmvni8mCdXHw216Xrm9bQe2mBH1P5RDjVJG", + "publicKeyBase58": "FcoNC5NqP9CePWbhfz95iHaEsCjGkZUioK9Ck7Qiw286", + "privateKeyBase58": "HBTcN2MrXNRj9xF9oi8QqYyuEPv3JLLjQKuEgW9oxVKP" + }, + "didDocument": { + "@context": [ + "https://www.w3.org/ns/did/v1", + "https://w3id.org/security/suites/ed25519-2018/v1", + "https://w3id.org/security/suites/x25519-2019/v1" + ], + "id": "did:key:z6MkjchhfUsD6mmvni8mCdXHw216Xrm9bQe2mBH1P5RDjVJG", + "verificationMethod": [ + { + "id": "did:key:z6MkjchhfUsD6mmvni8mCdXHw216Xrm9bQe2mBH1P5RDjVJG#z6MkjchhfUsD6mmvni8mCdXHw216Xrm9bQe2mBH1P5RDjVJG", + "type": "Ed25519VerificationKey2018", + "controller": "did:key:z6MkjchhfUsD6mmvni8mCdXHw216Xrm9bQe2mBH1P5RDjVJG", + "publicKeyBase58": "6ASf5EcmmEHTgDJ4X4ZT5vT6iHVJBXPg5AN5YoTCpGWt" + }, + { + "id": "did:key:z6MkjchhfUsD6mmvni8mCdXHw216Xrm9bQe2mBH1P5RDjVJG#z6LSrHyXiPBhUbvPUtyUCdf32sniiMGPTAesgHrtEa4FePtr", + "type": "X25519KeyAgreementKey2019", + "controller": "did:key:z6MkjchhfUsD6mmvni8mCdXHw216Xrm9bQe2mBH1P5RDjVJG", + "publicKeyBase58": "FcoNC5NqP9CePWbhfz95iHaEsCjGkZUioK9Ck7Qiw286" + } + ], + "assertionMethod": [ + "did:key:z6MkjchhfUsD6mmvni8mCdXHw216Xrm9bQe2mBH1P5RDjVJG#z6MkjchhfUsD6mmvni8mCdXHw216Xrm9bQe2mBH1P5RDjVJG" + ], + "authentication": [ + "did:key:z6MkjchhfUsD6mmvni8mCdXHw216Xrm9bQe2mBH1P5RDjVJG#z6MkjchhfUsD6mmvni8mCdXHw216Xrm9bQe2mBH1P5RDjVJG" + ], + "capabilityInvocation": [ + "did:key:z6MkjchhfUsD6mmvni8mCdXHw216Xrm9bQe2mBH1P5RDjVJG#z6MkjchhfUsD6mmvni8mCdXHw216Xrm9bQe2mBH1P5RDjVJG" + ], + "capabilityDelegation": [ + "did:key:z6MkjchhfUsD6mmvni8mCdXHw216Xrm9bQe2mBH1P5RDjVJG#z6MkjchhfUsD6mmvni8mCdXHw216Xrm9bQe2mBH1P5RDjVJG" + ], + "keyAgreement": [ + "did:key:z6MkjchhfUsD6mmvni8mCdXHw216Xrm9bQe2mBH1P5RDjVJG#z6LSrHyXiPBhUbvPUtyUCdf32sniiMGPTAesgHrtEa4FePtr" + ] + } + }, + "did:key:z6MknGc3ocHs3zdPiJbnaaqDi58NGb4pk1Sp9WxWufuXSdxf": { + "seed": "0000000000000000000000000000000000000000000000000000000000000002", + "verificationKeyPair": { + "id": "#z6MknGc3ocHs3zdPiJbnaaqDi58NGb4pk1Sp9WxWufuXSdxf", + "type": "Ed25519VerificationKey2018", + "controller": "did:key:z6MknGc3ocHs3zdPiJbnaaqDi58NGb4pk1Sp9WxWufuXSdxf", + "publicKeyBase58": "8pM1DN3RiT8vbom5u1sNryaNT1nyL8CTTW3b5PwWXRBH" + }, + "keyAgreementKeyPair": { + "id": "#z6LSkkqoZRC34AEpbkhZCqLDcHQVAxuLpQ7kC8XCXMVUfvjE", + "type": "X25519KeyAgreementKey2019", + "controller": "did:key:z6MknGc3ocHs3zdPiJbnaaqDi58NGb4pk1Sp9WxWufuXSdxf", + "publicKeyBase58": "A5fe37PAxhX5WNKngBpGHhC1KpNE7nwbK9oX2tqwxYxU", + "privateKeyBase58": "ACa4PPJ1LnPNq1iwS33V3Akh7WtnC71WkKFZ9ccM6sX2" + }, + "didDocument": { + "@context": [ + "https://www.w3.org/ns/did/v1", + "https://w3id.org/security/suites/ed25519-2018/v1", + "https://w3id.org/security/suites/x25519-2019/v1" + ], + "id": "did:key:z6MknGc3ocHs3zdPiJbnaaqDi58NGb4pk1Sp9WxWufuXSdxf", + "verificationMethod": [ + { + "id": "did:key:z6MknGc3ocHs3zdPiJbnaaqDi58NGb4pk1Sp9WxWufuXSdxf#z6MknGc3ocHs3zdPiJbnaaqDi58NGb4pk1Sp9WxWufuXSdxf", + "type": "Ed25519VerificationKey2018", + "controller": "did:key:z6MknGc3ocHs3zdPiJbnaaqDi58NGb4pk1Sp9WxWufuXSdxf", + "publicKeyBase58": "8pM1DN3RiT8vbom5u1sNryaNT1nyL8CTTW3b5PwWXRBH" + }, + { + "id": "did:key:z6MknGc3ocHs3zdPiJbnaaqDi58NGb4pk1Sp9WxWufuXSdxf#z6LSkkqoZRC34AEpbkhZCqLDcHQVAxuLpQ7kC8XCXMVUfvjE", + "type": "X25519KeyAgreementKey2019", + "controller": "did:key:z6MknGc3ocHs3zdPiJbnaaqDi58NGb4pk1Sp9WxWufuXSdxf", + "publicKeyBase58": "A5fe37PAxhX5WNKngBpGHhC1KpNE7nwbK9oX2tqwxYxU" + } + ], + "assertionMethod": [ + "did:key:z6MknGc3ocHs3zdPiJbnaaqDi58NGb4pk1Sp9WxWufuXSdxf#z6MknGc3ocHs3zdPiJbnaaqDi58NGb4pk1Sp9WxWufuXSdxf" + ], + "authentication": [ + "did:key:z6MknGc3ocHs3zdPiJbnaaqDi58NGb4pk1Sp9WxWufuXSdxf#z6MknGc3ocHs3zdPiJbnaaqDi58NGb4pk1Sp9WxWufuXSdxf" + ], + "capabilityInvocation": [ + "did:key:z6MknGc3ocHs3zdPiJbnaaqDi58NGb4pk1Sp9WxWufuXSdxf#z6MknGc3ocHs3zdPiJbnaaqDi58NGb4pk1Sp9WxWufuXSdxf" + ], + "capabilityDelegation": [ + "did:key:z6MknGc3ocHs3zdPiJbnaaqDi58NGb4pk1Sp9WxWufuXSdxf#z6MknGc3ocHs3zdPiJbnaaqDi58NGb4pk1Sp9WxWufuXSdxf" + ], + "keyAgreement": [ + "did:key:z6MknGc3ocHs3zdPiJbnaaqDi58NGb4pk1Sp9WxWufuXSdxf#z6LSkkqoZRC34AEpbkhZCqLDcHQVAxuLpQ7kC8XCXMVUfvjE" + ] + } + }, + "did:key:z6MkvqoYXQfDDJRv8L4wKzxYeuKyVZBfi9Qo6Ro8MiLH3kDQ": { + "seed": "0000000000000000000000000000000000000000000000000000000000000003", + "verificationKeyPair": { + "id": "#z6MkvqoYXQfDDJRv8L4wKzxYeuKyVZBfi9Qo6Ro8MiLH3kDQ", + "type": "Ed25519VerificationKey2018", + "controller": "did:key:z6MkvqoYXQfDDJRv8L4wKzxYeuKyVZBfi9Qo6Ro8MiLH3kDQ", + "publicKeyBase58": "HPYVwAQmskwT1qEEeRzhoomyfyupJGASQQtCXSNG8XS2" + }, + "keyAgreementKeyPair": { + "id": "#z6LSiUo6AEDat8Ze4nQzDo67SGuHLLwsUGkxndHGUjsywHow", + "type": "X25519KeyAgreementKey2019", + "controller": "did:key:z6MkvqoYXQfDDJRv8L4wKzxYeuKyVZBfi9Qo6Ro8MiLH3kDQ", + "publicKeyBase58": "7ocvdvQinfqtyQ3Dh9aA7ggoVCQkmfaoueZazHETDv3B", + "privateKeyBase58": "FZrzd1osCnbK6y6MJzMBW1RcVfL524sNKhSbqRwMuwHT" + }, + "didDocument": { + "@context": [ + "https://www.w3.org/ns/did/v1", + "https://w3id.org/security/suites/ed25519-2018/v1", + "https://w3id.org/security/suites/x25519-2019/v1" + ], + "id": "did:key:z6MkvqoYXQfDDJRv8L4wKzxYeuKyVZBfi9Qo6Ro8MiLH3kDQ", + "verificationMethod": [ + { + "id": "did:key:z6MkvqoYXQfDDJRv8L4wKzxYeuKyVZBfi9Qo6Ro8MiLH3kDQ#z6MkvqoYXQfDDJRv8L4wKzxYeuKyVZBfi9Qo6Ro8MiLH3kDQ", + "type": "Ed25519VerificationKey2018", + "controller": "did:key:z6MkvqoYXQfDDJRv8L4wKzxYeuKyVZBfi9Qo6Ro8MiLH3kDQ", + "publicKeyBase58": "HPYVwAQmskwT1qEEeRzhoomyfyupJGASQQtCXSNG8XS2" + }, + { + "id": "did:key:z6MkvqoYXQfDDJRv8L4wKzxYeuKyVZBfi9Qo6Ro8MiLH3kDQ#z6LSiUo6AEDat8Ze4nQzDo67SGuHLLwsUGkxndHGUjsywHow", + "type": "X25519KeyAgreementKey2019", + "controller": "did:key:z6MkvqoYXQfDDJRv8L4wKzxYeuKyVZBfi9Qo6Ro8MiLH3kDQ", + "publicKeyBase58": "7ocvdvQinfqtyQ3Dh9aA7ggoVCQkmfaoueZazHETDv3B" + } + ], + "assertionMethod": [ + "did:key:z6MkvqoYXQfDDJRv8L4wKzxYeuKyVZBfi9Qo6Ro8MiLH3kDQ#z6MkvqoYXQfDDJRv8L4wKzxYeuKyVZBfi9Qo6Ro8MiLH3kDQ" + ], + "authentication": [ + "did:key:z6MkvqoYXQfDDJRv8L4wKzxYeuKyVZBfi9Qo6Ro8MiLH3kDQ#z6MkvqoYXQfDDJRv8L4wKzxYeuKyVZBfi9Qo6Ro8MiLH3kDQ" + ], + "capabilityInvocation": [ + "did:key:z6MkvqoYXQfDDJRv8L4wKzxYeuKyVZBfi9Qo6Ro8MiLH3kDQ#z6MkvqoYXQfDDJRv8L4wKzxYeuKyVZBfi9Qo6Ro8MiLH3kDQ" + ], + "capabilityDelegation": [ + "did:key:z6MkvqoYXQfDDJRv8L4wKzxYeuKyVZBfi9Qo6Ro8MiLH3kDQ#z6MkvqoYXQfDDJRv8L4wKzxYeuKyVZBfi9Qo6Ro8MiLH3kDQ" + ], + "keyAgreement": [ + "did:key:z6MkvqoYXQfDDJRv8L4wKzxYeuKyVZBfi9Qo6Ro8MiLH3kDQ#z6LSiUo6AEDat8Ze4nQzDo67SGuHLLwsUGkxndHGUjsywHow" + ] + } + }, + "did:key:z6MkwYMhwTvsq376YBAcJHy3vyRWzBgn5vKfVqqDCgm7XVKU": { + "seed": "0000000000000000000000000000000000000000000000000000000000000005", + "verificationKeyPair": { + "id": "did:key:z6MkwYMhwTvsq376YBAcJHy3vyRWzBgn5vKfVqqDCgm7XVKU#z6MkwYMhwTvsq376YBAcJHy3vyRWzBgn5vKfVqqDCgm7XVKU", + "type": "JsonWebKey2020", + "controller": "did:key:z6MkwYMhwTvsq376YBAcJHy3vyRWzBgn5vKfVqqDCgm7XVKU", + "publicKeyJwk": { + "kty": "OKP", + "crv": "Ed25519", + "x": "_eT7oDCtAC98L31MMx9J0T-w7HR-zuvsY08f9MvKne8" + }, + "privateKeyJwk": { + "kty": "OKP", + "crv": "Ed25519", + "x": "_eT7oDCtAC98L31MMx9J0T-w7HR-zuvsY08f9MvKne8", + "d": "AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAU" + } + }, + "keyAgreementKeyPair": { + "id": "did:key:z6MkwYMhwTvsq376YBAcJHy3vyRWzBgn5vKfVqqDCgm7XVKU#z6LSmArkPSdTKjEESsExHRrSwUzYUHgDuWDewXc4nocasvFU", + "type": "JsonWebKey2020", + "controller": "did:key:z6MkwYMhwTvsq376YBAcJHy3vyRWzBgn5vKfVqqDCgm7XVKU", + "publicKeyJwk": { + "kty": "OKP", + "crv": "X25519", + "x": "jRIz3oriXDNZmnb35XQb7K1UIlz3ae1ao1YSqLeBXHs" + }, + "privateKeyJwk": { + "kty": "OKP", + "crv": "X25519", + "x": "jRIz3oriXDNZmnb35XQb7K1UIlz3ae1ao1YSqLeBXHs", + "d": "aEAAB3VBFPCQtgF3N__wRiXhMOgeiRGstpPC3gnJ1Eo" + } + }, + "didDocument": { + "@context": [ + "https://www.w3.org/ns/did/v1", + "https://w3id.org/security/suites/jws-2020/v1" + ], + "id": "did:key:z6MkwYMhwTvsq376YBAcJHy3vyRWzBgn5vKfVqqDCgm7XVKU", + "verificationMethod": [ + { + "id": "did:key:z6MkwYMhwTvsq376YBAcJHy3vyRWzBgn5vKfVqqDCgm7XVKU#z6MkwYMhwTvsq376YBAcJHy3vyRWzBgn5vKfVqqDCgm7XVKU", + "type": "JsonWebKey2020", + "controller": "did:key:z6MkwYMhwTvsq376YBAcJHy3vyRWzBgn5vKfVqqDCgm7XVKU", + "publicKeyJwk": { + "kty": "OKP", + "crv": "Ed25519", + "x": "_eT7oDCtAC98L31MMx9J0T-w7HR-zuvsY08f9MvKne8" + } + }, + { + "id": "did:key:z6MkwYMhwTvsq376YBAcJHy3vyRWzBgn5vKfVqqDCgm7XVKU#z6LSmArkPSdTKjEESsExHRrSwUzYUHgDuWDewXc4nocasvFU", + "type": "JsonWebKey2020", + "controller": "did:key:z6MkwYMhwTvsq376YBAcJHy3vyRWzBgn5vKfVqqDCgm7XVKU", + "publicKeyJwk": { + "kty": "OKP", + "crv": "X25519", + "x": "jRIz3oriXDNZmnb35XQb7K1UIlz3ae1ao1YSqLeBXHs" + } + } + ], + "assertionMethod": [ + "did:key:z6MkwYMhwTvsq376YBAcJHy3vyRWzBgn5vKfVqqDCgm7XVKU#z6MkwYMhwTvsq376YBAcJHy3vyRWzBgn5vKfVqqDCgm7XVKU" + ], + "authentication": [ + "did:key:z6MkwYMhwTvsq376YBAcJHy3vyRWzBgn5vKfVqqDCgm7XVKU#z6MkwYMhwTvsq376YBAcJHy3vyRWzBgn5vKfVqqDCgm7XVKU" + ], + "capabilityInvocation": [ + "did:key:z6MkwYMhwTvsq376YBAcJHy3vyRWzBgn5vKfVqqDCgm7XVKU#z6MkwYMhwTvsq376YBAcJHy3vyRWzBgn5vKfVqqDCgm7XVKU" + ], + "capabilityDelegation": [ + "did:key:z6MkwYMhwTvsq376YBAcJHy3vyRWzBgn5vKfVqqDCgm7XVKU#z6MkwYMhwTvsq376YBAcJHy3vyRWzBgn5vKfVqqDCgm7XVKU" + ], + "keyAgreement": [ + "did:key:z6MkwYMhwTvsq376YBAcJHy3vyRWzBgn5vKfVqqDCgm7XVKU#z6LSmArkPSdTKjEESsExHRrSwUzYUHgDuWDewXc4nocasvFU" + ] + } + } +} diff --git a/did/testdata/nist-curves.json b/did/testdata/nist-curves.json new file mode 100644 index 0000000..af3059c --- /dev/null +++ b/did/testdata/nist-curves.json @@ -0,0 +1,371 @@ +{ + "did:key:zDnaerx9CtbPJ1q36T5Ln5wYt3MQYeGRG5ehnPAmxcf5mDZpv": { + "verificationMethod": { + "id": "#zDnaerx9CtbPJ1q36T5Ln5wYt3MQYeGRG5ehnPAmxcf5mDZpv", + "type": "JsonWebKey2020", + "controller": "did:key:zDnaerx9CtbPJ1q36T5Ln5wYt3MQYeGRG5ehnPAmxcf5mDZpv", + "publicKeyJwk": { + "kty": "EC", + "crv": "P-256", + "x": "igrFmi0whuihKnj9R3Om1SoMph72wUGeFaBbzG2vzns", + "y": "efsX5b10x8yjyrj4ny3pGfLcY7Xby1KzgqOdqnsrJIM" + }, + "privateKeyJwk": { + "kty": "EC", + "crv": "P-256", + "x": "igrFmi0whuihKnj9R3Om1SoMph72wUGeFaBbzG2vzns", + "y": "efsX5b10x8yjyrj4ny3pGfLcY7Xby1KzgqOdqnsrJIM", + "d": "gPh-VvVS8MbvKQ9LSVVmfnxnKjHn4Tqj0bmbpehRlpc" + } + }, + "didDocument": { + "@context": [ + "https://www.w3.org/ns/did/v1", + "https://w3id.org/security/suites/jws-2020/v1" + ], + "id": "did:key:zDnaerx9CtbPJ1q36T5Ln5wYt3MQYeGRG5ehnPAmxcf5mDZpv", + "verificationMethod": [ + { + "id": "did:key:zDnaerx9CtbPJ1q36T5Ln5wYt3MQYeGRG5ehnPAmxcf5mDZpv#zDnaerx9CtbPJ1q36T5Ln5wYt3MQYeGRG5ehnPAmxcf5mDZpv", + "type": "JsonWebKey2020", + "controller": "did:key:zDnaerx9CtbPJ1q36T5Ln5wYt3MQYeGRG5ehnPAmxcf5mDZpv", + "publicKeyJwk": { + "kty": "EC", + "crv": "P-256", + "x": "igrFmi0whuihKnj9R3Om1SoMph72wUGeFaBbzG2vzns", + "y": "efsX5b10x8yjyrj4ny3pGfLcY7Xby1KzgqOdqnsrJIM" + } + } + ], + "assertionMethod": [ + "did:key:zDnaerx9CtbPJ1q36T5Ln5wYt3MQYeGRG5ehnPAmxcf5mDZpv#zDnaerx9CtbPJ1q36T5Ln5wYt3MQYeGRG5ehnPAmxcf5mDZpv" + ], + "authentication": [ + "did:key:zDnaerx9CtbPJ1q36T5Ln5wYt3MQYeGRG5ehnPAmxcf5mDZpv#zDnaerx9CtbPJ1q36T5Ln5wYt3MQYeGRG5ehnPAmxcf5mDZpv" + ], + "capabilityInvocation": [ + "did:key:zDnaerx9CtbPJ1q36T5Ln5wYt3MQYeGRG5ehnPAmxcf5mDZpv#zDnaerx9CtbPJ1q36T5Ln5wYt3MQYeGRG5ehnPAmxcf5mDZpv" + ], + "capabilityDelegation": [ + "did:key:zDnaerx9CtbPJ1q36T5Ln5wYt3MQYeGRG5ehnPAmxcf5mDZpv#zDnaerx9CtbPJ1q36T5Ln5wYt3MQYeGRG5ehnPAmxcf5mDZpv" + ], + "keyAgreement": [ + "did:key:zDnaerx9CtbPJ1q36T5Ln5wYt3MQYeGRG5ehnPAmxcf5mDZpv#zDnaerx9CtbPJ1q36T5Ln5wYt3MQYeGRG5ehnPAmxcf5mDZpv" + ] + } + }, + "did:key:zDnaerDaTF5BXEavCrfRZEk316dpbLsfPDZ3WJ5hRTPFU2169": { + "verificationMethod": { + "id": "#zDnaerDaTF5BXEavCrfRZEk316dpbLsfPDZ3WJ5hRTPFU2169", + "type": "JsonWebKey2020", + "controller": "did:key:zDnaerDaTF5BXEavCrfRZEk316dpbLsfPDZ3WJ5hRTPFU2169", + "publicKeyJwk": { + "kty": "EC", + "crv": "P-256", + "x": "fyNYMN0976ci7xqiSdag3buk-ZCwgXU4kz9XNkBlNUI", + "y": "hW2ojTNfH7Jbi8--CJUo3OCbH3y5n91g-IMA9MLMbTU" + }, + "privateKeyJwk": { + "kty": "EC", + "crv": "P-256", + "x": "fyNYMN0976ci7xqiSdag3buk-ZCwgXU4kz9XNkBlNUI", + "y": "hW2ojTNfH7Jbi8--CJUo3OCbH3y5n91g-IMA9MLMbTU", + "d": "YjRs6vNvw4sYrzVVY8ipkEpDAD9PFqw1sUnvPRMA-WI" + } + }, + "didDocument": { + "@context": [ + "https://www.w3.org/ns/did/v1", + "https://w3id.org/security/suites/jws-2020/v1" + ], + "id": "did:key:zDnaerDaTF5BXEavCrfRZEk316dpbLsfPDZ3WJ5hRTPFU2169", + "verificationMethod": [ + { + "id": "did:key:zDnaerDaTF5BXEavCrfRZEk316dpbLsfPDZ3WJ5hRTPFU2169#zDnaerDaTF5BXEavCrfRZEk316dpbLsfPDZ3WJ5hRTPFU2169", + "type": "JsonWebKey2020", + "controller": "did:key:zDnaerDaTF5BXEavCrfRZEk316dpbLsfPDZ3WJ5hRTPFU2169", + "publicKeyJwk": { + "kty": "EC", + "crv": "P-256", + "x": "fyNYMN0976ci7xqiSdag3buk-ZCwgXU4kz9XNkBlNUI", + "y": "hW2ojTNfH7Jbi8--CJUo3OCbH3y5n91g-IMA9MLMbTU" + } + } + ], + "assertionMethod": [ + "did:key:zDnaerDaTF5BXEavCrfRZEk316dpbLsfPDZ3WJ5hRTPFU2169#zDnaerDaTF5BXEavCrfRZEk316dpbLsfPDZ3WJ5hRTPFU2169" + ], + "authentication": [ + "did:key:zDnaerDaTF5BXEavCrfRZEk316dpbLsfPDZ3WJ5hRTPFU2169#zDnaerDaTF5BXEavCrfRZEk316dpbLsfPDZ3WJ5hRTPFU2169" + ], + "capabilityInvocation": [ + "did:key:zDnaerDaTF5BXEavCrfRZEk316dpbLsfPDZ3WJ5hRTPFU2169#zDnaerDaTF5BXEavCrfRZEk316dpbLsfPDZ3WJ5hRTPFU2169" + ], + "capabilityDelegation": [ + "did:key:zDnaerDaTF5BXEavCrfRZEk316dpbLsfPDZ3WJ5hRTPFU2169#zDnaerDaTF5BXEavCrfRZEk316dpbLsfPDZ3WJ5hRTPFU2169" + ], + "keyAgreement": [ + "did:key:zDnaerDaTF5BXEavCrfRZEk316dpbLsfPDZ3WJ5hRTPFU2169#zDnaerDaTF5BXEavCrfRZEk316dpbLsfPDZ3WJ5hRTPFU2169" + ] + } + }, + "did:key:z82Lm1MpAkeJcix9K8TMiLd5NMAhnwkjjCBeWHXyu3U4oT2MVJJKXkcVBgjGhnLBn2Kaau9": { + "verificationMethod": { + "id": "#z82Lm1MpAkeJcix9K8TMiLd5NMAhnwkjjCBeWHXyu3U4oT2MVJJKXkcVBgjGhnLBn2Kaau9", + "type": "JsonWebKey2020", + "controller": "did:key:z82Lm1MpAkeJcix9K8TMiLd5NMAhnwkjjCBeWHXyu3U4oT2MVJJKXkcVBgjGhnLBn2Kaau9", + "publicKeyJwk": { + "kty": "EC", + "crv": "P-384", + "x": "lInTxl8fjLKp_UCrxI0WDklahi-7-_6JbtiHjiRvMvhedhKVdHBfi2HCY8t_QJyc", + "y": "y6N1IC-2mXxHreETBW7K3mBcw0qGr3CWHCs-yl09yCQRLcyfGv7XhqAngHOu51Zv" + }, + "privateKeyJwk": { + "kty": "EC", + "crv": "P-384", + "x": "lInTxl8fjLKp_UCrxI0WDklahi-7-_6JbtiHjiRvMvhedhKVdHBfi2HCY8t_QJyc", + "y": "y6N1IC-2mXxHreETBW7K3mBcw0qGr3CWHCs-yl09yCQRLcyfGv7XhqAngHOu51Zv", + "d": "hAyGZNj9031guBCdpAOaZkO-E5m-LKLYnMIq0-msrp8JLctseaOeNTHmP3uKVWwX" + } + }, + "didDocument": { + "@context": [ + "https://www.w3.org/ns/did/v1", + "https://w3id.org/security/suites/jws-2020/v1" + ], + "id": "did:key:z82Lm1MpAkeJcix9K8TMiLd5NMAhnwkjjCBeWHXyu3U4oT2MVJJKXkcVBgjGhnLBn2Kaau9", + "verificationMethod": [ + { + "id": "did:key:z82Lm1MpAkeJcix9K8TMiLd5NMAhnwkjjCBeWHXyu3U4oT2MVJJKXkcVBgjGhnLBn2Kaau9#z82Lm1MpAkeJcix9K8TMiLd5NMAhnwkjjCBeWHXyu3U4oT2MVJJKXkcVBgjGhnLBn2Kaau9", + "type": "JsonWebKey2020", + "controller": "did:key:z82Lm1MpAkeJcix9K8TMiLd5NMAhnwkjjCBeWHXyu3U4oT2MVJJKXkcVBgjGhnLBn2Kaau9", + "publicKeyJwk": { + "kty": "EC", + "crv": "P-384", + "x": "lInTxl8fjLKp_UCrxI0WDklahi-7-_6JbtiHjiRvMvhedhKVdHBfi2HCY8t_QJyc", + "y": "y6N1IC-2mXxHreETBW7K3mBcw0qGr3CWHCs-yl09yCQRLcyfGv7XhqAngHOu51Zv" + } + } + ], + "assertionMethod": [ + "did:key:z82Lm1MpAkeJcix9K8TMiLd5NMAhnwkjjCBeWHXyu3U4oT2MVJJKXkcVBgjGhnLBn2Kaau9#z82Lm1MpAkeJcix9K8TMiLd5NMAhnwkjjCBeWHXyu3U4oT2MVJJKXkcVBgjGhnLBn2Kaau9" + ], + "authentication": [ + "did:key:z82Lm1MpAkeJcix9K8TMiLd5NMAhnwkjjCBeWHXyu3U4oT2MVJJKXkcVBgjGhnLBn2Kaau9#z82Lm1MpAkeJcix9K8TMiLd5NMAhnwkjjCBeWHXyu3U4oT2MVJJKXkcVBgjGhnLBn2Kaau9" + ], + "capabilityInvocation": [ + "did:key:z82Lm1MpAkeJcix9K8TMiLd5NMAhnwkjjCBeWHXyu3U4oT2MVJJKXkcVBgjGhnLBn2Kaau9#z82Lm1MpAkeJcix9K8TMiLd5NMAhnwkjjCBeWHXyu3U4oT2MVJJKXkcVBgjGhnLBn2Kaau9" + ], + "capabilityDelegation": [ + "did:key:z82Lm1MpAkeJcix9K8TMiLd5NMAhnwkjjCBeWHXyu3U4oT2MVJJKXkcVBgjGhnLBn2Kaau9#z82Lm1MpAkeJcix9K8TMiLd5NMAhnwkjjCBeWHXyu3U4oT2MVJJKXkcVBgjGhnLBn2Kaau9" + ], + "keyAgreement": [ + "did:key:z82Lm1MpAkeJcix9K8TMiLd5NMAhnwkjjCBeWHXyu3U4oT2MVJJKXkcVBgjGhnLBn2Kaau9#z82Lm1MpAkeJcix9K8TMiLd5NMAhnwkjjCBeWHXyu3U4oT2MVJJKXkcVBgjGhnLBn2Kaau9" + ] + } + }, + "did:key:z82LkvCwHNreneWpsgPEbV3gu1C6NFJEBg4srfJ5gdxEsMGRJUz2sG9FE42shbn2xkZJh54": { + "verificationMethod": { + "id": "#z82LkvCwHNreneWpsgPEbV3gu1C6NFJEBg4srfJ5gdxEsMGRJUz2sG9FE42shbn2xkZJh54", + "type": "JsonWebKey2020", + "controller": "did:key:z82LkvCwHNreneWpsgPEbV3gu1C6NFJEBg4srfJ5gdxEsMGRJUz2sG9FE42shbn2xkZJh54", + "publicKeyJwk": { + "kty": "EC", + "crv": "P-384", + "x": "CA-iNoHDg1lL8pvX3d1uvExzVfCz7Rn6tW781Ub8K5MrDf2IMPyL0RTDiaLHC1JT", + "y": "Kpnrn8DkXUD3ge4mFxi-DKr0DYO2KuJdwNBrhzLRtfMa3WFMZBiPKUPfJj8dYNl_" + }, + "privateKeyJwk": { + "kty": "EC", + "crv": "P-384", + "x": "CA-iNoHDg1lL8pvX3d1uvExzVfCz7Rn6tW781Ub8K5MrDf2IMPyL0RTDiaLHC1JT", + "y": "Kpnrn8DkXUD3ge4mFxi-DKr0DYO2KuJdwNBrhzLRtfMa3WFMZBiPKUPfJj8dYNl_", + "d": "Xe1HHeh-UsrJPRNLR_Y06VTrWpZYBXi7a7kiRqCgwnAOlJZPwE-xzL3DIIVMavAL" + } + }, + "didDocument": { + "@context": [ + "https://www.w3.org/ns/did/v1", + "https://w3id.org/security/suites/jws-2020/v1" + ], + "id": "did:key:z82LkvCwHNreneWpsgPEbV3gu1C6NFJEBg4srfJ5gdxEsMGRJUz2sG9FE42shbn2xkZJh54", + "verificationMethod": [ + { + "id": "did:key:z82LkvCwHNreneWpsgPEbV3gu1C6NFJEBg4srfJ5gdxEsMGRJUz2sG9FE42shbn2xkZJh54#z82LkvCwHNreneWpsgPEbV3gu1C6NFJEBg4srfJ5gdxEsMGRJUz2sG9FE42shbn2xkZJh54", + "type": "JsonWebKey2020", + "controller": "did:key:z82LkvCwHNreneWpsgPEbV3gu1C6NFJEBg4srfJ5gdxEsMGRJUz2sG9FE42shbn2xkZJh54", + "publicKeyJwk": { + "kty": "EC", + "crv": "P-384", + "x": "CA-iNoHDg1lL8pvX3d1uvExzVfCz7Rn6tW781Ub8K5MrDf2IMPyL0RTDiaLHC1JT", + "y": "Kpnrn8DkXUD3ge4mFxi-DKr0DYO2KuJdwNBrhzLRtfMa3WFMZBiPKUPfJj8dYNl_" + } + } + ], + "assertionMethod": [ + "did:key:z82LkvCwHNreneWpsgPEbV3gu1C6NFJEBg4srfJ5gdxEsMGRJUz2sG9FE42shbn2xkZJh54#z82LkvCwHNreneWpsgPEbV3gu1C6NFJEBg4srfJ5gdxEsMGRJUz2sG9FE42shbn2xkZJh54" + ], + "authentication": [ + "did:key:z82LkvCwHNreneWpsgPEbV3gu1C6NFJEBg4srfJ5gdxEsMGRJUz2sG9FE42shbn2xkZJh54#z82LkvCwHNreneWpsgPEbV3gu1C6NFJEBg4srfJ5gdxEsMGRJUz2sG9FE42shbn2xkZJh54" + ], + "capabilityInvocation": [ + "did:key:z82LkvCwHNreneWpsgPEbV3gu1C6NFJEBg4srfJ5gdxEsMGRJUz2sG9FE42shbn2xkZJh54#z82LkvCwHNreneWpsgPEbV3gu1C6NFJEBg4srfJ5gdxEsMGRJUz2sG9FE42shbn2xkZJh54" + ], + "capabilityDelegation": [ + "did:key:z82LkvCwHNreneWpsgPEbV3gu1C6NFJEBg4srfJ5gdxEsMGRJUz2sG9FE42shbn2xkZJh54#z82LkvCwHNreneWpsgPEbV3gu1C6NFJEBg4srfJ5gdxEsMGRJUz2sG9FE42shbn2xkZJh54" + ], + "keyAgreement": [ + "did:key:z82LkvCwHNreneWpsgPEbV3gu1C6NFJEBg4srfJ5gdxEsMGRJUz2sG9FE42shbn2xkZJh54#z82LkvCwHNreneWpsgPEbV3gu1C6NFJEBg4srfJ5gdxEsMGRJUz2sG9FE42shbn2xkZJh54" + ] + } + }, + "did:key:z2J9gaYxrKVpdoG9A4gRnmpnRCcxU6agDtFVVBVdn1JedouoZN7SzcyREXXzWgt3gGiwpoHq7K68X4m32D8HgzG8wv3sY5j7": { + "verificationMethod": { + "id": "#z2J9gaYxrKVpdoG9A4gRnmpnRCcxU6agDtFVVBVdn1JedouoZN7SzcyREXXzWgt3gGiwpoHq7K68X4m32D8HgzG8wv3sY5j7", + "type": "JsonWebKey2020", + "controller": "did:key:z2J9gaYxrKVpdoG9A4gRnmpnRCcxU6agDtFVVBVdn1JedouoZN7SzcyREXXzWgt3gGiwpoHq7K68X4m32D8HgzG8wv3sY5j7", + "publicKeyJwk": { + "kty": "EC", + "crv": "P-521", + "x": "ASUHPMyichQ0QbHZ9ofNx_l4y7luncn5feKLo3OpJ2nSbZoC7mffolj5uy7s6KSKXFmnNWxGJ42IOrjZ47qqwqyS", + "y": "AW9ziIC4ZQQVSNmLlp59yYKrjRY0_VqO-GOIYQ9tYpPraBKUloEId6cI_vynCzlZWZtWpgOM3HPhYEgawQ703RjC" + }, + "privateKeyJwk": { + "kty": "EC", + "crv": "P-521", + "x": "ASUHPMyichQ0QbHZ9ofNx_l4y7luncn5feKLo3OpJ2nSbZoC7mffolj5uy7s6KSKXFmnNWxGJ42IOrjZ47qqwqyS", + "y": "AW9ziIC4ZQQVSNmLlp59yYKrjRY0_VqO-GOIYQ9tYpPraBKUloEId6cI_vynCzlZWZtWpgOM3HPhYEgawQ703RjC", + "d": "AHwRaNaGs0jkj_pT6PK2aHep7dJK-yxyoL2bIfVRAceq1baxoiFDo3W14c8E2YZn1k5S53r4a11flhQdaB5guJ_X" + } + }, + "didDocument": { + "@context": [ + "https://www.w3.org/ns/did/v1", + "https://w3id.org/security/suites/jws-2020/v1" + ], + "id": "did:key:z2J9gaYxrKVpdoG9A4gRnmpnRCcxU6agDtFVVBVdn1JedouoZN7SzcyREXXzWgt3gGiwpoHq7K68X4m32D8HgzG8wv3sY5j7", + "verificationMethod": [ + { + "id": "did:key:z2J9gaYxrKVpdoG9A4gRnmpnRCcxU6agDtFVVBVdn1JedouoZN7SzcyREXXzWgt3gGiwpoHq7K68X4m32D8HgzG8wv3sY5j7#z2J9gaYxrKVpdoG9A4gRnmpnRCcxU6agDtFVVBVdn1JedouoZN7SzcyREXXzWgt3gGiwpoHq7K68X4m32D8HgzG8wv3sY5j7", + "type": "JsonWebKey2020", + "controller": "did:key:z2J9gaYxrKVpdoG9A4gRnmpnRCcxU6agDtFVVBVdn1JedouoZN7SzcyREXXzWgt3gGiwpoHq7K68X4m32D8HgzG8wv3sY5j7", + "publicKeyJwk": { + "kty": "EC", + "crv": "P-521", + "x": "ASUHPMyichQ0QbHZ9ofNx_l4y7luncn5feKLo3OpJ2nSbZoC7mffolj5uy7s6KSKXFmnNWxGJ42IOrjZ47qqwqyS", + "y": "AW9ziIC4ZQQVSNmLlp59yYKrjRY0_VqO-GOIYQ9tYpPraBKUloEId6cI_vynCzlZWZtWpgOM3HPhYEgawQ703RjC" + } + } + ], + "assertionMethod": [ + "did:key:z2J9gaYxrKVpdoG9A4gRnmpnRCcxU6agDtFVVBVdn1JedouoZN7SzcyREXXzWgt3gGiwpoHq7K68X4m32D8HgzG8wv3sY5j7#z2J9gaYxrKVpdoG9A4gRnmpnRCcxU6agDtFVVBVdn1JedouoZN7SzcyREXXzWgt3gGiwpoHq7K68X4m32D8HgzG8wv3sY5j7" + ], + "authentication": [ + "did:key:z2J9gaYxrKVpdoG9A4gRnmpnRCcxU6agDtFVVBVdn1JedouoZN7SzcyREXXzWgt3gGiwpoHq7K68X4m32D8HgzG8wv3sY5j7#z2J9gaYxrKVpdoG9A4gRnmpnRCcxU6agDtFVVBVdn1JedouoZN7SzcyREXXzWgt3gGiwpoHq7K68X4m32D8HgzG8wv3sY5j7" + ], + "capabilityInvocation": [ + "did:key:z2J9gaYxrKVpdoG9A4gRnmpnRCcxU6agDtFVVBVdn1JedouoZN7SzcyREXXzWgt3gGiwpoHq7K68X4m32D8HgzG8wv3sY5j7#z2J9gaYxrKVpdoG9A4gRnmpnRCcxU6agDtFVVBVdn1JedouoZN7SzcyREXXzWgt3gGiwpoHq7K68X4m32D8HgzG8wv3sY5j7" + ], + "capabilityDelegation": [ + "did:key:z2J9gaYxrKVpdoG9A4gRnmpnRCcxU6agDtFVVBVdn1JedouoZN7SzcyREXXzWgt3gGiwpoHq7K68X4m32D8HgzG8wv3sY5j7#z2J9gaYxrKVpdoG9A4gRnmpnRCcxU6agDtFVVBVdn1JedouoZN7SzcyREXXzWgt3gGiwpoHq7K68X4m32D8HgzG8wv3sY5j7" + ], + "keyAgreement": [ + "did:key:z2J9gaYxrKVpdoG9A4gRnmpnRCcxU6agDtFVVBVdn1JedouoZN7SzcyREXXzWgt3gGiwpoHq7K68X4m32D8HgzG8wv3sY5j7#z2J9gaYxrKVpdoG9A4gRnmpnRCcxU6agDtFVVBVdn1JedouoZN7SzcyREXXzWgt3gGiwpoHq7K68X4m32D8HgzG8wv3sY5j7" + ] + } + }, + "did:key:z2J9gcGdb2nEyMDmzQYv2QZQcM1vXktvy1Pw4MduSWxGabLZ9XESSWLQgbuPhwnXN7zP7HpTzWqrMTzaY5zWe6hpzJ2jnw4f": { + "verificationMethod": { + "id": "#z2J9gcGdb2nEyMDmzQYv2QZQcM1vXktvy1Pw4MduSWxGabLZ9XESSWLQgbuPhwnXN7zP7HpTzWqrMTzaY5zWe6hpzJ2jnw4f", + "type": "JsonWebKey2020", + "controller": "did:key:z2J9gcGdb2nEyMDmzQYv2QZQcM1vXktvy1Pw4MduSWxGabLZ9XESSWLQgbuPhwnXN7zP7HpTzWqrMTzaY5zWe6hpzJ2jnw4f", + "publicKeyJwk": { + "kty": "EC", + "crv": "P-521", + "x": "AQgyFy6EwH3_u_KXPw8aTXTY7WSVytmbuJeFpq4U6LipxtSmBJe_jjRzms9qubnwm_fGoHMQlvQ1vzS2YLusR2V0", + "y": "Ab06MCcgoG7dM2I-VppdLV1k3lDoeHMvyYqHVfP05Ep2O7Zu0Qwd6IVzfZi9K0KMDud22wdnGUpUtFukZo0EeO15" + }, + "privateKeyJwk": { + "kty": "EC", + "crv": "P-521", + "x": "AQgyFy6EwH3_u_KXPw8aTXTY7WSVytmbuJeFpq4U6LipxtSmBJe_jjRzms9qubnwm_fGoHMQlvQ1vzS2YLusR2V0", + "y": "Ab06MCcgoG7dM2I-VppdLV1k3lDoeHMvyYqHVfP05Ep2O7Zu0Qwd6IVzfZi9K0KMDud22wdnGUpUtFukZo0EeO15", + "d": "AbheZ-AA58LP4BpopCGCLH8ZoMdkdJaVOS6KK2NNmDCisr5_Ifxl-qcunrkOJ0CSauA4LJyNbCWcy28Bo6zgHTXQ" + } + }, + "didDocument": { + "@context": [ + "https://www.w3.org/ns/did/v1", + "https://w3id.org/security/suites/jws-2020/v1" + ], + "id": "did:key:z2J9gcGdb2nEyMDmzQYv2QZQcM1vXktvy1Pw4MduSWxGabLZ9XESSWLQgbuPhwnXN7zP7HpTzWqrMTzaY5zWe6hpzJ2jnw4f", + "verificationMethod": [ + { + "id": "did:key:z2J9gcGdb2nEyMDmzQYv2QZQcM1vXktvy1Pw4MduSWxGabLZ9XESSWLQgbuPhwnXN7zP7HpTzWqrMTzaY5zWe6hpzJ2jnw4f#z2J9gcGdb2nEyMDmzQYv2QZQcM1vXktvy1Pw4MduSWxGabLZ9XESSWLQgbuPhwnXN7zP7HpTzWqrMTzaY5zWe6hpzJ2jnw4f", + "type": "JsonWebKey2020", + "controller": "did:key:z2J9gcGdb2nEyMDmzQYv2QZQcM1vXktvy1Pw4MduSWxGabLZ9XESSWLQgbuPhwnXN7zP7HpTzWqrMTzaY5zWe6hpzJ2jnw4f", + "publicKeyJwk": { + "kty": "EC", + "crv": "P-521", + "x": "AQgyFy6EwH3_u_KXPw8aTXTY7WSVytmbuJeFpq4U6LipxtSmBJe_jjRzms9qubnwm_fGoHMQlvQ1vzS2YLusR2V0", + "y": "Ab06MCcgoG7dM2I-VppdLV1k3lDoeHMvyYqHVfP05Ep2O7Zu0Qwd6IVzfZi9K0KMDud22wdnGUpUtFukZo0EeO15" + } + } + ], + "assertionMethod": [ + "did:key:z2J9gcGdb2nEyMDmzQYv2QZQcM1vXktvy1Pw4MduSWxGabLZ9XESSWLQgbuPhwnXN7zP7HpTzWqrMTzaY5zWe6hpzJ2jnw4f#z2J9gcGdb2nEyMDmzQYv2QZQcM1vXktvy1Pw4MduSWxGabLZ9XESSWLQgbuPhwnXN7zP7HpTzWqrMTzaY5zWe6hpzJ2jnw4f" + ], + "authentication": [ + "did:key:z2J9gcGdb2nEyMDmzQYv2QZQcM1vXktvy1Pw4MduSWxGabLZ9XESSWLQgbuPhwnXN7zP7HpTzWqrMTzaY5zWe6hpzJ2jnw4f#z2J9gcGdb2nEyMDmzQYv2QZQcM1vXktvy1Pw4MduSWxGabLZ9XESSWLQgbuPhwnXN7zP7HpTzWqrMTzaY5zWe6hpzJ2jnw4f" + ], + "capabilityInvocation": [ + "did:key:z2J9gcGdb2nEyMDmzQYv2QZQcM1vXktvy1Pw4MduSWxGabLZ9XESSWLQgbuPhwnXN7zP7HpTzWqrMTzaY5zWe6hpzJ2jnw4f#z2J9gcGdb2nEyMDmzQYv2QZQcM1vXktvy1Pw4MduSWxGabLZ9XESSWLQgbuPhwnXN7zP7HpTzWqrMTzaY5zWe6hpzJ2jnw4f" + ], + "capabilityDelegation": [ + "did:key:z2J9gcGdb2nEyMDmzQYv2QZQcM1vXktvy1Pw4MduSWxGabLZ9XESSWLQgbuPhwnXN7zP7HpTzWqrMTzaY5zWe6hpzJ2jnw4f#z2J9gcGdb2nEyMDmzQYv2QZQcM1vXktvy1Pw4MduSWxGabLZ9XESSWLQgbuPhwnXN7zP7HpTzWqrMTzaY5zWe6hpzJ2jnw4f" + ], + "keyAgreement": [ + "did:key:z2J9gcGdb2nEyMDmzQYv2QZQcM1vXktvy1Pw4MduSWxGabLZ9XESSWLQgbuPhwnXN7zP7HpTzWqrMTzaY5zWe6hpzJ2jnw4f#z2J9gcGdb2nEyMDmzQYv2QZQcM1vXktvy1Pw4MduSWxGabLZ9XESSWLQgbuPhwnXN7zP7HpTzWqrMTzaY5zWe6hpzJ2jnw4f" + ] + } + }, + "did:key:zDnaeTiq1PdzvZXUaMdezchcMJQpBdH2VN4pgrrEhMCCbmwSb": { + "verificationMethod": { + "id": "did:key:zDnaeTiq1PdzvZXUaMdezchcMJQpBdH2VN4pgrrEhMCCbmwSb#zDnaeTiq1PdzvZXUaMdezchcMJQpBdH2VN4pgrrEhMCCbmwSb", + "type": "P256Key2021", + "controller": "did:key:zDnaeTiq1PdzvZXUaMdezchcMJQpBdH2VN4pgrrEhMCCbmwSb", + "publicKeyBase58": "ekVhkcBFq3w7jULLkBVye6PwaTuMbhJYuzwFnNcgQAPV", + "privateKeyBase58": "9p4VRzdmhsnq869vQjVCTrRry7u4TtfRxhvBFJTGU2Cp" + }, + "didDocument": { + "@context": [ + "https://www.w3.org/ns/did/v1", + "https://w3id.org/security/suites/multikey-2021/v1" + ], + "id": "did:key:zDnaeTiq1PdzvZXUaMdezchcMJQpBdH2VN4pgrrEhMCCbmwSb", + "verificationMethod": [ + { + "id": "did:key:zDnaeTiq1PdzvZXUaMdezchcMJQpBdH2VN4pgrrEhMCCbmwSb#zDnaeTiq1PdzvZXUaMdezchcMJQpBdH2VN4pgrrEhMCCbmwSb", + "type": "P256Key2021", + "controller": "did:key:zDnaeTiq1PdzvZXUaMdezchcMJQpBdH2VN4pgrrEhMCCbmwSb", + "publicKeyBase58": "ekVhkcBFq3w7jULLkBVye6PwaTuMbhJYuzwFnNcgQAPV" + } + ], + "assertionMethod": [ + "did:key:zDnaeTiq1PdzvZXUaMdezchcMJQpBdH2VN4pgrrEhMCCbmwSb#zDnaeTiq1PdzvZXUaMdezchcMJQpBdH2VN4pgrrEhMCCbmwSb" + ], + "authentication": [ + "did:key:zDnaeTiq1PdzvZXUaMdezchcMJQpBdH2VN4pgrrEhMCCbmwSb#zDnaeTiq1PdzvZXUaMdezchcMJQpBdH2VN4pgrrEhMCCbmwSb" + ], + "capabilityInvocation": [ + "did:key:zDnaeTiq1PdzvZXUaMdezchcMJQpBdH2VN4pgrrEhMCCbmwSb#zDnaeTiq1PdzvZXUaMdezchcMJQpBdH2VN4pgrrEhMCCbmwSb" + ], + "capabilityDelegation": [ + "did:key:zDnaeTiq1PdzvZXUaMdezchcMJQpBdH2VN4pgrrEhMCCbmwSb#zDnaeTiq1PdzvZXUaMdezchcMJQpBdH2VN4pgrrEhMCCbmwSb" + ], + "keyAgreement": [ + "did:key:zDnaeTiq1PdzvZXUaMdezchcMJQpBdH2VN4pgrrEhMCCbmwSb#zDnaeTiq1PdzvZXUaMdezchcMJQpBdH2VN4pgrrEhMCCbmwSb" + ] + } + } +} diff --git a/did/testdata/rsa.json b/did/testdata/rsa.json new file mode 100644 index 0000000..99d6ffa --- /dev/null +++ b/did/testdata/rsa.json @@ -0,0 +1,106 @@ +{ + "did:key:z4MXj1wBzi9jUstyPMS4jQqB6KdJaiatPkAtVtGc6bQEQEEsKTic4G7Rou3iBf9vPmT5dbkm9qsZsuVNjq8HCuW1w24nhBFGkRE4cd2Uf2tfrB3N7h4mnyPp1BF3ZttHTYv3DLUPi1zMdkULiow3M1GfXkoC6DoxDUm1jmN6GBj22SjVsr6dxezRVQc7aj9TxE7JLbMH1wh5X3kA58H3DFW8rnYMakFGbca5CB2Jf6CnGQZmL7o5uJAdTwXfy2iiiyPxXEGerMhHwhjTA1mKYobyk2CpeEcmvynADfNZ5MBvcCS7m3XkFCMNUYBS9NQ3fze6vMSUPsNa6GVYmKx2x6JrdEjCk3qRMMmyjnjCMfR4pXbRMZa3i": { + "publicKeyJwk": { + "kty": "RSA", + "n": "sbX82NTV6IylxCh7MfV4hlyvaniCajuP97GyOqSvTmoEdBOflFvZ06kR_9D6ctt45Fk6hskfnag2GG69NALVH2o4RCR6tQiLRpKcMRtDYE_thEmfBvDzm_VVkOIYfxu-Ipuo9J_S5XDNDjczx2v-3oDh5-CIHkU46hvFeCvpUS-L8TJSbgX0kjVk_m4eIb9wh63rtmD6Uz_KBtCo5mmR4TEtcLZKYdqMp3wCjN-TlgHiz_4oVXWbHUefCEe8rFnX1iQnpDHU49_SaXQoud1jCaexFn25n-Aa8f8bc5Vm-5SeRwidHa6ErvEhTvf1dz6GoNPp2iRvm-wJ1gxwWJEYPQ", + "e": "AQAB" + }, + "privateKeyJwk": { + "kty": "RSA", + "n": "sbX82NTV6IylxCh7MfV4hlyvaniCajuP97GyOqSvTmoEdBOflFvZ06kR_9D6ctt45Fk6hskfnag2GG69NALVH2o4RCR6tQiLRpKcMRtDYE_thEmfBvDzm_VVkOIYfxu-Ipuo9J_S5XDNDjczx2v-3oDh5-CIHkU46hvFeCvpUS-L8TJSbgX0kjVk_m4eIb9wh63rtmD6Uz_KBtCo5mmR4TEtcLZKYdqMp3wCjN-TlgHiz_4oVXWbHUefCEe8rFnX1iQnpDHU49_SaXQoud1jCaexFn25n-Aa8f8bc5Vm-5SeRwidHa6ErvEhTvf1dz6GoNPp2iRvm-wJ1gxwWJEYPQ", + "e": "AQAB", + "d": "Eym3sT4KLwBzo5pl5nY83-hAti92iLQRizkrKe22RbNi9Y1kKOBatdtGaJqFVztZZu5ERGKNuTd5VdsjJeekSbXviVGRtdHNCvgmRZlWA5261AgIUPxMmKW062GmGJbKQvscFfziBgHK6tyDBd8cZavqMFHi-7ilMYF7IsFBcJKM85x_30pnfd4YwhGQIc9hzv238aOwYKg8c-MzYhEVUnL273jaiLVlfZWQ5ca-GXJHmdOb_Y4fE5gpXfPFBseqleXsMp0VuXxCEsN30LIJHYscdPtbzLD3LFbuMJglFbQqYqssqymILGqJ7Tc2mB2LmXevfqRWz5D7A_K1WzvuoQ", + "p": "ANwlk-eVXPQplCmr7VddX8MAlN5YWvfXkbJe2KOhyS7naSlfMyeW6I0z6q6MAI4h8cs9yEzwmN1oEl_6tZ_-NPd1Oda2Hq5jHx0Jq2P5exIMMbzTTHbB-LjMB4c-b1DZLOrL7ZpCS-CcEHvBz4phzHa7gqz2SrNIGozufbjS_tK5", + "q": "AM6nKRFqRgHiUtGc0xJawpXJeokGhJQFfinDlakjkptuRQNv0BOz8fRUxk6zwwYrx-T_Yk-0oAFsD8qWIgiXg8Wf0bdRW0L0dIH4c6ff3mSREXeAT2h3XDaF0F1YKns08WyYWtOuIiYWChyO9sweK7AUuaOJ-6lr6lElzTGHVf-l", + "dp": "AIHFBPK2cRzchaIq3rVpLVHdveNzYexG_nOOxVVvwRANCUiB_b2Qj3Ts7aIGlS0zhTyxJql0Cig5eNtrBjVRvBdC2t1ebaeOdoC_enBsV8fDuG3-gExg-ySz4JwwiZ2252tg2qbb_a5hULYjARwpmkVDMzyR0mbsUfpRe3q_pcbB", + "dq": "Id2bCVOVLXHdiKReor9k7A8cmaAL0gYkasu2lwVRXU9w1-NXAiOXHydVaEhlSXmbRJflkJJVNmZzIAwCf830tko-oAAhKJPPFA2XRoeVdn2fkynf2YrV_cloICP2skI23kkJeW8sAXnTJmL3ZvP6zNxYn8hZCaa5u5qqSdeX7FE", + "qi": "WKIToXXnjl7GDbz7jCNbX9nWYOE5BDNzVmwiVOnyGoTZfwJ_qtgizj7pOapxi6dT9S9mMavmeAi6LAsEe1WUWtaKSNhbNh0PUGGXlXHGlhkS8jI1ot0e-scrHAuACE567YQ4VurpNorPKtZ5UENXIn74DEmt4l5m6902VF3X5Wo" + }, + "didDocument": { + "@context": [ + "https://www.w3.org/ns/did/v1", + "https://w3id.org/security/suites/jws-2020/v1" + ], + "id": "did:key:z4MXj1wBzi9jUstyPMS4jQqB6KdJaiatPkAtVtGc6bQEQEEsKTic4G7Rou3iBf9vPmT5dbkm9qsZsuVNjq8HCuW1w24nhBFGkRE4cd2Uf2tfrB3N7h4mnyPp1BF3ZttHTYv3DLUPi1zMdkULiow3M1GfXkoC6DoxDUm1jmN6GBj22SjVsr6dxezRVQc7aj9TxE7JLbMH1wh5X3kA58H3DFW8rnYMakFGbca5CB2Jf6CnGQZmL7o5uJAdTwXfy2iiiyPxXEGerMhHwhjTA1mKYobyk2CpeEcmvynADfNZ5MBvcCS7m3XkFCMNUYBS9NQ3fze6vMSUPsNa6GVYmKx2x6JrdEjCk3qRMMmyjnjCMfR4pXbRMZa3i", + "verificationMethod": [ + { + "id": "did:key:z4MXj1wBzi9jUstyPMS4jQqB6KdJaiatPkAtVtGc6bQEQEEsKTic4G7Rou3iBf9vPmT5dbkm9qsZsuVNjq8HCuW1w24nhBFGkRE4cd2Uf2tfrB3N7h4mnyPp1BF3ZttHTYv3DLUPi1zMdkULiow3M1GfXkoC6DoxDUm1jmN6GBj22SjVsr6dxezRVQc7aj9TxE7JLbMH1wh5X3kA58H3DFW8rnYMakFGbca5CB2Jf6CnGQZmL7o5uJAdTwXfy2iiiyPxXEGerMhHwhjTA1mKYobyk2CpeEcmvynADfNZ5MBvcCS7m3XkFCMNUYBS9NQ3fze6vMSUPsNa6GVYmKx2x6JrdEjCk3qRMMmyjnjCMfR4pXbRMZa3i#z4MXj1wBzi9jUstyPMS4jQqB6KdJaiatPkAtVtGc6bQEQEEsKTic4G7Rou3iBf9vPmT5dbkm9qsZsuVNjq8HCuW1w24nhBFGkRE4cd2Uf2tfrB3N7h4mnyPp1BF3ZttHTYv3DLUPi1zMdkULiow3M1GfXkoC6DoxDUm1jmN6GBj22SjVsr6dxezRVQc7aj9TxE7JLbMH1wh5X3kA58H3DFW8rnYMakFGbca5CB2Jf6CnGQZmL7o5uJAdTwXfy2iiiyPxXEGerMhHwhjTA1mKYobyk2CpeEcmvynADfNZ5MBvcCS7m3XkFCMNUYBS9NQ3fze6vMSUPsNa6GVYmKx2x6JrdEjCk3qRMMmyjnjCMfR4pXbRMZa3i", + "type": "JsonWebKey2020", + "controller": "did:key:z4MXj1wBzi9jUstyPMS4jQqB6KdJaiatPkAtVtGc6bQEQEEsKTic4G7Rou3iBf9vPmT5dbkm9qsZsuVNjq8HCuW1w24nhBFGkRE4cd2Uf2tfrB3N7h4mnyPp1BF3ZttHTYv3DLUPi1zMdkULiow3M1GfXkoC6DoxDUm1jmN6GBj22SjVsr6dxezRVQc7aj9TxE7JLbMH1wh5X3kA58H3DFW8rnYMakFGbca5CB2Jf6CnGQZmL7o5uJAdTwXfy2iiiyPxXEGerMhHwhjTA1mKYobyk2CpeEcmvynADfNZ5MBvcCS7m3XkFCMNUYBS9NQ3fze6vMSUPsNa6GVYmKx2x6JrdEjCk3qRMMmyjnjCMfR4pXbRMZa3i", + "publicKeyJwk": { + "kty": "RSA", + "n": "sbX82NTV6IylxCh7MfV4hlyvaniCajuP97GyOqSvTmoEdBOflFvZ06kR_9D6ctt45Fk6hskfnag2GG69NALVH2o4RCR6tQiLRpKcMRtDYE_thEmfBvDzm_VVkOIYfxu-Ipuo9J_S5XDNDjczx2v-3oDh5-CIHkU46hvFeCvpUS-L8TJSbgX0kjVk_m4eIb9wh63rtmD6Uz_KBtCo5mmR4TEtcLZKYdqMp3wCjN-TlgHiz_4oVXWbHUefCEe8rFnX1iQnpDHU49_SaXQoud1jCaexFn25n-Aa8f8bc5Vm-5SeRwidHa6ErvEhTvf1dz6GoNPp2iRvm-wJ1gxwWJEYPQ", + "e": "AQAB" + } + } + ], + "authentication": [ + "did:key:z4MXj1wBzi9jUstyPMS4jQqB6KdJaiatPkAtVtGc6bQEQEEsKTic4G7Rou3iBf9vPmT5dbkm9qsZsuVNjq8HCuW1w24nhBFGkRE4cd2Uf2tfrB3N7h4mnyPp1BF3ZttHTYv3DLUPi1zMdkULiow3M1GfXkoC6DoxDUm1jmN6GBj22SjVsr6dxezRVQc7aj9TxE7JLbMH1wh5X3kA58H3DFW8rnYMakFGbca5CB2Jf6CnGQZmL7o5uJAdTwXfy2iiiyPxXEGerMhHwhjTA1mKYobyk2CpeEcmvynADfNZ5MBvcCS7m3XkFCMNUYBS9NQ3fze6vMSUPsNa6GVYmKx2x6JrdEjCk3qRMMmyjnjCMfR4pXbRMZa3i#z4MXj1wBzi9jUstyPMS4jQqB6KdJaiatPkAtVtGc6bQEQEEsKTic4G7Rou3iBf9vPmT5dbkm9qsZsuVNjq8HCuW1w24nhBFGkRE4cd2Uf2tfrB3N7h4mnyPp1BF3ZttHTYv3DLUPi1zMdkULiow3M1GfXkoC6DoxDUm1jmN6GBj22SjVsr6dxezRVQc7aj9TxE7JLbMH1wh5X3kA58H3DFW8rnYMakFGbca5CB2Jf6CnGQZmL7o5uJAdTwXfy2iiiyPxXEGerMhHwhjTA1mKYobyk2CpeEcmvynADfNZ5MBvcCS7m3XkFCMNUYBS9NQ3fze6vMSUPsNa6GVYmKx2x6JrdEjCk3qRMMmyjnjCMfR4pXbRMZa3i" + ], + "assertionMethod": [ + "did:key:z4MXj1wBzi9jUstyPMS4jQqB6KdJaiatPkAtVtGc6bQEQEEsKTic4G7Rou3iBf9vPmT5dbkm9qsZsuVNjq8HCuW1w24nhBFGkRE4cd2Uf2tfrB3N7h4mnyPp1BF3ZttHTYv3DLUPi1zMdkULiow3M1GfXkoC6DoxDUm1jmN6GBj22SjVsr6dxezRVQc7aj9TxE7JLbMH1wh5X3kA58H3DFW8rnYMakFGbca5CB2Jf6CnGQZmL7o5uJAdTwXfy2iiiyPxXEGerMhHwhjTA1mKYobyk2CpeEcmvynADfNZ5MBvcCS7m3XkFCMNUYBS9NQ3fze6vMSUPsNa6GVYmKx2x6JrdEjCk3qRMMmyjnjCMfR4pXbRMZa3i#z4MXj1wBzi9jUstyPMS4jQqB6KdJaiatPkAtVtGc6bQEQEEsKTic4G7Rou3iBf9vPmT5dbkm9qsZsuVNjq8HCuW1w24nhBFGkRE4cd2Uf2tfrB3N7h4mnyPp1BF3ZttHTYv3DLUPi1zMdkULiow3M1GfXkoC6DoxDUm1jmN6GBj22SjVsr6dxezRVQc7aj9TxE7JLbMH1wh5X3kA58H3DFW8rnYMakFGbca5CB2Jf6CnGQZmL7o5uJAdTwXfy2iiiyPxXEGerMhHwhjTA1mKYobyk2CpeEcmvynADfNZ5MBvcCS7m3XkFCMNUYBS9NQ3fze6vMSUPsNa6GVYmKx2x6JrdEjCk3qRMMmyjnjCMfR4pXbRMZa3i" + ], + "capabilityDelegation": [ + "did:key:z4MXj1wBzi9jUstyPMS4jQqB6KdJaiatPkAtVtGc6bQEQEEsKTic4G7Rou3iBf9vPmT5dbkm9qsZsuVNjq8HCuW1w24nhBFGkRE4cd2Uf2tfrB3N7h4mnyPp1BF3ZttHTYv3DLUPi1zMdkULiow3M1GfXkoC6DoxDUm1jmN6GBj22SjVsr6dxezRVQc7aj9TxE7JLbMH1wh5X3kA58H3DFW8rnYMakFGbca5CB2Jf6CnGQZmL7o5uJAdTwXfy2iiiyPxXEGerMhHwhjTA1mKYobyk2CpeEcmvynADfNZ5MBvcCS7m3XkFCMNUYBS9NQ3fze6vMSUPsNa6GVYmKx2x6JrdEjCk3qRMMmyjnjCMfR4pXbRMZa3i#z4MXj1wBzi9jUstyPMS4jQqB6KdJaiatPkAtVtGc6bQEQEEsKTic4G7Rou3iBf9vPmT5dbkm9qsZsuVNjq8HCuW1w24nhBFGkRE4cd2Uf2tfrB3N7h4mnyPp1BF3ZttHTYv3DLUPi1zMdkULiow3M1GfXkoC6DoxDUm1jmN6GBj22SjVsr6dxezRVQc7aj9TxE7JLbMH1wh5X3kA58H3DFW8rnYMakFGbca5CB2Jf6CnGQZmL7o5uJAdTwXfy2iiiyPxXEGerMhHwhjTA1mKYobyk2CpeEcmvynADfNZ5MBvcCS7m3XkFCMNUYBS9NQ3fze6vMSUPsNa6GVYmKx2x6JrdEjCk3qRMMmyjnjCMfR4pXbRMZa3i" + ], + "capabilityInvocation": [ + "did:key:z4MXj1wBzi9jUstyPMS4jQqB6KdJaiatPkAtVtGc6bQEQEEsKTic4G7Rou3iBf9vPmT5dbkm9qsZsuVNjq8HCuW1w24nhBFGkRE4cd2Uf2tfrB3N7h4mnyPp1BF3ZttHTYv3DLUPi1zMdkULiow3M1GfXkoC6DoxDUm1jmN6GBj22SjVsr6dxezRVQc7aj9TxE7JLbMH1wh5X3kA58H3DFW8rnYMakFGbca5CB2Jf6CnGQZmL7o5uJAdTwXfy2iiiyPxXEGerMhHwhjTA1mKYobyk2CpeEcmvynADfNZ5MBvcCS7m3XkFCMNUYBS9NQ3fze6vMSUPsNa6GVYmKx2x6JrdEjCk3qRMMmyjnjCMfR4pXbRMZa3i#z4MXj1wBzi9jUstyPMS4jQqB6KdJaiatPkAtVtGc6bQEQEEsKTic4G7Rou3iBf9vPmT5dbkm9qsZsuVNjq8HCuW1w24nhBFGkRE4cd2Uf2tfrB3N7h4mnyPp1BF3ZttHTYv3DLUPi1zMdkULiow3M1GfXkoC6DoxDUm1jmN6GBj22SjVsr6dxezRVQc7aj9TxE7JLbMH1wh5X3kA58H3DFW8rnYMakFGbca5CB2Jf6CnGQZmL7o5uJAdTwXfy2iiiyPxXEGerMhHwhjTA1mKYobyk2CpeEcmvynADfNZ5MBvcCS7m3XkFCMNUYBS9NQ3fze6vMSUPsNa6GVYmKx2x6JrdEjCk3qRMMmyjnjCMfR4pXbRMZa3i" + ], + "keyAgreement": [ + "did:key:z4MXj1wBzi9jUstyPMS4jQqB6KdJaiatPkAtVtGc6bQEQEEsKTic4G7Rou3iBf9vPmT5dbkm9qsZsuVNjq8HCuW1w24nhBFGkRE4cd2Uf2tfrB3N7h4mnyPp1BF3ZttHTYv3DLUPi1zMdkULiow3M1GfXkoC6DoxDUm1jmN6GBj22SjVsr6dxezRVQc7aj9TxE7JLbMH1wh5X3kA58H3DFW8rnYMakFGbca5CB2Jf6CnGQZmL7o5uJAdTwXfy2iiiyPxXEGerMhHwhjTA1mKYobyk2CpeEcmvynADfNZ5MBvcCS7m3XkFCMNUYBS9NQ3fze6vMSUPsNa6GVYmKx2x6JrdEjCk3qRMMmyjnjCMfR4pXbRMZa3i#z4MXj1wBzi9jUstyPMS4jQqB6KdJaiatPkAtVtGc6bQEQEEsKTic4G7Rou3iBf9vPmT5dbkm9qsZsuVNjq8HCuW1w24nhBFGkRE4cd2Uf2tfrB3N7h4mnyPp1BF3ZttHTYv3DLUPi1zMdkULiow3M1GfXkoC6DoxDUm1jmN6GBj22SjVsr6dxezRVQc7aj9TxE7JLbMH1wh5X3kA58H3DFW8rnYMakFGbca5CB2Jf6CnGQZmL7o5uJAdTwXfy2iiiyPxXEGerMhHwhjTA1mKYobyk2CpeEcmvynADfNZ5MBvcCS7m3XkFCMNUYBS9NQ3fze6vMSUPsNa6GVYmKx2x6JrdEjCk3qRMMmyjnjCMfR4pXbRMZa3i" + ] + } + }, + "did:key:zgghBUVkqmWS8e1ioRVp2WN9Vw6x4NvnE9PGAyQsPqM3fnfPf8EdauiRVfBTcVDyzhqM5FFC7ekAvuV1cJHawtfgB9wDcru1hPDobk3hqyedijhgWmsYfJCmodkiiFnjNWATE7PvqTyoCjcmrc8yMRXmFPnoASyT5beUd4YZxTE9VfgmavcPy3BSouNmASMQ8xUXeiRwjb7xBaVTiDRjkmyPD7NYZdXuS93gFhyDFr5b3XLg7Rfj9nHEqtHDa7NmAX7iwDAbMUFEfiDEf9hrqZmpAYJracAjTTR8Cvn6mnDXMLwayNG8dcsXFodxok2qksYF4D8ffUxMRmyyQVQhhhmdSi4YaMPqTnC1J6HTG9Yfb98yGSVaWi4TApUhLXFow2ZvB6vqckCNhjCRL2R4MDUSk71qzxWHgezKyDeyThJgdxydrn1osqH94oSeA346eipkJvKqYREXBKwgB5VL6WF4qAK6sVZxJp2dQBfCPVZ4EbsBQaJXaVK7cNcWG8tZBFWZ79gG9Cu6C4u8yjBS8Ux6dCcJPUTLtixQu4z2n5dCsVSNdnP1EEs8ZerZo5pBgc68w4Yuf9KL3xVxPnAB1nRCBfs9cMU6oL1EdyHbqrTfnjE8HpY164akBqe92LFVsk8RusaGsVPrMekT8emTq5y8v8CabuZg5rDs3f9NPEtogjyx49wiub1FecM5B7QqEcZSYiKHgF4mfkteT2": { + "publicKeyJwk": { + "kty": "RSA", + "n": "qMCkFFRFWtzUyZeK8mgJdyM6SEQcXC5E6JwCRVDld-jlJs8sXNOE_vliexq34wZRQ4hk53-JPFlvZ_QjRgIxdUxSMiZ3S5hlNVvvRaue6SMakA9ugQhnfXaWORro0UbPuHLms-bg5StDP8-8tIezu9c1H1FjwPcdbV6rAvKhyhnsM10qP3v2CPbdE0q3FOsihoKuTelImtO110E7N6fLn4U3EYbC4OyViqlrP1o_1M-R-tiM1cb4pD7XKJnIs6ryZdfOQSPBJwjNqSdN6Py_tdrFgPDTyacSSdpTVADOM2IMAoYbhV1N5APhnjOHBRFyKkF1HffQKpmXQLBqvUNNjuhmpVKWBtrTdcCKrglFXiw0cKGHKxIirjmiOlB_HYHg5UdosyE3_1Txct2U7-WBB6QXak1UgxCzgKYBDI8UPA0RlkUuHHP_Zg0fVXrXIInHO04MYxUeSps5qqyP6dJBu_v_BDn3zUq6LYFwJ_-xsU7zbrKYB4jaRlHPoCj_eDC-rSA2uQ4KXHBB8_aAqNFC9ukWxc26Ifz9dF968DLuL30bi-ZAa2oUh492Pw1bg89J7i4qTsOOfpQvGyDV7TGhKuUG3Hbumfr2w16S-_3EI2RIyd1nYsflE6ZmCkZQMG_lwDAFXaqfyGKEDouJuja4XH8r4fGWeGTrozIoniXT1HU", + "e": "AQAB" + }, + "privateKeyJwk": { + "kty": "RSA", + "n": "qMCkFFRFWtzUyZeK8mgJdyM6SEQcXC5E6JwCRVDld-jlJs8sXNOE_vliexq34wZRQ4hk53-JPFlvZ_QjRgIxdUxSMiZ3S5hlNVvvRaue6SMakA9ugQhnfXaWORro0UbPuHLms-bg5StDP8-8tIezu9c1H1FjwPcdbV6rAvKhyhnsM10qP3v2CPbdE0q3FOsihoKuTelImtO110E7N6fLn4U3EYbC4OyViqlrP1o_1M-R-tiM1cb4pD7XKJnIs6ryZdfOQSPBJwjNqSdN6Py_tdrFgPDTyacSSdpTVADOM2IMAoYbhV1N5APhnjOHBRFyKkF1HffQKpmXQLBqvUNNjuhmpVKWBtrTdcCKrglFXiw0cKGHKxIirjmiOlB_HYHg5UdosyE3_1Txct2U7-WBB6QXak1UgxCzgKYBDI8UPA0RlkUuHHP_Zg0fVXrXIInHO04MYxUeSps5qqyP6dJBu_v_BDn3zUq6LYFwJ_-xsU7zbrKYB4jaRlHPoCj_eDC-rSA2uQ4KXHBB8_aAqNFC9ukWxc26Ifz9dF968DLuL30bi-ZAa2oUh492Pw1bg89J7i4qTsOOfpQvGyDV7TGhKuUG3Hbumfr2w16S-_3EI2RIyd1nYsflE6ZmCkZQMG_lwDAFXaqfyGKEDouJuja4XH8r4fGWeGTrozIoniXT1HU", + "e": "AQAB", + "d": "TMq1H-clVG7PihkjCqJbRFLMj9wmx6_qfauYwPBKK-HYfWujdW5vxBO6Q-jpqy7RxhiISmxYCBVuw_BuKMqQtR8Q_G9StBzaWYjHfn3Vp6Poz4umLqOjbI2NWNks_ybpGbd30oAK8V5ZkO04ozJpkN4i92hzK3mIc5-z1HiTNUPMn6cStab0VCn6em_ylltV774CEcRJ3OLgid7OUspRt_rID3qyreYbOulTu5WXHIGEnZDzrciIlz1dbcVldpUhD0VAP5ZErD2uUP5oztBNcTTn0YBF8CrOALuQVdaz_t_sNS3P0kWeT1eQ0QwDskO5Hw-Aey2tFeWk1bQyLoQ1A0jsw8mDbkO2zrGfJoxmVBkueTK-q64_n1kV7W1aeJFRj4NwEWmwcrs8GSOGOn38fGB_Y3Kci04qvD6L0QZbFkAVzcJracnxbTdHCEX0jsAAPbYC8M_8PyrPJvPC4IAAWTRrSRbysb7r7viRf4A1vTK9VT7uYyxj7Kzx2cU12d9QBXYfdQ2744bUE7HqN-Vh2rHvv2l5v6vzBRoZ5_OhHHVeUYwC9LouE9lSVAObbFM-Qe1SvzbbwN91LziI7UzUc_xMAEiNwt6PpnIAWAhdvSRawEllTwUcn89udHd5UhiAcm-RQOqXIdA9Aly6d8TT8R1p-ZnQ_gbZyBZeS39AuvU=", + "p": "1p4cypsJeTyVXXc5bQpvzVenPy78OHXtGcFQnbTjW8x1GsvJ-rlHAcjUImd44pgNQNe-iYpeUg3KqfONeedNgQCFd8kP7GoVAd45mEvsGBXvjoCXOBMQlsf8UU_hm_LKhVvTvTmMGoudnNv5qYNDMCGJGzwoG-aSvROlIoXzHmDnusZ-hKsDxM9j0PPz21t99Y_Fr30Oq3FIWXPVmLYmfyZYQkxm9a9WNMkqRbwJuMwGI6V9ABsQ1dW_KJzp_aEBbJLcDr9DsWhm9ErLeAlzyaDYEai6wCtKm9em4LDwCbKhJq3hWEp1sIG-hwx1sk7N4i-b8lBijjEQE-dbSQxUlw==", + "q": "yUqMejfrttGujadj7Uf7q91KM7nbQGny4TjD-CqibcFE-s2_DExCgP1wfhUPfJr2uPQDIe4g12uaNoa5GbCSDaQwEmQpurC_5mazt-z-_tbI24hoPQm5Hq67fZz-jDE_3OccLPLIWtajJqmxHbbB5VqskMuXo8KDxPRfBQBhykmb9_5M8pY2ggZOV4shCUn5E9nOnvibvw5Wx4CBtWUtca4rhpd3mVen1d8xCe4xTG_ni_w1lwdxzU1GmRFqgTuZWzL0r2FKzJg7hju1SOEe4tKMxQ-xs2HyNaMM__SLsNmS3lsYZ8r2hqcjEMQQZI0T_O-3BjIpyg986P8j055E0w==", + "dp": "DujzJRw6P0L3OYQT6EBmXgSt6NTRzvZaX4SvnhU4CmOc6xynTpTamwQhwLYhjtRzb0LNyO5k-RxeLQpvlL1-A-1OWHEOeyUvim6u36a-ozm659KFLu8cIu2H2PpMuTHX4gXsIuRBmIKEk6YwpRcqbsiVpt-6BZ4yKZKY0Vou9rhSwQYTOhJLc7vYumaIVX_4szumxzdP8pcvKI_EkhRtfj3iudBnAsCIo6gqGKgkoMMD1iwkEALRW5m66w5jrywlVi6pvRiKkmOna2da1V8KvUJAYJGxT7JyP3tu64M_Wd0gFvjTg_fAT1_kJau27YlOAl2-Xso43poH_OoAzIVfxw==", + "dq": "XI6Z76z9BxB9mgcpTLc3wzw63XQNnB3bn7JRcjBwhdVD2at3uLjsL5HaAy-98kbzQfJ56kUr9sI0o_Po8yYc0ob3z80c3wpdAx2gb-dbDWVH8KJVhBOPestPzR--cEpJGlNuwkBU3mgplyKaHZamq8a46M-lB5jurEbN1mfpj3GvdSYKzdVCdSFfLqP76eCI1pblinW4b-6w-oVdn0JJ1icHPpkxVmJW-2Hok69iHcqrBtRO9AZpTsTEvKekeI4mIyhYGLi9AzzQyhV0c3GImTXFoutng5t7GyzBUoRpI0W4YeQzYa6TEzGRTylIfGPemATF_OReENp0TlLbb3gsHw==", + "qi": "m7uZk4AsOfJ1V2RY8lmEF518toCV7juKuS_b_OUx8B0dRG0_kbF1cH-Tmrgsya3bwkYx5HeZG81rX7SRjh-0nVPOMW3tGqU5U9f59DXqvOItJIJ6wvWvWXnuna2-NstYCotFQWadIKjk4wjEKj-a4NJt4D_F4csyeyqWOH2DiUFzBGGxxdEoD5t_HEeNXuWQ6-SiV0x5ZVMln3TSh7IOMl70Smm8HcQF5mOsWg3N0wIg-yffxPrs6r15TRuW1MfT-bZk2GLrtHF1TkIoT1e00jWK4eBl2oRxiJGONUBMTEHV85Fr0yztnA99AgHnrMbE_4ehvev4h5DEWvFyFuJN_g==" + }, + "didDocument": { + "@context": [ + "https://www.w3.org/ns/did/v1", + "https://w3id.org/security/suites/jws-2020/v1" + ], + "id": "did:key:zgghBUVkqmWS8e1ioRVp2WN9Vw6x4NvnE9PGAyQsPqM3fnfPf8EdauiRVfBTcVDyzhqM5FFC7ekAvuV1cJHawtfgB9wDcru1hPDobk3hqyedijhgWmsYfJCmodkiiFnjNWATE7PvqTyoCjcmrc8yMRXmFPnoASyT5beUd4YZxTE9VfgmavcPy3BSouNmASMQ8xUXeiRwjb7xBaVTiDRjkmyPD7NYZdXuS93gFhyDFr5b3XLg7Rfj9nHEqtHDa7NmAX7iwDAbMUFEfiDEf9hrqZmpAYJracAjTTR8Cvn6mnDXMLwayNG8dcsXFodxok2qksYF4D8ffUxMRmyyQVQhhhmdSi4YaMPqTnC1J6HTG9Yfb98yGSVaWi4TApUhLXFow2ZvB6vqckCNhjCRL2R4MDUSk71qzxWHgezKyDeyThJgdxydrn1osqH94oSeA346eipkJvKqYREXBKwgB5VL6WF4qAK6sVZxJp2dQBfCPVZ4EbsBQaJXaVK7cNcWG8tZBFWZ79gG9Cu6C4u8yjBS8Ux6dCcJPUTLtixQu4z2n5dCsVSNdnP1EEs8ZerZo5pBgc68w4Yuf9KL3xVxPnAB1nRCBfs9cMU6oL1EdyHbqrTfnjE8HpY164akBqe92LFVsk8RusaGsVPrMekT8emTq5y8v8CabuZg5rDs3f9NPEtogjyx49wiub1FecM5B7QqEcZSYiKHgF4mfkteT2", + "verificationMethod": [ + { + "id": "did:key:zgghBUVkqmWS8e1ioRVp2WN9Vw6x4NvnE9PGAyQsPqM3fnfPf8EdauiRVfBTcVDyzhqM5FFC7ekAvuV1cJHawtfgB9wDcru1hPDobk3hqyedijhgWmsYfJCmodkiiFnjNWATE7PvqTyoCjcmrc8yMRXmFPnoASyT5beUd4YZxTE9VfgmavcPy3BSouNmASMQ8xUXeiRwjb7xBaVTiDRjkmyPD7NYZdXuS93gFhyDFr5b3XLg7Rfj9nHEqtHDa7NmAX7iwDAbMUFEfiDEf9hrqZmpAYJracAjTTR8Cvn6mnDXMLwayNG8dcsXFodxok2qksYF4D8ffUxMRmyyQVQhhhmdSi4YaMPqTnC1J6HTG9Yfb98yGSVaWi4TApUhLXFow2ZvB6vqckCNhjCRL2R4MDUSk71qzxWHgezKyDeyThJgdxydrn1osqH94oSeA346eipkJvKqYREXBKwgB5VL6WF4qAK6sVZxJp2dQBfCPVZ4EbsBQaJXaVK7cNcWG8tZBFWZ79gG9Cu6C4u8yjBS8Ux6dCcJPUTLtixQu4z2n5dCsVSNdnP1EEs8ZerZo5pBgc68w4Yuf9KL3xVxPnAB1nRCBfs9cMU6oL1EdyHbqrTfnjE8HpY164akBqe92LFVsk8RusaGsVPrMekT8emTq5y8v8CabuZg5rDs3f9NPEtogjyx49wiub1FecM5B7QqEcZSYiKHgF4mfkteT2#zgghBUVkqmWS8e1ioRVp2WN9Vw6x4NvnE9PGAyQsPqM3fnfPf8EdauiRVfBTcVDyzhqM5FFC7ekAvuV1cJHawtfgB9wDcru1hPDobk3hqyedijhgWmsYfJCmodkiiFnjNWATE7PvqTyoCjcmrc8yMRXmFPnoASyT5beUd4YZxTE9VfgmavcPy3BSouNmASMQ8xUXeiRwjb7xBaVTiDRjkmyPD7NYZdXuS93gFhyDFr5b3XLg7Rfj9nHEqtHDa7NmAX7iwDAbMUFEfiDEf9hrqZmpAYJracAjTTR8Cvn6mnDXMLwayNG8dcsXFodxok2qksYF4D8ffUxMRmyyQVQhhhmdSi4YaMPqTnC1J6HTG9Yfb98yGSVaWi4TApUhLXFow2ZvB6vqckCNhjCRL2R4MDUSk71qzxWHgezKyDeyThJgdxydrn1osqH94oSeA346eipkJvKqYREXBKwgB5VL6WF4qAK6sVZxJp2dQBfCPVZ4EbsBQaJXaVK7cNcWG8tZBFWZ79gG9Cu6C4u8yjBS8Ux6dCcJPUTLtixQu4z2n5dCsVSNdnP1EEs8ZerZo5pBgc68w4Yuf9KL3xVxPnAB1nRCBfs9cMU6oL1EdyHbqrTfnjE8HpY164akBqe92LFVsk8RusaGsVPrMekT8emTq5y8v8CabuZg5rDs3f9NPEtogjyx49wiub1FecM5B7QqEcZSYiKHgF4mfkteT2", + "type": "JsonWebKey2020", + "controller": "did:key:zgghBUVkqmWS8e1ioRVp2WN9Vw6x4NvnE9PGAyQsPqM3fnfPf8EdauiRVfBTcVDyzhqM5FFC7ekAvuV1cJHawtfgB9wDcru1hPDobk3hqyedijhgWmsYfJCmodkiiFnjNWATE7PvqTyoCjcmrc8yMRXmFPnoASyT5beUd4YZxTE9VfgmavcPy3BSouNmASMQ8xUXeiRwjb7xBaVTiDRjkmyPD7NYZdXuS93gFhyDFr5b3XLg7Rfj9nHEqtHDa7NmAX7iwDAbMUFEfiDEf9hrqZmpAYJracAjTTR8Cvn6mnDXMLwayNG8dcsXFodxok2qksYF4D8ffUxMRmyyQVQhhhmdSi4YaMPqTnC1J6HTG9Yfb98yGSVaWi4TApUhLXFow2ZvB6vqckCNhjCRL2R4MDUSk71qzxWHgezKyDeyThJgdxydrn1osqH94oSeA346eipkJvKqYREXBKwgB5VL6WF4qAK6sVZxJp2dQBfCPVZ4EbsBQaJXaVK7cNcWG8tZBFWZ79gG9Cu6C4u8yjBS8Ux6dCcJPUTLtixQu4z2n5dCsVSNdnP1EEs8ZerZo5pBgc68w4Yuf9KL3xVxPnAB1nRCBfs9cMU6oL1EdyHbqrTfnjE8HpY164akBqe92LFVsk8RusaGsVPrMekT8emTq5y8v8CabuZg5rDs3f9NPEtogjyx49wiub1FecM5B7QqEcZSYiKHgF4mfkteT2", + "publicKeyJwk": { + "kty": "RSA", + "n": "qMCkFFRFWtzUyZeK8mgJdyM6SEQcXC5E6JwCRVDld-jlJs8sXNOE_vliexq34wZRQ4hk53-JPFlvZ_QjRgIxdUxSMiZ3S5hlNVvvRaue6SMakA9ugQhnfXaWORro0UbPuHLms-bg5StDP8-8tIezu9c1H1FjwPcdbV6rAvKhyhnsM10qP3v2CPbdE0q3FOsihoKuTelImtO110E7N6fLn4U3EYbC4OyViqlrP1o_1M-R-tiM1cb4pD7XKJnIs6ryZdfOQSPBJwjNqSdN6Py_tdrFgPDTyacSSdpTVADOM2IMAoYbhV1N5APhnjOHBRFyKkF1HffQKpmXQLBqvUNNjuhmpVKWBtrTdcCKrglFXiw0cKGHKxIirjmiOlB_HYHg5UdosyE3_1Txct2U7-WBB6QXak1UgxCzgKYBDI8UPA0RlkUuHHP_Zg0fVXrXIInHO04MYxUeSps5qqyP6dJBu_v_BDn3zUq6LYFwJ_-xsU7zbrKYB4jaRlHPoCj_eDC-rSA2uQ4KXHBB8_aAqNFC9ukWxc26Ifz9dF968DLuL30bi-ZAa2oUh492Pw1bg89J7i4qTsOOfpQvGyDV7TGhKuUG3Hbumfr2w16S-_3EI2RIyd1nYsflE6ZmCkZQMG_lwDAFXaqfyGKEDouJuja4XH8r4fGWeGTrozIoniXT1HU", + "e": "AQAB" + } + } + ], + "authentication": [ + "did:key:zgghBUVkqmWS8e1ioRVp2WN9Vw6x4NvnE9PGAyQsPqM3fnfPf8EdauiRVfBTcVDyzhqM5FFC7ekAvuV1cJHawtfgB9wDcru1hPDobk3hqyedijhgWmsYfJCmodkiiFnjNWATE7PvqTyoCjcmrc8yMRXmFPnoASyT5beUd4YZxTE9VfgmavcPy3BSouNmASMQ8xUXeiRwjb7xBaVTiDRjkmyPD7NYZdXuS93gFhyDFr5b3XLg7Rfj9nHEqtHDa7NmAX7iwDAbMUFEfiDEf9hrqZmpAYJracAjTTR8Cvn6mnDXMLwayNG8dcsXFodxok2qksYF4D8ffUxMRmyyQVQhhhmdSi4YaMPqTnC1J6HTG9Yfb98yGSVaWi4TApUhLXFow2ZvB6vqckCNhjCRL2R4MDUSk71qzxWHgezKyDeyThJgdxydrn1osqH94oSeA346eipkJvKqYREXBKwgB5VL6WF4qAK6sVZxJp2dQBfCPVZ4EbsBQaJXaVK7cNcWG8tZBFWZ79gG9Cu6C4u8yjBS8Ux6dCcJPUTLtixQu4z2n5dCsVSNdnP1EEs8ZerZo5pBgc68w4Yuf9KL3xVxPnAB1nRCBfs9cMU6oL1EdyHbqrTfnjE8HpY164akBqe92LFVsk8RusaGsVPrMekT8emTq5y8v8CabuZg5rDs3f9NPEtogjyx49wiub1FecM5B7QqEcZSYiKHgF4mfkteT2#zgghBUVkqmWS8e1ioRVp2WN9Vw6x4NvnE9PGAyQsPqM3fnfPf8EdauiRVfBTcVDyzhqM5FFC7ekAvuV1cJHawtfgB9wDcru1hPDobk3hqyedijhgWmsYfJCmodkiiFnjNWATE7PvqTyoCjcmrc8yMRXmFPnoASyT5beUd4YZxTE9VfgmavcPy3BSouNmASMQ8xUXeiRwjb7xBaVTiDRjkmyPD7NYZdXuS93gFhyDFr5b3XLg7Rfj9nHEqtHDa7NmAX7iwDAbMUFEfiDEf9hrqZmpAYJracAjTTR8Cvn6mnDXMLwayNG8dcsXFodxok2qksYF4D8ffUxMRmyyQVQhhhmdSi4YaMPqTnC1J6HTG9Yfb98yGSVaWi4TApUhLXFow2ZvB6vqckCNhjCRL2R4MDUSk71qzxWHgezKyDeyThJgdxydrn1osqH94oSeA346eipkJvKqYREXBKwgB5VL6WF4qAK6sVZxJp2dQBfCPVZ4EbsBQaJXaVK7cNcWG8tZBFWZ79gG9Cu6C4u8yjBS8Ux6dCcJPUTLtixQu4z2n5dCsVSNdnP1EEs8ZerZo5pBgc68w4Yuf9KL3xVxPnAB1nRCBfs9cMU6oL1EdyHbqrTfnjE8HpY164akBqe92LFVsk8RusaGsVPrMekT8emTq5y8v8CabuZg5rDs3f9NPEtogjyx49wiub1FecM5B7QqEcZSYiKHgF4mfkteT2" + ], + "assertionMethod": [ + "did:key:zgghBUVkqmWS8e1ioRVp2WN9Vw6x4NvnE9PGAyQsPqM3fnfPf8EdauiRVfBTcVDyzhqM5FFC7ekAvuV1cJHawtfgB9wDcru1hPDobk3hqyedijhgWmsYfJCmodkiiFnjNWATE7PvqTyoCjcmrc8yMRXmFPnoASyT5beUd4YZxTE9VfgmavcPy3BSouNmASMQ8xUXeiRwjb7xBaVTiDRjkmyPD7NYZdXuS93gFhyDFr5b3XLg7Rfj9nHEqtHDa7NmAX7iwDAbMUFEfiDEf9hrqZmpAYJracAjTTR8Cvn6mnDXMLwayNG8dcsXFodxok2qksYF4D8ffUxMRmyyQVQhhhmdSi4YaMPqTnC1J6HTG9Yfb98yGSVaWi4TApUhLXFow2ZvB6vqckCNhjCRL2R4MDUSk71qzxWHgezKyDeyThJgdxydrn1osqH94oSeA346eipkJvKqYREXBKwgB5VL6WF4qAK6sVZxJp2dQBfCPVZ4EbsBQaJXaVK7cNcWG8tZBFWZ79gG9Cu6C4u8yjBS8Ux6dCcJPUTLtixQu4z2n5dCsVSNdnP1EEs8ZerZo5pBgc68w4Yuf9KL3xVxPnAB1nRCBfs9cMU6oL1EdyHbqrTfnjE8HpY164akBqe92LFVsk8RusaGsVPrMekT8emTq5y8v8CabuZg5rDs3f9NPEtogjyx49wiub1FecM5B7QqEcZSYiKHgF4mfkteT2#zgghBUVkqmWS8e1ioRVp2WN9Vw6x4NvnE9PGAyQsPqM3fnfPf8EdauiRVfBTcVDyzhqM5FFC7ekAvuV1cJHawtfgB9wDcru1hPDobk3hqyedijhgWmsYfJCmodkiiFnjNWATE7PvqTyoCjcmrc8yMRXmFPnoASyT5beUd4YZxTE9VfgmavcPy3BSouNmASMQ8xUXeiRwjb7xBaVTiDRjkmyPD7NYZdXuS93gFhyDFr5b3XLg7Rfj9nHEqtHDa7NmAX7iwDAbMUFEfiDEf9hrqZmpAYJracAjTTR8Cvn6mnDXMLwayNG8dcsXFodxok2qksYF4D8ffUxMRmyyQVQhhhmdSi4YaMPqTnC1J6HTG9Yfb98yGSVaWi4TApUhLXFow2ZvB6vqckCNhjCRL2R4MDUSk71qzxWHgezKyDeyThJgdxydrn1osqH94oSeA346eipkJvKqYREXBKwgB5VL6WF4qAK6sVZxJp2dQBfCPVZ4EbsBQaJXaVK7cNcWG8tZBFWZ79gG9Cu6C4u8yjBS8Ux6dCcJPUTLtixQu4z2n5dCsVSNdnP1EEs8ZerZo5pBgc68w4Yuf9KL3xVxPnAB1nRCBfs9cMU6oL1EdyHbqrTfnjE8HpY164akBqe92LFVsk8RusaGsVPrMekT8emTq5y8v8CabuZg5rDs3f9NPEtogjyx49wiub1FecM5B7QqEcZSYiKHgF4mfkteT2" + ], + "capabilityDelegation": [ + "did:key:zgghBUVkqmWS8e1ioRVp2WN9Vw6x4NvnE9PGAyQsPqM3fnfPf8EdauiRVfBTcVDyzhqM5FFC7ekAvuV1cJHawtfgB9wDcru1hPDobk3hqyedijhgWmsYfJCmodkiiFnjNWATE7PvqTyoCjcmrc8yMRXmFPnoASyT5beUd4YZxTE9VfgmavcPy3BSouNmASMQ8xUXeiRwjb7xBaVTiDRjkmyPD7NYZdXuS93gFhyDFr5b3XLg7Rfj9nHEqtHDa7NmAX7iwDAbMUFEfiDEf9hrqZmpAYJracAjTTR8Cvn6mnDXMLwayNG8dcsXFodxok2qksYF4D8ffUxMRmyyQVQhhhmdSi4YaMPqTnC1J6HTG9Yfb98yGSVaWi4TApUhLXFow2ZvB6vqckCNhjCRL2R4MDUSk71qzxWHgezKyDeyThJgdxydrn1osqH94oSeA346eipkJvKqYREXBKwgB5VL6WF4qAK6sVZxJp2dQBfCPVZ4EbsBQaJXaVK7cNcWG8tZBFWZ79gG9Cu6C4u8yjBS8Ux6dCcJPUTLtixQu4z2n5dCsVSNdnP1EEs8ZerZo5pBgc68w4Yuf9KL3xVxPnAB1nRCBfs9cMU6oL1EdyHbqrTfnjE8HpY164akBqe92LFVsk8RusaGsVPrMekT8emTq5y8v8CabuZg5rDs3f9NPEtogjyx49wiub1FecM5B7QqEcZSYiKHgF4mfkteT2#zgghBUVkqmWS8e1ioRVp2WN9Vw6x4NvnE9PGAyQsPqM3fnfPf8EdauiRVfBTcVDyzhqM5FFC7ekAvuV1cJHawtfgB9wDcru1hPDobk3hqyedijhgWmsYfJCmodkiiFnjNWATE7PvqTyoCjcmrc8yMRXmFPnoASyT5beUd4YZxTE9VfgmavcPy3BSouNmASMQ8xUXeiRwjb7xBaVTiDRjkmyPD7NYZdXuS93gFhyDFr5b3XLg7Rfj9nHEqtHDa7NmAX7iwDAbMUFEfiDEf9hrqZmpAYJracAjTTR8Cvn6mnDXMLwayNG8dcsXFodxok2qksYF4D8ffUxMRmyyQVQhhhmdSi4YaMPqTnC1J6HTG9Yfb98yGSVaWi4TApUhLXFow2ZvB6vqckCNhjCRL2R4MDUSk71qzxWHgezKyDeyThJgdxydrn1osqH94oSeA346eipkJvKqYREXBKwgB5VL6WF4qAK6sVZxJp2dQBfCPVZ4EbsBQaJXaVK7cNcWG8tZBFWZ79gG9Cu6C4u8yjBS8Ux6dCcJPUTLtixQu4z2n5dCsVSNdnP1EEs8ZerZo5pBgc68w4Yuf9KL3xVxPnAB1nRCBfs9cMU6oL1EdyHbqrTfnjE8HpY164akBqe92LFVsk8RusaGsVPrMekT8emTq5y8v8CabuZg5rDs3f9NPEtogjyx49wiub1FecM5B7QqEcZSYiKHgF4mfkteT2" + ], + "capabilityInvocation": [ + "did:key:zgghBUVkqmWS8e1ioRVp2WN9Vw6x4NvnE9PGAyQsPqM3fnfPf8EdauiRVfBTcVDyzhqM5FFC7ekAvuV1cJHawtfgB9wDcru1hPDobk3hqyedijhgWmsYfJCmodkiiFnjNWATE7PvqTyoCjcmrc8yMRXmFPnoASyT5beUd4YZxTE9VfgmavcPy3BSouNmASMQ8xUXeiRwjb7xBaVTiDRjkmyPD7NYZdXuS93gFhyDFr5b3XLg7Rfj9nHEqtHDa7NmAX7iwDAbMUFEfiDEf9hrqZmpAYJracAjTTR8Cvn6mnDXMLwayNG8dcsXFodxok2qksYF4D8ffUxMRmyyQVQhhhmdSi4YaMPqTnC1J6HTG9Yfb98yGSVaWi4TApUhLXFow2ZvB6vqckCNhjCRL2R4MDUSk71qzxWHgezKyDeyThJgdxydrn1osqH94oSeA346eipkJvKqYREXBKwgB5VL6WF4qAK6sVZxJp2dQBfCPVZ4EbsBQaJXaVK7cNcWG8tZBFWZ79gG9Cu6C4u8yjBS8Ux6dCcJPUTLtixQu4z2n5dCsVSNdnP1EEs8ZerZo5pBgc68w4Yuf9KL3xVxPnAB1nRCBfs9cMU6oL1EdyHbqrTfnjE8HpY164akBqe92LFVsk8RusaGsVPrMekT8emTq5y8v8CabuZg5rDs3f9NPEtogjyx49wiub1FecM5B7QqEcZSYiKHgF4mfkteT2#zgghBUVkqmWS8e1ioRVp2WN9Vw6x4NvnE9PGAyQsPqM3fnfPf8EdauiRVfBTcVDyzhqM5FFC7ekAvuV1cJHawtfgB9wDcru1hPDobk3hqyedijhgWmsYfJCmodkiiFnjNWATE7PvqTyoCjcmrc8yMRXmFPnoASyT5beUd4YZxTE9VfgmavcPy3BSouNmASMQ8xUXeiRwjb7xBaVTiDRjkmyPD7NYZdXuS93gFhyDFr5b3XLg7Rfj9nHEqtHDa7NmAX7iwDAbMUFEfiDEf9hrqZmpAYJracAjTTR8Cvn6mnDXMLwayNG8dcsXFodxok2qksYF4D8ffUxMRmyyQVQhhhmdSi4YaMPqTnC1J6HTG9Yfb98yGSVaWi4TApUhLXFow2ZvB6vqckCNhjCRL2R4MDUSk71qzxWHgezKyDeyThJgdxydrn1osqH94oSeA346eipkJvKqYREXBKwgB5VL6WF4qAK6sVZxJp2dQBfCPVZ4EbsBQaJXaVK7cNcWG8tZBFWZ79gG9Cu6C4u8yjBS8Ux6dCcJPUTLtixQu4z2n5dCsVSNdnP1EEs8ZerZo5pBgc68w4Yuf9KL3xVxPnAB1nRCBfs9cMU6oL1EdyHbqrTfnjE8HpY164akBqe92LFVsk8RusaGsVPrMekT8emTq5y8v8CabuZg5rDs3f9NPEtogjyx49wiub1FecM5B7QqEcZSYiKHgF4mfkteT2" + ], + "keyAgreement": [ + "did:key:zgghBUVkqmWS8e1ioRVp2WN9Vw6x4NvnE9PGAyQsPqM3fnfPf8EdauiRVfBTcVDyzhqM5FFC7ekAvuV1cJHawtfgB9wDcru1hPDobk3hqyedijhgWmsYfJCmodkiiFnjNWATE7PvqTyoCjcmrc8yMRXmFPnoASyT5beUd4YZxTE9VfgmavcPy3BSouNmASMQ8xUXeiRwjb7xBaVTiDRjkmyPD7NYZdXuS93gFhyDFr5b3XLg7Rfj9nHEqtHDa7NmAX7iwDAbMUFEfiDEf9hrqZmpAYJracAjTTR8Cvn6mnDXMLwayNG8dcsXFodxok2qksYF4D8ffUxMRmyyQVQhhhmdSi4YaMPqTnC1J6HTG9Yfb98yGSVaWi4TApUhLXFow2ZvB6vqckCNhjCRL2R4MDUSk71qzxWHgezKyDeyThJgdxydrn1osqH94oSeA346eipkJvKqYREXBKwgB5VL6WF4qAK6sVZxJp2dQBfCPVZ4EbsBQaJXaVK7cNcWG8tZBFWZ79gG9Cu6C4u8yjBS8Ux6dCcJPUTLtixQu4z2n5dCsVSNdnP1EEs8ZerZo5pBgc68w4Yuf9KL3xVxPnAB1nRCBfs9cMU6oL1EdyHbqrTfnjE8HpY164akBqe92LFVsk8RusaGsVPrMekT8emTq5y8v8CabuZg5rDs3f9NPEtogjyx49wiub1FecM5B7QqEcZSYiKHgF4mfkteT2#zgghBUVkqmWS8e1ioRVp2WN9Vw6x4NvnE9PGAyQsPqM3fnfPf8EdauiRVfBTcVDyzhqM5FFC7ekAvuV1cJHawtfgB9wDcru1hPDobk3hqyedijhgWmsYfJCmodkiiFnjNWATE7PvqTyoCjcmrc8yMRXmFPnoASyT5beUd4YZxTE9VfgmavcPy3BSouNmASMQ8xUXeiRwjb7xBaVTiDRjkmyPD7NYZdXuS93gFhyDFr5b3XLg7Rfj9nHEqtHDa7NmAX7iwDAbMUFEfiDEf9hrqZmpAYJracAjTTR8Cvn6mnDXMLwayNG8dcsXFodxok2qksYF4D8ffUxMRmyyQVQhhhmdSi4YaMPqTnC1J6HTG9Yfb98yGSVaWi4TApUhLXFow2ZvB6vqckCNhjCRL2R4MDUSk71qzxWHgezKyDeyThJgdxydrn1osqH94oSeA346eipkJvKqYREXBKwgB5VL6WF4qAK6sVZxJp2dQBfCPVZ4EbsBQaJXaVK7cNcWG8tZBFWZ79gG9Cu6C4u8yjBS8Ux6dCcJPUTLtixQu4z2n5dCsVSNdnP1EEs8ZerZo5pBgc68w4Yuf9KL3xVxPnAB1nRCBfs9cMU6oL1EdyHbqrTfnjE8HpY164akBqe92LFVsk8RusaGsVPrMekT8emTq5y8v8CabuZg5rDs3f9NPEtogjyx49wiub1FecM5B7QqEcZSYiKHgF4mfkteT2" + ] + } + } +} diff --git a/did/testdata/secp256k1.json b/did/testdata/secp256k1.json new file mode 100644 index 0000000..d7d9948 --- /dev/null +++ b/did/testdata/secp256k1.json @@ -0,0 +1,257 @@ +{ + "did:key:zQ3shokFTS3brHcDQrn82RUDfCZESWL1ZdCEJwekUDPQiYBme": { + "seed": "9085d2bef69286a6cbb51623c8fa258629945cd55ca705cc4e66700396894e0c", + "verificationKeyPair": { + "id": "#zQ3shokFTS3brHcDQrn82RUDfCZESWL1ZdCEJwekUDPQiYBme", + "type": "EcdsaSecp256k1VerificationKey2019", + "controller": "did:key:zQ3shokFTS3brHcDQrn82RUDfCZESWL1ZdCEJwekUDPQiYBme", + "publicKeyBase58": "23o6Sau8NxxzXcgSc3PLcNxrzrZpbLeBn1izfv3jbKhuv", + "privateKeyBase58": "AjA4cyPUbbfW5wr6iZeRbJLhgH3qDt6q6LMkRw36KpxT" + }, + "didDocument": { + "@context": [ + "https://www.w3.org/ns/did/v1", + "https://w3id.org/security/suites/secp256k1-2019/v1" + ], + "id": "did:key:zQ3shokFTS3brHcDQrn82RUDfCZESWL1ZdCEJwekUDPQiYBme", + "verificationMethod": [ + { + "id": "did:key:zQ3shokFTS3brHcDQrn82RUDfCZESWL1ZdCEJwekUDPQiYBme#zQ3shokFTS3brHcDQrn82RUDfCZESWL1ZdCEJwekUDPQiYBme", + "type": "EcdsaSecp256k1VerificationKey2019", + "controller": "did:key:zQ3shokFTS3brHcDQrn82RUDfCZESWL1ZdCEJwekUDPQiYBme", + "publicKeyBase58": "23o6Sau8NxxzXcgSc3PLcNxrzrZpbLeBn1izfv3jbKhuv" + } + ], + "assertionMethod": [ + "did:key:zQ3shokFTS3brHcDQrn82RUDfCZESWL1ZdCEJwekUDPQiYBme#zQ3shokFTS3brHcDQrn82RUDfCZESWL1ZdCEJwekUDPQiYBme" + ], + "authentication": [ + "did:key:zQ3shokFTS3brHcDQrn82RUDfCZESWL1ZdCEJwekUDPQiYBme#zQ3shokFTS3brHcDQrn82RUDfCZESWL1ZdCEJwekUDPQiYBme" + ], + "capabilityInvocation": [ + "did:key:zQ3shokFTS3brHcDQrn82RUDfCZESWL1ZdCEJwekUDPQiYBme#zQ3shokFTS3brHcDQrn82RUDfCZESWL1ZdCEJwekUDPQiYBme" + ], + "capabilityDelegation": [ + "did:key:zQ3shokFTS3brHcDQrn82RUDfCZESWL1ZdCEJwekUDPQiYBme#zQ3shokFTS3brHcDQrn82RUDfCZESWL1ZdCEJwekUDPQiYBme" + ], + "keyAgreement": [ + "did:key:zQ3shokFTS3brHcDQrn82RUDfCZESWL1ZdCEJwekUDPQiYBme#zQ3shokFTS3brHcDQrn82RUDfCZESWL1ZdCEJwekUDPQiYBme" + ] + } + }, + "did:key:zQ3shtxV1FrJfhqE1dvxYRcCknWNjHc3c5X1y3ZSoPDi2aur2": { + "seed": "f0f4df55a2b3ff13051ea814a8f24ad00f2e469af73c363ac7e9fb999a9072ed", + "verificationKeyPair": { + "id": "#zQ3shtxV1FrJfhqE1dvxYRcCknWNjHc3c5X1y3ZSoPDi2aur2", + "type": "EcdsaSecp256k1VerificationKey2019", + "controller": "did:key:zQ3shtxV1FrJfhqE1dvxYRcCknWNjHc3c5X1y3ZSoPDi2aur2", + "publicKeyBase58": "291KzQhqCPC18PqH83XKhxv1HdqrdnxyS7dh15t2uNRzJ", + "privateKeyBase58": "HDbR1D5W3CoNbUKYzUbHH2PRF1atshtVupXgXTQhNB9E" + }, + "didDocument": { + "@context": [ + "https://www.w3.org/ns/did/v1", + "https://w3id.org/security/suites/secp256k1-2019/v1" + ], + "id": "did:key:zQ3shtxV1FrJfhqE1dvxYRcCknWNjHc3c5X1y3ZSoPDi2aur2", + "verificationMethod": [ + { + "id": "did:key:zQ3shtxV1FrJfhqE1dvxYRcCknWNjHc3c5X1y3ZSoPDi2aur2#zQ3shtxV1FrJfhqE1dvxYRcCknWNjHc3c5X1y3ZSoPDi2aur2", + "type": "EcdsaSecp256k1VerificationKey2019", + "controller": "did:key:zQ3shtxV1FrJfhqE1dvxYRcCknWNjHc3c5X1y3ZSoPDi2aur2", + "publicKeyBase58": "291KzQhqCPC18PqH83XKhxv1HdqrdnxyS7dh15t2uNRzJ" + } + ], + "assertionMethod": [ + "did:key:zQ3shtxV1FrJfhqE1dvxYRcCknWNjHc3c5X1y3ZSoPDi2aur2#zQ3shtxV1FrJfhqE1dvxYRcCknWNjHc3c5X1y3ZSoPDi2aur2" + ], + "authentication": [ + "did:key:zQ3shtxV1FrJfhqE1dvxYRcCknWNjHc3c5X1y3ZSoPDi2aur2#zQ3shtxV1FrJfhqE1dvxYRcCknWNjHc3c5X1y3ZSoPDi2aur2" + ], + "capabilityInvocation": [ + "did:key:zQ3shtxV1FrJfhqE1dvxYRcCknWNjHc3c5X1y3ZSoPDi2aur2#zQ3shtxV1FrJfhqE1dvxYRcCknWNjHc3c5X1y3ZSoPDi2aur2" + ], + "capabilityDelegation": [ + "did:key:zQ3shtxV1FrJfhqE1dvxYRcCknWNjHc3c5X1y3ZSoPDi2aur2#zQ3shtxV1FrJfhqE1dvxYRcCknWNjHc3c5X1y3ZSoPDi2aur2" + ], + "keyAgreement": [ + "did:key:zQ3shtxV1FrJfhqE1dvxYRcCknWNjHc3c5X1y3ZSoPDi2aur2#zQ3shtxV1FrJfhqE1dvxYRcCknWNjHc3c5X1y3ZSoPDi2aur2" + ] + } + }, + "did:key:zQ3shZc2QzApp2oymGvQbzP8eKheVshBHbU4ZYjeXqwSKEn6N": { + "seed": "6b0b91287ae3348f8c2f2552d766f30e3604867e34adc37ccbb74a8e6b893e02", + "verificationKeyPair": { + "id": "#zQ3shZc2QzApp2oymGvQbzP8eKheVshBHbU4ZYjeXqwSKEn6N", + "type": "EcdsaSecp256k1VerificationKey2019", + "controller": "did:key:zQ3shZc2QzApp2oymGvQbzP8eKheVshBHbU4ZYjeXqwSKEn6N", + "publicKeyBase58": "oesQ92MLiAkt2pjBcJFbW7H4DvzKJv22cotjYbmC2JEe", + "privateKeyBase58": "8CrrWVdzDnvaS7vS5dd2HetFSebwEN46XEFrNDdtWZSZ" + }, + "didDocument": { + "@context": [ + "https://www.w3.org/ns/did/v1", + "https://w3id.org/security/suites/secp256k1-2019/v1" + ], + "id": "did:key:zQ3shZc2QzApp2oymGvQbzP8eKheVshBHbU4ZYjeXqwSKEn6N", + "verificationMethod": [ + { + "id": "did:key:zQ3shZc2QzApp2oymGvQbzP8eKheVshBHbU4ZYjeXqwSKEn6N#zQ3shZc2QzApp2oymGvQbzP8eKheVshBHbU4ZYjeXqwSKEn6N", + "type": "EcdsaSecp256k1VerificationKey2019", + "controller": "did:key:zQ3shZc2QzApp2oymGvQbzP8eKheVshBHbU4ZYjeXqwSKEn6N", + "publicKeyBase58": "oesQ92MLiAkt2pjBcJFbW7H4DvzKJv22cotjYbmC2JEe" + } + ], + "assertionMethod": [ + "did:key:zQ3shZc2QzApp2oymGvQbzP8eKheVshBHbU4ZYjeXqwSKEn6N#zQ3shZc2QzApp2oymGvQbzP8eKheVshBHbU4ZYjeXqwSKEn6N" + ], + "authentication": [ + "did:key:zQ3shZc2QzApp2oymGvQbzP8eKheVshBHbU4ZYjeXqwSKEn6N#zQ3shZc2QzApp2oymGvQbzP8eKheVshBHbU4ZYjeXqwSKEn6N" + ], + "capabilityInvocation": [ + "did:key:zQ3shZc2QzApp2oymGvQbzP8eKheVshBHbU4ZYjeXqwSKEn6N#zQ3shZc2QzApp2oymGvQbzP8eKheVshBHbU4ZYjeXqwSKEn6N" + ], + "capabilityDelegation": [ + "did:key:zQ3shZc2QzApp2oymGvQbzP8eKheVshBHbU4ZYjeXqwSKEn6N#zQ3shZc2QzApp2oymGvQbzP8eKheVshBHbU4ZYjeXqwSKEn6N" + ], + "keyAgreement": [ + "did:key:zQ3shZc2QzApp2oymGvQbzP8eKheVshBHbU4ZYjeXqwSKEn6N#zQ3shZc2QzApp2oymGvQbzP8eKheVshBHbU4ZYjeXqwSKEn6N" + ] + } + }, + "did:key:zQ3shadCps5JLAHcZiuX5YUtWHHL8ysBJqFLWvjZDKAWUBGzy": { + "seed": "c0a6a7c560d37d7ba81ecee9543721ff48fea3e0fb827d42c1868226540fac15", + "verificationKeyPair": { + "id": "#zQ3shadCps5JLAHcZiuX5YUtWHHL8ysBJqFLWvjZDKAWUBGzy", + "type": "EcdsaSecp256k1VerificationKey2019", + "controller": "did:key:zQ3shadCps5JLAHcZiuX5YUtWHHL8ysBJqFLWvjZDKAWUBGzy", + "publicKeyBase58": "pg3p1vprqePgUoqfAQ1TTgxhL6zLYhHyzooR1pqLxo9F", + "privateKeyBase58": "Dy2fnt8ba4NmbRBXas9bo1BtYgpYFr6ThpFhJbuA3PRn" + }, + "didDocument": { + "@context": [ + "https://www.w3.org/ns/did/v1", + "https://w3id.org/security/suites/secp256k1-2019/v1" + ], + "id": "did:key:zQ3shadCps5JLAHcZiuX5YUtWHHL8ysBJqFLWvjZDKAWUBGzy", + "verificationMethod": [ + { + "id": "did:key:zQ3shadCps5JLAHcZiuX5YUtWHHL8ysBJqFLWvjZDKAWUBGzy#zQ3shadCps5JLAHcZiuX5YUtWHHL8ysBJqFLWvjZDKAWUBGzy", + "type": "EcdsaSecp256k1VerificationKey2019", + "controller": "did:key:zQ3shadCps5JLAHcZiuX5YUtWHHL8ysBJqFLWvjZDKAWUBGzy", + "publicKeyBase58": "pg3p1vprqePgUoqfAQ1TTgxhL6zLYhHyzooR1pqLxo9F" + } + ], + "assertionMethod": [ + "did:key:zQ3shadCps5JLAHcZiuX5YUtWHHL8ysBJqFLWvjZDKAWUBGzy#zQ3shadCps5JLAHcZiuX5YUtWHHL8ysBJqFLWvjZDKAWUBGzy" + ], + "authentication": [ + "did:key:zQ3shadCps5JLAHcZiuX5YUtWHHL8ysBJqFLWvjZDKAWUBGzy#zQ3shadCps5JLAHcZiuX5YUtWHHL8ysBJqFLWvjZDKAWUBGzy" + ], + "capabilityInvocation": [ + "did:key:zQ3shadCps5JLAHcZiuX5YUtWHHL8ysBJqFLWvjZDKAWUBGzy#zQ3shadCps5JLAHcZiuX5YUtWHHL8ysBJqFLWvjZDKAWUBGzy" + ], + "capabilityDelegation": [ + "did:key:zQ3shadCps5JLAHcZiuX5YUtWHHL8ysBJqFLWvjZDKAWUBGzy#zQ3shadCps5JLAHcZiuX5YUtWHHL8ysBJqFLWvjZDKAWUBGzy" + ], + "keyAgreement": [ + "did:key:zQ3shadCps5JLAHcZiuX5YUtWHHL8ysBJqFLWvjZDKAWUBGzy#zQ3shadCps5JLAHcZiuX5YUtWHHL8ysBJqFLWvjZDKAWUBGzy" + ] + } + }, + "did:key:zQ3shptjE6JwdkeKN4fcpnYQY3m9Cet3NiHdAfpvSUZBFoKBj": { + "seed": "175a232d440be1e0788f25488a73d9416c04b6f924bea6354bf05dd2f1a75133", + "verificationKeyPair": { + "id": "#zQ3shptjE6JwdkeKN4fcpnYQY3m9Cet3NiHdAfpvSUZBFoKBj", + "type": "EcdsaSecp256k1VerificationKey2019", + "controller": "did:key:zQ3shptjE6JwdkeKN4fcpnYQY3m9Cet3NiHdAfpvSUZBFoKBj", + "publicKeyBase58": "24waDFAUAS16UpZwQQTXVEAmm17rQRjadjuAeBDW8aqL1", + "privateKeyBase58": "2aA6WgZnPiVMBX3LvKSTg3KaFKyzfKpvEacixB3yyTgv" + }, + "didDocument": { + "@context": [ + "https://www.w3.org/ns/did/v1", + "https://w3id.org/security/suites/secp256k1-2019/v1" + ], + "id": "did:key:zQ3shptjE6JwdkeKN4fcpnYQY3m9Cet3NiHdAfpvSUZBFoKBj", + "verificationMethod": [ + { + "id": "did:key:zQ3shptjE6JwdkeKN4fcpnYQY3m9Cet3NiHdAfpvSUZBFoKBj#zQ3shptjE6JwdkeKN4fcpnYQY3m9Cet3NiHdAfpvSUZBFoKBj", + "type": "EcdsaSecp256k1VerificationKey2019", + "controller": "did:key:zQ3shptjE6JwdkeKN4fcpnYQY3m9Cet3NiHdAfpvSUZBFoKBj", + "publicKeyBase58": "24waDFAUAS16UpZwQQTXVEAmm17rQRjadjuAeBDW8aqL1" + } + ], + "assertionMethod": [ + "did:key:zQ3shptjE6JwdkeKN4fcpnYQY3m9Cet3NiHdAfpvSUZBFoKBj#zQ3shptjE6JwdkeKN4fcpnYQY3m9Cet3NiHdAfpvSUZBFoKBj" + ], + "authentication": [ + "did:key:zQ3shptjE6JwdkeKN4fcpnYQY3m9Cet3NiHdAfpvSUZBFoKBj#zQ3shptjE6JwdkeKN4fcpnYQY3m9Cet3NiHdAfpvSUZBFoKBj" + ], + "capabilityInvocation": [ + "did:key:zQ3shptjE6JwdkeKN4fcpnYQY3m9Cet3NiHdAfpvSUZBFoKBj#zQ3shptjE6JwdkeKN4fcpnYQY3m9Cet3NiHdAfpvSUZBFoKBj" + ], + "capabilityDelegation": [ + "did:key:zQ3shptjE6JwdkeKN4fcpnYQY3m9Cet3NiHdAfpvSUZBFoKBj#zQ3shptjE6JwdkeKN4fcpnYQY3m9Cet3NiHdAfpvSUZBFoKBj" + ], + "keyAgreement": [ + "did:key:zQ3shptjE6JwdkeKN4fcpnYQY3m9Cet3NiHdAfpvSUZBFoKBj#zQ3shptjE6JwdkeKN4fcpnYQY3m9Cet3NiHdAfpvSUZBFoKBj" + ] + } + }, + "did:key:zQ3shjmnWpSDEbYKpaFm4kTs9kXyqG6N2QwCYHNPP4yubqgJS": { + "verificationKeyPair": { + "id": "did:key:zQ3shjmnWpSDEbYKpaFm4kTs9kXyqG6N2QwCYHNPP4yubqgJS#zQ3shjmnWpSDEbYKpaFm4kTs9kXyqG6N2QwCYHNPP4yubqgJS", + "type": "JsonWebKey2020", + "controller": "did:key:zQ3shjmnWpSDEbYKpaFm4kTs9kXyqG6N2QwCYHNPP4yubqgJS", + "publicKeyJwk": { + "kty": "EC", + "crv": "secp256k1", + "x": "TEIJN9vnTq1EXMkqzo7yN_867-foKc2pREv45Fw_QA8", + "y": "9yiymlzdxKCiRbYq7p-ArRB-C1ytjHE-eb7RDTi6rVc" + }, + "privateKeyJwk": { + "kty": "EC", + "crv": "secp256k1", + "x": "TEIJN9vnTq1EXMkqzo7yN_867-foKc2pREv45Fw_QA8", + "y": "9yiymlzdxKCiRbYq7p-ArRB-C1ytjHE-eb7RDTi6rVc", + "d": "J5yKm7OXFsXDEutteGYeT0CAfQJwIlHLSYkQxKtgiyo" + } + }, + "didDocument": { + "@context": [ + "https://www.w3.org/ns/did/v1", + "https://w3id.org/security/suites/jws-2020/v1" + ], + "id": "did:key:zQ3shjmnWpSDEbYKpaFm4kTs9kXyqG6N2QwCYHNPP4yubqgJS", + "verificationMethod": [ + { + "id": "did:key:zQ3shjmnWpSDEbYKpaFm4kTs9kXyqG6N2QwCYHNPP4yubqgJS#zQ3shjmnWpSDEbYKpaFm4kTs9kXyqG6N2QwCYHNPP4yubqgJS", + "type": "JsonWebKey2020", + "controller": "did:key:zQ3shjmnWpSDEbYKpaFm4kTs9kXyqG6N2QwCYHNPP4yubqgJS", + "publicKeyJwk": { + "kty": "EC", + "crv": "secp256k1", + "x": "TEIJN9vnTq1EXMkqzo7yN_867-foKc2pREv45Fw_QA8", + "y": "9yiymlzdxKCiRbYq7p-ArRB-C1ytjHE-eb7RDTi6rVc" + } + } + ], + "assertionMethod": [ + "did:key:zQ3shjmnWpSDEbYKpaFm4kTs9kXyqG6N2QwCYHNPP4yubqgJS#zQ3shjmnWpSDEbYKpaFm4kTs9kXyqG6N2QwCYHNPP4yubqgJS" + ], + "authentication": [ + "did:key:zQ3shjmnWpSDEbYKpaFm4kTs9kXyqG6N2QwCYHNPP4yubqgJS#zQ3shjmnWpSDEbYKpaFm4kTs9kXyqG6N2QwCYHNPP4yubqgJS" + ], + "capabilityInvocation": [ + "did:key:zQ3shjmnWpSDEbYKpaFm4kTs9kXyqG6N2QwCYHNPP4yubqgJS#zQ3shjmnWpSDEbYKpaFm4kTs9kXyqG6N2QwCYHNPP4yubqgJS" + ], + "capabilityDelegation": [ + "did:key:zQ3shjmnWpSDEbYKpaFm4kTs9kXyqG6N2QwCYHNPP4yubqgJS#zQ3shjmnWpSDEbYKpaFm4kTs9kXyqG6N2QwCYHNPP4yubqgJS" + ], + "keyAgreement": [ + "did:key:zQ3shjmnWpSDEbYKpaFm4kTs9kXyqG6N2QwCYHNPP4yubqgJS#zQ3shjmnWpSDEbYKpaFm4kTs9kXyqG6N2QwCYHNPP4yubqgJS" + ] + } + } +} diff --git a/did/testdata/x25519.json b/did/testdata/x25519.json new file mode 100644 index 0000000..6d02e43 --- /dev/null +++ b/did/testdata/x25519.json @@ -0,0 +1,80 @@ +{ + "didDocument": { + "did:key:z6LSeu9HkTHSfLLeUs2nnzUSNedgDUevfNQgQjQC23ZCit6F": { + "@context": [ + "https://www.w3.org/ns/did/v1", + "https://w3id.org/security/suites/x25519-2019/v1" + ], + "id": "did:key:z6LSeu9HkTHSfLLeUs2nnzUSNedgDUevfNQgQjQC23ZCit6F", + "verificationMethod": [ + { + "id": "did:key:z6LSeu9HkTHSfLLeUs2nnzUSNedgDUevfNQgQjQC23ZCit6F#z6LSeu9HkTHSfLLeUs2nnzUSNedgDUevfNQgQjQC23ZCit6F", + "type": "X25519KeyAgreementKey2019", + "controller": "did:key:z6LSeu9HkTHSfLLeUs2nnzUSNedgDUevfNQgQjQC23ZCit6F", + "publicKeyBase58": "4Dy8E9UaZscuPUf2GLxV44RCNL7oxmEXXkgWXaug1WKV" + } + ], + "keyAgreement": [ + "did:key:z6LSeu9HkTHSfLLeUs2nnzUSNedgDUevfNQgQjQC23ZCit6F#z6LSeu9HkTHSfLLeUs2nnzUSNedgDUevfNQgQjQC23ZCit6F" + ] + }, + "did:key:z6LStiZsmxiK4odS4Sb6JmdRFuJ6e1SYP157gtiCyJKfrYha": { + "@context": [ + "https://www.w3.org/ns/did/v1", + "https://w3id.org/security/suites/x25519-2019/v1" + ], + "id": "did:key:z6LStiZsmxiK4odS4Sb6JmdRFuJ6e1SYP157gtiCyJKfrYha", + "verificationMethod": [ + { + "id": "did:key:z6LStiZsmxiK4odS4Sb6JmdRFuJ6e1SYP157gtiCyJKfrYha#z6LStiZsmxiK4odS4Sb6JmdRFuJ6e1SYP157gtiCyJKfrYha", + "type": "X25519KeyAgreementKey2019", + "controller": "did:key:z6LStiZsmxiK4odS4Sb6JmdRFuJ6e1SYP157gtiCyJKfrYha", + "publicKeyBase58": "J3PiFeuSyLugy4DKn87TwK5cnruRgPtxouzXUqg99Avp" + } + ], + "keyAgreement": [ + "did:key:z6LStiZsmxiK4odS4Sb6JmdRFuJ6e1SYP157gtiCyJKfrYha#z6LStiZsmxiK4odS4Sb6JmdRFuJ6e1SYP157gtiCyJKfrYha" + ] + }, + "did:key:z6LSoMdmJz2Djah2P4L9taDmtqeJ6wwd2HhKZvNToBmvaczQ": { + "@context": [ + "https://www.w3.org/ns/did/v1", + "https://w3id.org/security/suites/x25519-2019/v1" + ], + "id": "did:key:z6LSoMdmJz2Djah2P4L9taDmtqeJ6wwd2HhKZvNToBmvaczQ", + "verificationMethod": [ + { + "id": "did:key:z6LSoMdmJz2Djah2P4L9taDmtqeJ6wwd2HhKZvNToBmvaczQ#z6LSoMdmJz2Djah2P4L9taDmtqeJ6wwd2HhKZvNToBmvaczQ", + "type": "X25519KeyAgreementKey2019", + "controller": "did:key:z6LSoMdmJz2Djah2P4L9taDmtqeJ6wwd2HhKZvNToBmvaczQ", + "publicKeyBase58": "CgTbngDMe7yHHfxPMvhpaFRpFoQWKgXAgwenJj8PsFDe" + } + ], + "keyAgreement": [ + "did:key:z6LSoMdmJz2Djah2P4L9taDmtqeJ6wwd2HhKZvNToBmvaczQ#z6LSoMdmJz2Djah2P4L9taDmtqeJ6wwd2HhKZvNToBmvaczQ" + ] + }, + "did:key:z6LSrzxMVydCourtpA6JLEYupT7ZUQ34hLfQZfRN5H47zLdz": { + "@context": [ + "https://www.w3.org/ns/did/v1", + "https://w3id.org/security/suites/jws-2020/v1" + ], + "id": "did:key:z6LSrzxMVydCourtpA6JLEYupT7ZUQ34hLfQZfRN5H47zLdz", + "verificationMethod": [ + { + "id": "did:key:z6LSrzxMVydCourtpA6JLEYupT7ZUQ34hLfQZfRN5H47zLdz#z6LSrzxMVydCourtpA6JLEYupT7ZUQ34hLfQZfRN5H47zLdz", + "type": "JsonWebKey2020", + "controller": "did:key:z6LSrzxMVydCourtpA6JLEYupT7ZUQ34hLfQZfRN5H47zLdz", + "publicKeyJwk": { + "kty": "OKP", + "crv": "X25519", + "x": "467ap28wHJGEXJAb4mLrokqq8A-txA_KmoQTcj31XzU" + } + } + ], + "keyAgreement": [ + "did:key:z6LSrzxMVydCourtpA6JLEYupT7ZUQ34hLfQZfRN5H47zLdz#z6LSrzxMVydCourtpA6JLEYupT7ZUQ34hLfQZfRN5H47zLdz" + ] + } + } +} From 2bd177ce4d039b34ec8f5a0eb1aa49edc9332ad2 Mon Sep 17 00:00:00 2001 From: Steve Moyer Date: Mon, 21 Oct 2024 10:59:27 -0400 Subject: [PATCH 05/11] fix(did): correct function names for key/DID generators --- did/crypto.go | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/did/crypto.go b/did/crypto.go index 9b11d75..4546a52 100644 --- a/did/crypto.go +++ b/did/crypto.go @@ -28,7 +28,7 @@ func GenerateEd25519() (crypto.PrivKey, DID, error) { } // GenerateRSA generates a RSA private key and the matching DID. -func GenerateSecp256k1() (crypto.PrivKey, DID, error) { +func GenerateRSA() (crypto.PrivKey, DID, error) { // NIST Special Publication 800-57 Part 1 Revision 5 // Section 5.6.1.1 (Table 2) // Paraphrased: 2048-bit RSA keys are secure until 2030 and 3072-bit keys are recommended for longer-term security. @@ -43,7 +43,7 @@ func GenerateSecp256k1() (crypto.PrivKey, DID, error) { } // GenerateEd25519 generates a Secp256k1 private key and the matching DID. -func GenerateRSA() (crypto.PrivKey, DID, error) { +func GenerateSecp256k1() (crypto.PrivKey, DID, error) { priv, pub, err := crypto.GenerateSecp256k1Key(rand.Reader) if err != nil { return nil, Undef, nil From 6011f0740ab25c4008cdebdd2ef7b4116812b500 Mon Sep 17 00:00:00 2001 From: Steve Moyer Date: Mon, 21 Oct 2024 11:03:43 -0400 Subject: [PATCH 06/11] fix(did): finish the GenerateECDSAWithCurve function --- did/crypto.go | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) diff --git a/did/crypto.go b/did/crypto.go index 4546a52..8eed59a 100644 --- a/did/crypto.go +++ b/did/crypto.go @@ -79,11 +79,9 @@ func GenerateECDSAWithCurve(code multicodec.Code) (crypto.PrivKey, DID, error) { return nil, Undef, err } - _ = priv - _ = pub - - return nil, Undef, nil // TODO + did, err := FromPubKey(pub) + return priv, did, err } // FromPrivKey is a convenience function that returns the DID associated From 87e25090bb847be5e9612db02855b9fddbab7b08 Mon Sep 17 00:00:00 2001 From: Steve Moyer Date: Mon, 21 Oct 2024 15:29:51 -0400 Subject: [PATCH 07/11] test(did): verifies that ECDSA keys with the secp256k1 curve are "coerced" into crypto.Secp256k1 keys --- did/crypto_test.go | 24 +++++++++++++++++++++--- 1 file changed, 21 insertions(+), 3 deletions(-) diff --git a/did/crypto_test.go b/did/crypto_test.go index 43d0bea..c60f21b 100644 --- a/did/crypto_test.go +++ b/did/crypto_test.go @@ -5,7 +5,9 @@ import ( "crypto/rand" "testing" + "github.com/decred/dcrd/dcrec/secp256k1/v4" "github.com/libp2p/go-libp2p/core/crypto" + "github.com/libp2p/go-libp2p/core/crypto/pb" "github.com/multiformats/go-multicodec" "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" @@ -27,6 +29,8 @@ func TestFromPubKey(t *testing.T) { require.NoError(t, err) _, ecdsaP521, err := crypto.GenerateECDSAKeyPairWithCurve(elliptic.P521(), rand.Reader) require.NoError(t, err) + _, ecdsaSecp256k1, err := crypto.GenerateECDSAKeyPairWithCurve(secp256k1.S256(), rand.Reader) + require.NoError(t, err) _, ed25519, err := crypto.GenerateEd25519Key(rand.Reader) require.NoError(t, err) _, rsa, err := crypto.GenerateRSAKeyPair(2048, rand.Reader) @@ -55,9 +59,23 @@ func TestFromPubKey(t *testing.T) { t.Run("RSA", test(rsa, did.RSA)) t.Run("secp256k1", test(secp256k1PubKey1, did.Secp256k1)) - id, err := did.FromPubKey(examplePubKey(t)) - require.NoError(t, err) - require.Equal(t, exampleDID(t), id) + t.Run("ECDSA with secp256k1 curve (coerced)", func(t *testing.T) { + t.Parallel() + + id, err := did.FromPubKey(ecdsaSecp256k1) + require.NoError(t, err) + p, err := id.PubKey() + require.NoError(t, err) + require.Equal(t, pb.KeyType_Secp256k1, p.Type()) + }) + + t.Run("unmarshaled example key (secp256k1)", func(t *testing.T) { + t.Parallel() + + id, err := did.FromPubKey(examplePubKey(t)) + require.NoError(t, err) + require.Equal(t, exampleDID(t), id) + }) } func TestToPubKey(t *testing.T) { From 2ffdf004acef73d74d6c08a6ba096451e43e36c9 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Michael=20Mur=C3=A9?= Date: Thu, 24 Oct 2024 12:03:23 +0200 Subject: [PATCH 08/11] test(did): split the test vector reading code in a separate file/package tests are much cleaner and explicit now --- did/key_spec_test.go | 175 +----------------- did/{testdata => testvectors}/bls12381.json | 0 .../ed25519-x25519.json | 0 .../nist-curves.json | 0 did/{testdata => testvectors}/rsa.json | 0 did/{testdata => testvectors}/secp256k1.json | 0 did/testvectors/vectors.go | 163 ++++++++++++++++ did/{testdata => testvectors}/x25519.json | 0 8 files changed, 171 insertions(+), 167 deletions(-) rename did/{testdata => testvectors}/bls12381.json (100%) rename did/{testdata => testvectors}/ed25519-x25519.json (100%) rename did/{testdata => testvectors}/nist-curves.json (100%) rename did/{testdata => testvectors}/rsa.json (100%) rename did/{testdata => testvectors}/secp256k1.json (100%) create mode 100644 did/testvectors/vectors.go rename did/{testdata => testvectors}/x25519.json (100%) diff --git a/did/key_spec_test.go b/did/key_spec_test.go index bcc5098..7d4e4b2 100644 --- a/did/key_spec_test.go +++ b/did/key_spec_test.go @@ -1,26 +1,19 @@ -// go:build jwx_es256k +//go:build jwx_es256k package did_test import ( - "crypto/ecdsa" - "crypto/ed25519" - "crypto/elliptic" - "crypto/rsa" - "crypto/x509" "encoding/json" - "errors" "os" "path/filepath" "testing" - "github.com/decred/dcrd/dcrec/secp256k1/v4" - "github.com/lestrrat-go/jwx/v2/jwk" "github.com/libp2p/go-libp2p/core/crypto" - "github.com/mr-tron/base58" "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" + "github.com/ucan-wg/go-ucan/did" + "github.com/ucan-wg/go-ucan/did/testvectors" ) // TestDidKeyVectors executes tests read from the [test vector files] provided @@ -67,177 +60,25 @@ func TestDidKeyVectors(t *testing.T) { } } -func loadTestVectors(t *testing.T, filename string) vectors { +func loadTestVectors(t *testing.T, filename string) testvectors.Vectors { t.Helper() - data, err := os.ReadFile(filepath.Join("testdata", filename)) + data, err := os.ReadFile(filepath.Join("testvectors", filename)) require.NoError(t, err) - var vs vectors + var vs testvectors.Vectors require.NoError(t, json.Unmarshal(data, &vs)) return vs } -func vectorPubKey(t *testing.T, v vector) crypto.PubKey { +func vectorPubKey(t *testing.T, v testvectors.Vector) crypto.PubKey { t.Helper() - pubKey, err := v.pubKey() + pubKey, err := v.PubKey() require.NoError(t, err) require.NotZero(t, pubKey) return pubKey } - -func vectorType(t *testing.T, v vector) string { - vectorType, err := v.pubKeyType() - require.NoError(t, err) - - return vectorType -} - -type vectors map[string]vector - -// This is pretty gross but the structure allows the repeated verifier, -// PublicKeyJwk and PublicKeyBase58 account for the fact that the test -// files are very inconsistent. -type vector struct { - VerificationKeyPair verifier - VerificationMethod verifier - PublicKeyJwk json.RawMessage - DidDocument json.RawMessage // TODO: if we start producing DID documents, we should test this too -} - -type verifier struct { - ID string - Type string - PublicKeyBase58 string - PublicKeyJwk json.RawMessage -} - -func (v vector) pubKey() (crypto.PubKey, error) { - // If the public key is in base58 - if pubB58 := v.pubKeyBase58(); len(pubB58) > 0 { - pubBytes, err := base58.Decode(pubB58) - if err != nil { - return nil, err - } - - t, err := v.pubKeyType() - if err != nil { - return nil, err - } - - var unmarshaler crypto.PubKeyUnmarshaller - - switch t { - case "Ed25519VerificationKey2018": - unmarshaler = crypto.UnmarshalEd25519PublicKey - case "EcdsaSecp256k1VerificationKey2019": - unmarshaler = crypto.UnmarshalSecp256k1PublicKey - // This is weak as it assumes the P256 curve - that's all the vectors contain (for now) - case "P256Key2021": - unmarshaler = compressedEcdsaPublicKeyUnmarshaler - default: - return nil, errors.New("failed to resolve unmarshaler") - } - - return unmarshaler(pubBytes) - } - - // If the public key is in a JWK - if pubJwk := v.pubKeyJwk(); len(pubJwk) > 0 { - key, err := jwk.ParseKey(pubJwk) - if err != nil { - return nil, err - } - - var a any - - if err := key.Raw(&a); err != nil { - return nil, err - } - - switch a.(type) { - case *ecdsa.PublicKey: - epub := a.(*ecdsa.PublicKey) - - if epub.Curve == secp256k1.S256() { - bytes := append([]byte{0x04}, append(epub.X.Bytes(), epub.Y.Bytes()...)...) - - return crypto.UnmarshalSecp256k1PublicKey(bytes) - } - - asn1, err := x509.MarshalPKIXPublicKey(epub) - if err != nil { - return nil, err - } - - return crypto.UnmarshalECDSAPublicKey(asn1) - case ed25519.PublicKey: - return crypto.UnmarshalEd25519PublicKey(a.(ed25519.PublicKey)) - case *rsa.PublicKey: - asn1, err := x509.MarshalPKIXPublicKey(a.(*rsa.PublicKey)) - if err != nil { - return nil, err - } - - return crypto.UnmarshalRsaPublicKey(asn1) - default: - return nil, errors.New("unsupported key type") - } - } - - // If we don't find a public key at all - return nil, errors.New("vector's public key not found") -} - -func (v vector) pubKeyBase58() string { - if len(v.VerificationKeyPair.PublicKeyBase58) > 0 { - return v.VerificationKeyPair.PublicKeyBase58 - } - - return v.VerificationMethod.PublicKeyBase58 -} - -func (v vector) pubKeyJwk() json.RawMessage { - if len(v.VerificationKeyPair.PublicKeyJwk) > 0 { - return v.VerificationKeyPair.PublicKeyJwk - } - - if len(v.VerificationMethod.PublicKeyJwk) > 0 { - return v.VerificationMethod.PublicKeyJwk - } - - return v.PublicKeyJwk -} - -func (v vector) pubKeyType() (string, error) { - if len(v.VerificationKeyPair.Type) > 0 { - return v.VerificationKeyPair.Type, nil - } - - if len(v.VerificationMethod.Type) > 0 { - return v.VerificationMethod.Type, nil - } - - return "", errors.New("vector's type not found") -} - -func compressedEcdsaPublicKeyUnmarshaler(data []byte) (crypto.PubKey, error) { - x, y := elliptic.UnmarshalCompressed(elliptic.P256(), data) - - ecdsaPublicKey := ecdsa.PublicKey{ - Curve: elliptic.P256(), - X: x, - Y: y, - } - - asn1, err := x509.MarshalPKIXPublicKey(&ecdsaPublicKey) - if err != nil { - return nil, err - } - - return crypto.UnmarshalECDSAPublicKey(asn1) -} diff --git a/did/testdata/bls12381.json b/did/testvectors/bls12381.json similarity index 100% rename from did/testdata/bls12381.json rename to did/testvectors/bls12381.json diff --git a/did/testdata/ed25519-x25519.json b/did/testvectors/ed25519-x25519.json similarity index 100% rename from did/testdata/ed25519-x25519.json rename to did/testvectors/ed25519-x25519.json diff --git a/did/testdata/nist-curves.json b/did/testvectors/nist-curves.json similarity index 100% rename from did/testdata/nist-curves.json rename to did/testvectors/nist-curves.json diff --git a/did/testdata/rsa.json b/did/testvectors/rsa.json similarity index 100% rename from did/testdata/rsa.json rename to did/testvectors/rsa.json diff --git a/did/testdata/secp256k1.json b/did/testvectors/secp256k1.json similarity index 100% rename from did/testdata/secp256k1.json rename to did/testvectors/secp256k1.json diff --git a/did/testvectors/vectors.go b/did/testvectors/vectors.go new file mode 100644 index 0000000..6e3cc2d --- /dev/null +++ b/did/testvectors/vectors.go @@ -0,0 +1,163 @@ +//go:build jwx_es256k + +package testvectors + +import ( + "crypto/ecdsa" + "crypto/ed25519" + "crypto/elliptic" + "crypto/rsa" + "crypto/x509" + "encoding/json" + "errors" + + "github.com/decred/dcrd/dcrec/secp256k1/v4" + "github.com/lestrrat-go/jwx/v2/jwk" + "github.com/libp2p/go-libp2p/core/crypto" + "github.com/mr-tron/base58" +) + +type Vectors map[string]Vector + +// This is pretty gross but the structure allows the repeated Verifier, +// PublicKeyJwk and PublicKeyBase58 account for the fact that the test +// files are very inconsistent. +type Vector struct { + VerificationKeyPair Verifier + VerificationMethod Verifier + PublicKeyJwk json.RawMessage + DidDocument json.RawMessage // TODO: if we start producing DID documents, we should test this too +} + +type Verifier struct { + ID string + Type string + PublicKeyBase58 string + PublicKeyJwk json.RawMessage +} + +func (v Vector) PubKey() (crypto.PubKey, error) { + // If the public key is in base58 + if pubB58 := v.PubKeyBase58(); len(pubB58) > 0 { + pubBytes, err := base58.Decode(pubB58) + if err != nil { + return nil, err + } + + t, err := v.PubKeyType() + if err != nil { + return nil, err + } + + var unmarshaler crypto.PubKeyUnmarshaller + + switch t { + case "Ed25519VerificationKey2018": + unmarshaler = crypto.UnmarshalEd25519PublicKey + case "EcdsaSecp256k1VerificationKey2019": + unmarshaler = crypto.UnmarshalSecp256k1PublicKey + // This is weak as it assumes the P256 curve - that's all the vectors contain (for now) + case "P256Key2021": + unmarshaler = compressedEcdsaPublicKeyUnmarshaler + default: + return nil, errors.New("failed to resolve unmarshaler") + } + + return unmarshaler(pubBytes) + } + + // If the public key is in a JWK + if pubJwk := v.PubKeyJwk(); len(pubJwk) > 0 { + key, err := jwk.ParseKey(pubJwk) + if err != nil { + return nil, err + } + + var a any + + if err := key.Raw(&a); err != nil { + return nil, err + } + + switch a.(type) { + case *ecdsa.PublicKey: + epub := a.(*ecdsa.PublicKey) + + if epub.Curve == secp256k1.S256() { + bytes := append([]byte{0x04}, append(epub.X.Bytes(), epub.Y.Bytes()...)...) + + return crypto.UnmarshalSecp256k1PublicKey(bytes) + } + + asn1, err := x509.MarshalPKIXPublicKey(epub) + if err != nil { + return nil, err + } + + return crypto.UnmarshalECDSAPublicKey(asn1) + case ed25519.PublicKey: + return crypto.UnmarshalEd25519PublicKey(a.(ed25519.PublicKey)) + case *rsa.PublicKey: + asn1, err := x509.MarshalPKIXPublicKey(a.(*rsa.PublicKey)) + if err != nil { + return nil, err + } + + return crypto.UnmarshalRsaPublicKey(asn1) + default: + return nil, errors.New("unsupported key type") + } + } + + // If we don't find a public key at all + return nil, errors.New("vector's public key not found") +} + +func (v Vector) PubKeyBase58() string { + if len(v.VerificationKeyPair.PublicKeyBase58) > 0 { + return v.VerificationKeyPair.PublicKeyBase58 + } + + return v.VerificationMethod.PublicKeyBase58 +} + +func (v Vector) PubKeyJwk() json.RawMessage { + if len(v.VerificationKeyPair.PublicKeyJwk) > 0 { + return v.VerificationKeyPair.PublicKeyJwk + } + + if len(v.VerificationMethod.PublicKeyJwk) > 0 { + return v.VerificationMethod.PublicKeyJwk + } + + return v.PublicKeyJwk +} + +func (v Vector) PubKeyType() (string, error) { + if len(v.VerificationKeyPair.Type) > 0 { + return v.VerificationKeyPair.Type, nil + } + + if len(v.VerificationMethod.Type) > 0 { + return v.VerificationMethod.Type, nil + } + + return "", errors.New("vector's type not found") +} + +func compressedEcdsaPublicKeyUnmarshaler(data []byte) (crypto.PubKey, error) { + x, y := elliptic.UnmarshalCompressed(elliptic.P256(), data) + + ecdsaPublicKey := ecdsa.PublicKey{ + Curve: elliptic.P256(), + X: x, + Y: y, + } + + asn1, err := x509.MarshalPKIXPublicKey(&ecdsaPublicKey) + if err != nil { + return nil, err + } + + return crypto.UnmarshalECDSAPublicKey(asn1) +} diff --git a/did/testdata/x25519.json b/did/testvectors/x25519.json similarity index 100% rename from did/testdata/x25519.json rename to did/testvectors/x25519.json From 2c58fedfd528925a42cdbf188e87fb5dbe03aed5 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Michael=20Mur=C3=A9?= Date: Thu, 24 Oct 2024 12:51:21 +0200 Subject: [PATCH 09/11] did: last cleanups --- did/did_test.go | 4 ---- did/key_spec_test.go | 10 ++++------ 2 files changed, 4 insertions(+), 10 deletions(-) diff --git a/did/did_test.go b/did/did_test.go index f536c32..47585af 100644 --- a/did/did_test.go +++ b/did/did_test.go @@ -25,10 +25,6 @@ func TestMustParseDIDKey(t *testing.T) { }) } -func TestRoundTrip(t *testing.T) { - // TODO: round-trip pubkey-->did-->pubkey for all supported types -} - func TestEquivalence(t *testing.T) { undef0 := DID{} undef1 := Undef diff --git a/did/key_spec_test.go b/did/key_spec_test.go index 7d4e4b2..51b8f76 100644 --- a/did/key_spec_test.go +++ b/did/key_spec_test.go @@ -34,18 +34,16 @@ func TestDidKeyVectors(t *testing.T) { // This test vector only contains a DID Document // "x25519.json", } { - vs := loadTestVectors(t, f) + vectors := loadTestVectors(t, f) t.Run(f, func(t *testing.T) { t.Parallel() - for k, v := range vs { - f := f - + for k, vector := range vectors { t.Run(k, func(t *testing.T) { - t.Parallel() + // round-trip pubkey-->did-->pubkey, verified against the test vectors. - exp := vectorPubKey(t, v) + exp := vectorPubKey(t, vector) id, err := did.FromPubKey(exp) require.NoError(t, err, f, k) From 0d63e90b67e52c8c3e13d6733a80ddf9735234c6 Mon Sep 17 00:00:00 2001 From: Steve Moyer Date: Thu, 24 Oct 2024 10:54:43 -0400 Subject: [PATCH 10/11] docs(did): add comment explaining why some ECDSA public keys are "coerced" to Secp256k1 public keys --- did/crypto.go | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/did/crypto.go b/did/crypto.go index 8eed59a..da2a7aa 100644 --- a/did/crypto.go +++ b/did/crypto.go @@ -200,6 +200,13 @@ func codeForCurve(pubKey crypto.PubKey) (multicodec.Code, error) { } } +// secp256k1.S256 is a valid ECDSA curve, but the go-libp2p/core/crypto +// package treats it ask a different type and has a different format for +// the raw bytes of the public key. +// +// If a valid ECDSA public key was created the secp256k1.S256 curve, this +// function will "convert" it from a crypto.ECDSAPubKey to a +// crypto.Secp256k1PublicKey. func coerceECDSAToSecp256k1(pubKey crypto.PubKey) (crypto.PubKey, error) { stdPub, err := crypto.PubKeyToStdKey(pubKey) if err != nil { From ccc85d46978946d2e018aaeb96bf214cc2a75b89 Mon Sep 17 00:00:00 2001 From: Steve Moyer Date: Thu, 24 Oct 2024 10:59:27 -0400 Subject: [PATCH 11/11] docs(did): correct typos --- did/crypto.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/did/crypto.go b/did/crypto.go index da2a7aa..87e561f 100644 --- a/did/crypto.go +++ b/did/crypto.go @@ -201,7 +201,7 @@ func codeForCurve(pubKey crypto.PubKey) (multicodec.Code, error) { } // secp256k1.S256 is a valid ECDSA curve, but the go-libp2p/core/crypto -// package treats it ask a different type and has a different format for +// package treats it as a different type and has a different format for // the raw bytes of the public key. // // If a valid ECDSA public key was created the secp256k1.S256 curve, this