diff --git a/x/ssi/tests/common.go b/x/ssi/tests/common.go new file mode 100644 index 0000000..00e3c07 --- /dev/null +++ b/x/ssi/tests/common.go @@ -0,0 +1,57 @@ +package tests + +import ( + "context" + "strings" + + testcrypto "github.com/hypersign-protocol/hid-node/x/ssi/tests/crypto" + testconstants "github.com/hypersign-protocol/hid-node/x/ssi/tests/constants" + "github.com/hypersign-protocol/hid-node/x/ssi/types" +) + + +func GenerateSchemaDocumentRPCElements(keyPair testcrypto.IKeyPair, authorId string, verficationMethodId string) *types.MsgRegisterCredentialSchema { + var schemaId string = "sch:" + testconstants.DidMethod + ":" + testconstants.ChainNamespace + ":" + strings.Split(authorId, ":")[3] + ":1.0" + var schemaDocument *types.CredentialSchemaDocument = &types.CredentialSchemaDocument{ + Type: "https://w3c-ccg.github.io/vc-json-schemas/schema/1.0/schema.json", + ModelVersion: "v1.0", + Name: "HS Credential", + Author: authorId, + Id: schemaId, + Authored: "2022-04-10T04:07:12Z", + Schema: &types.CredentialSchemaProperty{ + Schema: "https://json-schema.org/draft-07/schema#", + Description: "test", + Type: "Object", + Properties: "{myString:{type:string}}", + Required: []string{"myString"}, + AdditionalProperties: false, + }, + } + + var schemaProof *types.DocumentProof = &types.DocumentProof{ + Created: "2022-04-10T04:07:12Z", + VerificationMethod: verficationMethodId, + ProofPurpose: "assertionMethod", + } + + var schemaDocumentSignature string = testcrypto.SignGeneric(keyPair, schemaDocument, schemaProof) + + schemaProof.ProofValue = schemaDocumentSignature + + return &types.MsgRegisterCredentialSchema{ + CredentialSchemaDocument: schemaDocument, + CredentialSchemaProof: schemaProof, + TxAuthor: testconstants.Creator, + } +} + + +func UpdateDidTx(msgServer types.MsgServer, ctx context.Context, rpcElements *types.MsgUpdateDID, versionId string) error { + _, err := msgServer.UpdateDID(ctx, rpcElements) + if err != nil { + return err + } + return nil +} + diff --git a/x/ssi/tests/constants.go b/x/ssi/tests/constants.go new file mode 100644 index 0000000..08024c5 --- /dev/null +++ b/x/ssi/tests/constants.go @@ -0,0 +1,3 @@ +package tests + +const errExpectedToFail = "the tx was expected to fail, but it didn't" \ No newline at end of file diff --git a/x/ssi/tests/constants/constants.go b/x/ssi/tests/constants/constants.go new file mode 100644 index 0000000..7c54df6 --- /dev/null +++ b/x/ssi/tests/constants/constants.go @@ -0,0 +1,5 @@ +package constants + +const Creator = "hid1kxqk5ejca8nfpw8pg47484rppv359xh7qcasy4" +const DidMethod = "hid" +const ChainNamespace = "devnet" \ No newline at end of file diff --git a/x/ssi/tests/crypto/babyJubJub.go b/x/ssi/tests/crypto/babyJubJub.go new file mode 100644 index 0000000..32a9d08 --- /dev/null +++ b/x/ssi/tests/crypto/babyJubJub.go @@ -0,0 +1,38 @@ +package crypto + +import ( + "encoding/hex" + + "github.com/hypersign-protocol/hid-node/x/ssi/types" + "github.com/iden3/go-iden3-crypto/babyjub" + "github.com/multiformats/go-multibase" +) + +func GenerateBabyJubJubKeyPair() *BabyJubJubKeyPair { + // Generate Key Pair + babyJubjubPrivKey := babyjub.NewRandPrivKey() + babyJubjubPubKey := babyJubjubPrivKey.Public() + + // Prepare Priv key + var privKeyBytes [32]byte = babyJubjubPrivKey + var privKeyHex string = hex.EncodeToString(privKeyBytes[:]) + + // Prepare Public Key + var pubKeyHex string = babyJubjubPubKey.Compress().String() + + // Prepare Multibase Public Key + pubKeyBytes, err := hex.DecodeString(pubKeyHex) + if err != nil { + panic(err) + } + pubKeyMultibase, err := multibase.Encode(multibase.Base58BTC, pubKeyBytes) + if err != nil { + panic(err) + } + + return &BabyJubJubKeyPair{ + Type: types.BabyJubJubKey2021, + PublicKey: pubKeyMultibase, + PrivateKey: privKeyHex, + } +} diff --git a/x/ssi/tests/crypto/bbs_bls.go b/x/ssi/tests/crypto/bbs_bls.go new file mode 100644 index 0000000..cfa3d72 --- /dev/null +++ b/x/ssi/tests/crypto/bbs_bls.go @@ -0,0 +1,40 @@ +package crypto + +import ( + "crypto/sha256" + "encoding/base64" + + bbs "github.com/hyperledger/aries-framework-go/component/kmscrypto/crypto/primitive/bbs12381g2pub" + "github.com/hypersign-protocol/hid-node/x/ssi/types" + "github.com/multiformats/go-multibase" +) + +func GenerateBbsBlsKeyPair() *BbsBlsKeyPair { + pubKey, privKey, err := bbs.GenerateKeyPair(sha256.New, nil) + if err != nil { + panic(err) + } + + // Convert Public Key Object to Multibase + pubKeyBytes, err := pubKey.Marshal() + if err != nil { + panic(err) + } + + publicKeyMultibase, err := multibase.Encode(multibase.Base58BTC, pubKeyBytes) + if err != nil { + panic(err) + } + + // Convert Private Object to Bytes + privKeyBytes, err := privKey.Marshal() + if err != nil { + panic(err) + } + + return &BbsBlsKeyPair{ + Type: types.Bls12381G2Key2020, + PublicKey: publicKeyMultibase, + PrivateKey: base64.StdEncoding.EncodeToString(privKeyBytes), + } +} diff --git a/x/ssi/tests/crypto/ed25519.go b/x/ssi/tests/crypto/ed25519.go new file mode 100644 index 0000000..66eda29 --- /dev/null +++ b/x/ssi/tests/crypto/ed25519.go @@ -0,0 +1,33 @@ +package crypto + +import ( + "crypto/ed25519" + "crypto/rand" + "encoding/base64" + + "github.com/hypersign-protocol/hid-node/x/ssi/types" + "github.com/multiformats/go-multibase" +) + +func GenerateEd25519KeyPair() *Ed25519KeyPair { + publicKey, privateKey, err := ed25519.GenerateKey(rand.Reader) + if err != nil { + panic(err) + } + + var publicKeyWithHeader []byte + publicKeyWithHeader = append(publicKeyWithHeader, append([]byte{0xed, 0x01}, publicKey...)...) + + publicKeyMultibase, err := multibase.Encode(multibase.Base58BTC, publicKeyWithHeader) + if err != nil { + panic("Error while encoding multibase string") + } + + privKeyBase64String := base64.StdEncoding.EncodeToString(privateKey) + + return &Ed25519KeyPair{ + Type: types.Ed25519VerificationKey2020, + PublicKey: publicKeyMultibase, + PrivateKey: privKeyBase64String, + } +} diff --git a/x/ssi/tests/crypto/secp256k1.go b/x/ssi/tests/crypto/secp256k1.go new file mode 100644 index 0000000..d04f8a5 --- /dev/null +++ b/x/ssi/tests/crypto/secp256k1.go @@ -0,0 +1,48 @@ +package crypto + +import ( + "encoding/base64" + "encoding/hex" + + "github.com/cometbft/cometbft/crypto/secp256k1" + "github.com/hypersign-protocol/hid-node/x/ssi/types" + "github.com/multiformats/go-multibase" + + ethercrypto "github.com/ethereum/go-ethereum/crypto" +) + +func GenerateSecp256k1KeyPair() *Secp256k1Pair { + privateKey := secp256k1.GenPrivKey() + + publicKey := privateKey.PubKey().Bytes() + + publicKeyMultibase, err := multibase.Encode(multibase.Base58BTC, publicKey) + if err != nil { + panic("Error while encoding multibase string") + } + return &Secp256k1Pair{ + Type: types.EcdsaSecp256k1VerificationKey2019, + PublicKey: publicKeyMultibase, + PrivateKey: base64.StdEncoding.EncodeToString(privateKey), + } +} + +func GenerateSecp256k1RecoveryKeyPair() *Secp256k1RecoveryPair { + privateKeyObj := secp256k1.GenPrivKey() + privateKey := privateKeyObj.Bytes() + + publicKeyCompressed := privateKeyObj.PubKey().Bytes() + + publicKeyUncompressed, err := ethercrypto.DecompressPubkey(publicKeyCompressed) + if err != nil { + panic(err) + } + ethereumAddress := ethercrypto.PubkeyToAddress(*publicKeyUncompressed).Hex() + + return &Secp256k1RecoveryPair{ + Type: types.EcdsaSecp256k1RecoveryMethod2020, + PublicKey: hex.EncodeToString(publicKeyCompressed), + PrivateKey: hex.EncodeToString(privateKey), + OptionalID: ethereumAddress, + } +} diff --git a/x/ssi/tests/crypto/signature.go b/x/ssi/tests/crypto/signature.go new file mode 100644 index 0000000..361dff7 --- /dev/null +++ b/x/ssi/tests/crypto/signature.go @@ -0,0 +1,87 @@ +package crypto + +import ( + ldcontext "github.com/hypersign-protocol/hid-node/x/ssi/ld-context" + cli "github.com/hypersign-protocol/hid-node/x/ssi/client/cli" + "github.com/hypersign-protocol/hid-node/x/ssi/types" +) + +func SignGeneric(keyPair IKeyPair, doc types.SsiMsg, docProof *types.DocumentProof) string { + docProof.Type = GetSignatureTypeFromVmType(keyPair.GetType()) + + signature, err := GetDocumentSignature(doc, docProof, keyPair.GetPrivateKey()) + if err != nil { + panic(err) + } + return signature +} + +func GetPublicKeyAndOptionalID(keyPair IKeyPair) (string, string) { + return keyPair.GetPublicKey(), keyPair.GetOptionalID() +} + +func GetDocumentSignature(doc types.SsiMsg, docProof *types.DocumentProof, privateKey string) (string, error) { + var signature string + + switch docProof.Type { + case types.Ed25519Signature2020: + var docBytes []byte + docBytes, err := ldcontext.Ed25519Signature2020Normalize(doc, docProof) + if err != nil { + return "", err + } + + signature, err = cli.GetEd25519Signature2020(privateKey, docBytes) + if err != nil { + return "", err + } + case types.EcdsaSecp256k1Signature2019: + var docBytes []byte + docBytes, err := ldcontext.EcdsaSecp256k1Signature2019Normalize(doc, docProof) + if err != nil { + return "", err + } + + signature, err = cli.GetEcdsaSecp256k1Signature2019(privateKey, docBytes) + if err != nil { + return "", err + } + case types.EcdsaSecp256k1RecoverySignature2020: + var docBytes []byte + docBytes, err := ldcontext.EcdsaSecp256k1RecoverySignature2020Normalize(doc, docProof) + if err != nil { + return "", err + } + + signature, err = cli.GetEcdsaSecp256k1RecoverySignature2020(privateKey, docBytes) + if err != nil { + return "", err + } + case types.BbsBlsSignature2020: + var docBytes []byte + docBytes, err := ldcontext.BbsBlsSignature2020Normalize(doc, docProof) + if err != nil { + return "", err + } + + signature, err = cli.GetBbsBlsSignature2020(privateKey, docBytes) + if err != nil { + return "", err + } + case types.BJJSignature2021: + var docBytes []byte + docBytes, err := ldcontext.BJJSignature2021Normalize(doc) + if err != nil { + return "", err + } + + signature, err = cli.GetBJJSignature2021(privateKey, docBytes) + if err != nil { + return "", err + } + default: + panic("recieved unsupported signing-algo. Supported algorithms are: [Ed25519Signature2020, EcdsaSecp256k1Signature2019, EcdsaSecp256k1RecoverySignature2020, BbsBlsSignature2020, BJJSignature2021]") + } + + return signature, nil +} diff --git a/x/ssi/tests/crypto/types.go b/x/ssi/tests/crypto/types.go new file mode 100644 index 0000000..ec524d0 --- /dev/null +++ b/x/ssi/tests/crypto/types.go @@ -0,0 +1,178 @@ +package crypto + +import ( + "fmt" + + "github.com/hypersign-protocol/hid-node/x/ssi/types" +) + +type IKeyPair interface { + GetType() string + GetPublicKey() string + GetPrivateKey() string + GetVerificationMethodId() string + GetOptionalID() string +} + +type Ed25519KeyPair struct { + Type string + PublicKey string + PrivateKey string + VerificationMethodId string + OptionalID string // If this field is not empty, it will override publicKey as the method specific id +} + +func (kp *Ed25519KeyPair) GetType() string { + return kp.Type +} + +func (kp *Ed25519KeyPair) GetPublicKey() string { + return kp.PublicKey +} + +func (kp *Ed25519KeyPair) GetPrivateKey() string { + return kp.PrivateKey +} + +func (kp *Ed25519KeyPair) GetVerificationMethodId() string { + return kp.VerificationMethodId +} + +func (kp *Ed25519KeyPair) GetOptionalID() string { + return kp.OptionalID +} + +type Secp256k1Pair struct { + Type string + PublicKey string + PrivateKey string + VerificationMethodId string + OptionalID string // If this field is not empty, it will override publicKey as the method specific id +} + +func (kp *Secp256k1Pair) GetType() string { + return kp.Type +} + +func (kp *Secp256k1Pair) GetPublicKey() string { + return kp.PublicKey +} + +func (kp *Secp256k1Pair) GetPrivateKey() string { + return kp.PrivateKey +} + +func (kp *Secp256k1Pair) GetVerificationMethodId() string { + return kp.VerificationMethodId +} + +func (kp *Secp256k1Pair) GetOptionalID() string { + return kp.OptionalID +} + + +type Secp256k1RecoveryPair struct { + Type string + PublicKey string + PrivateKey string + VerificationMethodId string + OptionalID string // If this field is not empty, it will override publicKey as the method specific id +} + +func (kp *Secp256k1RecoveryPair) GetType() string { + return kp.Type +} + +func (kp *Secp256k1RecoveryPair) GetPublicKey() string { + return kp.PublicKey +} + +func (kp *Secp256k1RecoveryPair) GetPrivateKey() string { + return kp.PrivateKey +} + +func (kp *Secp256k1RecoveryPair) GetVerificationMethodId() string { + return kp.VerificationMethodId +} + +func (kp *Secp256k1RecoveryPair) GetOptionalID() string { + return kp.OptionalID +} + +type BabyJubJubKeyPair struct { + Type string + PublicKey string + PrivateKey string + VerificationMethodId string + OptionalID string // If this field is not empty, it will override publicKey as the method specific id +} + +func (kp *BabyJubJubKeyPair) GetType() string { + return kp.Type +} + +func (kp *BabyJubJubKeyPair) GetPublicKey() string { + return kp.PublicKey +} + +func (kp *BabyJubJubKeyPair) GetPrivateKey() string { + return kp.PrivateKey +} + +func (kp *BabyJubJubKeyPair) GetVerificationMethodId() string { + return kp.VerificationMethodId +} + +func (kp *BabyJubJubKeyPair) GetOptionalID() string { + return kp.OptionalID +} + +type BbsBlsKeyPair struct { + Type string + PublicKey string + PrivateKey string + VerificationMethodId string + OptionalID string // If this field is not empty, it will override publicKey as the method specific id +} + +func (kp *BbsBlsKeyPair) GetType() string { + return kp.Type +} + +func (kp *BbsBlsKeyPair) GetPublicKey() string { + return kp.PublicKey +} + +func (kp *BbsBlsKeyPair) GetPrivateKey() string { + return kp.PrivateKey +} + +func (kp *BbsBlsKeyPair) GetVerificationMethodId() string { + return kp.VerificationMethodId +} + +func (kp *BbsBlsKeyPair) GetOptionalID() string { + return kp.OptionalID +} + + +func CollectKeysPairs(kps ...IKeyPair) []IKeyPair { + return kps +} + +func GetSignatureTypeFromVmType(vmType string) string { + switch vmType { + case types.Ed25519VerificationKey2020: + return types.Ed25519Signature2020 + case types.EcdsaSecp256k1VerificationKey2019: + return types.EcdsaSecp256k1Signature2019 + case types.EcdsaSecp256k1RecoveryMethod2020: + return types.EcdsaSecp256k1RecoverySignature2020 + case types.Bls12381G2Key2020: + return types.BbsBlsSignature2020 + case types.BabyJubJubKey2021: + return types.BJJSignature2021 + default: + panic(fmt.Sprintf("Unsupported vm Type: %v", vmType)) + } +} \ No newline at end of file diff --git a/x/ssi/tests/keeper.go b/x/ssi/tests/keeper.go new file mode 100644 index 0000000..78f6690 --- /dev/null +++ b/x/ssi/tests/keeper.go @@ -0,0 +1,53 @@ +package tests + +import ( + "testing" + + dbm "github.com/cometbft/cometbft-db" + "github.com/cometbft/cometbft/libs/log" + cmtproto "github.com/cometbft/cometbft/proto/tendermint/types" + "github.com/cosmos/cosmos-sdk/codec" + codectypes "github.com/cosmos/cosmos-sdk/codec/types" + "github.com/cosmos/cosmos-sdk/store" + storetypes "github.com/cosmos/cosmos-sdk/store/types" + sdk "github.com/cosmos/cosmos-sdk/types" + typesparams "github.com/cosmos/cosmos-sdk/x/params/types" + "github.com/hypersign-protocol/hid-node/x/ssi/keeper" + "github.com/hypersign-protocol/hid-node/x/ssi/types" + "github.com/stretchr/testify/require" +) + +func TestKeeper(t testing.TB) (*keeper.Keeper, sdk.Context) { + storeKey := sdk.NewKVStoreKey(types.StoreKey) + memStoreKey := storetypes.NewMemoryStoreKey(types.MemStoreKey) + + db := dbm.NewMemDB() + stateStore := store.NewCommitMultiStore(db) + stateStore.MountStoreWithDB(storeKey, storetypes.StoreTypeIAVL, db) + stateStore.MountStoreWithDB(memStoreKey, storetypes.StoreTypeMemory, nil) + require.NoError(t, stateStore.LoadLatestVersion()) + + registry := codectypes.NewInterfaceRegistry() + cdc := codec.NewProtoCodec(registry) + + paramsSubspace := typesparams.NewSubspace(cdc, + types.Amino, + storeKey, + memStoreKey, + "SsiParams", + ) + k := keeper.NewKeeper( + cdc, + storeKey, + memStoreKey, + paramsSubspace, + ) + + ctx := sdk.NewContext(stateStore, + cmtproto.Header{ + ChainID: "hidnode", + }, false, log.NewNopLogger()) + + k.SetChainNamespace(&ctx, "devnet") + return k, ctx +} diff --git a/x/ssi/tests/ssi/credential_schema.go b/x/ssi/tests/ssi/credential_schema.go new file mode 100644 index 0000000..fee604e --- /dev/null +++ b/x/ssi/tests/ssi/credential_schema.go @@ -0,0 +1,57 @@ +package ssi + +import ( + "strings" + + ldcontext "github.com/hypersign-protocol/hid-node/x/ssi/ld-context" + "github.com/hypersign-protocol/hid-node/x/ssi/types" + + testconstants "github.com/hypersign-protocol/hid-node/x/ssi/tests/constants" + testcrypto "github.com/hypersign-protocol/hid-node/x/ssi/tests/crypto" +) + +func GenerateSchema(keyPair testcrypto.IKeyPair, authorId string) *types.CredentialSchemaDocument { + var schemaId = "sch:" + testconstants.DidMethod + ":" + testconstants.ChainNamespace + ":" + strings.Split(authorId, ":")[3] + ":" + "1.0" + var vmContextUrl = GetContextFromKeyPair(keyPair) + + var credentialSchema *types.CredentialSchemaDocument = &types.CredentialSchemaDocument{ + Context: []string{ + ldcontext.CredentialSchemaContext, + vmContextUrl, + }, + Type: "https://w3c-ccg.github.io/vc-json-schemas/v1/schema/1.0/schema.json", + ModelVersion: "1.0", + Id: schemaId, + Name: "SomeSchema", + Author: authorId, + Authored: "2022-04-10T02:07:12Z", + Schema: &types.CredentialSchemaProperty{ + Schema: "http://json-schema.org/draft-07/schema", + Description: "Student ID Credential Schema", + Type: "https://schema.org/object", + Properties: "{\"jayeshL\":{\"type\":\"string\"}}", + Required: []string{"jayeshL"}, + AdditionalProperties: false, + }, + } + + return credentialSchema +} + +func GenerateSchemaRPCElements(keyPair testcrypto.IKeyPair, credentialSchema *types.CredentialSchemaDocument, verficationMethod *types.VerificationMethod) *types.MsgRegisterCredentialSchema { + + var credentialProof *types.DocumentProof = &types.DocumentProof{ + Created: "2022-04-10T04:07:12Z", + VerificationMethod: verficationMethod.Id, + ProofPurpose: "assertionMethod", + } + + var credentialStatusSignature string = testcrypto.SignGeneric(keyPair, credentialSchema, credentialProof) + credentialProof.ProofValue = credentialStatusSignature + + return &types.MsgRegisterCredentialSchema{ + CredentialSchemaDocument: credentialSchema, + CredentialSchemaProof: credentialProof, + TxAuthor: testconstants.Creator, + } +} diff --git a/x/ssi/tests/ssi/credential_status.go b/x/ssi/tests/ssi/credential_status.go new file mode 100644 index 0000000..8b295ef --- /dev/null +++ b/x/ssi/tests/ssi/credential_status.go @@ -0,0 +1,67 @@ +package ssi + +import ( + "crypto/sha256" + "encoding/hex" + "strings" + + ldcontext "github.com/hypersign-protocol/hid-node/x/ssi/ld-context" + testconstants "github.com/hypersign-protocol/hid-node/x/ssi/tests/constants" + testcrypto "github.com/hypersign-protocol/hid-node/x/ssi/tests/crypto" + "github.com/hypersign-protocol/hid-node/x/ssi/types" +) + +func GenerateCredentialStatus(keyPair testcrypto.IKeyPair, issuerId string) *types.CredentialStatusDocument { + var credentialId = "vc:" + testconstants.DidMethod + ":" + testconstants.ChainNamespace + ":" + strings.Split(issuerId, ":")[3] + var credHash = sha256.Sum256([]byte("Hash1234")) + var vmContextUrl = GetContextFromKeyPair(keyPair) + + var credentialStatus *types.CredentialStatusDocument = &types.CredentialStatusDocument{ + Context: []string{ + ldcontext.CredentialStatusContext, + vmContextUrl, + }, + Id: credentialId, + Remarks: "Live", + Revoked: false, + Suspended: false, + Issuer: issuerId, + IssuanceDate: "2022-04-10T04:07:12Z", + CredentialMerkleRootHash: hex.EncodeToString(credHash[:]), + } + return credentialStatus +} + +func GenerateRegisterCredStatusRPCElements(keyPair testcrypto.IKeyPair, credentialStatus *types.CredentialStatusDocument, verficationMethod *types.VerificationMethod) *types.MsgRegisterCredentialStatus { + var credentialProof *types.DocumentProof = &types.DocumentProof{ + Created: "2022-04-10T04:07:12Z", + VerificationMethod: verficationMethod.Id, + ProofPurpose: "assertionMethod", + } + + var credentialStatusSignature string = testcrypto.SignGeneric(keyPair, credentialStatus, credentialProof) + credentialProof.ProofValue = credentialStatusSignature + + return &types.MsgRegisterCredentialStatus{ + CredentialStatusDocument: credentialStatus, + CredentialStatusProof: credentialProof, + TxAuthor: testconstants.Creator, + } +} + +func GenerateUpdateCredStatusRPCElements(keyPair testcrypto.IKeyPair, credentialStatus *types.CredentialStatusDocument, verficationMethod *types.VerificationMethod) *types.MsgUpdateCredentialStatus { + var credentialProof *types.DocumentProof = &types.DocumentProof{ + Created: "2022-04-10T04:07:12Z", + VerificationMethod: verficationMethod.Id, + ProofPurpose: "assertionMethod", + } + + var credentialStatusSignature string = testcrypto.SignGeneric(keyPair, credentialStatus, credentialProof) + credentialProof.ProofValue = credentialStatusSignature + + return &types.MsgUpdateCredentialStatus{ + CredentialStatusDocument: credentialStatus, + CredentialStatusProof: credentialProof, + TxAuthor: testconstants.Creator, + } +} diff --git a/x/ssi/tests/ssi/did_document.go b/x/ssi/tests/ssi/did_document.go new file mode 100644 index 0000000..a8aa980 --- /dev/null +++ b/x/ssi/tests/ssi/did_document.go @@ -0,0 +1,133 @@ +package ssi + +import ( + sdk "github.com/cosmos/cosmos-sdk/types" + "github.com/hypersign-protocol/hid-node/x/ssi/keeper" + + testconstants "github.com/hypersign-protocol/hid-node/x/ssi/tests/constants" + testcrypto "github.com/hypersign-protocol/hid-node/x/ssi/tests/crypto" + "github.com/hypersign-protocol/hid-node/x/ssi/types" +) + +func GetRegisterDidDocumentRPC( + didDocument *types.DidDocument, + keyPairs []testcrypto.IKeyPair, +) *types.MsgRegisterDID { + var proofs []*types.DocumentProof = getDocumentProof( + didDocument, + keyPairs, + ) + + return &types.MsgRegisterDID{ + DidDocument: didDocument, + DidDocumentProofs: proofs, + TxAuthor: testconstants.Creator, + } +} + +func GetUpdateDidDocumentRPC( + k *keeper.Keeper, + ctx sdk.Context, + didDocument *types.DidDocument, + keyPairs []testcrypto.IKeyPair, +) *types.MsgUpdateDID { + // Get Version ID + didDocFromState := QueryDid(k, ctx, didDocument.Id) + versionId := didDocFromState.DidDocumentMetadata.VersionId + + var proofs []*types.DocumentProof = getDocumentProof( + didDocument, + keyPairs, + ) + + return &types.MsgUpdateDID{ + DidDocument: didDocument, + DidDocumentProofs: proofs, + TxAuthor: testconstants.Creator, + VersionId: versionId, + } +} + +func GetDeactivateDidDocumentRPC( + k *keeper.Keeper, + ctx sdk.Context, + didDocument *types.DidDocument, + keyPairs []testcrypto.IKeyPair, +) *types.MsgDeactivateDID { + // Get Version ID + didId := didDocument.Id + didDocFromState := QueryDid(k, ctx, didId) + versionId := didDocFromState.DidDocumentMetadata.VersionId + + var proofs []*types.DocumentProof = getDocumentProof( + didDocument, + keyPairs, + ) + + return &types.MsgDeactivateDID{ + DidDocumentId: didId, + DidDocumentProofs: proofs, + TxAuthor: testconstants.Creator, + VersionId: versionId, + } +} + +func GenerateDidDoc(keyPair testcrypto.IKeyPair) *types.DidDocument { + publicKey, optionalID := testcrypto.GetPublicKeyAndOptionalID(keyPair) + var didId string + if optionalID == "" { + didId = "did:" + testconstants.DidMethod + ":" + testconstants.ChainNamespace + ":" + publicKey + } else { + didId = "did:" + testconstants.DidMethod + ":" + testconstants.ChainNamespace + ":" + optionalID + } + + var verificationMethodId string = didId + "#" + "key-1" + + var vmType string = keyPair.GetType() + + var vm = &types.VerificationMethod{ + Id: verificationMethodId, + Type: vmType, + Controller: didId, + PublicKeyMultibase: publicKey, + } + + if optionalID != "" { + if vm.Type == types.EcdsaSecp256k1RecoveryMethod2020 { + vm.PublicKeyMultibase = "" + vm.BlockchainAccountId = "eip155:1:" + optionalID + } + if vm.Type == types.EcdsaSecp256k1VerificationKey2019 { + vm.BlockchainAccountId = "cosmos:prajna:" + optionalID + } + } + + vmContextUrl := GetContextFromKeyPair(keyPair) + var didDocument *types.DidDocument = &types.DidDocument{ + Context: []string{ + "https://www.w3.org/ns/did/v1", + vmContextUrl, + }, + Id: didId, + Controller: []string{}, + VerificationMethod: []*types.VerificationMethod{ + vm, + }, + } + + return didDocument +} + +func QueryDid(k *keeper.Keeper, ctx sdk.Context, Id string) *types.DidDocumentState { + resolvedDidDocument, errResolve := k.DidDocumentByID(&ctx, &types.QueryDidDocumentRequest{ + DidId: Id, + }) + if errResolve != nil { + panic(errResolve) + } + + return &types.DidDocumentState{ + DidDocument: resolvedDidDocument.DidDocument, + DidDocumentMetadata: resolvedDidDocument.DidDocumentMetadata, + } +} diff --git a/x/ssi/tests/ssi/document_proof.go b/x/ssi/tests/ssi/document_proof.go new file mode 100644 index 0000000..a97d69e --- /dev/null +++ b/x/ssi/tests/ssi/document_proof.go @@ -0,0 +1,25 @@ +package ssi + +import ( + testcrypto "github.com/hypersign-protocol/hid-node/x/ssi/tests/crypto" + "github.com/hypersign-protocol/hid-node/x/ssi/types" +) + +func getDocumentProof(ssiDoc types.SsiMsg, keyPairs []testcrypto.IKeyPair) []*types.DocumentProof { + var docProofs []*types.DocumentProof + + for i := 0; i < len(keyPairs); i++ { + var genericDocumentProof *types.DocumentProof = &types.DocumentProof{ + Type: testcrypto.GetSignatureTypeFromVmType(keyPairs[i].GetType()), + Created: "2023-08-16T09:37:12Z", + ProofPurpose: "assertionMethod", + } + genericDocumentProof.VerificationMethod = keyPairs[i].GetVerificationMethodId() + + signature := testcrypto.SignGeneric(keyPairs[i], ssiDoc, genericDocumentProof) + genericDocumentProof.ProofValue = signature + + docProofs = append(docProofs, genericDocumentProof) + } + return docProofs +} diff --git a/x/ssi/tests/ssi/types.go b/x/ssi/tests/ssi/types.go new file mode 100644 index 0000000..5d8e4a5 --- /dev/null +++ b/x/ssi/tests/ssi/types.go @@ -0,0 +1,2 @@ +package ssi + diff --git a/x/ssi/tests/ssi/utils.go b/x/ssi/tests/ssi/utils.go new file mode 100644 index 0000000..0d4199d --- /dev/null +++ b/x/ssi/tests/ssi/utils.go @@ -0,0 +1,23 @@ +package ssi + +import ( + ldcontext "github.com/hypersign-protocol/hid-node/x/ssi/ld-context" + testcrypto "github.com/hypersign-protocol/hid-node/x/ssi/tests/crypto" +) + +func GetContextFromKeyPair(kp testcrypto.IKeyPair) string { + switch kp.(type) { + case *testcrypto.Ed25519KeyPair: + return ldcontext.Ed25519Context2020 + case *testcrypto.Secp256k1Pair: + return ldcontext.Secp256k12019Context + case *testcrypto.Secp256k1RecoveryPair: + return ldcontext.Secp256k1Recovery2020Context + case *testcrypto.BabyJubJubKeyPair: + return ldcontext.BabyJubJubKey2021Context + case *testcrypto.BbsBlsKeyPair: + return ldcontext.BbsSignature2020Context + default: + panic("Unsupported IKeyPair type") + } +} diff --git a/x/ssi/tests/tx_credential_status_test.go b/x/ssi/tests/tx_credential_status_test.go new file mode 100644 index 0000000..d0fc988 --- /dev/null +++ b/x/ssi/tests/tx_credential_status_test.go @@ -0,0 +1,261 @@ +package tests + +import ( + "testing" + + sdk "github.com/cosmos/cosmos-sdk/types" + "github.com/hypersign-protocol/hid-node/x/ssi/keeper" + + testcrypto "github.com/hypersign-protocol/hid-node/x/ssi/tests/crypto" + testssi "github.com/hypersign-protocol/hid-node/x/ssi/tests/ssi" +) + +func TestCredentialStatusTC1(t *testing.T) { + k, ctx := TestKeeper(t) + msgServer := keeper.NewMsgServerImpl(*k) + goCtx := sdk.WrapSDKContext(ctx) + + t.Log("FAIL: Alice creates a DID, deactivates it and attempts to create a credential status document") + + t.Log("Create Alice's DID") + alice_kp := testcrypto.GenerateEd25519KeyPair() + alice_didDoc := testssi.GenerateDidDoc(alice_kp) + alice_didDoc.Controller = append(alice_didDoc.Controller, alice_didDoc.Id) + t.Logf("Alice's DID Id: %s", alice_didDoc.Id) + alice_kp.VerificationMethodId = alice_didDoc.VerificationMethod[0].Id + didDocTx := testssi.GetRegisterDidDocumentRPC(alice_didDoc, []testcrypto.IKeyPair{alice_kp}) + _, err := msgServer.RegisterDID(goCtx, didDocTx) + if err != nil { + t.Log(err) + t.FailNow() + } + + t.Log("Alice attempts to deactivate DID Document") + deactivateDidElements := testssi.GetDeactivateDidDocumentRPC(k, ctx, alice_didDoc, []testcrypto.IKeyPair{alice_kp}) + _, err = msgServer.DeactivateDID(goCtx, deactivateDidElements) + if err != nil { + t.Log(err) + t.FailNow() + } + + t.Log("Alice creates a credential status with her deactivated DID Document") + credentialStatus := testssi.GenerateCredentialStatus(alice_kp, alice_didDoc.Id) + credentialStatusRPCElements := testssi.GenerateRegisterCredStatusRPCElements(alice_kp, credentialStatus, alice_didDoc.VerificationMethod[0]) + _, err = msgServer.RegisterCredentialStatus(goCtx, credentialStatusRPCElements) + if err == nil { + t.Log(errExpectedToFail) + t.FailNow() + } +} + +func TestCredentialStatusTC2(t *testing.T) { + k, ctx := TestKeeper(t) + msgServer := keeper.NewMsgServerImpl(*k) + goCtx := sdk.WrapSDKContext(ctx) + + t.Log("PASS: Alice creates a DID and attempts to create a credential status document") + + t.Log("Create Alice's DID") + alice_kp := testcrypto.GenerateEd25519KeyPair() + alice_didDoc := testssi.GenerateDidDoc(alice_kp) + alice_didDoc.Controller = append(alice_didDoc.Controller, alice_didDoc.Id) + t.Logf("Alice's DID Id: %s", alice_didDoc.Id) + alice_kp.VerificationMethodId = alice_didDoc.VerificationMethod[0].Id + didDocTx := testssi.GetRegisterDidDocumentRPC(alice_didDoc, []testcrypto.IKeyPair{alice_kp}) + _, err := msgServer.RegisterDID(goCtx, didDocTx) + if err != nil { + t.Log(err) + t.FailNow() + } + + t.Log("Alice creates a credential status document") + credentialStatus := testssi.GenerateCredentialStatus(alice_kp, alice_didDoc.Id) + credentialStatusRPCElements := testssi.GenerateRegisterCredStatusRPCElements(alice_kp, credentialStatus, alice_didDoc.VerificationMethod[0]) + _, err = msgServer.RegisterCredentialStatus(goCtx, credentialStatusRPCElements) + if err != nil { + t.Log(err) + t.FailNow() + } +} + +func TestCredentialStatusTC3(t *testing.T) { + k, ctx := TestKeeper(t) + msgServer := keeper.NewMsgServerImpl(*k) + goCtx := sdk.WrapSDKContext(ctx) + + t.Log("FAIL: Alice attempts to update credential status without any changes") + + t.Log("Create Alice's DID") + alice_kp := testcrypto.GenerateEd25519KeyPair() + alice_didDoc := testssi.GenerateDidDoc(alice_kp) + alice_didDoc.Controller = append(alice_didDoc.Controller, alice_didDoc.Id) + t.Logf("Alice's DID Id: %s", alice_didDoc.Id) + alice_kp.VerificationMethodId = alice_didDoc.VerificationMethod[0].Id + didDocTx := testssi.GetRegisterDidDocumentRPC(alice_didDoc, []testcrypto.IKeyPair{alice_kp}) + _, err := msgServer.RegisterDID(goCtx, didDocTx) + if err != nil { + t.Log(err) + t.FailNow() + } + + t.Log("Alice creates a credential status document") + credentialStatus := testssi.GenerateCredentialStatus(alice_kp, alice_didDoc.Id) + credentialStatusRPCElements := testssi.GenerateRegisterCredStatusRPCElements(alice_kp, credentialStatus, alice_didDoc.VerificationMethod[0]) + _, err = msgServer.RegisterCredentialStatus(goCtx, credentialStatusRPCElements) + if err != nil { + t.Log(err) + t.FailNow() + } + + t.Log("Alice attempts to update credential status document without changes") + updateCredentialStatusRPCElements := testssi.GenerateUpdateCredStatusRPCElements(alice_kp, credentialStatus, alice_didDoc.VerificationMethod[0]) + _, err = msgServer.UpdateCredentialStatus(goCtx, updateCredentialStatusRPCElements) + if err == nil { + t.Log(errExpectedToFail) + t.FailNow() + } +} + +func TestCredentialStatusTC4(t *testing.T) { + k, ctx := TestKeeper(t) + msgServer := keeper.NewMsgServerImpl(*k) + goCtx := sdk.WrapSDKContext(ctx) + + t.Log("PASS: Alice suspends the credential status using one of his VMs and then un-suspends it") + + t.Log("Create Alice's DID") + alice_kp := testcrypto.GenerateEd25519KeyPair() + alice_didDoc := testssi.GenerateDidDoc(alice_kp) + alice_didDoc.Controller = append(alice_didDoc.Controller, alice_didDoc.Id) + t.Logf("Alice's DID Id: %s", alice_didDoc.Id) + alice_kp.VerificationMethodId = alice_didDoc.VerificationMethod[0].Id + didDocTx := testssi.GetRegisterDidDocumentRPC(alice_didDoc, []testcrypto.IKeyPair{alice_kp}) + _, err := msgServer.RegisterDID(goCtx, didDocTx) + if err != nil { + t.Log(err) + t.FailNow() + } + + t.Log("Alice creates a credential status document") + credentialStatus := testssi.GenerateCredentialStatus(alice_kp, alice_didDoc.Id) + credentialStatusRPCElements := testssi.GenerateRegisterCredStatusRPCElements(alice_kp, credentialStatus, alice_didDoc.VerificationMethod[0]) + _, err = msgServer.RegisterCredentialStatus(goCtx, credentialStatusRPCElements) + if err != nil { + t.Log(err) + t.FailNow() + } + + t.Log("Alice attempts to suspend her credential status") + credentialStatus.Suspended = true + credentialStatus.Remarks = "Test" + updateCredentialStatusRPCElements := testssi.GenerateUpdateCredStatusRPCElements(alice_kp, credentialStatus, alice_didDoc.VerificationMethod[0]) + _, err = msgServer.UpdateCredentialStatus(goCtx, updateCredentialStatusRPCElements) + if err != nil { + t.Log(err) + t.FailNow() + } + + t.Log("Alice attempts to un-suspend her credential status") + credentialStatus.Suspended = false + credentialStatus.Remarks = "Test" + updateCredentialStatusRPCElements = testssi.GenerateUpdateCredStatusRPCElements(alice_kp, credentialStatus, alice_didDoc.VerificationMethod[0]) + _, err = msgServer.UpdateCredentialStatus(goCtx, updateCredentialStatusRPCElements) + if err != nil { + t.Log(err) + t.FailNow() + } + +} + +func TestCredentialStatusTC5(t *testing.T) { + k, ctx := TestKeeper(t) + msgServer := keeper.NewMsgServerImpl(*k) + goCtx := sdk.WrapSDKContext(ctx) + + t.Log("Alice revokes the credential status using one of his VMs (PASS) and then attempts to un-revoke it (FAIL)") + + t.Log("Create Alice's DID") + alice_kp := testcrypto.GenerateEd25519KeyPair() + alice_didDoc := testssi.GenerateDidDoc(alice_kp) + alice_didDoc.Controller = append(alice_didDoc.Controller, alice_didDoc.Id) + t.Logf("Alice's DID Id: %s", alice_didDoc.Id) + alice_kp.VerificationMethodId = alice_didDoc.VerificationMethod[0].Id + didDocTx := testssi.GetRegisterDidDocumentRPC(alice_didDoc, []testcrypto.IKeyPair{alice_kp}) + _, err := msgServer.RegisterDID(goCtx, didDocTx) + if err != nil { + t.Log(err) + t.FailNow() + } + + t.Log("Alice creates a credential status document") + credentialStatus := testssi.GenerateCredentialStatus(alice_kp, alice_didDoc.Id) + credentialStatusRPCElements := testssi.GenerateRegisterCredStatusRPCElements(alice_kp, credentialStatus, alice_didDoc.VerificationMethod[0]) + _, err = msgServer.RegisterCredentialStatus(goCtx, credentialStatusRPCElements) + if err != nil { + t.Log(err) + t.FailNow() + } + + t.Log("Alice attempts to revokes her credential status") + credentialStatus.Revoked = true + credentialStatus.Remarks = "Test" + updateCredentialStatusRPCElements := testssi.GenerateUpdateCredStatusRPCElements(alice_kp, credentialStatus, alice_didDoc.VerificationMethod[0]) + _, err = msgServer.UpdateCredentialStatus(goCtx, updateCredentialStatusRPCElements) + if err != nil { + t.Log(err) + t.FailNow() + } + + t.Log("Alice attempts to un-revokes her credential status") + credentialStatus.Revoked = false + credentialStatus.Remarks = "Test" + updateCredentialStatusRPCElements = testssi.GenerateUpdateCredStatusRPCElements(alice_kp, credentialStatus, alice_didDoc.VerificationMethod[0]) + _, err = msgServer.UpdateCredentialStatus(goCtx, updateCredentialStatusRPCElements) + if err == nil { + t.Log(errExpectedToFail) + t.FailNow() + } + +} + +func TestCredentialStatusTC6(t *testing.T) { + k, ctx := TestKeeper(t) + msgServer := keeper.NewMsgServerImpl(*k) + goCtx := sdk.WrapSDKContext(ctx) + + t.Log("FAIL: Alice attempts to update her credential status by changing Merkle Root Hash") + + t.Log("Create Alice's DID") + alice_kp := testcrypto.GenerateEd25519KeyPair() + alice_didDoc := testssi.GenerateDidDoc(alice_kp) + alice_didDoc.Controller = append(alice_didDoc.Controller, alice_didDoc.Id) + t.Logf("Alice's DID Id: %s", alice_didDoc.Id) + alice_kp.VerificationMethodId = alice_didDoc.VerificationMethod[0].Id + didDocTx := testssi.GetRegisterDidDocumentRPC(alice_didDoc, []testcrypto.IKeyPair{alice_kp}) + _, err := msgServer.RegisterDID(goCtx, didDocTx) + if err != nil { + t.Log(err) + t.FailNow() + } + + t.Log("Alice creates a credential status document") + credentialStatus := testssi.GenerateCredentialStatus(alice_kp, alice_didDoc.Id) + credentialStatusRPCElements := testssi.GenerateRegisterCredStatusRPCElements(alice_kp, credentialStatus, alice_didDoc.VerificationMethod[0]) + _, err = msgServer.RegisterCredentialStatus(goCtx, credentialStatusRPCElements) + if err != nil { + t.Log(err) + t.FailNow() + } + + t.Log("Alice attempts to update her credential status by changing Merkle Root Hash") + credentialStatus.CredentialMerkleRootHash = "9de17abaffe74f4675c738f5d69c28a329aff8721cb0ed4808d8616e26280ed9" + updateCredentialStatusRPCElements := testssi.GenerateUpdateCredStatusRPCElements(alice_kp, credentialStatus, alice_didDoc.VerificationMethod[0]) + _, err = msgServer.UpdateCredentialStatus(goCtx, updateCredentialStatusRPCElements) + if err == nil { + t.Log(errExpectedToFail) + t.FailNow() + } + +} + + diff --git a/x/ssi/tests/tx_deactivate_did_test.go b/x/ssi/tests/tx_deactivate_did_test.go new file mode 100644 index 0000000..7fe8f1e --- /dev/null +++ b/x/ssi/tests/tx_deactivate_did_test.go @@ -0,0 +1,104 @@ +package tests + +import ( + "testing" + + sdk "github.com/cosmos/cosmos-sdk/types" + "github.com/hypersign-protocol/hid-node/x/ssi/keeper" + "github.com/hypersign-protocol/hid-node/x/ssi/types" + + testcrypto "github.com/hypersign-protocol/hid-node/x/ssi/tests/crypto" + testssi "github.com/hypersign-protocol/hid-node/x/ssi/tests/ssi" +) + +func TestDeactivateDidTC1(t *testing.T) { + k, ctx := TestKeeper(t) + msgServer := keeper.NewMsgServerImpl(*k) + goCtx := sdk.WrapSDKContext(ctx) + + t.Log("PASS: Alice creates an Org DID with herself and Bob being the Controller. Bob attempts to deactivate it") + + t.Log("Create Alice's DID") + alice_kp := testcrypto.GenerateEd25519KeyPair() + alice_didDoc := testssi.GenerateDidDoc(alice_kp) + alice_didDoc.Controller = append(alice_didDoc.Controller, alice_didDoc.Id) + t.Logf("Alice's DID Id: %s", alice_didDoc.Id) + alice_kp.VerificationMethodId = alice_didDoc.VerificationMethod[0].Id + didDocTx := testssi.GetRegisterDidDocumentRPC(alice_didDoc, []testcrypto.IKeyPair{alice_kp}) + _, err := msgServer.RegisterDID(goCtx, didDocTx) + if err != nil { + t.Log(err) + t.FailNow() + } + + t.Log("Create Bob's DID") + bob_kp := testcrypto.GenerateEd25519KeyPair() + bob_didDoc := testssi.GenerateDidDoc(bob_kp) + bob_didDoc.Controller = append(bob_didDoc.Controller, bob_didDoc.Id) + t.Logf("Bob's DID Id: %s", bob_didDoc.Id) + bob_kp.VerificationMethodId = bob_didDoc.VerificationMethod[0].Id + didDocTx = testssi.GetRegisterDidDocumentRPC(bob_didDoc, []testcrypto.IKeyPair{bob_kp}) + _, err = msgServer.RegisterDID(goCtx, didDocTx) + if err != nil { + t.Log(err) + t.FailNow() + } + + t.Log("Create Organization DID") + org_kp := testcrypto.GenerateEd25519KeyPair() + org_didDoc := testssi.GenerateDidDoc(org_kp) + org_didDoc.Controller = []string{alice_didDoc.Id, bob_didDoc.Id} + org_didDoc.VerificationMethod = []*types.VerificationMethod{} + didDocTx = testssi.GetRegisterDidDocumentRPC(org_didDoc, []testcrypto.IKeyPair{alice_kp, bob_kp}) + _, err = msgServer.RegisterDID(goCtx, didDocTx) + if err != nil { + t.Log(err) + t.FailNow() + } + + t.Log("Bob attempts to deactivate DID Document") + rpcElements := testssi.GetDeactivateDidDocumentRPC(k, ctx, org_didDoc, []testcrypto.IKeyPair{bob_kp}) + _, err = msgServer.DeactivateDID(goCtx, rpcElements) + if err != nil { + t.Log(err) + t.FailNow() + } +} + +func TestDeactivateDidTC2(t *testing.T) { + k, ctx := TestKeeper(t) + msgServer := keeper.NewMsgServerImpl(*k) + goCtx := sdk.WrapSDKContext(ctx) + + t.Log("FAIL: Alice creates a DID for herself. She deactivates it and attempts to update it.") + + t.Log("Create Alice's DID") + alice_kp := testcrypto.GenerateEd25519KeyPair() + alice_didDoc := testssi.GenerateDidDoc(alice_kp) + alice_didDoc.Controller = append(alice_didDoc.Controller, alice_didDoc.Id) + t.Logf("Alice's DID Id: %s", alice_didDoc.Id) + alice_kp.VerificationMethodId = alice_didDoc.VerificationMethod[0].Id + didDocTx := testssi.GetRegisterDidDocumentRPC(alice_didDoc, []testcrypto.IKeyPair{alice_kp}) + _, err := msgServer.RegisterDID(goCtx, didDocTx) + if err != nil { + t.Log(err) + t.FailNow() + } + + t.Log("Alice attempts to deactivate DID Document") + deactivateDidElements := testssi.GetDeactivateDidDocumentRPC(k, ctx, alice_didDoc, []testcrypto.IKeyPair{alice_kp}) + _, err = msgServer.DeactivateDID(goCtx, deactivateDidElements) + if err != nil { + t.Log(err) + t.FailNow() + } + + t.Log("Alice attempts to update it") + alice_didDoc.CapabilityDelegation = append(alice_didDoc.CapabilityDelegation, alice_didDoc.VerificationMethod[0].Id) + updateDidElements := testssi.GetUpdateDidDocumentRPC(k, ctx, alice_didDoc, []testcrypto.IKeyPair{alice_kp}) + _, err = msgServer.UpdateDID(goCtx, updateDidElements) + if err == nil { + t.Log(errExpectedToFail) + t.FailNow() + } +} diff --git a/x/ssi/tests/tx_register_did_test.go b/x/ssi/tests/tx_register_did_test.go new file mode 100644 index 0000000..ee841bb --- /dev/null +++ b/x/ssi/tests/tx_register_did_test.go @@ -0,0 +1,237 @@ +package tests + +import ( + "testing" + + sdk "github.com/cosmos/cosmos-sdk/types" + "github.com/hypersign-protocol/hid-node/x/ssi/keeper" + "github.com/hypersign-protocol/hid-node/x/ssi/types" + + testcrypto "github.com/hypersign-protocol/hid-node/x/ssi/tests/crypto" + testssi "github.com/hypersign-protocol/hid-node/x/ssi/tests/ssi" +) + +func TestCreateDidTC1(t *testing.T) { + k, ctx := TestKeeper(t) + msgServer := keeper.NewMsgServerImpl(*k) + goCtx := sdk.WrapSDKContext(ctx) + + var didDocTx *types.MsgRegisterDID + var err error + t.Log("1. Alice has a registered DID Document where Alice is the controller. Bob tries to register their DID Document by keeping both Alice and Bob as controllers.") + t.Log("Create Alice's DID") + + alice_kp := testcrypto.GenerateEd25519KeyPair() + alice_didDoc := testssi.GenerateDidDoc(alice_kp) + alice_didDoc.Controller = append(alice_didDoc.Controller, alice_didDoc.Id) + + t.Logf("Alice's DID Id: %s", alice_didDoc.Id) + alice_kp.VerificationMethodId = alice_didDoc.VerificationMethod[0].Id + + didDocTx = testssi.GetRegisterDidDocumentRPC(alice_didDoc, []testcrypto.IKeyPair{alice_kp}) + _, err = msgServer.RegisterDID(goCtx, didDocTx) + if err != nil { + t.Log(err) + t.FailNow() + } + + t.Log("1.1 FAIL: Only Bob's signature is sent") + t.Log("Create Bob's DID") + bob_kp := testcrypto.GenerateEd25519KeyPair() + bob_didDoc := testssi.GenerateDidDoc(bob_kp) + bob_didDoc.Controller = []string{alice_didDoc.Id, bob_didDoc.Id} + t.Logf("Bob's DID Id: %s", bob_didDoc.Id) + bob_kp.VerificationMethodId = bob_didDoc.VerificationMethod[0].Id + + didDocTx = testssi.GetRegisterDidDocumentRPC(bob_didDoc, []testcrypto.IKeyPair{bob_kp}) + _, err = msgServer.RegisterDID(goCtx, didDocTx) + if err == nil { + t.Log(errExpectedToFail) + t.FailNow() + } + + t.Log("1.2 PASS: Both Alice's and Bob's signatures are sent") + didDocTx = testssi.GetRegisterDidDocumentRPC(bob_didDoc, []testcrypto.IKeyPair{alice_kp, bob_kp}) + _, err = msgServer.RegisterDID(goCtx, didDocTx) + if err != nil { + t.Log(err) + t.FailNow() + } +} + +func TestCreateDidTC2(t *testing.T) { + k, ctx := TestKeeper(t) + msgServer := keeper.NewMsgServerImpl(*k) + goCtx := sdk.WrapSDKContext(ctx) + + t.Log("2. PASS: Alice has a registered DID Document where they are the controller. They attempt to create an organization DID, in which they are the only controller and the verification method field is empty.") + + t.Log("Create Alice's DID") + alice_kp := testcrypto.GenerateEd25519KeyPair() + alice_didDoc := testssi.GenerateDidDoc(alice_kp) + alice_didDoc.Controller = append(alice_didDoc.Controller, alice_didDoc.Id) + t.Logf("Alice's DID Id: %s", alice_didDoc.Id) + alice_kp.VerificationMethodId = alice_didDoc.VerificationMethod[0].Id + didDocTx := testssi.GetRegisterDidDocumentRPC(alice_didDoc, []testcrypto.IKeyPair{alice_kp}) + _, err := msgServer.RegisterDID(goCtx, didDocTx) + if err != nil { + t.Log(err) + t.FailNow() + } + + t.Log("Create Organization DID") + org_kp := testcrypto.GenerateEd25519KeyPair() + org_didDoc := testssi.GenerateDidDoc(org_kp) + org_didDoc.Controller = []string{alice_didDoc.Id} + org_didDoc.VerificationMethod = []*types.VerificationMethod{} + + t.Logf("Organization DID Id: %s", org_didDoc.Id) + didDocTx = testssi.GetRegisterDidDocumentRPC(org_didDoc, []testcrypto.IKeyPair{alice_kp}) + _, err = msgServer.RegisterDID(goCtx, didDocTx) + if err != nil { + t.Log(err) + t.FailNow() + } +} + +func TestCreateDidTC3(t *testing.T) { + k, ctx := TestKeeper(t) + msgServer := keeper.NewMsgServerImpl(*k) + goCtx := sdk.WrapSDKContext(ctx) + + t.Log("3. Alice has a registered DID Document where they are the controller. Alice tries to register an Org DID Document where they are the sole controller, and there are two verification Methods, of type EcdsaSecp256k1RecoveryMethod2020, and Alice is the controller for each one of them.") + + t.Log("Create Alice's DID") + alice_kp := testcrypto.GenerateEd25519KeyPair() + alice_didDoc := testssi.GenerateDidDoc(alice_kp) + alice_didDoc.Controller = append(alice_didDoc.Controller, alice_didDoc.Id) + t.Logf("Alice's DID Id: %s", alice_didDoc.Id) + alice_kp.VerificationMethodId = alice_didDoc.VerificationMethod[0].Id + didDocTx := testssi.GetRegisterDidDocumentRPC(alice_didDoc, []testcrypto.IKeyPair{alice_kp}) + _, err := msgServer.RegisterDID(goCtx, didDocTx) + if err != nil { + t.Log(err) + t.FailNow() + } + + wallet1_kp := testcrypto.GenerateEd25519KeyPair() + wallet1_didDoc := testssi.GenerateDidDoc(wallet1_kp) + wallet1_didDoc.VerificationMethod[0].Controller = alice_didDoc.Id + t.Logf("Wallet 1 DID Id: %s", wallet1_didDoc.Id) + wallet1_kp.VerificationMethodId = wallet1_didDoc.VerificationMethod[0].Id + + wallet2_kp := testcrypto.GenerateSecp256k1KeyPair() + wallet2_didDoc := testssi.GenerateDidDoc(wallet2_kp) + wallet2_didDoc.VerificationMethod[0].Controller = alice_didDoc.Id + t.Logf("Wallet 2 DID Id: %s", wallet2_didDoc.Id) + wallet2_kp.VerificationMethodId = wallet2_didDoc.VerificationMethod[0].Id + + t.Log("Create Org DID") + org_kp := testcrypto.GenerateEd25519KeyPair() + org_didDoc := testssi.GenerateDidDoc(org_kp) + org_didDoc.Controller = []string{alice_didDoc.Id} + org_didDoc.VerificationMethod = []*types.VerificationMethod{ + wallet1_didDoc.VerificationMethod[0], + wallet2_didDoc.VerificationMethod[0], + } + + t.Log("3.1 FAIL: Signature is provided by only one of the VMs.") + t.Logf("Org DID Id: %s", org_didDoc.Id) + didDocTx2 := testssi.GetRegisterDidDocumentRPC(org_didDoc, []testcrypto.IKeyPair{wallet2_kp}) + _, err2 := msgServer.RegisterDID(goCtx, didDocTx2) + if err2 == nil { + t.Log(errExpectedToFail) + t.FailNow() + } + + t.Log("3.2 PASS: Signature is provided by both VMs.") + t.Logf("Org DID Id: %s", org_didDoc.Id) + didDocTx2 = testssi.GetRegisterDidDocumentRPC(org_didDoc, []testcrypto.IKeyPair{wallet1_kp, wallet2_kp}) + _, err3 := msgServer.RegisterDID(goCtx, didDocTx2) + if err3 != nil { + t.Log(err3) + t.FailNow() + } +} + +func TestCreateDidTC4(t *testing.T) { + k, ctx := TestKeeper(t) + msgServer := keeper.NewMsgServerImpl(*k) + goCtx := sdk.WrapSDKContext(ctx) + + t.Log("4. Alice creates an Org DID where Alice is the controller, and she adds a verification method of her friend Eve.") + + t.Log("Create Alice's DID") + alice_kp := testcrypto.GenerateEd25519KeyPair() + alice_didDoc := testssi.GenerateDidDoc(alice_kp) + alice_didDoc.Controller = append(alice_didDoc.Controller, alice_didDoc.Id) + t.Logf("Alice's DID Id: %s", alice_didDoc.Id) + alice_kp.VerificationMethodId = alice_didDoc.VerificationMethod[0].Id + didDocTx := testssi.GetRegisterDidDocumentRPC(alice_didDoc, []testcrypto.IKeyPair{alice_kp}) + _, err := msgServer.RegisterDID(goCtx, didDocTx) + if err != nil { + t.Log(err) + t.FailNow() + } + + t.Log("Create Eve's DID") + eve_kp := testcrypto.GenerateEd25519KeyPair() + eve_didDoc := testssi.GenerateDidDoc(eve_kp) + eve_didDoc.Controller = append(eve_didDoc.Controller, eve_didDoc.Id) + t.Logf("eve's DID Id: %s", eve_didDoc.Id) + eve_kp.VerificationMethodId = eve_didDoc.VerificationMethod[0].Id + didDocTx2 := testssi.GetRegisterDidDocumentRPC(eve_didDoc, []testcrypto.IKeyPair{eve_kp}) + _, err2 := msgServer.RegisterDID(goCtx, didDocTx2) + if err2 != nil { + t.Log(err) + t.FailNow() + } + + t.Log("Create a random DID Document with Alice being the controller, and Eve's VM being the only Verification Method") + random_kp := testcrypto.GenerateEd25519KeyPair() + random_didDoc := testssi.GenerateDidDoc(random_kp) + random_didDoc.Controller = []string{alice_didDoc.Id} + random_didDoc.VerificationMethod = []*types.VerificationMethod{ + eve_didDoc.VerificationMethod[0], + } + t.Logf("Random DID Id: %s", random_didDoc.Id) + random_kp.VerificationMethodId = random_didDoc.VerificationMethod[0].Id + + t.Log("4.1 FAIL: Only Alice sends their singature") + didDocTx3 := testssi.GetRegisterDidDocumentRPC(random_didDoc, []testcrypto.IKeyPair{alice_kp}) + _, err3 := msgServer.RegisterDID(goCtx, didDocTx3) + if err3 == nil { + t.Log(errExpectedToFail) + t.FailNow() + } + + t.Log("4.2 PASS: Both Alice and Eve send their singatures") + didDocTx3 = testssi.GetRegisterDidDocumentRPC(random_didDoc, []testcrypto.IKeyPair{alice_kp, eve_kp}) + _, err4 := msgServer.RegisterDID(goCtx, didDocTx3) + if err4 != nil { + t.Log(err4) + t.FailNow() + } +} + +func TestCreateDidTC5(t *testing.T) { + k, ctx := TestKeeper(t) + msgServer := keeper.NewMsgServerImpl(*k) + goCtx := sdk.WrapSDKContext(ctx) + + t.Log("5. FAIL: Alice tries to register a DID Document with duplicate publicKeyMultibase of type Ed25519VerificationKey2020.") + + t.Log("Create Alice's DID") + alice_kp := testcrypto.GenerateEd25519KeyPair() + alice_didDoc := testssi.GenerateDidDoc(alice_kp) + alice_didDoc.Controller = append(alice_didDoc.Controller, alice_didDoc.Id) + alice_didDoc.VerificationMethod = append(alice_didDoc.VerificationMethod, alice_didDoc.VerificationMethod[0]) + t.Logf("Alice's DID Id: %s", alice_didDoc.Id) + alice_kp.VerificationMethodId = alice_didDoc.VerificationMethod[0].Id + didDocTx := testssi.GetRegisterDidDocumentRPC(alice_didDoc, []testcrypto.IKeyPair{alice_kp}) + _, err := msgServer.RegisterDID(goCtx, didDocTx) + if err == nil { + t.Log(errExpectedToFail) + t.FailNow() + } +} diff --git a/x/ssi/tests/tx_schema_test.go b/x/ssi/tests/tx_schema_test.go new file mode 100644 index 0000000..e0984d8 --- /dev/null +++ b/x/ssi/tests/tx_schema_test.go @@ -0,0 +1,199 @@ +package tests + +import ( + "testing" + + sdk "github.com/cosmos/cosmos-sdk/types" + "github.com/hypersign-protocol/hid-node/x/ssi/keeper" + + testcrypto "github.com/hypersign-protocol/hid-node/x/ssi/tests/crypto" + testssi "github.com/hypersign-protocol/hid-node/x/ssi/tests/ssi" +) + +func TestSchemaTC1(t *testing.T) { + k, ctx := TestKeeper(t) + msgServer := keeper.NewMsgServerImpl(*k) + goCtx := sdk.WrapSDKContext(ctx) + + t.Log("FAIL: Alice creates a DID, deactivates it and attempts to create a schema") + + t.Log("Create Alice's DID") + alice_kp := testcrypto.GenerateEd25519KeyPair() + alice_didDoc := testssi.GenerateDidDoc(alice_kp) + alice_didDoc.Controller = append(alice_didDoc.Controller, alice_didDoc.Id) + t.Logf("Alice's DID Id: %s", alice_didDoc.Id) + alice_kp.VerificationMethodId = alice_didDoc.VerificationMethod[0].Id + didDocTx := testssi.GetRegisterDidDocumentRPC(alice_didDoc, []testcrypto.IKeyPair{alice_kp}) + _, err := msgServer.RegisterDID(goCtx, didDocTx) + if err != nil { + t.Log(err) + t.FailNow() + } + + t.Log("Alice attempts to deactivate DID Document") + deactivateDidElements := testssi.GetDeactivateDidDocumentRPC(k, ctx, alice_didDoc, []testcrypto.IKeyPair{alice_kp}) + _, err = msgServer.DeactivateDID(goCtx, deactivateDidElements) + if err != nil { + t.Log(err) + t.FailNow() + } + + t.Log("Alice creates a schema with her deactivated DID Document") + credentialSchema := testssi.GenerateSchema(alice_kp, alice_didDoc.Id) + schemaRPCElements := testssi.GenerateSchemaRPCElements(alice_kp, credentialSchema, alice_didDoc.VerificationMethod[0]) + _, err = msgServer.RegisterCredentialSchema(goCtx, schemaRPCElements) + if err == nil { + t.Log(errExpectedToFail) + t.FailNow() + } +} + +func TestSchemaTC2(t *testing.T) { + k, ctx := TestKeeper(t) + msgServer := keeper.NewMsgServerImpl(*k) + goCtx := sdk.WrapSDKContext(ctx) + + t.Log("PASS: Bob creates a DID and attempts to register a Schema") + + t.Log("Create Bob's DID") + bob_kp := testcrypto.GenerateEd25519KeyPair() + bob_didDoc := testssi.GenerateDidDoc(bob_kp) + bob_didDoc.Controller = append(bob_didDoc.Controller, bob_didDoc.Id) + t.Logf("bob's DID Id: %s", bob_didDoc.Id) + bob_kp.VerificationMethodId = bob_didDoc.VerificationMethod[0].Id + didDocTx := testssi.GetRegisterDidDocumentRPC(bob_didDoc, []testcrypto.IKeyPair{bob_kp}) + _, err := msgServer.RegisterDID(goCtx, didDocTx) + if err != nil { + t.Log(err) + t.FailNow() + } + + t.Log("Bob creates a schema") + credentialSchema := testssi.GenerateSchema(bob_kp, bob_didDoc.Id) + schemaRPCElements := testssi.GenerateSchemaRPCElements(bob_kp, credentialSchema, bob_didDoc.VerificationMethod[0]) + _, err = msgServer.RegisterCredentialSchema(goCtx, schemaRPCElements) + if err != nil { + t.Log(err) + t.FailNow() + } +} + +func TestSchemaTC3(t *testing.T) { + k, ctx := TestKeeper(t) + msgServer := keeper.NewMsgServerImpl(*k) + goCtx := sdk.WrapSDKContext(ctx) + + t.Log("FAIL: Bob creates a Schema where the name field is not in Pascal Case") + + t.Log("Create Bob's DID") + bob_kp := testcrypto.GenerateEd25519KeyPair() + bob_didDoc := testssi.GenerateDidDoc(bob_kp) + bob_didDoc.Controller = append(bob_didDoc.Controller, bob_didDoc.Id) + t.Logf("bob's DID Id: %s", bob_didDoc.Id) + bob_kp.VerificationMethodId = bob_didDoc.VerificationMethod[0].Id + didDocTx := testssi.GetRegisterDidDocumentRPC(bob_didDoc, []testcrypto.IKeyPair{bob_kp}) + _, err := msgServer.RegisterDID(goCtx, didDocTx) + if err != nil { + t.Log(err) + t.FailNow() + } + + credentialSchema := testssi.GenerateSchema(bob_kp, bob_didDoc.Id) + credentialSchema.Name = "Day Pass" + schemaRPCElements := testssi.GenerateSchemaRPCElements(bob_kp, credentialSchema, bob_didDoc.VerificationMethod[0]) + _, err = msgServer.RegisterCredentialSchema(goCtx, schemaRPCElements) + if err == nil { + t.Log(errExpectedToFail) + t.FailNow() + } +} + +func TestSchemaTC4(t *testing.T) { + k, ctx := TestKeeper(t) + msgServer := keeper.NewMsgServerImpl(*k) + goCtx := sdk.WrapSDKContext(ctx) + + t.Log("FAIL: Bob creates a Schema where the property field is some random string") + + t.Log("Create Bob's DID") + bob_kp := testcrypto.GenerateEd25519KeyPair() + bob_didDoc := testssi.GenerateDidDoc(bob_kp) + bob_didDoc.Controller = append(bob_didDoc.Controller, bob_didDoc.Id) + t.Logf("bob's DID Id: %s", bob_didDoc.Id) + bob_kp.VerificationMethodId = bob_didDoc.VerificationMethod[0].Id + didDocTx := testssi.GetRegisterDidDocumentRPC(bob_didDoc, []testcrypto.IKeyPair{bob_kp}) + _, err := msgServer.RegisterDID(goCtx, didDocTx) + if err != nil { + t.Log(err) + t.FailNow() + } + + credentialSchema := testssi.GenerateSchema(bob_kp, bob_didDoc.Id) + credentialSchema.Schema.Properties = "someString" + schemaRPCElements := testssi.GenerateSchemaRPCElements(bob_kp, credentialSchema, bob_didDoc.VerificationMethod[0]) + _, err = msgServer.RegisterCredentialSchema(goCtx, schemaRPCElements) + if err == nil { + t.Log(errExpectedToFail) + t.FailNow() + } +} + +func TestSchemaTC5(t *testing.T) { + k, ctx := TestKeeper(t) + msgServer := keeper.NewMsgServerImpl(*k) + goCtx := sdk.WrapSDKContext(ctx) + + t.Log("FAIL: Bob creates a Schema where the property field is a valid JSON, but one of the attributes has an invalid sub-attribute") + + t.Log("Create Bob's DID") + bob_kp := testcrypto.GenerateEd25519KeyPair() + bob_didDoc := testssi.GenerateDidDoc(bob_kp) + bob_didDoc.Controller = append(bob_didDoc.Controller, bob_didDoc.Id) + t.Logf("bob's DID Id: %s", bob_didDoc.Id) + bob_kp.VerificationMethodId = bob_didDoc.VerificationMethod[0].Id + didDocTx := testssi.GetRegisterDidDocumentRPC(bob_didDoc, []testcrypto.IKeyPair{bob_kp}) + _, err := msgServer.RegisterDID(goCtx, didDocTx) + if err != nil { + t.Log(err) + t.FailNow() + } + + credentialSchema := testssi.GenerateSchema(bob_kp, bob_didDoc.Id) + credentialSchema.Schema.Properties = "{\"fullName\":{\"type\":\"string\",\"sda\":\"string\"},\"companyName\":{\"type\":\"string\"},\"center\":{\"type\":\"string\"},\"invoiceNumber\":{\"type\":\"string\"}}" + schemaRPCElements := testssi.GenerateSchemaRPCElements(bob_kp, credentialSchema, bob_didDoc.VerificationMethod[0]) + _, err = msgServer.RegisterCredentialSchema(goCtx, schemaRPCElements) + if err == nil { + t.Log(errExpectedToFail) + t.FailNow() + } +} + +func TestSchemaTC6(t *testing.T) { + k, ctx := TestKeeper(t) + msgServer := keeper.NewMsgServerImpl(*k) + goCtx := sdk.WrapSDKContext(ctx) + + t.Log("FAIL: Bob creates a Schema where the property field is a valid JSON, but `type` sub-attribute is missing") + + t.Log("Create Bob's DID") + bob_kp := testcrypto.GenerateEd25519KeyPair() + bob_didDoc := testssi.GenerateDidDoc(bob_kp) + bob_didDoc.Controller = append(bob_didDoc.Controller, bob_didDoc.Id) + t.Logf("bob's DID Id: %s", bob_didDoc.Id) + bob_kp.VerificationMethodId = bob_didDoc.VerificationMethod[0].Id + didDocTx := testssi.GetRegisterDidDocumentRPC(bob_didDoc, []testcrypto.IKeyPair{bob_kp}) + _, err := msgServer.RegisterDID(goCtx, didDocTx) + if err != nil { + t.Log(err) + t.FailNow() + } + + credentialSchema := testssi.GenerateSchema(bob_kp, bob_didDoc.Id) + credentialSchema.Schema.Properties = "{\"fullName\":{\"format\":\"string\"},\"companyName\":{\"type\":\"string\"},\"center\":{\"type\":\"string\"},\"invoiceNumber\":{\"type\":\"string\"}}" + schemaRPCElements := testssi.GenerateSchemaRPCElements(bob_kp, credentialSchema, bob_didDoc.VerificationMethod[0]) + _, err = msgServer.RegisterCredentialSchema(goCtx, schemaRPCElements) + if err == nil { + t.Log(errExpectedToFail) + t.FailNow() + } +} \ No newline at end of file diff --git a/x/ssi/tests/tx_update_did_test.go b/x/ssi/tests/tx_update_did_test.go new file mode 100644 index 0000000..58e68f9 --- /dev/null +++ b/x/ssi/tests/tx_update_did_test.go @@ -0,0 +1,138 @@ +package tests + +import ( + "testing" + + sdk "github.com/cosmos/cosmos-sdk/types" + "github.com/hypersign-protocol/hid-node/x/ssi/keeper" + "github.com/hypersign-protocol/hid-node/x/ssi/types" + + testcrypto "github.com/hypersign-protocol/hid-node/x/ssi/tests/crypto" + testssi "github.com/hypersign-protocol/hid-node/x/ssi/tests/ssi" +) + +func TestUpdateDidTC(t *testing.T) { + k, ctx := TestKeeper(t) + msgServer := keeper.NewMsgServerImpl(*k) + goCtx := sdk.WrapSDKContext(ctx) + + t.Log("1 FAIL: Alice creates an Org DID where alice is the controller, and Bob's VM is added to its VM List only. Bob attempts to update Org DID by sending his signature.") + + t.Log("Create Alice's DID") + alice_kp := testcrypto.GenerateEd25519KeyPair() + alice_didDoc := testssi.GenerateDidDoc(alice_kp) + alice_didDoc.Controller = append(alice_didDoc.Controller, alice_didDoc.Id) + t.Logf("Alice's DID Id: %s", alice_didDoc.Id) + alice_kp.VerificationMethodId = alice_didDoc.VerificationMethod[0].Id + didDocTx := testssi.GetRegisterDidDocumentRPC(alice_didDoc, []testcrypto.IKeyPair{alice_kp}) + _, err := msgServer.RegisterDID(goCtx, didDocTx) + if err != nil { + t.Log(err) + t.FailNow() + } + + t.Log("Create Bob's DID") + bob_kp := testcrypto.GenerateEd25519KeyPair() + bob_didDoc := testssi.GenerateDidDoc(bob_kp) + bob_didDoc.Controller = append(bob_didDoc.Controller, bob_didDoc.Id) + t.Logf("Bob's DID Id: %s", bob_didDoc.Id) + bob_kp.VerificationMethodId = bob_didDoc.VerificationMethod[0].Id + didDocTx = testssi.GetRegisterDidDocumentRPC(bob_didDoc, []testcrypto.IKeyPair{bob_kp}) + _, err = msgServer.RegisterDID(goCtx, didDocTx) + if err != nil { + t.Log(err) + t.FailNow() + } + + t.Log("Create Organization DID") + org_kp := testcrypto.GenerateEd25519KeyPair() + org_didDoc := testssi.GenerateDidDoc(org_kp) + org_didDoc.Controller = []string{alice_didDoc.Id} + org_didDoc.VerificationMethod = []*types.VerificationMethod{bob_didDoc.VerificationMethod[0]} + didDocTx = testssi.GetRegisterDidDocumentRPC(org_didDoc, []testcrypto.IKeyPair{alice_kp, bob_kp}) + _, err = msgServer.RegisterDID(goCtx, didDocTx) + if err != nil { + t.Log(err) + t.FailNow() + } + + t.Log("Bob not being controller, attempts to change Organization DID") + org_didDoc.CapabilityDelegation = []string{org_didDoc.VerificationMethod[0].Id} + updateDidDocTx := testssi.GetUpdateDidDocumentRPC(k, ctx, org_didDoc, []testcrypto.IKeyPair{bob_kp}) + _, err = msgServer.UpdateDID(goCtx, updateDidDocTx) + if err == nil { + t.Log(errExpectedToFail) + t.FailNow() + } + + t.Log("2 PASS: Alice being the controller, attempts to update Org DID by sending their signature.") + updateDidDocTx = testssi.GetUpdateDidDocumentRPC(k, ctx, org_didDoc, []testcrypto.IKeyPair{alice_kp}) + _, err = msgServer.UpdateDID(goCtx, updateDidDocTx) + if err != nil { + t.Log(err) + t.FailNow() + } + + t.Log("3 FAIL: George tries to add himself as a controller in Org DID by only passing his signature") + george_kp := testcrypto.GenerateEd25519KeyPair() + george_didDoc := testssi.GenerateDidDoc(george_kp) + george_didDoc.Controller = append(george_didDoc.Controller, george_didDoc.Id) + t.Logf("george's DID Id: %s", george_didDoc.Id) + george_kp.VerificationMethodId = george_didDoc.VerificationMethod[0].Id + didDocTx = testssi.GetRegisterDidDocumentRPC(george_didDoc, []testcrypto.IKeyPair{george_kp}) + _, err = msgServer.RegisterDID(goCtx, didDocTx) + if err != nil { + t.Log(err) + t.FailNow() + } + + org_didDoc.Controller = append(org_didDoc.Controller, george_didDoc.Id) + updateDidDocTx = testssi.GetUpdateDidDocumentRPC(k, ctx, org_didDoc, []testcrypto.IKeyPair{george_kp}) + _, err = msgServer.UpdateDID(goCtx, updateDidDocTx) + if err == nil { + t.Log(errExpectedToFail) + t.FailNow() + } + + t.Log("4 FAIL: Alice attemps to add George as controller, by only sender her signature") + updateDidDocTx = testssi.GetUpdateDidDocumentRPC(k, ctx, org_didDoc, []testcrypto.IKeyPair{alice_kp}) + _, err = msgServer.UpdateDID(goCtx, updateDidDocTx) + if err == nil { + t.Log(errExpectedToFail) + t.FailNow() + } + + t.Log("5 PASS: Both Alice and George's signature are passed") + updateDidDocTx = testssi.GetUpdateDidDocumentRPC(k, ctx, org_didDoc, []testcrypto.IKeyPair{alice_kp, george_kp}) + _, err = msgServer.UpdateDID(goCtx, updateDidDocTx) + if err != nil { + t.Log(err) + t.FailNow() + } + + t.Log("6 PASS: Alice attempts to remove George as a cotroller by passing only her signature") + org_didDoc.Controller = []string{alice_didDoc.Id} + updateDidDocTx = testssi.GetUpdateDidDocumentRPC(k, ctx, org_didDoc, []testcrypto.IKeyPair{alice_kp}) + _, err = msgServer.UpdateDID(goCtx, updateDidDocTx) + if err != nil { + t.Log(err) + t.FailNow() + } + + t.Log("7 PASS: Addition of George as a controller and simultaneous removal of Alice as a controller. Both alice's and george's signature are passed") + org_didDoc.Controller = []string{george_didDoc.Id} + updateDidDocTx = testssi.GetUpdateDidDocumentRPC(k, ctx, org_didDoc, []testcrypto.IKeyPair{alice_kp, george_kp}) + _, err = msgServer.UpdateDID(goCtx, updateDidDocTx) + if err != nil { + t.Log(err) + t.FailNow() + } + + t.Log("8 FAIL: Alice attempts to perform UpdateDID by not changing any property of DID Document") + updateDidDocTx = testssi.GetUpdateDidDocumentRPC(k, ctx, org_didDoc, []testcrypto.IKeyPair{alice_kp, george_kp}) + _, err = msgServer.UpdateDID(goCtx, updateDidDocTx) + if err == nil { + t.Log(errExpectedToFail) + t.FailNow() + } +} diff --git a/x/ssi/tests/verification_method_test.go b/x/ssi/tests/verification_method_test.go new file mode 100644 index 0000000..a1cda72 --- /dev/null +++ b/x/ssi/tests/verification_method_test.go @@ -0,0 +1,242 @@ +package tests + +import ( + "testing" + + sdk "github.com/cosmos/cosmos-sdk/types" + "github.com/hypersign-protocol/hid-node/x/ssi/keeper" + + testcrypto "github.com/hypersign-protocol/hid-node/x/ssi/tests/crypto" + testssi "github.com/hypersign-protocol/hid-node/x/ssi/tests/ssi" +) + +// Note: Ed25519VerificationKey2020 tests are skipped as it is being +// used in other tests. + +func TestEcdsaSecp256k1VerificationKey2019(t *testing.T) { + k, ctx := TestKeeper(t) + msgServer := keeper.NewMsgServerImpl(*k) + goCtx := sdk.WrapSDKContext(ctx) + + alice_kp := testcrypto.GenerateSecp256k1KeyPair() + + t.Log("Register DID Document") + + alice_didDoc := testssi.GenerateDidDoc(alice_kp) + alice_didDoc.Controller = append(alice_didDoc.Controller, alice_didDoc.Id) + + alice_kp.VerificationMethodId = alice_didDoc.VerificationMethod[0].Id + + didDocTx := testssi.GetRegisterDidDocumentRPC(alice_didDoc, []testcrypto.IKeyPair{alice_kp}) + _, err := msgServer.RegisterDID(goCtx, didDocTx) + if err != nil { + t.Log(err) + t.FailNow() + } + + t.Log("Update DID Document") + alice_didDoc.CapabilityDelegation = []string{alice_didDoc.VerificationMethod[0].Id} + updateDidDocTx := testssi.GetUpdateDidDocumentRPC(k, ctx, alice_didDoc, []testcrypto.IKeyPair{alice_kp}) + _, err = msgServer.UpdateDID(goCtx, updateDidDocTx) + if err != nil { + t.Log(err) + t.FailNow() + } + + t.Log("Register Credential Schema Document") + credentialSchema := testssi.GenerateSchema(alice_kp, alice_didDoc.Id) + schemaRPCElements := testssi.GenerateSchemaRPCElements(alice_kp, credentialSchema, alice_didDoc.VerificationMethod[0]) + _, err = msgServer.RegisterCredentialSchema(goCtx, schemaRPCElements) + if err != nil { + t.Log(err) + t.FailNow() + } + + t.Log("Register Credential Status Document") + credentialStatus := testssi.GenerateCredentialStatus(alice_kp, alice_didDoc.Id) + credentialStatusRPCElements := testssi.GenerateRegisterCredStatusRPCElements(alice_kp, credentialStatus, alice_didDoc.VerificationMethod[0]) + _, err = msgServer.RegisterCredentialStatus(goCtx, credentialStatusRPCElements) + if err != nil { + t.Log(err) + t.FailNow() + } + + t.Log("Deactivate DID Document") + deactivateDidElements := testssi.GetDeactivateDidDocumentRPC(k, ctx, alice_didDoc, []testcrypto.IKeyPair{alice_kp}) + _, err = msgServer.DeactivateDID(goCtx, deactivateDidElements) + if err != nil { + t.Log(err) + t.FailNow() + } +} + +func TestEcdsaSecp256k1RecoveryMethod2020(t *testing.T) { + k, ctx := TestKeeper(t) + msgServer := keeper.NewMsgServerImpl(*k) + goCtx := sdk.WrapSDKContext(ctx) + + alice_kp := testcrypto.GenerateSecp256k1RecoveryKeyPair() + + t.Log("Register DID Document") + + alice_didDoc := testssi.GenerateDidDoc(alice_kp) + alice_didDoc.Controller = append(alice_didDoc.Controller, alice_didDoc.Id) + + alice_kp.VerificationMethodId = alice_didDoc.VerificationMethod[0].Id + + didDocTx := testssi.GetRegisterDidDocumentRPC(alice_didDoc, []testcrypto.IKeyPair{alice_kp}) + _, err := msgServer.RegisterDID(goCtx, didDocTx) + if err != nil { + t.Log(err) + t.FailNow() + } + + t.Log("Update DID Document") + alice_didDoc.CapabilityDelegation = []string{alice_didDoc.VerificationMethod[0].Id} + updateDidDocTx := testssi.GetUpdateDidDocumentRPC(k, ctx, alice_didDoc, []testcrypto.IKeyPair{alice_kp}) + _, err = msgServer.UpdateDID(goCtx, updateDidDocTx) + if err != nil { + t.Log(err) + t.FailNow() + } + + t.Log("Register Credential Schema Document") + credentialSchema := testssi.GenerateSchema(alice_kp, alice_didDoc.Id) + schemaRPCElements := testssi.GenerateSchemaRPCElements(alice_kp, credentialSchema, alice_didDoc.VerificationMethod[0]) + _, err = msgServer.RegisterCredentialSchema(goCtx, schemaRPCElements) + if err != nil { + t.Log(err) + t.FailNow() + } + + t.Log("Register Credential Status Document") + credentialStatus := testssi.GenerateCredentialStatus(alice_kp, alice_didDoc.Id) + credentialStatusRPCElements := testssi.GenerateRegisterCredStatusRPCElements(alice_kp, credentialStatus, alice_didDoc.VerificationMethod[0]) + _, err = msgServer.RegisterCredentialStatus(goCtx, credentialStatusRPCElements) + if err != nil { + t.Log(err) + t.FailNow() + } + + t.Log("Deactivate DID Document") + deactivateDidElements := testssi.GetDeactivateDidDocumentRPC(k, ctx, alice_didDoc, []testcrypto.IKeyPair{alice_kp}) + _, err = msgServer.DeactivateDID(goCtx, deactivateDidElements) + if err != nil { + t.Log(err) + t.FailNow() + } +} + +func TestBabyJubJubKey2021(t *testing.T) { + k, ctx := TestKeeper(t) + msgServer := keeper.NewMsgServerImpl(*k) + goCtx := sdk.WrapSDKContext(ctx) + + alice_kp := testcrypto.GenerateBabyJubJubKeyPair() + + t.Log("Register DID Document") + + alice_didDoc := testssi.GenerateDidDoc(alice_kp) + alice_didDoc.Controller = append(alice_didDoc.Controller, alice_didDoc.Id) + + alice_kp.VerificationMethodId = alice_didDoc.VerificationMethod[0].Id + + didDocTx := testssi.GetRegisterDidDocumentRPC(alice_didDoc, []testcrypto.IKeyPair{alice_kp}) + _, err := msgServer.RegisterDID(goCtx, didDocTx) + if err != nil { + t.Log(err) + t.FailNow() + } + + t.Log("Update DID Document") + alice_didDoc.CapabilityDelegation = []string{alice_didDoc.VerificationMethod[0].Id} + updateDidDocTx := testssi.GetUpdateDidDocumentRPC(k, ctx, alice_didDoc, []testcrypto.IKeyPair{alice_kp}) + _, err = msgServer.UpdateDID(goCtx, updateDidDocTx) + if err != nil { + t.Log(err) + t.FailNow() + } + + t.Log("Register Credential Schema Document") + credentialSchema := testssi.GenerateSchema(alice_kp, alice_didDoc.Id) + schemaRPCElements := testssi.GenerateSchemaRPCElements(alice_kp, credentialSchema, alice_didDoc.VerificationMethod[0]) + _, err = msgServer.RegisterCredentialSchema(goCtx, schemaRPCElements) + if err != nil { + t.Log(err) + t.FailNow() + } + + t.Log("Register Credential Status Document") + credentialStatus := testssi.GenerateCredentialStatus(alice_kp, alice_didDoc.Id) + credentialStatusRPCElements := testssi.GenerateRegisterCredStatusRPCElements(alice_kp, credentialStatus, alice_didDoc.VerificationMethod[0]) + _, err = msgServer.RegisterCredentialStatus(goCtx, credentialStatusRPCElements) + if err != nil { + t.Log(err) + t.FailNow() + } + + t.Log("Deactivate DID Document") + deactivateDidElements := testssi.GetDeactivateDidDocumentRPC(k, ctx, alice_didDoc, []testcrypto.IKeyPair{alice_kp}) + _, err = msgServer.DeactivateDID(goCtx, deactivateDidElements) + if err != nil { + t.Log(err) + t.FailNow() + } +} + +func TestBbsBls(t *testing.T) { + k, ctx := TestKeeper(t) + msgServer := keeper.NewMsgServerImpl(*k) + goCtx := sdk.WrapSDKContext(ctx) + + alice_kp := testcrypto.GenerateBbsBlsKeyPair() + + t.Log("Register DID Document") + + alice_didDoc := testssi.GenerateDidDoc(alice_kp) + alice_didDoc.Controller = append(alice_didDoc.Controller, alice_didDoc.Id) + + alice_kp.VerificationMethodId = alice_didDoc.VerificationMethod[0].Id + + didDocTx := testssi.GetRegisterDidDocumentRPC(alice_didDoc, []testcrypto.IKeyPair{alice_kp}) + _, err := msgServer.RegisterDID(goCtx, didDocTx) + if err != nil { + t.Log(err) + t.FailNow() + } + + t.Log("Update DID Document") + alice_didDoc.CapabilityDelegation = []string{alice_didDoc.VerificationMethod[0].Id} + updateDidDocTx := testssi.GetUpdateDidDocumentRPC(k, ctx, alice_didDoc, []testcrypto.IKeyPair{alice_kp}) + _, err = msgServer.UpdateDID(goCtx, updateDidDocTx) + if err != nil { + t.Log(err) + t.FailNow() + } + + t.Log("Register Credential Schema Document") + credentialSchema := testssi.GenerateSchema(alice_kp, alice_didDoc.Id) + schemaRPCElements := testssi.GenerateSchemaRPCElements(alice_kp, credentialSchema, alice_didDoc.VerificationMethod[0]) + _, err = msgServer.RegisterCredentialSchema(goCtx, schemaRPCElements) + if err != nil { + t.Log(err) + t.FailNow() + } + + t.Log("Register Credential Status Document") + credentialStatus := testssi.GenerateCredentialStatus(alice_kp, alice_didDoc.Id) + credentialStatusRPCElements := testssi.GenerateRegisterCredStatusRPCElements(alice_kp, credentialStatus, alice_didDoc.VerificationMethod[0]) + _, err = msgServer.RegisterCredentialStatus(goCtx, credentialStatusRPCElements) + if err != nil { + t.Log(err) + t.FailNow() + } + + t.Log("Deactivate DID Document") + deactivateDidElements := testssi.GetDeactivateDidDocumentRPC(k, ctx, alice_didDoc, []testcrypto.IKeyPair{alice_kp}) + _, err = msgServer.DeactivateDID(goCtx, deactivateDidElements) + if err != nil { + t.Log(err) + t.FailNow() + } +}