Skip to content

Commit

Permalink
Merge pull request hyperledger-archives#2579 from troyronda/didkey
Browse files Browse the repository at this point in the history
feat: add bbs to did:key resolver
  • Loading branch information
fqutishat authored Mar 1, 2021
2 parents 629fa41 + 28056d1 commit dc1a9b3
Show file tree
Hide file tree
Showing 4 changed files with 114 additions and 39 deletions.
10 changes: 6 additions & 4 deletions pkg/vdr/key/creator.go
Original file line number Diff line number Diff line change
Expand Up @@ -21,12 +21,14 @@ const (
schemaV1 = "https://w3id.org/did/v1"
ed25519VerificationKey2018 = "Ed25519VerificationKey2018"
x25519KeyAgreementKey2019 = "X25519KeyAgreementKey2019"
bls12381G2Key2020 = "Bls12381G2Key2020"
)

const (
// source: https://github.com/multiformats/multicodec/blob/master/table.csv.
x25519pub = 0xec // Curve25519 public key in multicodec table
ed25519pub = 0xed // Ed25519 public key in multicodec table
x25519pub = 0xec // Curve25519 public key in multicodec table
ed25519pub = 0xed // Ed25519 public key in multicodec table
bls12381g2pub = 0xeb // BLS12-381 G2 public key in multicodec table
)

// Create new DID document.
Expand Down Expand Up @@ -64,7 +66,7 @@ func (v *VDR) Create(keyManager kms.KeyManager, didDoc *did.Doc,
publicKey = did.NewVerificationMethodFromBytes(keyID, ed25519VerificationKey2018, didKey,
didDoc.VerificationMethod[0].Value)

keyAgr, err = keyAgreement(didKey, didDoc.VerificationMethod[0].Value)
keyAgr, err = keyAgreementFromEd25519(didKey, didDoc.VerificationMethod[0].Value)
if err != nil {
return nil, err
}
Expand Down Expand Up @@ -109,7 +111,7 @@ func createDoc(pubKey, keyAgreement *did.VerificationMethod, didKey string) *did
}
}

