Skip to content

Commit

Permalink
feat: added secp256k1-2019 ld context
Browse files Browse the repository at this point in the history
  • Loading branch information
arnabghose997 committed Sep 25, 2023
1 parent 00f27e4 commit e7f86b5
Show file tree
Hide file tree
Showing 11 changed files with 176 additions and 39 deletions.
8 changes: 4 additions & 4 deletions cmd/hid-noded/cmd/debug_extensions.go
Original file line number Diff line number Diff line change
Expand Up @@ -332,8 +332,8 @@ func signSchemaDocCmd() *cobra.Command {
if err != nil {
return err
}
case "secp256k1":
signature, err = hidnodecli.GetSecp256k1Signature(argPrivateKey, schemaDocBytes)
case types.EcdsaSecp256k1Signature2019:
signature, err = hidnodecli.GetEcdsaSecp256k1Signature2019(argPrivateKey, schemaDocBytes)
if err != nil {
return err
}
Expand Down Expand Up @@ -394,8 +394,8 @@ func signCredStatusDocCmd() *cobra.Command {
if err != nil {
return err
}
case "secp256k1":
signature, err = hidnodecli.GetSecp256k1Signature(argPrivateKey, credStatusDocBytes)
case types.EcdsaSecp256k1Signature2019:
signature, err = hidnodecli.GetEcdsaSecp256k1Signature2019(argPrivateKey, credStatusDocBytes)
if err != nil {
return err
}
Expand Down
14 changes: 7 additions & 7 deletions tests/e2e/ssi_tests/e2e_tests.py
Original file line number Diff line number Diff line change
Expand Up @@ -952,7 +952,7 @@ def caip10_ethereum_support_test():
def caip10_cosmos_support_test():
print("\n--- CAIP-10 Test: Cosmos Chains ---\n")

kp_algo = "secp256k1"
kp_algo = "EcdsaSecp256k1Signature2019"

# Invalid blockchain Account Ids
invalid_blockchain_account_ids = [
Expand Down Expand Up @@ -1209,7 +1209,7 @@ def vm_type_test():

# EcdsaSecp256k1VerificationKey2019
print("4. PASS: Registering DID Document with a verification method of type EcdsaSecp256k1VerificationKey2019. Only publicKeyMultibase is passed.")
kp_algo = "secp256k1"
kp_algo = "EcdsaSecp256k1Signature2019"
kp = generate_key_pair(algo=kp_algo)
did_doc_string = generate_did_document(kp, kp_algo, is_uuid=True, bech32prefix="")
did_doc_id = did_doc_string["id"]
Expand All @@ -1225,7 +1225,7 @@ def vm_type_test():
run_blockchain_command(create_tx_cmd, f"Registering DID with Id: {did_doc_id}")

print("5. PASS: Registering DID Document with a verification method of type EcdsaSecp256k1VerificationKey2019. Both publicKeyMultibase and blockchainAccountId are passed.")
kp_algo = "secp256k1"
kp_algo = "EcdsaSecp256k1Signature2019"
kp = generate_key_pair(algo=kp_algo)
did_doc_string = generate_did_document(kp, kp_algo)
did_doc_id = did_doc_string["id"]
Expand All @@ -1240,7 +1240,7 @@ def vm_type_test():
run_blockchain_command(create_tx_cmd, f"Registering DID with Id: {did_doc_id}")

print("6. FAIL: Registering DID Document with a verification method of type EcdsaSecp256k1VerificationKey2019. Only blockchainAccountId is passed.")
kp_algo = "secp256k1"
kp_algo = "EcdsaSecp256k1Signature2019"
kp = generate_key_pair(algo=kp_algo)
did_doc_string = generate_did_document(kp, kp_algo)
did_doc_id = did_doc_string["id"]
Expand Down Expand Up @@ -1311,7 +1311,7 @@ def method_specific_id_test():

print("1. PASS: Registering a DID Document where the user provides a blockchain address in MSI that they own")

kp_algo = "secp256k1"
kp_algo = "EcdsaSecp256k1Signature2019"
kp_alice = generate_key_pair(algo=kp_algo)
signers = []
did_doc_string = generate_did_document(kp_alice, algo=kp_algo)
Expand All @@ -1328,7 +1328,7 @@ def method_specific_id_test():

print("2. FAIL: Registering a DID Document where the user provides a blockchain address in MSI that they don't own")

kp_algo = "secp256k1"
kp_algo = "EcdsaSecp256k1Signature2019"
kp_bob = generate_key_pair(algo=kp_algo)
signers = []
did_doc_string = generate_did_document(kp_bob, algo=kp_algo)
Expand Down Expand Up @@ -1392,7 +1392,7 @@ def method_specific_id_test():

print("6. PASS: Alice tries to update their DID Document by removing the Verification Method associated with the method specific id (CAIP-10 Blockchain Address)")

kp_algo = "secp256k1"
kp_algo = "EcdsaSecp256k1Signature2019"
kp_alice = generate_key_pair(algo=kp_algo)
signers = []
did_doc_string = generate_did_document(kp_alice, algo=kp_algo)
Expand Down
15 changes: 9 additions & 6 deletions tests/e2e/ssi_tests/generate_doc.py
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@
ED25519_CONTEXT = "https://w3id.org/security/suites/ed25519-2020/v1"
DID_CONTEXT = "https://www.w3.org/ns/did/v1"
SECP256K1_RECOVERY_CONTEXT = "https://ns.did.ai/suites/secp256k1-2020/v1"
SECP256K1_VER_KEY_2019_CONTEXT = "https://ns.did.ai/suites/secp256k1-2019/v1"

def generate_did_document(key_pair, algo="Ed25519Signature2020", bech32prefix="hid", is_uuid=False):
base_document = {
Expand All @@ -24,14 +25,16 @@ def generate_did_document(key_pair, algo="Ed25519Signature2020", bech32prefix="h
base_document["context"].append(ED25519_CONTEXT)
if algo == "EcdsaSecp256k1RecoverySignature2020":
base_document["context"].append(SECP256K1_RECOVERY_CONTEXT)
if algo == "EcdsaSecp256k1Signature2019":
base_document["context"].append(SECP256K1_VER_KEY_2019_CONTEXT)

did_id = generate_document_id("did", key_pair, algo, is_uuid)

# Form the DID Document
vm_type = ""
if algo == "Ed25519Signature2020":
vm_type = "Ed25519VerificationKey2020"
elif algo == "secp256k1":
elif algo == "EcdsaSecp256k1Signature2019":
vm_type = "EcdsaSecp256k1VerificationKey2019"
elif algo == "EcdsaSecp256k1RecoverySignature2020":
vm_type = "EcdsaSecp256k1RecoveryMethod2020"
Expand All @@ -40,7 +43,7 @@ def generate_did_document(key_pair, algo="Ed25519Signature2020", bech32prefix="h
elif algo == "bjj":
vm_type = "BabyJubJubVerificationKey2023"
else:
raise Exception("unknown signing algorithm: " + key_pair)
raise Exception("unknown signing algorithm: " + algo)

verification_method = {}
if algo == "EcdsaSecp256k1RecoverySignature2020":
Expand All @@ -60,7 +63,7 @@ def generate_did_document(key_pair, algo="Ed25519Signature2020", bech32prefix="h

if algo == "EcdsaSecp256k1RecoverySignature2020":
verification_method["blockchainAccountId"] = "eip155:1:" + key_pair["ethereum_address"]
elif algo == "secp256k1":
elif algo == "EcdsaSecp256k1Signature2019":

if bech32prefix == "hid":
verification_method["blockchainAccountId"] = "cosmos:jagrat:" + \
Expand Down Expand Up @@ -108,7 +111,7 @@ def generate_schema_document(key_pair, schema_author, vm, signature=None, algo="
proof_type = ""
if algo == "Ed25519Signature2020":
proof_type = "Ed25519Signature2020"
elif algo == "secp256k1":
elif algo == "EcdsaSecp256k1Signature2019":
proof_type = "EcdsaSecp256k1Signature2019"
elif algo == "EcdsaSecp256k1RecoverySignature2020":
proof_type = "EcdsaSecp256k1RecoverySignature2020"
Expand Down Expand Up @@ -156,7 +159,7 @@ def generate_cred_status_document(key_pair, cred_author, vm, signature=None, alg
proof_type = ""
if algo == "Ed25519Signature2020":
proof_type = "Ed25519Signature2020"
elif algo == "secp256k1":
elif algo == "EcdsaSecp256k1Signature2019":
proof_type = "EcdsaSecp256k1Signature2019"
elif algo == "EcdsaSecp256k1RecoverySignature2020":
proof_type = "EcdsaSecp256k1RecoverySignature2020"
Expand Down
24 changes: 12 additions & 12 deletions tests/e2e/ssi_tests/run.py
Original file line number Diff line number Diff line change
Expand Up @@ -24,19 +24,19 @@ def generate_report(func):
def run_all_tests():
print("============= 🔧️ Running all x/ssi e2e tests ============== \n")

# create_did_test()
# update_did_test()
# schema_test()
# deactivate_did()
# credential_status_test()
# caip10_ethereum_support_test()
# caip10_cosmos_support_test()
# vm_type_test()
# method_specific_id_test()
# unique_wallet_address_test()
# key_agrement_test()
create_did_test()
update_did_test()
schema_test()
deactivate_did()
credential_status_test()
caip10_ethereum_support_test()
caip10_cosmos_support_test()
vm_type_test()
method_specific_id_test()
unique_wallet_address_test()
key_agrement_test()
bbs_signature_test()
# bjj_signature_test()
bjj_signature_test()

print("============= 😃️ All test cases completed successfully ============== \n")

Expand Down
2 changes: 1 addition & 1 deletion tests/e2e/ssi_tests/utils.py
Original file line number Diff line number Diff line change
Expand Up @@ -49,7 +49,7 @@ def generate_key_pair(algo="Ed25519Signature2020"):
cmd = ""
if algo == "Ed25519Signature2020":
cmd = "hid-noded debug ed25519 random"
elif algo == "secp256k1":
elif algo == "EcdsaSecp256k1Signature2019":
cmd = "hid-noded debug secp256k1 random"
elif algo == "EcdsaSecp256k1RecoverySignature2020":
cmd = "hid-noded debug secp256k1 eth-hex-random"
Expand Down
11 changes: 8 additions & 3 deletions x/ssi/client/cli/tx_utils.go
Original file line number Diff line number Diff line change
Expand Up @@ -116,7 +116,7 @@ func GetEcdsaSecp256k1RecoverySignature2020(privateKey string, message []byte) (
return etherhexutil.Encode(sigBytes), nil
}

func GetSecp256k1Signature(privateKey string, message []byte) (string, error) {
func GetEcdsaSecp256k1Signature2019(privateKey string, message []byte) (string, error) {
// Decode key into bytes
privKeyBytes, err := base64.StdEncoding.DecodeString(privateKey)
if err != nil {
Expand Down Expand Up @@ -174,8 +174,13 @@ func getSignatures(cmd *cobra.Command, didDoc *types.Did, cmdArgs []string) ([]*
if err != nil {
return nil, err
}
case "secp256k1":
signInfoList[i].Signature, err = GetSecp256k1Signature(didSigningElementsList[i].SignKey, didDoc.GetSignBytes())
case types.EcdsaSecp256k1Signature2019:
didDocBytes, err := ldcontext.EcdsaSecp256k1Signature2019Canonize(didDoc)
if err != nil {
return nil, err
}

signInfoList[i].Signature, err = GetEcdsaSecp256k1Signature2019(didSigningElementsList[i].SignKey, didDocBytes)
if err != nil {
return nil, err
}
Expand Down
101 changes: 101 additions & 0 deletions x/ssi/ld-context/context.go
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@ const ed25519Context2020 string = "https://w3id.org/security/suites/ed25519-2020
const x25519KeyAgreement2020Context string = "https://ns.did.ai/suites/x25519-2020/v1"
const secp256k1Recovery2020Context string = "https://ns.did.ai/suites/secp256k1-2020/v1"
const bbsSignature2020Context string = "https://ns.did.ai/suites/bls12381-2020/v1"
const secp256k12019Context string = "https://ns.did.ai/suites/secp256k1-2019/v1"

// As hid-node is not supposed to perform any GET request, the complete Context body of their
// respective Context urls has been maintained below.
Expand Down Expand Up @@ -508,4 +509,104 @@ var ContextUrlMap map[string]contextObject = map[string]contextObject{
},
},
},
secp256k12019Context: {
"id": "@id",
"type": "@type",
"@protected": true,
"proof": map[string]interface{}{
"@id": "https://w3id.org/security#proof",
"@type": "@id",
"@container": "@graph",
},
"EcdsaSecp256k1VerificationKey2019": map[string]interface{}{
"@id": "https://w3id.org/security#EcdsaSecp256k1VerificationKey2019",
"@context": map[string]interface{}{
"@protected": true,
"id": "@id",
"type": "@type",
"controller": map[string]interface{}{
"@id": "https://w3id.org/security#controller",
"@type": "@id",
},
"revoked": map[string]interface{}{
"@id": "https://w3id.org/security#revoked",
"@type": "http://www.w3.org/2001/XMLSchema#dateTime",
},
"blockchainAccountId": map[string]interface{}{
"@id": "https://w3id.org/security#blockchainAccountId",
},
"publicKeyJwk": map[string]interface{}{
"@id": "https://w3id.org/security#publicKeyJwk",
"@type": "@json",
},
"publicKeyBase58": map[string]interface{}{
"@id": "https://w3id.org/security#publicKeyBase58",
},
"publicKeyMultibase": map[string]interface{}{
"@id": "https://w3id.org/security#publicKeyMultibase",
"@type": "https://w3id.org/security#multibase",
},
},
},
"EcdsaSecp256k1Signature2019": map[string]interface{}{
"@id": "https://w3id.org/security#EcdsaSecp256k1Signature2019",
"@context": map[string]interface{}{
"@protected": true,
"id": "@id",
"type": "@type",
"challenge": "https://w3id.org/security#challenge",
"created": map[string]interface{}{
"@id": "http://purl.org/dc/terms/created",
"@type": "http://www.w3.org/2001/XMLSchema#dateTime",
},
"domain": "https://w3id.org/security#domain",
"expires": map[string]interface{}{
"@id": "https://w3id.org/security#expiration",
"@type": "http://www.w3.org/2001/XMLSchema#dateTime",
},
"nonce": "https://w3id.org/security#nonce",
"proofPurpose": map[string]interface{}{
"@id": "https://w3id.org/security#proofPurpose",
"@type": "@vocab",
"@context": map[string]interface{}{
"@protected": true,
"id": "@id",
"type": "@type",
"assertionMethod": map[string]interface{}{
"@id": "https://w3id.org/security#assertionMethod",
"@type": "@id",
"@container": "@set",
},
"authentication": map[string]interface{}{
"@id": "https://w3id.org/security#authenticationMethod",
"@type": "@id",
"@container": "@set",
},
"capabilityInvocation": map[string]interface{}{
"@id": "https://w3id.org/security#capabilityInvocationMethod",
"@type": "@id",
"@container": "@set",
},
"capabilityDelegation": map[string]interface{}{
"@id": "https://w3id.org/security#capabilityDelegationMethod",
"@type": "@id",
"@container": "@set",
},
"keyAgreement": map[string]interface{}{
"@id": "https://w3id.org/security#keyAgreementMethod",
"@type": "@id",
"@container": "@set",
},
},
},
"jws": map[string]interface{}{
"@id": "https://w3id.org/security#jws",
},
"verificationMethod": map[string]interface{}{
"@id": "https://w3id.org/security#verificationMethod",
"@type": "@id",
},
},
},
},
}
6 changes: 6 additions & 0 deletions x/ssi/ld-context/normalize.go
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,12 @@ func NormalizeByVerificationMethodType(didDoc *types.Did, vmType string) ([]byte
return nil, err
}
return didDocBytes, nil
case types.EcdsaSecp256k1VerificationKey2019:
didDocBytes, err := EcdsaSecp256k1Signature2019Canonize(didDoc)
if err != nil {
return nil, err
}
return didDocBytes, nil
default:
return didDoc.GetSignBytes(), nil
}
Expand Down
14 changes: 14 additions & 0 deletions x/ssi/ld-context/suite.go
Original file line number Diff line number Diff line change
Expand Up @@ -45,3 +45,17 @@ func BbsBlsSignature2020Canonize(didDoc *types.Did) ([]byte, error) {
canonizedDidDocumentHash := sha256.Sum256([]byte(canonizedDidDocument))
return canonizedDidDocumentHash[:], nil
}


// EcdsaSecp256k1Signature2019Canonize canonizes the DID Document for the
// EcdsaSecp256k1Signature2019 signature type
func EcdsaSecp256k1Signature2019Canonize(didDoc *types.Did) ([]byte, error) {
jsonLdDid := NewJsonLdDid(didDoc)
canonizedDidDocument, err := jsonLdDid.NormalizeWithURDNA2015()
if err != nil {
return nil, err
}

canonizedDidDocumentHash := sha256.Sum256([]byte(canonizedDidDocument))
return canonizedDidDocumentHash[:], nil
}
14 changes: 11 additions & 3 deletions x/ssi/verification/client_spec.go
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@ import (

// Read more about Cosmos's ADR Spec from the following:
// https://docs.cosmos.network/v0.45/architecture/adr-036-arbitrary-signature.html
func getCosmosADR036SignDocBytes(ssiMsg types.SsiMsg, clientSpec *types.ClientSpec) ([]byte, error) {
func getCosmosADR036SignDocBytes(ssiDocBytes []byte, clientSpec *types.ClientSpec) ([]byte, error) {
var msgSignData types.Msg = types.Msg{
Type: "sign/MsgSignData",
Value: types.Val{
Expand All @@ -34,7 +34,7 @@ func getCosmosADR036SignDocBytes(ssiMsg types.SsiMsg, clientSpec *types.ClientSp
},
Sequence: "0",
}
ssiDocBytes := ssiMsg.GetSignBytes()

baseCosmosADR036SignDoc.Msgs[0].Value.Data = base64.StdEncoding.EncodeToString(
ssiDocBytes)
baseCosmosADR036SignDoc.Msgs[0].Value.Signer = clientSpec.Adr036SignerAddress
Expand All @@ -57,7 +57,15 @@ func getDocBytesByClientSpec(ssiMsg types.SsiMsg, extendedVm *types.ExtendedVeri
if extendedVm.ClientSpec != nil {
switch extendedVm.ClientSpec.Type {
case types.ADR036ClientSpec:
return getCosmosADR036SignDocBytes(ssiMsg, extendedVm.ClientSpec)
if didDoc, ok := ssiMsg.(*types.Did); ok {
canonizedDidDocHash, err := ldcontext.EcdsaSecp256k1Signature2019Canonize(didDoc)
if err != nil {
return nil, err
}

return getCosmosADR036SignDocBytes(canonizedDidDocHash, extendedVm.ClientSpec)
}
return getCosmosADR036SignDocBytes(ssiMsg.GetSignBytes(), extendedVm.ClientSpec)
case types.PersonalSignClientSpec:
if didDoc, ok := ssiMsg.(*types.Did); ok {
canonizedDidDocHash, err := ldcontext.EcdsaSecp256k1RecoverySignature2020Canonize(didDoc)
Expand Down
Loading

0 comments on commit e7f86b5

Please sign in to comment.