/// <inheritdoc />
        protected override Task <JObject> SignAsync(IVerifyData verifyData, JObject proof, ProofOptions options)
        {
            var verifyDataArray = verifyData as StringArray ?? throw new Exception("Unsupported verify data type");

            var derivedProof = new JObject {
                { "@context", Constants.SECURITY_CONTEXT_V3_URL }
            };
            var originalProof = options.AdditonalData["originalDocument"]["proof"];
            var signature     = Convert.FromBase64String(originalProof["proofValue"].ToString());

            var keyPair = new Bls12381G2Key2020(GetVerificationMethod(originalProof as JObject, options));
            var bbsKey  = keyPair.ToBlsKeyPair().GetBbsKey((uint)verifyDataArray.Data.Length);
            var nonce   = Nonce ?? Encoding.UTF8.GetBytes(Guid.NewGuid().ToString());

            var proofMessages = GetProofMessages(
                allInputStatements: verifyDataArray.Data,
                revealIndicies: options.AdditonalData["revealIndicies"].ToObject <int[]>());

            var outputProof = Service.CreateProof(new CreateProofRequest(
                                                      publicKey: bbsKey,
                                                      messages: proofMessages.ToArray(),
                                                      signature: signature,
                                                      blindingFactor: null,
                                                      nonce: nonce));

            // Set the proof value on the derived proof
            derivedProof["proofValue"]         = Convert.ToBase64String(outputProof);
            derivedProof["nonce"]              = Convert.ToBase64String(nonce);
            derivedProof["created"]            = originalProof["created"];
            derivedProof["proofPurpose"]       = originalProof["proofPurpose"];
            derivedProof["verificationMethod"] = originalProof["verificationMethod"];
            derivedProof["type"] = "BbsBlsSignatureProof2020";

            return(Task.FromResult(derivedProof));
        }
        protected override Task VerifyAsync(IVerifyData payload, JToken proof, JToken verificationMethod, ProofOptions options)
        {
            var verifyData = payload as StringArray ?? throw new ArgumentException("Invalid data type");

            var blsVerificationMethod = new Bls12381G2Key2020(verificationMethod as JObject);

            var key       = new BlsKeyPair(Multibase.Base58.Decode(blsVerificationMethod.PublicKeyBase58));
            var signature = Helpers.FromBase64String(proof["proofValue"]?.ToString() ?? throw new Exception("Proof value not found"));

            var valid = SignatureService.Verify(new VerifyRequest(key, signature, verifyData.Data));

            if (!valid)
            {
                throw new Exception("Invalid signature");
            }
            return(Task.CompletedTask);
        }
        /// <inheritdoc />
        protected override Task VerifyAsync(IVerifyData verifyData, JToken proof, JToken verificationMethod, ProofOptions options)
        {
            var stringArray = verifyData as StringArray ?? throw new Exception("Unsupported verify data type");

            var proofData = Helpers.FromBase64String(proof["proofValue"]?.ToString() ?? throw new Exception("Proof value not found"));
            var nonce     = Helpers.FromBase64String(proof["nonce"]?.ToString() ?? throw new Exception("Nonce not found"));
            var keyPair   = new Bls12381G2Key2020(GetVerificationMethod(proof as JObject, options));

            var messageCount = Service.GetTotalMessageCount(proofData);

            var verifyResult = Service.VerifyProof(new VerifyProofRequest(
                                                       publicKey: keyPair.ToBlsKeyPair().GetBbsKey((uint)messageCount),
                                                       proof: proofData,
                                                       messages: stringArray.Data,
                                                       nonce: nonce));

            if (!verifyResult)
            {
                throw new Exception("Invalid signature proof");
            }
            return(Task.CompletedTask);
        }