protected virtual IVerifyData CreateVerifyData(JObject proof, ProofOptions options)
        {
            var processorOptions = options.GetProcessorOptions();

            var c14nProofOptions = Helpers.CanonizeProof(proof, processorOptions);
            var c14nDocument     = Helpers.Canonize(options.Input, processorOptions);

            var sha256 = SHA256.Create();

            return((ByteArray)sha256.ComputeHash(Encoding.UTF8.GetBytes(c14nProofOptions))
                   .Concat(sha256.ComputeHash(Encoding.UTF8.GetBytes(c14nDocument)))
                   .ToArray());
        }
예제 #2
0
        /// <summary>
        /// Get a proof from a signed document
        /// </summary>
        /// <param name="document"></param>
        /// <param name="options"></param>
        /// <returns></returns>
        public static (JToken proof, JToken document) GetProof(JToken document, ProofOptions options)
        {
            var documentCopy = options.CompactProof
                ? JsonLdProcessor.Compact(
                input: document,
                context: Constants.SECURITY_CONTEXT_V2_URL,
                options: options.GetProcessorOptions())
                : document.DeepClone();

            var proof = documentCopy["proof"].DeepClone();

            document.Remove("proof");

            if (proof == null)
            {
                throw new Exception("No matching proofs found in the given document.");
            }

            proof["@context"] = Constants.SECURITY_CONTEXT_V2_URL;

            return(proof, document);
        }
        protected VerificationMethod GetVerificationMethod(JObject proof, ProofOptions options)
        {
            var verificationMethod = proof["verificationMethod"] ?? throw new Exception("No 'verificationMethod' found in proof.");

            var verificationMethodId = verificationMethod.Type switch
            {
                JTokenType.String => verificationMethod.ToString(),
                JTokenType.Object => verificationMethod["id"]?.ToString() ?? throw new Exception("Verification Method found, but it's 'id' property was empty"),
                      _ => throw new Exception($"Invalid verification method type: {verificationMethod.Type}")
            };
            var processorOptions = options.GetProcessorOptions();

            processorOptions.ExpandContext = Constants.SECURITY_CONTEXT_V2_URL;

            var result = JsonLdProcessor.Frame(
                verificationMethodId,
                new JObject
            {
                { "@context", Constants.SECURITY_CONTEXT_V2_URL },
                { "@embed", "@always" },
                { "id", verificationMethod }
            },
                processorOptions);

            if (result == null || result["id"] == null)
            {
                throw new Exception($"Verification method {verificationMethod} not found.");
            }

            if (result["revoked"] != null)
            {
                throw new Exception("The verification method has been revoked.");
            }

            return(new VerificationMethod(result));
        }
예제 #4
0
        /// <summary>
        /// Cryptographically signs the provided document by adding a `proof` section,
        /// based on the provided suite and proof purpose.
        /// </summary>
        /// <param name="document"></param>
        /// <param name="options"></param>
        /// <returns></returns>
        public static async Task <JToken> SignAsync(JToken document, ProofOptions options)
        {
            if (options.Purpose is null)
            {
                throw new Exception("Proof purpose is required.");
            }
            if (options.Suite is null)
            {
                throw new Exception("Suite is required.");
            }

            options.AdditonalData["originalDocument"] = document;
            var documentCopy = document.DeepClone();

            documentCopy = options.CompactProof
                ? JsonLdProcessor.Compact(documentCopy, Constants.SECURITY_CONTEXT_V2_URL, options.GetProcessorOptions())
                : document.DeepClone();
            documentCopy.Remove("proof");

            // create the new proof (suites MUST output a proof using the security-v2
            // `@context`)
            options.Input = documentCopy;
            var proof = await options.Suite.CreateProofAsync(options);

            // TODO: Check compaction again
            proof.Proof.Remove("@context");

            var result = proof.UpdatedDocument ?? document.DeepClone();

            result["proof"] = proof.Proof;
            return(result);
        }
        /// <summary>
        /// Create proof
        /// </summary>
        /// <param name="options"></param>
        /// <returns></returns>
        public override async Task <ProofResult> CreateProofAsync(ProofOptions options)
        {
            if (VerificationMethod == null)
            {
                throw new ArgumentNullException(nameof(VerificationMethod), "VerificationMethod must be specified.");
            }
            if (TypeName == null)
            {
                throw new ArgumentNullException(nameof(TypeName), "TypeName must be specified.");
            }

            var proof = InitialProof != null
                ? JsonLdProcessor.Compact(InitialProof, Constants.SECURITY_CONTEXT_V2_URL, options.GetProcessorOptions())
                : new JObject
            {
                { "@context", Constants.SECURITY_CONTEXT_V2_URL }
            };

            proof["type"]               = TypeName;
            proof["created"]            = Date.HasValue ? Date.Value.ToString("s") : DateTime.Now.ToString("s");
            proof["verificationMethod"] = VerificationMethod;

            // allow purpose to update the proof; the `proof` is in the
            // SECURITY_CONTEXT_URL `@context` -- therefore the `purpose` must
            // ensure any added fields are also represented in that same `@context`
            proof = await options.Purpose.UpdateAsync(proof, options);

            // create data to sign
            var verifyData = CreateVerifyData(proof, options);

            // sign data
            proof = await SignAsync(verifyData, proof, options);

            return(new ProofResult {
                Proof = proof
            });
        }