diff --git a/tests/e2e/ssi_tests/e2e_tests.py b/tests/e2e/ssi_tests/e2e_tests.py index b6a22c6..e065f61 100644 --- a/tests/e2e/ssi_tests/e2e_tests.py +++ b/tests/e2e/ssi_tests/e2e_tests.py @@ -141,6 +141,31 @@ def create_did_test(): create_tx_cmd = form_did_create_tx_multisig(did_doc_string, signers, DEFAULT_BLOCKCHAIN_ACCOUNT_NAME) run_blockchain_command(create_tx_cmd, f"Registering DID by passing both Alice's and Eve's Signature") + print("8. FAIL: Alice tries to register a DID Document with duplicate publicKeyMultibase of type Ed25519VerificationKey2020 \n") + kp_alice = generate_key_pair() + signers = [] + did_doc_string = generate_did_document(kp_alice) + did_doc_string_2 = generate_did_document(kp_alice) + + did_doc_string_vm_1 = did_doc_string["verificationMethod"][0] + did_doc_string_vm_2 = did_doc_string_2["verificationMethod"][0] + did_doc_string_vm_2["id"] = did_doc_string_vm_2["id"] + "new" + + did_doc_string["verificationMethod"] = [ + did_doc_string_vm_1, + did_doc_string_vm_2 + ] + + did_doc_alice = did_doc_string["id"] + signPair_alice = { + "kp": kp_alice, + "verificationMethodId": did_doc_string["verificationMethod"][0]["id"], + "signing_algo": "ed25519" + } + signers.append(signPair_alice) + create_tx_cmd = form_did_create_tx_multisig(did_doc_string, signers, DEFAULT_BLOCKCHAIN_ACCOUNT_NAME) + run_blockchain_command(create_tx_cmd, f"Registering Alice's DID with Id: {did_doc_alice}", True, True) + print("--- Test Completed ---\n") # TC - II : Update DID scenarios @@ -730,7 +755,7 @@ def caip10_cosmos_support_test(): "cosmos:::::23", "cosmos::0x1234567" ] - + print("1. FAIL: Registering a DID Document with an invalid blockchainAccountIds.\n") for invalid_blockchain_id in invalid_blockchain_account_ids: print("Registering a DID Document with an invalid blockchainAccountId:", invalid_blockchain_id) kp = generate_key_pair(algo=kp_algo) @@ -749,7 +774,7 @@ def caip10_cosmos_support_test(): create_tx_cmd = form_did_create_tx_multisig(did_doc_string, signers, DEFAULT_BLOCKCHAIN_ACCOUNT_NAME) run_blockchain_command(create_tx_cmd, f"Registering a DID Document with an invalid blockchainAccountId: {invalid_blockchain_id}", True, True) - print("Registering a DID with a VM of type EcdsaSecp256k1VerificationKey2019 having both publicKeyMultibase and blockchainAccountId attributes populated") + print("2. PASS: Registering a DID with a VM of type EcdsaSecp256k1VerificationKey2019 having both publicKeyMultibase and blockchainAccountId attributes populated") kp = generate_key_pair(algo=kp_algo) did_doc_string = generate_did_document(kp, kp_algo) did_doc_id = did_doc_string["id"] @@ -763,7 +788,7 @@ def caip10_cosmos_support_test(): create_tx_cmd = form_did_create_tx_multisig(did_doc_string, signers, DEFAULT_BLOCKCHAIN_ACCOUNT_NAME) run_blockchain_command(create_tx_cmd, f"Registering the DID with DID Id {did_doc_id}") - print("Registering a DID with invalid chain-id in blockchainAccountId") + print("3. FAIL: Registering a DID with invalid chain-id in blockchainAccountId") kp = generate_key_pair(algo=kp_algo) did_doc_string = generate_did_document(kp, kp_algo) did_doc_id = did_doc_string["id"] @@ -777,10 +802,147 @@ def caip10_cosmos_support_test(): "signing_algo": kp_algo } signers.append(signPair) - create_tx_cmd = form_did_create_tx_multisig(did_doc_string, signers, DEFAULT_BLOCKCHAIN_ACCOUNT_NAME) run_blockchain_command(create_tx_cmd, f"Registering DID with Id: {did_doc_id}", True, True) + print("4. PASS: Registering a DID with two VM of type EcdsaSecp256k1VerificationKey2019 with duplicate publicKeyMultibase and different blockchain account Id") + kp = generate_key_pair(algo=kp_algo) + + did_doc_string_1 = generate_did_document(kp, kp_algo) + did_doc_string_2 = generate_did_document(kp, kp_algo, "osmo") + did_doc_string_2_vm = did_doc_string_2["verificationMethod"][0] + did_doc_string_2_vm["id"] = did_doc_string_2_vm["id"] + "new" + + did_doc_string_1["verificationMethod"] = [ + did_doc_string_1["verificationMethod"][0], + did_doc_string_2_vm, + ] + did_doc_id = did_doc_string_1["id"] + + signers = [] + signPair1 = { + "kp": kp, + "verificationMethodId": did_doc_string_1["verificationMethod"][0]["id"], + "signing_algo": kp_algo + } + signPair2 = { + "kp": kp, + "verificationMethodId": did_doc_string_2["verificationMethod"][0]["id"], + "signing_algo": kp_algo + } + signers.append(signPair1) + signers.append(signPair2) + create_tx_cmd = form_did_create_tx_multisig(did_doc_string_1, signers, DEFAULT_BLOCKCHAIN_ACCOUNT_NAME) + run_blockchain_command(create_tx_cmd, f"Registering the DID with DID Id {did_doc_id}") + + print("5. PASS: Registering a DID with two VM of type EcdsaSecp256k1VerificationKey2019 with duplicate publicKeyMultibase but one of them is without a blockchain account id") + kp = generate_key_pair(algo=kp_algo) + + did_doc_string_1 = generate_did_document(kp, kp_algo) + did_doc_string_2 = generate_did_document(kp, kp_algo) + did_doc_string_2_vm = did_doc_string_2["verificationMethod"][0] + did_doc_string_2_vm["id"] = did_doc_string_2_vm["id"] + "new" + + #Remove blockchainAccountIds + did_doc_string_1["verificationMethod"][0]["blockchainAccountId"] = "" + + did_doc_string_1["verificationMethod"] = [ + did_doc_string_1["verificationMethod"][0], + did_doc_string_2_vm, + ] + did_doc_id = did_doc_string_1["id"] + + signers = [] + signPair1 = { + "kp": kp, + "verificationMethodId": did_doc_string_1["verificationMethod"][0]["id"], + "signing_algo": kp_algo + } + signPair2 = { + "kp": kp, + "verificationMethodId": did_doc_string_2["verificationMethod"][0]["id"], + "signing_algo": kp_algo + } + signers.append(signPair1) + signers.append(signPair2) + create_tx_cmd = form_did_create_tx_multisig(did_doc_string_1, signers, DEFAULT_BLOCKCHAIN_ACCOUNT_NAME) + run_blockchain_command(create_tx_cmd, f"Registering the DID with DID Id {did_doc_id}") + + print("6. FAIL: Registering a DID with two VM of type EcdsaSecp256k1VerificationKey2019 with duplicate publicKeyMultibase and duplicate blockchainAccountId") + kp = generate_key_pair(algo=kp_algo) + + did_doc_string_1 = generate_did_document(kp, kp_algo) + did_doc_string_2 = generate_did_document(kp, kp_algo) + + did_doc_vm1 = did_doc_string_1["verificationMethod"][0] + did_doc_vm2 = did_doc_string_2["verificationMethod"][0] + + # Change vm id + did_doc_vm1["id"] = did_doc_vm1["id"] + "news" + did_doc_vm2["id"] = did_doc_vm1["id"] + "2" + + + did_doc_string_1["verificationMethod"] = [ + did_doc_vm1, + did_doc_vm2 + ] + did_doc_id = did_doc_string_1["id"] + + signers = [] + signPair1 = { + "kp": kp, + "verificationMethodId": did_doc_string_1["verificationMethod"][0]["id"], + "signing_algo": kp_algo + } + signPair2 = { + "kp": kp, + "verificationMethodId": did_doc_string_1["verificationMethod"][1]["id"], + "signing_algo": kp_algo + } + signers.append(signPair1) + signers.append(signPair2) + create_tx_cmd = form_did_create_tx_multisig(did_doc_string_1, signers, DEFAULT_BLOCKCHAIN_ACCOUNT_NAME) + run_blockchain_command(create_tx_cmd, f"Registering the DID with DID Id {did_doc_id}", True, True) + + print("7. FAIL: Registering a DID with two VM of type EcdsaSecp256k1VerificationKey2019 with duplicate publicKeyMultibase and no blockchainAccountId in either of them") + kp = generate_key_pair(algo=kp_algo) + + did_doc_string_1 = generate_did_document(kp, kp_algo) + did_doc_string_2 = generate_did_document(kp, kp_algo) + + did_doc_vm1 = did_doc_string_1["verificationMethod"][0] + did_doc_vm2 = did_doc_string_2["verificationMethod"][0] + + # Change vm id + did_doc_vm1["id"] = did_doc_vm1["id"] + "news" + did_doc_vm2["id"] = did_doc_vm1["id"] + "2" + + # Remove blockchainAccountId + did_doc_vm1["blockchainAccountId"] = "" + did_doc_vm2["blockchainAccountId"] = "" + + did_doc_string_1["verificationMethod"] = [ + did_doc_vm1, + did_doc_vm2 + ] + did_doc_id = did_doc_string_1["id"] + + signers = [] + signPair1 = { + "kp": kp, + "verificationMethodId": did_doc_string_1["verificationMethod"][0]["id"], + "signing_algo": kp_algo + } + signPair2 = { + "kp": kp, + "verificationMethodId": did_doc_vm2["id"], + "signing_algo": kp_algo + } + signers.append(signPair1) + signers.append(signPair2) + create_tx_cmd = form_did_create_tx_multisig(did_doc_string_1, signers, DEFAULT_BLOCKCHAIN_ACCOUNT_NAME) + run_blockchain_command(create_tx_cmd, f"Registering the DID with DID Id {did_doc_id}", True, True) + print("--- Test Completed ---\n") def vm_type_test(): diff --git a/tests/e2e/ssi_tests/generate_doc.py b/tests/e2e/ssi_tests/generate_doc.py index a1aea56..ecdc3e5 100644 --- a/tests/e2e/ssi_tests/generate_doc.py +++ b/tests/e2e/ssi_tests/generate_doc.py @@ -6,7 +6,7 @@ from utils import run_command, generate_document_id, get_document_signature, \ secp256k1_pubkey_to_address -def generate_did_document(key_pair, algo="ed25519"): +def generate_did_document(key_pair, algo="ed25519", bech32prefix="hid"): base_document = { "context" : [ "https://www.w3.org/ns/did/v1" @@ -41,8 +41,15 @@ def generate_did_document(key_pair, algo="ed25519"): verification_method["blockchainAccountId"] = "eip155:1:" + key_pair["ethereum_address"] elif algo == "secp256k1": - verification_method["blockchainAccountId"] = "cosmos:jagrat:" + \ - secp256k1_pubkey_to_address(key_pair["pub_key_base_64"], "hid") + if bech32prefix == "hid": + verification_method["blockchainAccountId"] = "cosmos:jagrat:" + \ + secp256k1_pubkey_to_address(key_pair["pub_key_base_64"], bech32prefix) + elif bech32prefix == "osmo": + verification_method["blockchainAccountId"] = "cosmos:osmosis-1:" + \ + secp256k1_pubkey_to_address(key_pair["pub_key_base_64"], bech32prefix) + else: + raise Exception("unsupported bech32 prefix " + bech32prefix) + verification_method["publicKeyMultibase"] = key_pair["pub_key_multibase"] else: verification_method["publicKeyMultibase"] = key_pair["pub_key_multibase"] diff --git a/x/ssi/types/diddoc_validation.go b/x/ssi/types/diddoc_validation.go index e035a11..d228459 100644 --- a/x/ssi/types/diddoc_validation.go +++ b/x/ssi/types/diddoc_validation.go @@ -143,8 +143,8 @@ func verificationKeyCheck(vm *VerificationMethod) error { return nil } -// checkDuplicateId return a duplicate Id from the list, if found -func checkDuplicateId(list []string) string { +// checkDuplicateItems return a duplicate Id from the list, if found +func checkDuplicateItems(list []string) string { presentMap := map[string]bool{} for idx := range list { if _, present := presentMap[list[idx]]; !present { @@ -183,7 +183,7 @@ func validateServices(services []*Service) error { for _, service := range services { serviceIdList = append(serviceIdList, service.Id) } - if duplicateId := checkDuplicateId(serviceIdList); duplicateId != "" { + if duplicateId := checkDuplicateItems(serviceIdList); duplicateId != "" { return fmt.Errorf("duplicate service found with Id: %s ", duplicateId) } @@ -224,19 +224,42 @@ func validateVerificationMethods(vms []*VerificationMethod) error { vmIdList := []string{} publicKeyMultibaseList := []string{} blockchainAccountIdList := []string{} + + var pubKeyMultibaseBlockchainAccIdMap map[string]bool = map[string]bool{} for _, vm := range vms { vmIdList = append(vmIdList, vm.Id) - publicKeyMultibaseList = append(publicKeyMultibaseList, vm.PublicKeyMultibase) + + if vm.Type == EcdsaSecp256k1VerificationKey2019 { + if _, present := pubKeyMultibaseBlockchainAccIdMap[vm.PublicKeyMultibase]; present { + // TODO: Following is a temporary measure, where we will be allowing duplicate publicKeyMultibase values + // for type EcdsaSecp256k1VerificationKey2019, provided if blockchainAccountId field is populated. This is done since + // one secp256k1 key pair from Keplr wallet can have multiple blockchain addresses depending upon the bech32 + // prefix. This will eventually be removed once the successful recovery of public key from the `signEthereum()` + // generated signature is figured out. + if vm.BlockchainAccountId == "" { + return fmt.Errorf( + "duplicate publicKeyMultibase of type EcdsaSecp256k1VerificationKey2019 without blockchainAccountId is not allowed: %s ", + vm.PublicKeyMultibase, + ) + } + } else { + pubKeyMultibaseBlockchainAccIdMap[vm.PublicKeyMultibase] = true + } + } else { + publicKeyMultibaseList = append(publicKeyMultibaseList, vm.PublicKeyMultibase) + } + blockchainAccountIdList = append(blockchainAccountIdList, vm.BlockchainAccountId) } - if duplicateId := checkDuplicateId(vmIdList); duplicateId != "" { + + if duplicateId := checkDuplicateItems(vmIdList); duplicateId != "" { return fmt.Errorf("duplicate verification method Id found: %s ", duplicateId) } - if duplicateKey := checkDuplicateId(publicKeyMultibaseList); duplicateKey != "" { + if duplicateKey := checkDuplicateItems(publicKeyMultibaseList); duplicateKey != "" { return fmt.Errorf("duplicate publicKeyMultibase found: %s ", duplicateKey) } - if duplicateKey := checkDuplicateId(blockchainAccountIdList); duplicateKey != "" { + if duplicateKey := checkDuplicateItems(blockchainAccountIdList); duplicateKey != "" { return fmt.Errorf("duplicate blockchainAccountId found: %s ", duplicateKey) }