コード例 #1
0
        public static IEnumerable <string> ToRdf(JToken token, JsonLdProcessorOptions options)
        {
            var jsonLdParser = new JsonLdParser(options);
            var store        = new TripleStore();

            jsonLdParser.Load(store, new StringReader(token.ToString(Newtonsoft.Json.Formatting.None)));

            var nqWriter = new NQuadsWriter(NQuadsSyntax.Rdf11);

            using var expectedTextWriter = new System.IO.StringWriter();
            nqWriter.Save(store, expectedTextWriter);
            return(expectedTextWriter.ToString()
                   .Split(expectedTextWriter.NewLine)
                   .Select(x => x.Trim())
                   .Where(x => !string.IsNullOrWhiteSpace(x))
                   .OrderBy(x => x));
        }
コード例 #2
0
        public override async Task <JObject> UpdateAsync(JObject proof, ProofOptions options)
        {
            proof = await base.UpdateAsync(proof, options);

            // no capability chain given, attempt to compute from parent
            if (CapabilityChain == null)
            {
                var processorOptions = new JsonLdProcessorOptions
                {
                    CompactToRelative = false,
                    DocumentLoader    = options.DocumentLoader.Load
                };

                var capability = await Utils.FetchInSecurityContextAsync(
                    options.Input, false, processorOptions);

                CapabilityChain = await Utils.ComputeCapabilityChainAsync(
                    capability, processorOptions);
            }

            proof["capabilityChain"] = new JArray(CapabilityChain);
            return(proof);
        }
コード例 #3
0
        public async Task <JToken> CreateProofAsync(CreateProofOptions options)
        {
            if (options.VerificationMethod is null)
            {
                throw new Exception("Verification method is required.");
            }
            if (options.ProofPurpose is null)
            {
                throw new Exception("Proof purpose is required.");
            }
            if (options.LdSuiteType is null)
            {
                throw new Exception("Suite type is required.");
            }

            var suite            = suiteFactory.GetSuite(options.LdSuiteType) ?? throw new Exception($"Suite not found for type '{options.LdSuiteType}'");
            var processorOptions = new JsonLdProcessorOptions
            {
                CompactToRelative = false,
                DocumentLoader    = documentLoader.GetDocumentLoader()
            };

            var original = options.Document.DeepClone();

            if (options.CompactProof)
            {
                options.Document = JsonLdProcessor.Compact(
                    input: options.Document,
                    context: Constants.SECURITY_CONTEXT_V2_URL,
                    options: processorOptions);
            }

            original["proof"] = await suite.CreateProofAsync(options, processorOptions);

            return(original);
        }
        public bool VerifyProof(VerifyProofOptions options, JsonLdProcessorOptions processorOptions)
        {
            options.Proof["type"] = "https://w3c-ccg.github.io/ldp-bbs2020/context/v1#BbsBlsSignature2020";

            var documentStatements = BbsBlsSignature2020Suite.CreateVerifyDocumentData(options.Document, processorOptions);
            var proofStatements    = BbsBlsSignature2020Suite.CreateVerifyProofData(options.Proof, processorOptions);

            var transformedInputDocumentStatements = documentStatements.Select(TransformIdToBlankNode).ToArray();

            var statementsToVerify = proofStatements.Concat(transformedInputDocumentStatements);

            var verificationMethod = BbsBlsSignature2020Suite.GetVerificationMethod(options.Proof, processorOptions);

            var proofData = Convert.FromBase64String(options.Proof["proofValue"].ToString());
            var nonce     = options.Proof["nonce"].ToString();

            var verifyResult = BbsProvider.VerifyProof(new VerifyProofRequest(
                                                           publicKey: verificationMethod.ToBlsKeyPair().GeyBbsKeyPair((uint)statementsToVerify.Count()),
                                                           proof: proofData,
                                                           messages: GetIndexedMessages(statementsToVerify.ToArray()).ToArray(),
                                                           nonce: nonce));

            return(verifyResult == SignatureProofStatus.Success);
        }
コード例 #5
0
 /// <summary>
 /// Creates a new GZipped JSON-LD parser with a specific set of <see cref="JsonLdProcessorOptions"/>.
 /// </summary>
 /// <param name="parserOptions">The options to pass to the underlying <see cref="JsonLdParser"/></param>
 public GZippedJsonLdParser(JsonLdProcessorOptions parserOptions) : base(new JsonLdParser(parserOptions))
 {
 }
コード例 #6
0
 /// <summary>
 /// Create a new processor instance that uses the specified processor options.
 /// </summary>
 /// <param name="options"></param>
 /// <param name="warnings">The list to add any generated warnings to</param>
 public ProcessorBase(JsonLdProcessorOptions options, IList <JsonLdProcessorWarning> warnings)
 {
     Options  = options;
     Warnings = warnings;
 }