func keyAgreement(didKey string, ed25519PubKey []byte) (*did.VerificationMethod, error) {
func keyAgreementFromEd25519(didKey string, ed25519PubKey []byte) (*did.VerificationMethod, error) {
curve25519PubKey, err := cryptoutil.PublicEd25519toCurve25519(ed25519PubKey)
if err != nil {
return nil, err
Expand Down
44 changes: 29 additions & 15 deletions pkg/vdr/key/creator_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -16,22 +16,17 @@ import (
"github.com/hyperledger/aries-framework-go/pkg/doc/did"
)

const (
didKey = "did:key:z6MkpTHR8VNsBxYAAWHut2Geadd9jSwuBV8xRoAnwWsdvktH"
didKeyID = "did:key:z6MkpTHR8VNsBxYAAWHut2Geadd9jSwuBV8xRoAnwWsdvktH#z6MkpTHR8VNsBxYAAWHut2Geadd9jSwuBV8xRoAnwWsdvktH" //nolint:lll
agreementKeyID = "did:key:z6MkpTHR8VNsBxYAAWHut2Geadd9jSwuBV8xRoAnwWsdvktH#z6LSbysY2xFMRpGMhb7tFTLMpeuPRaqaWM1yECx2AtzE3KCc" //nolint:lll

pubKeyBase58 = "B12NYF8RrR3h41TDCTJojY59usg3mbtbjnFs7Eud1Y6u"
keyAgreementBase58 = "JhNWeSVLMYccCk7iopQW4guaSJTojqpMEELgSLhKwRr"
)

func TestBuild(t *testing.T) {
const (
pubKeyBase58Ed25519 = "B12NYF8RrR3h41TDCTJojY59usg3mbtbjnFs7Eud1Y6u"
)

t.Run("validate did:key compliance with generic syntax", func(t *testing.T) {
v := New()

pubKey := did.VerificationMethod{
Type: ed25519VerificationKey2018,
Value: ed25519.PublicKey(base58.Decode(pubKeyBase58)),
Value: ed25519.PublicKey(base58.Decode(pubKeyBase58Ed25519)),
}

docResolution, err := v.Create(nil, &did.Doc{VerificationMethod: []did.VerificationMethod{pubKey}})
Expand All @@ -48,18 +43,37 @@ func TestBuild(t *testing.T) {

pubKey := did.VerificationMethod{
Type: ed25519VerificationKey2018,
Value: base58.Decode(pubKeyBase58),
Value: base58.Decode(pubKeyBase58Ed25519),
}

docResolution, err := v.Create(nil, &did.Doc{VerificationMethod: []did.VerificationMethod{pubKey}})
require.NoError(t, err)
require.NotNil(t, docResolution.DIDDocument)

assertDoc(t, docResolution.DIDDocument)
assertEd25519Doc(t, docResolution.DIDDocument)
})
}

func assertDoc(t *testing.T, doc *did.Doc) {
func assertEd25519Doc(t *testing.T, doc *did.Doc) {
const (
didKey = "did:key:z6MkpTHR8VNsBxYAAWHut2Geadd9jSwuBV8xRoAnwWsdvktH"
didKeyID = "did:key:z6MkpTHR8VNsBxYAAWHut2Geadd9jSwuBV8xRoAnwWsdvktH#z6MkpTHR8VNsBxYAAWHut2Geadd9jSwuBV8xRoAnwWsdvktH" //nolint:lll
agreementKeyID = "did:key:z6MkpTHR8VNsBxYAAWHut2Geadd9jSwuBV8xRoAnwWsdvktH#z6LSbysY2xFMRpGMhb7tFTLMpeuPRaqaWM1yECx2AtzE3KCc" //nolint:lll

pubKeyBase58 = "B12NYF8RrR3h41TDCTJojY59usg3mbtbjnFs7Eud1Y6u"
keyAgreementBase58 = "JhNWeSVLMYccCk7iopQW4guaSJTojqpMEELgSLhKwRr"
)

assertDualBase58Doc(t, doc, didKey, didKeyID, ed25519VerificationKey2018, pubKeyBase58,
agreementKeyID, x25519KeyAgreementKey2019, keyAgreementBase58)
}

func assertBase58Doc(t *testing.T, doc *did.Doc, didKey, didKeyID, didKeyType, pubKeyBase58 string) {
assertDualBase58Doc(t, doc, didKey, didKeyID, didKeyType, pubKeyBase58, didKeyID, didKeyType, pubKeyBase58)
}

func assertDualBase58Doc(t *testing.T, doc *did.Doc, didKey, didKeyID, didKeyType, pubKeyBase58,
agreementKeyID, keyAgreementType, keyAgreementBase58 string) {
// validate @context
require.Equal(t, schemaV1, doc.Context[0])

Expand All @@ -68,14 +82,14 @@ func assertDoc(t *testing.T, doc *did.Doc) {

expectedPubKey := &did.VerificationMethod{
ID: didKeyID,
Type: ed25519VerificationKey2018,
Type: didKeyType,
Controller: didKey,
Value: base58.Decode(pubKeyBase58),
}

expectedKeyAgreement := &did.VerificationMethod{
ID: agreementKeyID,
Type: x25519KeyAgreementKey2019,
Type: keyAgreementType,
Controller: didKey,
Value: base58.Decode(keyAgreementBase58),
}
Expand Down
40 changes: 32 additions & 8 deletions pkg/vdr/key/resolver.go
Original file line number Diff line number Diff line change
Expand Up @@ -31,30 +31,54 @@ func (v *VDR) Read(didKey string, opts ...vdrapi.ResolveOption) (*did.DocResolut
return nil, fmt.Errorf("pub:key vdr Read: failed to get key fingerPrint: %w", err)
}

// TODO: support additional codes for did:key
didDoc, err := createDIDDocFromPubKey(parsed.MethodSpecificID, code, pubKeyBytes)
if err != nil {
return nil, fmt.Errorf("creating did document from public key failed: %w", err)
}

return &did.DocResolution{DIDDocument: didDoc}, nil
}

func createDIDDocFromPubKey(kid string, code uint64, pubKeyBytes []byte) (*did.Doc, error) {
switch code {
case ed25519pub:
break
default:
return nil, fmt.Errorf("unsupported key multicodec code [0x%x]", code)
return createEd25519DIDDoc(kid, pubKeyBytes)
case bls12381g2pub:
return createBase58DIDDoc(kid, bls12381G2Key2020, pubKeyBytes)
}

return nil, fmt.Errorf("unsupported key multicodec code [0x%x]", code)
}

func createBase58DIDDoc(kid, keyType string, pubKeyBytes []byte) (*did.Doc, error) {
didKey := fmt.Sprintf("did:key:%s", kid)

keyID := fmt.Sprintf("%s#%s", didKey, kid)
publicKey := did.NewVerificationMethodFromBytes(keyID, keyType, didKey, pubKeyBytes)

didDoc := createDoc(publicKey, publicKey, didKey)

return didDoc, nil
}

func createEd25519DIDDoc(kid string, pubKeyBytes []byte) (*did.Doc, error) {
didKey := fmt.Sprintf("did:key:%s", kid)

// did:key can't add non converted encryption key as keyAgreement (unless it's added as an option just like creator,
// it can be added and read here if needed. Below TODO is a reminder for this)
// TODO find a way to get the Encryption key as in creator.go
// for now keeping original ed25519 to X25519 key conversion as keyAgreement.
keyAgr, err := keyAgreement(didKey, pubKeyBytes)
keyAgr, err := keyAgreementFromEd25519(didKey, pubKeyBytes)
if err != nil {
return nil, fmt.Errorf("pub:key vdr Read: failed to fetch KeyAgreement: %w", err)
}

didKey = fmt.Sprintf("did:key:%s", parsed.MethodSpecificID)
keyID := fmt.Sprintf("%s#%s", didKey, parsed.MethodSpecificID)
keyID := fmt.Sprintf("%s#%s", didKey, kid)
publicKey := did.NewVerificationMethodFromBytes(keyID, ed25519VerificationKey2018, didKey, pubKeyBytes)

didDoc := createDoc(publicKey, keyAgr, didKey)

return &did.DocResolution{DIDDocument: didDoc}, nil
return didDoc, nil
}

func isValidMethodID(id string) bool {
Expand Down
59 changes: 47 additions & 12 deletions pkg/vdr/key/resolver_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -12,16 +12,7 @@ import (
"github.com/stretchr/testify/require"
)

func TestRead(t *testing.T) {
t.Run("validate did:key", func(t *testing.T) {
v := New()

doc, err := v.Read("invalid")
require.Error(t, err)
require.Contains(t, err.Error(), "invalid did: invalid")
require.Nil(t, doc)
})

func TestReadInvalid(t *testing.T) {
t.Run("validate did:key method specific ID", func(t *testing.T) {
v := New()

Expand All @@ -40,14 +31,58 @@ func TestRead(t *testing.T) {
require.Nil(t, doc)
})

t.Run("validate did:key", func(t *testing.T) {
v := New()

doc, err := v.Read("invalid")
require.Error(t, err)
require.Contains(t, err.Error(), "invalid did: invalid")
require.Nil(t, doc)
})
}

func TestReadEd25519(t *testing.T) {
const (
didEd25519 = "did:key:z6MkpTHR8VNsBxYAAWHut2Geadd9jSwuBV8xRoAnwWsdvktH"
)

t.Run("resolve assuming default key type", func(t *testing.T) {
v := New()

docResolution, err := v.Read(didKey)
docResolution, err := v.Read(didEd25519)
require.NoError(t, err)
require.NotNil(t, docResolution.DIDDocument)
require.True(t, docResolution.DIDDocument.KeyAgreement[0].Embedded)

assertDoc(t, docResolution.DIDDocument)
assertEd25519Doc(t, docResolution.DIDDocument)
})
}

func TestReadBBS(t *testing.T) {
v := New()

const (
k1 = "did:key:zUC7K4ndUaGZgV7Cp2yJy6JtMoUHY6u7tkcSYUvPrEidqBmLCTLmi6d5WvwnUqejscAkERJ3bfjEiSYtdPkRSE8kSa11hFBr4sTgnbZ95SJj19PN2jdvJjyzpSZgxkyyxNnBNnY" //nolint:lll
k1KID = "did:key:zUC7K4ndUaGZgV7Cp2yJy6JtMoUHY6u7tkcSYUvPrEidqBmLCTLmi6d5WvwnUqejscAkERJ3bfjEiSYtdPkRSE8kSa11hFBr4sTgnbZ95SJj19PN2jdvJjyzpSZgxkyyxNnBNnY#zUC7K4ndUaGZgV7Cp2yJy6JtMoUHY6u7tkcSYUvPrEidqBmLCTLmi6d5WvwnUqejscAkERJ3bfjEiSYtdPkRSE8kSa11hFBr4sTgnbZ95SJj19PN2jdvJjyzpSZgxkyyxNnBNnY" //nolint:lll
k1Base58 = "25EEkQtcLKsEzQ6JTo9cg4W7NHpaurn4Wg6LaNPFq6JQXnrP91SDviUz7KrJVMJd76CtAZFsRLYzvgX2JGxo2ccUHtuHk7ELCWwrkBDfrXCFVfqJKDootee9iVaF6NpdJtBE" //nolint:lll
k2 = "did:key:zUC7KKoJk5ttwuuc8pmQDiUmtckEPTwcaFVZe4DSFV7fURuoRnD17D3xkBK3A9tZqdADkTTMKSwNkhjo9Hs6HfgNUXo48TNRaxU6XPLSPdRgMc15jCD5DfN34ixjoVemY62JxnW" //nolint:lll
k2KID = "did:key:zUC7KKoJk5ttwuuc8pmQDiUmtckEPTwcaFVZe4DSFV7fURuoRnD17D3xkBK3A9tZqdADkTTMKSwNkhjo9Hs6HfgNUXo48TNRaxU6XPLSPdRgMc15jCD5DfN34ixjoVemY62JxnW#zUC7KKoJk5ttwuuc8pmQDiUmtckEPTwcaFVZe4DSFV7fURuoRnD17D3xkBK3A9tZqdADkTTMKSwNkhjo9Hs6HfgNUXo48TNRaxU6XPLSPdRgMc15jCD5DfN34ixjoVemY62JxnW" //nolint:lll
k2Base58 = "25VFRgQEfbJ3Pit6Z3mnZbKPK9BdQYGwdmfdcmderjYZ12BFNQYeowjMN1AYKKKcacF3UH35ZNpBqCR8y8QLeeaGLL7UKdKLcFje3VQnosesDNHsU8jBvtvYmLJusxXsSUBC" //nolint:lll
)

t.Run("key 1", func(t *testing.T) {
docResolution, err := v.Read(k1)
require.NoError(t, err)
require.NotNil(t, docResolution.DIDDocument)

assertBase58Doc(t, docResolution.DIDDocument, k1, k1KID, bls12381G2Key2020, k1Base58)
})

t.Run("key 2", func(t *testing.T) {
docResolution, err := v.Read(k2)
require.NoError(t, err)
require.NotNil(t, docResolution.DIDDocument)

assertBase58Doc(t, docResolution.DIDDocument, k2, k2KID, bls12381G2Key2020, k2Base58)
})
}

0 comments on commit dc1a9b3

Please sign in to comment.