Skip to content

Commit

Permalink
Use DID verificationMethod terminology and Add the method controller
Browse files Browse the repository at this point in the history
  • Loading branch information
Youngjoon Lee committed Sep 10, 2020
1 parent ac147c3 commit 37344c3
Show file tree
Hide file tree
Showing 10 changed files with 268 additions and 241 deletions.
25 changes: 17 additions & 8 deletions docs/did.md
Original file line number Diff line number Diff line change
Expand Up @@ -78,10 +78,11 @@ The details are described below.
{
"@context": "https://www.w3.org/ns/did/v1",
"id": "did:panacea:mainnet:G3UzSnRRsyApppuHVuaff",
"publicKey": [
"verificationMethod": [
{
"id": "did:panacea:mainnet:G3UzSnRRsyApppuHVuaff#key1",
"type": "Secp256k1VerificationKey2018",
"controller": "did:panacea:mainnet:G3UzSnRRsyApppuHVuaff",
"publicKeyBase58": "dBuN4i7dqwCLzSX7GHBLsfUoXw5RmWQ3DwQ9Ee4bfh5Y"
}
],
Expand All @@ -91,7 +92,10 @@ The details are described below.
}
```

The Key IDs in the `authentication` are references to one of public keys specified in the `publicKey`.
Currently, the `controller` in the `verificationMethod` must be equal to the [DID subject](https://www.w3.org/TR/2020/WD-did-core-20200907/#dfn-did-subjects).
It would be extended later.

The Key IDs in the `authentication` are references to one of public keys specified in the `verificationMethod`.
The spec of the `authentication` would be extended in the future.

The Panacea DID Document doesn't contain the `service` field currently. It would be extended soon.
Expand All @@ -106,14 +110,15 @@ To create a DID Document in Panacea, the following transaction should be submitt
{
"type": "did/MsgCreateDID",
"value": {
"did": "did:panacea:mainnet:DnreD8QqXAQaEW9DwC16Wh",
"did": "did:panacea:mainnet:G3UzSnRRsyApppuHVuaff",
"document": {
"@context": "https://www.w3.org/ns/did/v1",
"id": "did:panacea:mainnet:G3UzSnRRsyApppuHVuaff",
"publicKey": [
"verificationMethod": [
{
"id": "did:panacea:mainnet:G3UzSnRRsyApppuHVuaff#key1",
"type": "Secp256k1VerificationKey2018",
"controller": "did:panacea:mainnet:G3UzSnRRsyApppuHVuaff",
"publicKeyBase58": "dBuN4i7dqwCLzSX7GHBLsfUoXw5RmWQ3DwQ9Ee4bfh5Y"
}
],
Expand Down Expand Up @@ -166,10 +171,11 @@ If the DID exists (not deactivated yet), the result is:
"document": {
"@context": "https://www.w3.org/ns/did/v1",
"id": "did:panacea:mainnet:G3UzSnRRsyApppuHVuaff",
"publicKey": [
"verificationMethod": [
{
"id": "did:panacea:mainnet:G3UzSnRRsyApppuHVuaff#key1",
"type": "Secp256k1VerificationKey2018",
"controller": "did:panacea:mainnet:G3UzSnRRsyApppuHVuaff",
"publicKeyBase58": "dBuN4i7dqwCLzSX7GHBLsfUoXw5RmWQ3DwQ9Ee4bfh5Y"
}
],
Expand All @@ -188,24 +194,26 @@ It must be included in the subsequent transaction (update/deactivate) for preven

Only the DID owner can replace the DID Document using the following transaction.

This example is for adding a new public key to the `publicKey` and adding a dedicated public key to the `authentication`.
This example is for adding a new public key to the `verificationMethod` and adding a dedicated public key to the `authentication`.
```json
{
"type": "did/MsgUpdateDID",
"value": {
"did": "did:panacea:mainnet:DnreD8QqXAQaEW9DwC16Wh",
"did": "did:panacea:mainnet:G3UzSnRRsyApppuHVuaff",
"document": {
"@context": "https://www.w3.org/ns/did/v1",
"id": "did:panacea:mainnet:G3UzSnRRsyApppuHVuaff",
"publicKey": [
"verificationMethod": [
{
"id": "did:panacea:mainnet:G3UzSnRRsyApppuHVuaff#key1",
"type": "Secp256k1VerificationKey2018",
"controller": "did:panacea:mainnet:G3UzSnRRsyApppuHVuaff",
"publicKeyBase58": "dBuN4i7dqwCLzSX7GHBLsfUoXw5RmWQ3DwQ9Ee4bfh5Y"
},
{
"id": "did:panacea:mainnet:G3UzSnRRsyApppuHVuaff#key2",
"type": "Secp256k1VerificationKey2018",
"controller": "did:panacea:mainnet:G3UzSnRRsyApppuHVuaff",
"publicKeyBase58": "2BjcxuwijyE1om4991ANiFrwZJ3Ev5YYX9KiPKgaHmGsi"
}
],
Expand All @@ -214,6 +222,7 @@ This example is for adding a new public key to the `publicKey` and adding a dedi
{
"id": "did:panacea:mainnet:G3UzSnRRsyApppuHVuaff#key3",
"type": "Secp256k1VerificationKey2018",
"controller": "did:panacea:mainnet:G3UzSnRRsyApppuHVuaff",
"publicKeyBase58": "yE1om4991ANiFrwZJ3Ev5YYX9KiPKgaHmGsi2Bjcxuwij"
}
]
Expand Down
28 changes: 14 additions & 14 deletions x/did/client/cli/tx.go
Original file line number Diff line number Diff line change
Expand Up @@ -56,7 +56,7 @@ func GetCmdCreateDID(cdc *codec.Codec) *cobra.Command {
return err
}

if err := savePrivKeyToKeyStore(msg.SigKeyID, privKey, client.BufferStdin()); err != nil {
if err := savePrivKeyToKeyStore(msg.VeriMethodID, privKey, client.BufferStdin()); err != nil {
return err
}

Expand All @@ -74,15 +74,15 @@ func GetCmdCreateDID(cdc *codec.Codec) *cobra.Command {
func newMsgCreateDID(cliCtx context.CLIContext, networkID types.NetworkID, privKey secp256k1.PrivKeySecp256k1) (types.MsgCreateDID, error) {
pubKey := privKey.PubKey()
did := types.NewDID(networkID, pubKey, types.ES256K)
keyID := types.NewKeyID(did, "key1")
doc := types.NewDIDDocument(did, types.NewPubKey(keyID, types.ES256K, pubKey))
veriMethodID := types.NewVeriMethodID(did, "key1")
doc := types.NewDIDDocument(did, types.NewVeriMethod(veriMethodID, types.ES256K, did, pubKey))

sig, err := types.Sign(doc, types.InitialSequence, privKey)
if err != nil {
return types.MsgCreateDID{}, err
}

msg := types.NewMsgCreateDID(did, doc, keyID, sig, cliCtx.GetFromAddress())
msg := types.NewMsgCreateDID(did, doc, veriMethodID, sig, cliCtx.GetFromAddress())
if err := msg.ValidateBasic(); err != nil {
return types.MsgCreateDID{}, err
}
Expand All @@ -102,7 +102,7 @@ func GetCmdUpdateDID(cdc *codec.Codec) *cobra.Command {
if err != nil {
return err
}
keyID, err := types.ParseKeyID(args[1], did)
veriMethodID, err := types.ParseVeriMethodID(args[1], did)
if err != nil {
return err
}
Expand All @@ -111,7 +111,7 @@ func GetCmdUpdateDID(cdc *codec.Codec) *cobra.Command {
if err != nil {
return err
}
privKey, err := getPrivKeyFromKeyStore(keyID, client.BufferStdin())
privKey, err := getPrivKeyFromKeyStore(veriMethodID, client.BufferStdin())
if err != nil {
return err
}
Expand All @@ -122,7 +122,7 @@ func GetCmdUpdateDID(cdc *codec.Codec) *cobra.Command {
return err
}

msg := types.NewMsgUpdateDID(did, doc, keyID, sig, cliCtx.GetFromAddress())
msg := types.NewMsgUpdateDID(did, doc, veriMethodID, sig, cliCtx.GetFromAddress())
if err := msg.ValidateBasic(); err != nil {
return err
}
Expand All @@ -145,11 +145,11 @@ func GetCmdDeactivateDID(cdc *codec.Codec) *cobra.Command {
if err != nil {
return err
}
keyID, err := types.ParseKeyID(args[1], did)
veriMethodID, err := types.ParseVeriMethodID(args[1], did)
if err != nil {
return err
}
privKey, err := getPrivKeyFromKeyStore(keyID, client.BufferStdin())
privKey, err := getPrivKeyFromKeyStore(veriMethodID, client.BufferStdin())
if err != nil {
return err
}
Expand All @@ -160,7 +160,7 @@ func GetCmdDeactivateDID(cdc *codec.Codec) *cobra.Command {
return err
}

msg := types.NewMsgDeactivateDID(did, keyID, sig, cliCtx.GetFromAddress())
msg := types.NewMsgDeactivateDID(did, veriMethodID, sig, cliCtx.GetFromAddress())
if err := msg.ValidateBasic(); err != nil {
return err
}
Expand Down Expand Up @@ -231,7 +231,7 @@ func keystoreBaseDir() string {
}

// savePrivKeyToKeyStore saves a privKey using a password which is read from the reader.
func savePrivKeyToKeyStore(keyID types.KeyID, privKey secp256k1.PrivKeySecp256k1, reader *bufio.Reader) error {
func savePrivKeyToKeyStore(veriMethodID types.VeriMethodID, privKey secp256k1.PrivKeySecp256k1, reader *bufio.Reader) error {
passwd, err := client.GetCheckPassword(
"Enter a password to encrypt your key for DID to disk:",
"Repeat the password:",
Expand All @@ -244,12 +244,12 @@ func savePrivKeyToKeyStore(keyID types.KeyID, privKey secp256k1.PrivKeySecp256k1
if err != nil {
return err
}
_, err = ks.Save(string(keyID), privKey[:], passwd)
_, err = ks.Save(string(veriMethodID), privKey[:], passwd)
return err
}

// getPrivKeyFromKeyStore loads a privKey using a password which is read from the reader.
func getPrivKeyFromKeyStore(keyID types.KeyID, reader *bufio.Reader) (secp256k1.PrivKeySecp256k1, error) {
func getPrivKeyFromKeyStore(veriMethodID types.VeriMethodID, reader *bufio.Reader) (secp256k1.PrivKeySecp256k1, error) {
passwd, err := client.GetPassword("Enter a password to decrypt your key for DID on disk:", reader)
if err != nil {
return secp256k1.PrivKeySecp256k1{}, err
Expand All @@ -260,7 +260,7 @@ func getPrivKeyFromKeyStore(keyID types.KeyID, reader *bufio.Reader) (secp256k1.
return secp256k1.PrivKeySecp256k1{}, err
}

privKeyBytes, err := ks.LoadByAddress(string(keyID), passwd)
privKeyBytes, err := ks.LoadByAddress(string(veriMethodID), passwd)
if err != nil {
return secp256k1.PrivKeySecp256k1{}, err
}
Expand Down
12 changes: 6 additions & 6 deletions x/did/client/cli/tx_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -33,9 +33,9 @@ func TestNewMsgCreateDID(t *testing.T) {
msg, err := newMsgCreateDID(getCliContext(t), "testnet", privKey)
require.NoError(t, err)

// check if pubKey is correct
pub, _ := msg.Document.PubKeyByID(msg.SigKeyID)
pubKey, _ := types.NewPubKeyFromBase58(pub.KeyBase58)
// check if veriMethod is correct
veriMethod, _ := msg.Document.VeriMethodByID(msg.VeriMethodID)
pubKey, _ := types.NewPubKeyFromBase58(veriMethod.PubKeyBase58)
require.Equal(t, privKey.PubKey(), pubKey)

// check if the signature can be verifiable with the initial sequence
Expand Down Expand Up @@ -102,14 +102,14 @@ func TestReadBIP39ParamsFrom_InvalidMnemonic(t *testing.T) {

// Check if the private key is stored and loaded correctly by the password specified.
func TestSaveAndGetPrivKeyFromKeyStore(t *testing.T) {
keyID := types.KeyID("key1")
veriMethodID := types.VeriMethodID("key1")
privKey, _ := crypto.GenSecp256k1PrivKey("", "")

reader := bufio.NewReader(strings.NewReader("mypassword1\nmypassword1\n"))
require.NoError(t, savePrivKeyToKeyStore(keyID, privKey, reader))
require.NoError(t, savePrivKeyToKeyStore(veriMethodID, privKey, reader))

reader = bufio.NewReader(strings.NewReader("mypassword1\n"))
privKeyLoaded, err := getPrivKeyFromKeyStore(keyID, reader)
privKeyLoaded, err := getPrivKeyFromKeyStore(veriMethodID, reader)
require.NoError(t, err)
require.Equal(t, privKey, privKeyLoaded)
}
Expand Down
20 changes: 12 additions & 8 deletions x/did/handler.go
Original file line number Diff line number Diff line change
Expand Up @@ -35,7 +35,7 @@ func handleMsgCreateDID(ctx sdk.Context, keeper Keeper, msg MsgCreateDID) sdk.Re

seq := types.InitialSequence

_, err := verifyDIDOwnership(msg.Document, seq, msg.Document, msg.SigKeyID, msg.Signature)
_, err := verifyDIDOwnership(msg.Document, seq, msg.Document, msg.VeriMethodID, msg.Signature)
if err != nil {
return err.Result()
}
Expand All @@ -54,7 +54,7 @@ func handleMsgUpdateDID(ctx sdk.Context, keeper Keeper, msg MsgUpdateDID) sdk.Re
return types.ErrDIDDeactivated(msg.DID).Result()
}

newSeq, err := verifyDIDOwnership(msg.Document, docWithSeq.Seq, docWithSeq.Document, msg.SigKeyID, msg.Signature)
newSeq, err := verifyDIDOwnership(msg.Document, docWithSeq.Seq, docWithSeq.Document, msg.VeriMethodID, msg.Signature)
if err != nil {
return err.Result()
}
Expand All @@ -73,7 +73,7 @@ func handleMsgDeactivateDID(ctx sdk.Context, keeper Keeper, msg MsgDeactivateDID
return types.ErrDIDDeactivated(msg.DID).Result()
}

newSeq, err := verifyDIDOwnership(msg.DID, docWithSeq.Seq, docWithSeq.Document, msg.SigKeyID, msg.Signature)
newSeq, err := verifyDIDOwnership(msg.DID, docWithSeq.Seq, docWithSeq.Document, msg.VeriMethodID, msg.Signature)
if err != nil {
return err.Result()
}
Expand All @@ -84,14 +84,18 @@ func handleMsgDeactivateDID(ctx sdk.Context, keeper Keeper, msg MsgDeactivateDID
}

// verifyDIDOwnership verifies the DID ownership from a sig which is based on the data.
// It fetches a public key from a doc using keyID. It also uses a seq to verifyDIDOwnership the sig.
// It fetches a public key from a doc using veriMethodID. It also uses a seq to verifyDIDOwnership the sig.
// If the verification is successful, it returns a new sequence. If not, it returns an error.
func verifyDIDOwnership(data types.Signable, seq types.Sequence, doc types.DIDDocument, keyID types.KeyID, sig []byte) (types.Sequence, sdk.Error) {
pubKey, ok := doc.PubKeyByID(keyID)
func verifyDIDOwnership(data types.Signable, seq types.Sequence, doc types.DIDDocument, veriMethodID types.VeriMethodID, sig []byte) (types.Sequence, sdk.Error) {
veriMethod, ok := doc.VeriMethodByID(veriMethodID)
if !ok {
return 0, types.ErrKeyIDNotFound(keyID)
return 0, types.ErrVeriMethodIDNotFound(veriMethodID)
}
pubKeySecp256k1, err := types.NewPubKeyFromBase58(pubKey.KeyBase58)
if veriMethod.Controller != doc.ID { // TODO: support other controllers
return 0, types.ErrInvalidKeyController(veriMethod.Controller)
}

pubKeySecp256k1, err := types.NewPubKeyFromBase58(veriMethod.PubKeyBase58)
if err != nil {
return 0, types.ErrInvalidSecp256k1PublicKey(err)
}
Expand Down
Loading

0 comments on commit 37344c3

Please sign in to comment.