コード例 #7
0
 /// <summary>
 /// Create an instace of the parser configured with the provided parser options
 /// </summary>
 /// <param name="parserOptions"></param>
 public JsonLdParser(JsonLdProcessorOptions parserOptions)
 {
     ParserOptions = parserOptions;
 }
 public Task <JToken> CreateProofAsync(CreateProofOptions options, JsonLdProcessorOptions processorOptions) => Task.FromResult(CreateProof(options, processorOptions));
 public Task <bool> VerifyProofAsync(VerifyProofOptions options, JsonLdProcessorOptions processorOptions) => Task.FromResult(VerifyProof(options, processorOptions));
コード例 #10
0
        /// <summary>
        /// Creates a `capabilityChain` for delegating the given capability.
        /// </summary>
        /// <param name="capability"></param>
        /// <param name="processorOptions"></param>
        /// <returns></returns>
        public static Task <IEnumerable <string> > ComputeCapabilityChainAsync(JObject capability, JsonLdProcessorOptions processorOptions)
        {
            if (capability["parentCapability"] == null)
            {
                throw new Exception("Cannot compute capability chain; capability has no 'parentCapability");
            }

            // TODO
            throw new NotImplementedException("Cannot compute capability chain.");
        }
コード例 #11
0
        /// <summary>
        /// Fetches a JSON-LD document from a URL and, if necessary, compacts it to
        /// the security v2 context.
        /// </summary>
        /// <param name="document"></param>
        /// <param name="isRoot"></param>
        /// <param name="options"></param>
        /// <returns></returns>
        public static async Task <JObject> FetchInSecurityContextAsync(JToken document, bool isRoot = false, JsonLdProcessorOptions options = null)
        {
            await Task.Yield();

            if (document.Type == JTokenType.Object &&
                document["@context"]?.Value <string>() == Constants.SECURITY_CONTEXT_V2_URL &&
                !isRoot)
            {
                return(document as JObject);
            }

            return(JsonLdProcessor.Compact(document, Constants.SECURITY_CONTEXT_V2_URL, options));
        }
コード例 #12
0
        /// <summary>
        /// Verifies the capability chain, if any, attached to the given capability.
        /// </summary>
        /// <param name="capability"></param>
        /// <returns></returns>
        public static async Task <JToken> VerifyCapabilityChain(JToken capability, PurposeOptions purposeOptions, JsonLdProcessorOptions options = null)
        {
            /* Verification process is:
             *  1. Fetch capability if only its ID was passed.
             *  1.1. Ensure `capabilityAction` is allowed.
             *  2. Get the capability delegation chain for the capability.
             *  3. Validate the capability delegation chain.
             *  4. Verify the root capability:
             *      4.1. Check the expected target, if one was specified.
             *      4.2. Ensure that the caveats are met on the root capability.
             *      4.3. Ensure root capability is expected and has no invocation target.
             *  5. If `excludeGivenCapability` is not true, then we need to verify the
             *      capability delegation proof on `capability`, so add it to the chain to
             *      get processed below.
             *  6. For each capability `cap` in the chain, verify the capability delegation
             *      proof on `cap`. This will validate everything else for `cap` including
             *      that caveats are met.
             *
             *  Note: We start verifying a capability from its root of trust (the
             *  beginning or head of the capability chain) as this approach limits an
             *  attacker's ability to waste our time and effort traversing from the tail
             *  to the head.
             */

            // 1. Fetch capability if only its ID was passed.
            capability = await FetchInSecurityContextAsync(capability, false, options);

            //capability = new CapabilityDelegation(cap as JObject);

            // TODO: Add allowed action validation

            // 2. Get the capability delegation chain for the capability.
            var capabilityChain = GetCapabilityChain(capability);

            // 3. Validate the capability delegation chain.
            ValidateCapabilityChain(capability, capabilityChain);

            // 4. Verify root capability (note: it must *always* be dereferenced since
            // it does not need to have a delegation proof to vouch for its authenticity
            // ... dereferencing it prevents adversaries from submitting an invalid
            // root capability that is accepted):
            var isRoot         = !capabilityChain.Any();
            var rootCapability = isRoot ? capability : capabilityChain.First();

            capabilityChain = capabilityChain.Skip(1).ToArray();

            rootCapability = await Utils.FetchInSecurityContextAsync(rootCapability, isRoot, null);

            // 4.1. Check the expected target, if one was specified.
            if (purposeOptions.ExpectedTarget != null)
            {
                var target = GetTarget(rootCapability);
                if (target != purposeOptions.ExpectedTarget)
                {
                    throw new Exception($"Expected target ({purposeOptions.ExpectedTarget}) does not match " +
                                        $"root capability target({target}).");
                }
            }

            // 4.2. Ensure that the caveats are met on the root capability.
            // TODO: Add caveats

            // 4.3. Ensure root capability is expected and has no invocation target.

            // run root capability checks (note that these will only be run once
            // because the `verifiedParentCapability` parameter stops recursion
            // from happening below)

            // ensure that the invocation target matches the root capability or,
            // if `expectedRootCapability` is present, that it matches that
            if (purposeOptions.ExpectedRootCapability != null)
            {
                if (purposeOptions.ExpectedRootCapability != rootCapability["id"].Value <string>())
                {
                    throw new Exception($"Expected root capability ({purposeOptions.ExpectedRootCapability}) does not " +
                                        $"match actual root capability({rootCapability["id"]}).");
                }
            }
            else if (GetTarget(rootCapability) != rootCapability["id"].Value <string>())
            {
                throw new Exception("The root capability must not specify a different " +
                                    "invocation target.");
            }

            // root capability now verified
            var verifiedParentCapability = rootCapability;

            // if verifying a delegation proof and we're at the root, exit early
            if (isRoot)
            {
                return(verifiedParentCapability);
            }

            // create a document loader that will use properly embedded capabilities
            var documentLoader = new CachingDocumentLoader(Array.Empty <IDocumentResolver>());
            var next           = capabilityChain;

            while (next.Any())
            {
                // the only capability that may be embedded (if the zcap is valid) is
                // the last one in the chain, if it is embedded, add it to `dlMap` and
                // recurse into its chain and loop to collect all embedded zcaps
                var cap = next.Last();

                if (!(cap is JObject))
                {
                    break;
                }

                if (cap["@context"] == null)
                {
                    // the capabilities in the chain are already in the security context
                    // if no context has been specified
                    cap["@context"] = Constants.SECURITY_CONTEXT_V2_URL;
                }

                // Transforms the `capability` into the security context (the native
                // context this code uses) so we can process it cleanly and then
                // verifies the capability delegation proof on `capability`. This allows
                // capabilities to be expressed using custom contexts.
                cap = await FetchInSecurityContextAsync(cap, false, options);

                documentLoader.AddCached(cap["id"].Value <string>(), cap as JObject);

                next = GetCapabilityChain(cap);
            }
            options.DocumentLoader = documentLoader.Load;

            // 5. If `excludeGivenCapability` is not true, then we need to verify the
            //  capability delegation proof on `capability`, so add it to the chain to
            //  get processed below. If an `inspectCapabilityChain` handler has been
            //  provided, the verify results are required on all capabilities.
            // TODO: Add support for `excludeGivenCapability`

            // 6. For each capability `cap` in the chain, verify the capability
            //   delegation proof on `cap`. This will validate everything else for
            //   `cap` including that caveats are met.

            // note that `verifiedParentCapability` will prevent repetitive checking
            // of the same segments of the chain (once a parent is verified, its chain
            // is not checked again when checking its children)

            for (int i = 0; i < capabilityChain.Count(); i++)
            {
                var cap = capabilityChain.ElementAt(i);
                cap = await FetchInSecurityContextAsync(cap, false, options);

                var verifyResult = LdSignatures.VerifyAsync(cap, new ProofOptions
                {
                    Suite   = purposeOptions.Suite,
                    Purpose = new CapabilityDelegationProofPurpose
                    {
                        Options = new PurposeOptions
                        {
                            ExpectedTarget         = purposeOptions.ExpectedTarget,
                            ExpectedRootCapability = purposeOptions.ExpectedRootCapability
                        },
                        VerifiedParentCapability = verifiedParentCapability
                    },
                    DocumentLoader = documentLoader,
                    CompactProof   = false
                });
            }

            return(null);
        }
コード例 #13
0
        public static (JToken, IEnumerable <JObject>) GetProofs(this JToken document, JsonLdProcessorOptions options, bool compactProof = true, string proofPropertyName = "proof")
        {
            if (compactProof)
            {
                document = JsonLdProcessor.Compact(document, Constants.SECURITY_CONTEXT_V2_URL, options);
            }
            var proofs = document[proofPropertyName];

            (document as JObject).Remove(proofPropertyName);

            return(document, proofs switch
            {
                JObject _ => new[] { proofs as JObject },
                JArray _ => proofs.Select(x => x as JObject),
                _ => throw new Exception("Unexpected proof type")
            });