diff --git a/Makefile b/Makefile new file mode 100755 index 0000000..ec3436b --- /dev/null +++ b/Makefile @@ -0,0 +1,19 @@ +#!/usr/bin/env nix-shell +#!nix-shell -i "make -f" -p go golint + +PKGS=./cardano ./cmd ./header ./ipfs ./key ./ledger ./rdf ./tgdh + +SRCS=$(shell find $(PKGS) -type f -name \*.go) + +nacatgunma: main.go $(SRCS) + GOPATH= go build -o nacatgunma $< + +test: $(SRCS) + GOPATH= go test -v $(PKGS) + +format: $(SRCS) + GOPATH= go fmt $(PKGS) + +.SUFFIXES: + +.PHONY: test format \ No newline at end of file diff --git a/RDF-Specialization.md b/RDF-Specialization.md index ef4acaf..96d3d0e 100644 --- a/RDF-Specialization.md +++ b/RDF-Specialization.md @@ -3,22 +3,22 @@ ## RDF graph payload -Assume that the content identifier $\mathsf{body}(B) \in \mathcal{C}$ references a concrete RDF graph: $\mathsf{G}(B) \subseteq \mathcal{T}$ where $\mathcal{T}$ is the set of RDF triples of the form $(s, p, o)$. +Assume that the content identifier $`\mathsf{body}(B) \in \mathcal{C}`$ references a concrete RDF graph: $`\mathsf{G}(B) \subseteq \mathcal{T}`$ where $`\mathcal{T}`$ is the set of RDF triples of the form $`(s, p, o)`$. -We interpret $\mathsf{G}(B)$ as the **payload graph** authored by $\mathsf{issuer}(B)$. +We interpret $`\mathsf{G}(B)`$ as the **payload graph** authored by $`\mathsf{issuer}(B)`$. ## Reification -We define a reification function $\mathsf{reify}(B)$ that maps the signed graph to a **named graph** or **quads** with provenance. +We define a reification function $`\mathsf{reify}(B)`$ that maps the signed graph to a **named graph** or **quads** with provenance. -For each triple $t \in \mathsf{G}(B)$, define the reified form: +For each triple $`t \in \mathsf{G}(B)`$, define the reified form: $$ \mathsf{reify}(B) = \{ (s, p, o, g\_B) \mid (s, p, o) \in \mathsf{G}(B) \} $$ -where $g\_B \in \mathcal{U}$ is a unique graph name associated with the block $B$, such as: +where $`g\_B \in \mathcal{U}`$ is a unique graph name associated with the block $`B`$, such as: $$ g\_B := \texttt{did:} \mathsf{issuer}(B) \\# \mathsf{id}(B) @@ -28,23 +28,23 @@ Alternatively, if using RDF-star or PROV-O, the reification can instead be: - A named graph or blank node denoting the assertion - Annotated with: - - $\texttt{prov:wasAttributedTo} \ \mathsf{issuer}(B)$ - - $\texttt{prov:wasDerivedFrom} \ \mathsf{id}(B)$ + - $`\texttt{prov:wasAttributedTo} \ \mathsf{issuer}(B)`$ + - $`\texttt{prov:wasDerivedFrom} \ \mathsf{id}(B)`$ The exact form depends on the RDF dialect used, but semantically the payload is treated as **authored assertions by the signer**. ## State computation -Given a participant $u$, let $\mathcal{V}_u$ be the set of blocks **visible** under subjective traversal (see prior section with accept/reject logic). +Given a participant $`u`$, let $`\mathcal{V}_u`$ be the set of blocks **visible** under subjective traversal (see prior section with accept/reject logic). -Define the participant’s **assembled state graph** $\mathsf{S}_u$ as: +Define the participant’s **assembled state graph** $`\mathsf{S}_u`$ as: $$ \mathsf{S}\_u := \bigcup\_{B \in \mathcal{V}\_u} \mathsf{reify}(B) $$ -That is, the total RDF graph is the union of all reified block payloads visible under $u$'s trust and traversal policy. +That is, the total RDF graph is the union of all reified block payloads visible under $`u`$'s trust and traversal policy. If RDF-star is used, this could equivalently be: @@ -56,7 +56,7 @@ $$ ## Conflict handling -If blocks in $\mathcal{V}_u$ make **conflicting assertions** (e.g., two blocks claim different values for the same triple), this is **not a protocol error** — the provenance-aware model allows: +If blocks in $`\mathcal{V}_u`$ make **conflicting assertions** (e.g., two blocks claim different values for the same triple), this is **not a protocol error** — the provenance-aware model allows: - Leaving conflicting assertions coexisting with different graph names - Using downstream logic to resolve (e.g., trust-weighted resolution, query filtering) @@ -68,9 +68,9 @@ Thus, **state** is: ## Summary -| Concept | Description | -|---------------------|----------------------------------------------------------------------------| -| $\mathsf{G}(B)$ | RDF graph payload of block $B$ | -| $\mathsf{reify}(B)$ | Provenance-aware named graph or RDF-star reification | -| $\mathsf{S}_u$ | State for participant $u$: union of all reified payloads of visible blocks | -| Conflicts | Allowed; resolution is subjective and external | +| Concept | Description | +|-----------------------|------------------------------------------------------------------------------| +| $`\mathsf{G}(B)`$ | RDF graph payload of block $`B`$ | +| $`\mathsf{reify}(B)`$ | Provenance-aware named graph or RDF-star reification | +| $`\mathsf{S}_u`$ | State for participant $`u`$: union of all reified payloads of visible blocks | +| Conflicts | Allowed; resolution is subjective and external | diff --git a/ReadMe.md b/ReadMe.md index 504eaf9..165d4ab 100755 --- a/ReadMe.md +++ b/ReadMe.md @@ -29,6 +29,7 @@ The combination of signed RDF graphs + DAG tips + subjective tip choice constitu - [General specification](Specification.md) - [Specialization to RDF bodies](RDF-Specialization.md) +- [Specialization to TGDH encryption](TGDH-Specialization.md) - [Using Cardano for Layer 1](Cardano-for-Layer-1.md) diff --git a/Specification.md b/Specification.md index b64221e..72772ba 100644 --- a/Specification.md +++ b/Specification.md @@ -34,7 +34,7 @@ type Payload struct { ## Blocks -Let $\mathcal{C}$ be the set of content identifiers (e.g., CIDs), and let $\mathcal{P}$ be the set of participants with associated public keys. +Let $`\mathcal{C}`$ be the set of content identifiers (e.g., CIDs), and let $`\mathcal{P}`$ be the set of participants with associated public keys. Each block is a tuple: @@ -43,31 +43,31 @@ B = (\text{id}, \mathsf{accept}(B), \mathsf{reject}(B), \mathsf{body}(B), \maths $$ where: -- $\text{id} \in \mathcal{C}$: the content identifier of the block itself. -- $\mathsf{accept}(B) \subset \mathcal{C}$: set of parent block CIDs that this block explicitly extends. -- $\mathsf{reject}(B) \subset \mathcal{C}$: set of block CIDs that this block rejects. -- $\mathsf{body}(B) \in \mathcal{C}$: CID of the block’s body (arbitrary content). -- $\mathsf{schema}(B) \in \mathbb{S}$: schema URI string. -- $\mathsf{media}(B) \in \mathbb{M}$: media type string. -- $\mathsf{comment}(B)$: comment string. -- $\mathsf{issuer}(B) \in \mathcal{P}$: DID of the block’s issuer. -- $\mathsf{sig}(B)$: digital signature over the payload fields, created using the issuer’s secret key. +- $`\text{id} \in \mathcal{C}`$: the content identifier of the block itself. +- $`\mathsf{accept}(B) \subset \mathcal{C}`$: set of parent block CIDs that this block explicitly extends. +- $`\mathsf{reject}(B) \subset \mathcal{C}`$: set of block CIDs that this block rejects. +- $`\mathsf{body}(B) \in \mathcal{C}`$: CID of the block’s body (arbitrary content). +- $`\mathsf{schema}(B) \in \mathbb{S}`$: schema URI string. +- $`\mathsf{media}(B) \in \mathbb{M}`$: media type string. +- $`\mathsf{comment}(B)`$: comment string. +- $`\mathsf{issuer}(B) \in \mathcal{P}`$: DID of the block’s issuer. +- $`\mathsf{sig}(B)`$: digital signature over the payload fields, created using the issuer’s secret key. ## DAG Structure and validity -Let the **global DAG** be a graph $\mathcal{D}$ where nodes are block identifiers and edges are induced by $\mathsf{accept}(B)$. +Let the **global DAG** be a graph $`\mathcal{D}`$ where nodes are block identifiers and edges are induced by $`\mathsf{accept}(B)`$. -A block $B$ is **valid** iff: +A block $`B`$ is **valid** iff: -1. All parent CIDs in $\mathsf{accept}(B)$ exist in the DAG. -2. The signature $\mathsf{sig}(B)$ verifies under $\mathsf{issuer}(B)$ against a canonical serialization of the payload. -3. $B$ does not create a cycle when added to $\mathcal{D}$. +1. All parent CIDs in $`\mathsf{accept}(B)`$ exist in the DAG. +2. The signature $`\mathsf{sig}(B)`$ verifies under $`\mathsf{issuer}(B)`$ against a canonical serialization of the payload. +3. $`B`$ does not create a cycle when added to $`\mathcal{D}`$. ## Participant trust and views -Each participant $u \in \mathcal{P}$ maintains: +Each participant $`u \in \mathcal{P}`$ maintains: - A **trust function**: @@ -75,28 +75,28 @@ $$ T\_u : \mathcal{P} \to [0,1] $$ -- A set of **trusted tips** $\mathcal{T}_u \subseteq \mathcal{C}$ used as starting points for state computation. +- A set of **trusted tips** $`\mathcal{T}_u \subseteq \mathcal{C}`$ used as starting points for state computation. ## Subjective traversal with rejection -For a participant $u$, the **visible subgraph** $\mathcal{D}_u \subseteq \mathcal{D}$ is constructed as follows: +For a participant $`u`$, the **visible subgraph** $`\mathcal{D}_u \subseteq \mathcal{D}`$ is constructed as follows: -1. Start from trusted tips $\mathcal{T}_u$. -2. Traverse backward along $\mathsf{accept}$ edges recursively. -3. Whenever a block $B$ is encountered: - - If any ancestor block $A$ declares $B \in \mathsf{reject}(A)$, then: - - Omit $B$ and all descendants reachable via $\mathsf{accept}$ edges **unless** they are also reachable via a separate path that does not pass through a rejecting ancestor. +1. Start from trusted tips $`\mathcal{T}_u`$. +2. Traverse backward along $`\mathsf{accept}`$ edges recursively. +3. Whenever a block $`B`$ is encountered: + - If any ancestor block $`A`$ declares $`B \in \mathsf{reject}(A)`$, then: + - Omit $`B`$ and all descendants reachable via $`\mathsf{accept}`$ edges **unless** they are also reachable via a separate path that does not pass through a rejecting ancestor. This defines **rejection as a pruning operator** on traversal. -Formally, the **visible blocks** for participant $u$ are: +Formally, the **visible blocks** for participant $`u`$ are: $$ \mathcal{V}_u = \{ B \in \mathcal{D} \mid B \text{ is reachable from } \mathcal{T}_u \text{ via non-rejected paths} \} $$ -A path is **non-rejected** if no intermediate block $A$ along the path has $\mathsf{reject}(A) \ni B'$ for any $B'$ also on the path. +A path is **non-rejected** if no intermediate block $`A`$ along the path has $`\mathsf{reject}(A) \ni B'`$ for any $`B'`$ also on the path. The following non-normative pseudo-code sketches the subjective DAG traversal and rejection. See [Pruning.lean](Pruning.lean) for Lean4 code and examples of pruning rejected blocks. One can experiment with the pruning algorithm [here](https://live.lean-lang.org/#codez=FASwtgDg9gTgLgAgMpwCYDoAiBDO30AS2AzgBYCy2EoksiKGOehJpSApnMMFBOwHbI03bACNRMdgDcEAYRCoEALgC8QmCH4BzbsTgwArgGM4ByQgBCAGyhGA1ggDupdpOAIERhR59K5C9wRsIyN2CERlBAAZED1/VEDJACt2Ew8/GLj5BOAxCWlLG3tKCGU1IjIS+MLbO1zxSRkAJXYUkxAofllOuHYAD0RVBAqKKmqAChGORGyASm4IbHgQbCsEVHYAM08oSANegDVYkFErdiP2R0Dx09riSOtakvmPcf0DPXZUABUQCHuMrEZgoXpEppxqqpAmdEJIjAgpMcuD4EOM9MEHICsiDAq9EcQQL1FH5wcDUKC8cdTuwwaxpvEKaijD1+oMEC02nAOl0WQNGSS6RDsmVcT4wLgjKQEOj7E5CaRRR4AD4IADaAF0ECoAHwIqlnRUIFVeYl+SRxHWGjwgbb4wlfdDM/h4TT3E0IOAufhWnx22HsOJ+r56gnUnbO1k+9hWYg0n0ecVwSUIW72YjoLScAD8nm8jnl8aNCH4nRpOpDhIQ5sQ4yDGFdrkQJtmFbDTt6A0LKuIuxpqYclpRQ58MIQmhcGiJHJFw9nKaKdnTmygVkU400laGgFAiFubAyCYLwgD6nlIIFXWu1heHNtP54wh7CcEdPWwrtzik9Amvs8PCEAVEThh2z6ZnAmB3qujreFuP4otGsZBCEP6jnuVhWNOQzjq49qoNOgGkugUCbJkiD9ugySpMic4jhC7asgA5GUQGsugDbwB+CCoehrQ/reXEci+zpvvwbreF+3rUUOfpVgGNZ1qxImNh+LZ2m2vJwPRP7wewsEIKOdaMUM8lsU2ASSSi+n6uwhlqKpZwKbG7Emrpo4ynYNnzrU6CPuECAANR+TJei6dJbmMQZrZnIxdEDJpHjSe8nw/H89xbggaWTKwJToOwkBwAAngA6vKshUMEhL5QgACMAAM8zcBs2zinY7CPMUYxYogbUOIASYQ1O1pRQh4IzZURJEIIAGESoiR6DiqUe6CKIl4IAACjAUAYGADiiFBiiiPVwAQBoUi4DSjUIP0NUPAuVRDQgzWtTdVCiqqhqABfkCAAEQWDVn0IAANOlANA4Al+QA6K6rAAAxNIqxMrsED7OcVkXI4F19Fdqrfb96qzOgcBQONahYz9n2Q4dx2nesWzo1V11PB1KiBA93UlC971faTwNpYDaVg/9HPfVVf2AyTOPcwg/MQ9DsNrOMzJ7IcKMgJctNqkLZN4wTRPq1zgMa+TR0gCdvTU9s/QAEz0wNM73dgLWs89KKvcOH3YyLQO85L4Ou5zwvA2LZMS1LvvfRbHsk8LmpeyHPiQzDJ1ywriNK6GZyo+jVsk+HuP44TQJarrv36xY4cl1HCyU6b539AAzNbdi3UzCb249DPUM7gt657oM+0ObsWP7ovu9HvcC6HpcRwbwd9yiA+11Pk+j4Hmqxx48ey/DivI2nyOq3XusL7n2sF8TYefSXC/l2TlfG1TNd9AALA3TfM63jsdz4Lv95zv0SzHs8fADyHkXIOADx4/3PgHae4Cu6P0XjnaBg8g5rwQBvROW8U47xOOnFWaN+jPxJvA4++cLS63gSXHOt8TZnRpv0AArC/Rmb8HZPU/h4b+c9f4ex5mPLuICV4zwgVwqBw9kGjz5oAjwA96EILAbrRBqD0Fw3lgjJGRxd4ZwYbrWRJCdYk10dQ++dC+gADYmGDWbnbVh7d2YTz/l7WBE8BEjyEV3cOSCo5uInqYxeXinGQIsAAdjkSXXxEjvbCLQTLDBqjt4aJwXvfBZjdYhL0afUBlCL6cxCdfMJN8KZ32riYoJFjbYszYXYwJDie6SKidIv2i9xYBJEZPTx8i6ld18e0iJqCGnfRCUgsunNwneMCQADkXmkpBoylExJUcndRyt959FKSTSZ6SyGByySXXJjSS4bKMcU82fRxllLuhU2xnd7E8LGa0lxpNelSIQAPDxYj/F8J8X4jpkSu6DLEcM76oyWlAM5pMpB0yxGzOeQPAAnN8p59SXl+xqSTeFiL+EPMmeXZpny47zKTmo1OiStGnN1lVKOWtSGIDPqTHF2Tz67IZYPYWeSwXMvRUc2hJzYXnKsZcgaVTWk1N4Z05xTSfl9ORaI8lkqYUjIRXc0FAzQkKoxRPcFYjIW62hUiuFiqQX9MHqi766KlVGopYvbFKK5V6r9m88lHzs4oMAcowl8TlnJN5ZHHOVL9Hu3pUy8urL7XMpDd9a1pqClGxoWbWmV0/Af3Ke/Sp1zqm3MNdK5BSDcVisCQ6yOtqukGrxa0/5CjmXAtLcqiwmrUnyJJrqru8KenmqzbVReZrM3AKxWG3NvznEFqFk68+q95VCwXhCsNiCQVuswUszReD43kqPn6jJ2ybXBuncywFwSw1X32ey/JJdOWFNjQ/ClfKWFt0FWm4VGbq0Woleq/NJa82tO6e8otE9y3OvyS+1pdaSbasbS6u1UbW3dptUgrtj7229vpQBmtVUh0sobaOgdgSqqTq1dupDFr4GeKPjBsD0sE4LKJdg6kpLL2R2IWurZAbN1+3DYPXdu69kTrDcyyNFhfHl2IVyuN/QUNXpbjY29X9BYAEEH3vprVPWT+HpWyEU9+yBmAp6qeU27AAolPTTOmvoADFF4Mv08vT6hnMMiIAOJT1M0hudcSsEJOo0ukTWdPr2c2TS3WDL7P61k/rfT+tHNCYvfXRNbDk0Scbk7KTodZP/zgwPNTlntM2eVap6BSm21u009AzLUHPr6egdZkrpmkHmfU3ZhztXonkfda5z1tN65Yx8wxvzJMAsMs00FhlqmQsMvC8AC9z9ovt1ize+L7C1SCyaHJyW4GLBT0W5Z9by2ZNmd6eBgAmjt4O4GAAaU8Du7cFt8NT+tTsXZROTJr87iXuZWVVQhn0ru+cLljU7JcGVXYG/rc7wAgA). @@ -155,9 +155,9 @@ partial def computeVisibleView ## State interpretation -Each participant $u$ uses their local visible DAG $\mathcal{V}_u$ to compute a **state view**, interpreted according to application-specific logic on: +Each participant $`u`$ uses their local visible DAG $`\mathcal{V}_u`$ to compute a **state view**, interpreted according to application-specific logic on: -- Block bodies $\mathsf{body}(B)$, using $\mathsf{schema}(B)$ and $\mathsf{media}(B)$ +- Block bodies $`\mathsf{body}(B)`$, using $`\mathsf{schema}(B)`$ and $`\mathsf{media}(B)`$ - Provenance (issuer of each block) - Ordering (topological or heuristic over the DAG) @@ -172,11 +172,11 @@ This may include reconstructing RDF graphs, applying CRDT logic, filtering by is ## Summary -| Concept | Formally | -|-----------|-----------------------------------------------------------------| -| Block | Tuple of accepted/rejected parents, body CID, issuer, signature | -| DAG | Induced by accepted parent links | -| Trust | Local function $T\_u : \mathcal{P} \to [0,1]$ | -| View | Blocks visible from tips via non-rejected paths | -| Rejection | Explicitly prunes traversal unless overridden later | -| State | Application-defined interpretation of visible block bodies | +| Concept | Formally | +|-----------|-------------------------------------------------------------------| +| Block | Tuple of accepted/rejected parents, body CID, issuer, signature | +| DAG | Induced by accepted parent links | +| Trust | Local function $`T\_u : \mathcal{P} \to [0,1]`$ | +| View | Blocks visible from tips via non-rejected paths | +| Rejection | Explicitly prunes traversal unless overridden later | +| State | Application-defined interpretation of visible block bodies | diff --git a/TGDH-Specialization.md b/TGDH-Specialization.md new file mode 100644 index 0000000..d08ae9b --- /dev/null +++ b/TGDH-Specialization.md @@ -0,0 +1,214 @@ +# Extension: Tree-based group Diffie-Hellman (TGDH) encryption + +## TGDH encrypted payload + +The TGDH scheme described here allows the decentralized addition and removal of keys for a shared secret that is recomputed upon each addition or removal. + +Each node in the a TGDH key contains the following: + +- BLS12-381 G1 public key +- An optional BLS12-381 Fr private key. +- Optional left and right child nodes. + +The public key is simply the exponentiation of the private key, with G1 as the base. + +The private key of a leaf is simply a randomly chosen member of the Fr group. The private key of a node is computed as the SHA256-based HKDF Fr hash of the product of the private key of one child and the public key of the other child. The string `nacatgunma-tgdh-bls12381g1` is used as the information field for HKDF. + +These keys can be used to derive a symmetric key for AES256-GCM encryption, but a unique salt must be used each time in the symmetric-key derivation. + +The reference implementation resides in [tgdh/][./tgdh/]. + +## Command-line tool + +The `nacatgunma body tgdh` subcommands implement the TGDH specification described above. + +```console +$ nacatgunma body tgdh --help + +NAME: + nacatgunma body tgdh - Tree-based group DH (BLS12-381) management subcommands + +USAGE: + nacatgunma body tgdh [command options] + +COMMANDS: + decrypt Decrypt a file using a TGDH private key. + encrypt Encrypt a file using a TGDH private key. + generate Generate a TGDH private key. + join Join two TGDH keys into an aggregate TGDH key, where at least one of the keys is private. + public Strip private key information from a TGDH key. + private Apply a private TGHD key to a public one, deriving the private root. + remove Remove a TGDH keys from an aggregate TGDH key, where at least one of the root keys is private. + help, h Shows a list of commands or help for one command + +OPTIONS: + --help, -h show help +``` + +### Generate a key + +```console +$ nacatgunma body tgdh generate --private-file A.pri + +did:key:z3tEEhukKAKcFEGQn3fCFngDPForeCYJA2kSnhyvJmzDg4VqgxyKBQitb3LKjxLAzmdH3w + +$ json2yaml A.pri + +private: 126822990fac11644ded34c7e887a9c239b627f34e082c68d3e03e25b59f3b16 +public: 82ecf95216b95e634bfda85171d5a10abadfc9cfb5226133c3dbe6496f11d1aebbb586ead61d382de2be22eebb646aaa +``` + +### Extract the public key + +The public key can safely be posted on the blockchain so that other parties can include it in group encryption. + +```console +$ nacatgunma body tgdh public --private-file A.pri --public-file A.pub + +did:key:z3tEEhukKAKcFEGQn3fCFngDPForeCYJA2kSnhyvJmzDg4VqgxyKBQitb3LKjxLAzmdH3w + +$ json2yaml A.pub + +public: 82ecf95216b95e634bfda85171d5a10abadfc9cfb5226133c3dbe6496f11d1aebbb586ead61d382de2be22eebb646aaa +``` + +### Aggregate two keys + +One of the keys joined into an aggregate must be private, so that the public key of the aggregate can be derived. + +```console +$ nacatgunma body tgdh join --left-file A.pri --right-file B.pub --private-file AB.pri + +did:key:z3tEFnWHMrZzbc4MqYGNF2hrH2LeaEN9FgxVsizEao8QgMCJcDQJCgYMEGLyfMBtYYFNGR + +$ json2yaml AB.pri + +private: 46560d7d32f9149b214d5764e1679a58e4750605780ad4cf6c8a3b7c7811a1c9 +public: a058b91fe134956663aa5f5775b486622caa2f8fc00f3b71c2c0c378e6677808e307470e74bfad8306ae84d83c5098b2 +left: + private: 126822990fac11644ded34c7e887a9c239b627f34e082c68d3e03e25b59f3b16 + public: 82ecf95216b95e634bfda85171d5a10abadfc9cfb5226133c3dbe6496f11d1aebbb586ead61d382de2be22eebb646aaa +right: + public: 930f91677ed24327207f2bf154dac458208ab664f80549305663e1c412fb2d692c45991aae4446a099fdf586daf39322 +``` + +The public aggregate key can be shared on the blockchain so that other parties can include it in their key derivations. + +```console +$ nacatgunma body tgdh public --private-file AB.pri --public-file AB.pub +did:key:z3tEFnWHMrZzbc4MqYGNF2hrH2LeaEN9FgxVsizEao8QgMCJcDQJCgYMEGLyfMBtYYFNGR + + +$ json2yaml AB.pub + +public: a058b91fe134956663aa5f5775b486622caa2f8fc00f3b71c2c0c378e6677808e307470e74bfad8306ae84d83c5098b2 +left: + public: 82ecf95216b95e634bfda85171d5a10abadfc9cfb5226133c3dbe6496f11d1aebbb586ead61d382de2be22eebb646aaa +right: + public: 930f91677ed24327207f2bf154dac458208ab664f80549305663e1c412fb2d692c45991aae4446a099fdf586daf39322 +``` + +### Recover the private key of an aggregate + +If one of the leaf private keys of the aggregate is known, the root private key can be derived. + +```console +$ nacatgunma body tgdh private --private-file A.pri --public-file AB.pub --root-file AB.pri + +did:key:z3tEFnWHMrZzbc4MqYGNF2hrH2LeaEN9FgxVsizEao8QgMCJcDQJCgYMEGLyfMBtYYFNGR + +$ json2yaml AB.pri + +private: 46560d7d32f9149b214d5764e1679a58e4750605780ad4cf6c8a3b7c7811a1c9 +public: a058b91fe134956663aa5f5775b486622caa2f8fc00f3b71c2c0c378e6677808e307470e74bfad8306ae84d83c5098b2 +left: + private: 126822990fac11644ded34c7e887a9c239b627f34e082c68d3e03e25b59f3b16 + public: 82ecf95216b95e634bfda85171d5a10abadfc9cfb5226133c3dbe6496f11d1aebbb586ead61d382de2be22eebb646aaa +right: + public: 930f91677ed24327207f2bf154dac458208ab664f80549305663e1c412fb2d692c45991aae4446a099fdf586daf39322 +``` + +### Remove a party from an aggregate + +At least one private key must be known to remove a party from an aggregate key. + +```console +$ nacatgunma body tgdh remove --leaf-file B.pub --root-file ABCD.pri --private-file ACD.pri + +did:key:z3tEGJJpro3jZseNAFjT8dH8UW3KXY2bLwmayjhUNau3EehzdWhtzMhohgSZvuwdWB4qxi + +$ json2yaml ACD.pri + +private: 54214cb4eee507a2ac6862d54eade6c7b79efd768af2d139129d549c28ee8ed4 +public: ae5aaecbf1315d09b24801255190709a53bf170e10518dadf7bb2109a94092ecc8d5d7258c31aa3c32546c8e6303ed97 +left: + private: 4fc6442ead18c3122bc3351bedf69b115c1ec5b07e2ff7ce459d23adb82b5687 + public: ac879c4bd3f97720e0a7fd84980b3aa0f241b27bcab7c1f83399adc41704d7019ef5e90339c7f65ffa358e19f35cc986 + left: + public: 86b53d5f07478c943ed255b1c0808d81a41ade43e88caf5e9ea8a423e683a8ed7e2d77af7c6a48ffba45ec6b18bda8bd + right: + private: 657090a5812aec229e621fd0bfdc01313ab40c660638616d62de356cfe9f073f + public: b27be6d6d50c6c43758d7f4a5b413311a7e9dafaf57c562b6937e4b9f650f0c0ed008dcc76021d30751b4a8436bbf0e7 +right: + public: 82ecf95216b95e634bfda85171d5a10abadfc9cfb5226133c3dbe6496f11d1aebbb586ead61d382de2be22eebb646aaa +``` + +### Encrypt to an aggregate key + +Each encryption uses the aggregate private key and randomly chosen salt to derive the AES256 symmetric key. + +```console +$ echo "Hello, TGDH!" > hello.txt + +$ nacatgunma body tgdh encrypt --private-file ACD.pri --plaintext-file hello.txt --content-type "text/plain" --jwe-file hello.jwe --jwk-file hello.jwk + +$ json2yaml hello.jwe + +ciphertext: MnU5R1izHU_KlaKZ3w +header: + alg: dir +iv: pmUodiNTGFUhj8NV +protected: eyJhbGciOiJkaXIiLCJjdHkiOiJ0ZXh0L3BsYWluIiwiZW5jIjoiQTI1NkdDTSIsImtpZCI6ImRpZDprZXk6ejN0RUdKSnBybzNqWnNlTkFGalQ4ZEg4VVczS1hZMmJMd21heWpoVU5hdTNFZWh6ZFdodHpNaG9oZ1NadnV3ZFdCNHF4aSIsInAycyI6Ijc2ajlfeUxraUtYQTdBak5wVnM1Wkk3N29VUFdZQUN6UERwdHFhUWc0c0UiLCJ0eXAiOiJuYWNhdGd1bm1hLXRnZGgrc2FsdCJ9 +tag: iLBi6HxnT8E7C-RiqB9UuA + +$ jq -r .protected hello.jwe | basenc --decode --base64 | json2yaml + +alg: dir +cty: text/plain +enc: A256GCM +kid: did:key:z3tEGJJpro3jZseNAFjT8dH8UW3KXY2bLwmayjhUNau3EehzdWhtzMhohgSZvuwdWB4qxi +p2s: 76j9_yLkiKXA7AjNpVs5ZI77oUPWYACzPDptqaQg4sE +typ: nacatgunma-tgdh+salt + +$ json2yaml hello.jwk +alg: dir +k: fCFeQob5Vh0Zl9JvoLZ4KOSKnhPfi7i9QLEGuEqTi-4 +key_ops: +- encrypt +- decrypt +kid: did:key:z3tEGJJpro3jZseNAFjT8dH8UW3KXY2bLwmayjhUNau3EehzdWhtzMhohgSZvuwdWB4qxi +kty: oct +use: enc +``` +Supplying the content type or the JWK filename are optional. The JWK file is useful because it can be used with third-party tools to decrypt the JWE file. + +### Decrypt a message + +```console +$ nacatgunma body tgdh decrypt --private-file ACD.pri --jwe-file hello.jwe --plaintext-file hello.txt --headers-file headers.json + +$ cat hello.txt + +Hello, TGDH! + +$ json2yaml headers.json + +alg: dir +cty: text/plain +enc: A256GCM +kid: did:key:z3tEGJJpro3jZseNAFjT8dH8UW3KXY2bLwmayjhUNau3EehzdWhtzMhohgSZvuwdWB4qxi +p2s: 76j9_yLkiKXA7AjNpVs5ZI77oUPWYACzPDptqaQg4sE +typ: nacatgunma-tgdh+salt +``` + +Creating the headers file is optional. \ No newline at end of file diff --git a/build.sh b/build.sh deleted file mode 100755 index e77a7a2..0000000 --- a/build.sh +++ /dev/null @@ -1,4 +0,0 @@ -#!/usr/bin/env nix-shell -#!nix-shell -i bash -p go - -go build -o nacatgunma main.go diff --git a/cmd/body.go b/cmd/body.go index c2e5925..876d975 100644 --- a/cmd/body.go +++ b/cmd/body.go @@ -8,7 +8,6 @@ import ( "github.com/urfave/cli/v2" "github.com/functionally/nacatgunma/ipfs" - "github.com/functionally/nacatgunma/rdf" ) func BodyCmds() *cli.Command { @@ -17,7 +16,8 @@ func BodyCmds() *cli.Command { Usage: "Body management subcommands", Subcommands: []*cli.Command{ bodyExportCmd(), - bodyRdfCmd(), + rdfCmd(), + tgdhCmds(), }, } } @@ -62,63 +62,3 @@ func bodyExportCmd() *cli.Command { } } - -func bodyRdfCmd() *cli.Command { - - var rdfFile string - var bodyFile string - var baseUri string - var format string - - return &cli.Command{ - Name: "rdf", - Usage: "Build a body of RDF N-quads.", - Flags: []cli.Flag{ - &cli.StringFlag{ - Name: "rdf-file", - Required: true, - Usage: "Input file of RDF N-quads", - Destination: &rdfFile, - }, - &cli.StringFlag{ - Name: "base-uri", - Value: "", - Usage: "Base URI of the RDF", - Destination: &baseUri, - }, - &cli.StringFlag{ - Name: "format", - Value: "application/n-quads", - Usage: "MIME type of the RDF format", - Destination: &format, - }, - &cli.StringFlag{ - Name: "body-file", - Required: true, - Usage: "Output file for the block body", - Destination: &bodyFile, - }, - }, - Action: func(*cli.Context) error { - rdf, err := rdf.ReadRdf(rdfFile, baseUri, format) - if err != nil { - return err - } - bodyBytes, err := ipfs.EncodeToDagCbor(rdf) - if err != nil { - return err - } - bodyCid, err := ipfs.CidV1(bodyBytes) - if err != nil { - return err - } - err = os.WriteFile(bodyFile, bodyBytes, 0644) - if err != nil { - return err - } - fmt.Println(bodyCid) - return nil - }, - } - -} diff --git a/cmd/header.go b/cmd/header.go index 74083e7..0dee77d 100644 --- a/cmd/header.go +++ b/cmd/header.go @@ -91,7 +91,7 @@ func headerBuildCmd() *cli.Command { }, }, Action: func(*cli.Context) error { - key, err := key.ReadPrivateKey(keyFile) + k, err := key.ReadPrivateKey(keyFile) if err != nil { return err } @@ -110,7 +110,7 @@ func headerBuildCmd() *cli.Command { return err } payload.Reject = rejectCids - header, err := payload.Sign(key) + header, err := payload.Sign(k) if err != nil { return err } diff --git a/cmd/ipfs.go b/cmd/ipfs.go index 3984e60..690d3e6 100644 --- a/cmd/ipfs.go +++ b/cmd/ipfs.go @@ -212,7 +212,7 @@ func ipfsStoreCmd() *cli.Command { }, Action: func(*cli.Context) error { sh := shell.NewShell(ipfsApi) - key, err := key.ReadPrivateKey(keyFile) + k, err := key.ReadPrivateKey(keyFile) if err != nil { return err } @@ -235,7 +235,7 @@ func ipfsStoreCmd() *cli.Command { return err } payload.Reject = rejectCids - header, err := payload.Sign(key) + header, err := payload.Sign(k) if err != nil { return err } diff --git a/cmd/key.go b/cmd/key.go index 86fa33b..bd6b148 100644 --- a/cmd/key.go +++ b/cmd/key.go @@ -14,19 +14,48 @@ func KeyCmds() *cli.Command { Name: "key", Usage: "Key management subcommands", Subcommands: []*cli.Command{ + keyDidCmd(), keyGenerateCmd(), keyResolveCmd(), }, } } +func keyDidCmd() *cli.Command { + + var keyFile string + + return &cli.Command{ + Name: "did", + Usage: "Print the DID of a cryptographic key.", + Flags: []cli.Flag{ + &cli.StringFlag{ + Name: "key-file", + Required: true, + Usage: "Input file for private key", + Destination: &keyFile, + }, + }, + Action: func(*cli.Context) error { + k, err := key.ReadPrivateKey(keyFile) + if err != nil { + return err + } + fmt.Println(key.Did(k)) + return nil + }, + } + +} + func keyGenerateCmd() *cli.Command { var keyFile string + var keyType string return &cli.Command{ Name: "generate", - Usage: "Generate an Ed25519 key.", + Usage: "Generate a cryptographic key.", Flags: []cli.Flag{ &cli.StringFlag{ Name: "key-file", @@ -34,17 +63,31 @@ func keyGenerateCmd() *cli.Command { Usage: "Output file for private key", Destination: &keyFile, }, + &cli.StringFlag{ + Name: "key-type", + Value: "Ed25519", + Usage: "The key type, either \"Ed25519\" or \"BLS12-381\"", + Destination: &keyType, + }, }, Action: func(*cli.Context) error { - key, err := key.GenerateKey() + allowed := map[string]key.KeyType{ + "Ed25519": key.Ed25519, + "BLS12-381": key.Bls12381, + } + kt, okay := allowed[keyType] + if !okay { + return fmt.Errorf("unsupported key type: %v", keyType) + } + k, err := key.GenerateKey(kt) if err != nil { return err } - err = key.WritePrivateKey(keyFile) + err = key.WritePrivateKey(k, keyFile) if err != nil { return err } - fmt.Println(key.Did) + fmt.Println(key.Did(k)) return nil }, } diff --git a/cmd/rdf.go b/cmd/rdf.go new file mode 100644 index 0000000..a35995e --- /dev/null +++ b/cmd/rdf.go @@ -0,0 +1,70 @@ +package cmd + +import ( + "fmt" + "os" + + "github.com/functionally/nacatgunma/ipfs" + "github.com/functionally/nacatgunma/rdf" + "github.com/urfave/cli/v2" +) + +func rdfCmd() *cli.Command { + + var rdfFile string + var bodyFile string + var baseUri string + var format string + + return &cli.Command{ + Name: "rdf", + Usage: "Build a body of RDF N-quads.", + Flags: []cli.Flag{ + &cli.StringFlag{ + Name: "rdf-file", + Required: true, + Usage: "Input file of RDF N-quads", + Destination: &rdfFile, + }, + &cli.StringFlag{ + Name: "base-uri", + Value: "", + Usage: "Base URI of the RDF", + Destination: &baseUri, + }, + &cli.StringFlag{ + Name: "format", + Value: "application/n-quads", + Usage: "MIME type of the RDF format", + Destination: &format, + }, + &cli.StringFlag{ + Name: "body-file", + Required: true, + Usage: "Output file for the block body", + Destination: &bodyFile, + }, + }, + Action: func(*cli.Context) error { + rdf, err := rdf.ReadRdf(rdfFile, baseUri, format) + if err != nil { + return err + } + bodyBytes, err := ipfs.EncodeToDagCbor(rdf) + if err != nil { + return err + } + bodyCid, err := ipfs.CidV1(bodyBytes) + if err != nil { + return err + } + err = os.WriteFile(bodyFile, bodyBytes, 0644) + if err != nil { + return err + } + fmt.Println(bodyCid) + return nil + }, + } + +} diff --git a/cmd/tgdh.go b/cmd/tgdh.go new file mode 100644 index 0000000..79839ae --- /dev/null +++ b/cmd/tgdh.go @@ -0,0 +1,501 @@ +package cmd + +import ( + "encoding/json" + "fmt" + "os" + + "github.com/functionally/nacatgunma/tgdh" + "github.com/lestrrat-go/jwx/v3/jwe" + "github.com/lestrrat-go/jwx/v3/jwk" + "github.com/urfave/cli/v2" +) + +func tgdhCmds() *cli.Command { + return &cli.Command{ + Name: "tgdh", + Usage: "Tree-based group DH (BLS12-381) management subcommands", + Subcommands: []*cli.Command{ + tgdhDecryptCmd(), + tgdhEncryptCmd(), + tgdhGenerateCmd(), + tgdhJoinCmd(), + tgdhPublicCmd(), + tgdhPrivateCmd(), + tgdhRemoveCmd(), + }, + } +} + +func tgdhGenerateCmd() *cli.Command { + + var privateFile string + + return &cli.Command{ + Name: "generate", + Usage: "Generate a TGDH private key.", + Flags: []cli.Flag{ + &cli.StringFlag{ + Name: "private-file", + Required: true, + Usage: "Output file of TGDH private key", + Destination: &privateFile, + }, + }, + Action: func(*cli.Context) error { + leaf, err := tgdh.GenerateLeaf() + if err != nil { + return err + } + leafBytes, err := leaf.MarshalJSON() + if err != nil { + return err + } + err = os.WriteFile(privateFile, leafBytes, 0644) + if err != nil { + return err + } + fmt.Println(leaf.Did()) + return nil + }, + } + +} + +func tgdhPublicCmd() *cli.Command { + + var privateFile string + var publicFile string + + return &cli.Command{ + Name: "public", + Usage: "Strip private key information from a TGDH key.", + Flags: []cli.Flag{ + &cli.StringFlag{ + Name: "private-file", + Required: true, + Usage: "Input file of TGDH private key", + Destination: &privateFile, + }, + &cli.StringFlag{ + Name: "public-file", + Required: true, + Usage: "Output file of TGDH public key", + Destination: &publicFile, + }, + }, + Action: func(*cli.Context) error { + privateBytes, err := os.ReadFile(privateFile) + if err != nil { + return err + } + private, err := tgdh.UnmarshalJSON(privateBytes) + if err != nil { + return err + } + public := private.DeepStrip() + publicBytes, err := public.MarshalJSON() + if err != nil { + return err + } + err = os.WriteFile(publicFile, publicBytes, 0644) + if err != nil { + return err + } + fmt.Println(public.Did()) + return nil + }, + } + +} + +func tgdhJoinCmd() *cli.Command { + + var leftFile string + var rightFile string + var privateFile string + + return &cli.Command{ + Name: "join", + Usage: "Join two TGDH keys into an aggregate TGDH key, where at least one of the keys is private.", + Flags: []cli.Flag{ + &cli.StringFlag{ + Name: "left-file", + Required: true, + Usage: "Input file of leftmost TGDH key", + Destination: &leftFile, + }, + &cli.StringFlag{ + Name: "right-file", + Required: true, + Usage: "Input file of rightmost TGDH key", + Destination: &rightFile, + }, + &cli.StringFlag{ + Name: "private-file", + Required: true, + Usage: "Output file of TGDH private key", + Destination: &privateFile, + }, + }, + Action: func(*cli.Context) error { + leftBytes, err := os.ReadFile(leftFile) + if err != nil { + return err + } + left, err := tgdh.UnmarshalJSON(leftBytes) + if err != nil { + return err + } + rightBytes, err := os.ReadFile(rightFile) + if err != nil { + return err + } + right, err := tgdh.UnmarshalJSON(rightBytes) + if err != nil { + return err + } + private, err := tgdh.Join(left, right) + if err != nil { + return err + } + privateBytes, err := private.MarshalJSON() + if err != nil { + return err + } + err = os.WriteFile(privateFile, privateBytes, 0644) + if err != nil { + return err + } + fmt.Println(private.Did()) + return nil + }, + } + +} + +func tgdhRemoveCmd() *cli.Command { + + var leafFile string + var rootFile string + var privateFile string + + return &cli.Command{ + Name: "remove", + Usage: "Remove a TGDH keys from an aggregate TGDH key, where at least one of the root keys is private.", + Flags: []cli.Flag{ + &cli.StringFlag{ + Name: "leaf-file", + Required: true, + Usage: "Input file of TGDH key to be removed", + Destination: &leafFile, + }, + &cli.StringFlag{ + Name: "root-file", + Required: true, + Usage: "Input file of root TGDH private key", + Destination: &rootFile, + }, + &cli.StringFlag{ + Name: "private-file", + Required: true, + Usage: "Output file of new root TGDH private key", + Destination: &privateFile, + }, + }, + Action: func(*cli.Context) error { + leafBytes, err := os.ReadFile(leafFile) + if err != nil { + return err + } + leaf, err := tgdh.UnmarshalJSON(leafBytes) + if err != nil { + return err + } + rootBytes, err := os.ReadFile(rootFile) + if err != nil { + return err + } + root, err := tgdh.UnmarshalJSON(rootBytes) + if err != nil { + return err + } + private, err := root.Remove(leaf) + if err != nil { + return err + } + privateBytes, err := private.MarshalJSON() + if err != nil { + return err + } + err = os.WriteFile(privateFile, privateBytes, 0644) + if err != nil { + return err + } + fmt.Println(private.Did()) + return nil + }, + } + +} + +func tgdhPrivateCmd() *cli.Command { + + var privateFile string + var publicFile string + var rootFile string + + return &cli.Command{ + Name: "private", + Usage: "Apply a private TGHD key to a public one, deriving the private root.", + Flags: []cli.Flag{ + &cli.StringFlag{ + Name: "private-file", + Required: true, + Usage: "Input file of private TGDH key", + Destination: &privateFile, + }, + &cli.StringFlag{ + Name: "public-file", + Required: true, + Usage: "Input file of public TGDH key", + Destination: &publicFile, + }, + &cli.StringFlag{ + Name: "root-file", + Required: true, + Usage: "Output file of TGDH root private key", + Destination: &rootFile, + }, + }, + Action: func(*cli.Context) error { + privateBytes, err := os.ReadFile(privateFile) + if err != nil { + return err + } + private, err := tgdh.UnmarshalJSON(privateBytes) + if err != nil { + return err + } + publicBytes, err := os.ReadFile(publicFile) + if err != nil { + return err + } + public, err := tgdh.UnmarshalJSON(publicBytes) + if err != nil { + return err + } + root, err := tgdh.DerivePrivates(private, public) + if err != nil { + return err + } + rootBytes, err := root.MarshalJSON() + if err != nil { + return err + } + err = os.WriteFile(rootFile, rootBytes, 0644) + if err != nil { + return err + } + fmt.Println(root.Did()) + return nil + }, + } + +} + +func tgdhEncryptCmd() *cli.Command { + + var privateFile string + var plaintextFile string + var contentType string + var jweFile string + var jwkFile string + + return &cli.Command{ + Name: "encrypt", + Usage: "Encrypt a file using a TGDH private key.", + Flags: []cli.Flag{ + &cli.StringFlag{ + Name: "private-file", + Required: true, + Usage: "Input file of private TGDH key", + Destination: &privateFile, + }, + &cli.StringFlag{ + Name: "plaintext-file", + Required: true, + Usage: "Input file of plaintext", + Destination: &plaintextFile, + }, + &cli.StringFlag{ + Name: "content-type", + Value: "", + Usage: "The content type for the plaintext", + Destination: &contentType, + }, + &cli.StringFlag{ + Name: "jwe-file", + Required: true, + Usage: "Output JWE file for the ciphertext", + Destination: &jweFile, + }, + &cli.StringFlag{ + Name: "jwk-file", + Required: false, + Usage: "Output JWK file for the ephemeral AES256 key", + Destination: &jwkFile, + }, + }, + Action: func(ctx *cli.Context) error { + privateBytes, err := os.ReadFile(privateFile) + if err != nil { + return err + } + private, err := tgdh.UnmarshalJSON(privateBytes) + if err != nil { + return err + } + plaintext, err := os.ReadFile(plaintextFile) + if err != nil { + return err + } + jwkBytes, jweBytes, err := private.Encrypt(plaintext, contentType) + if err != nil { + return err + } + err = os.WriteFile(jweFile, jweBytes, 0644) + if err != nil { + return err + } + if ctx.IsSet("jwk-file") { + err = os.WriteFile(jwkFile, jwkBytes, 0644) + if err != nil { + return err + } + } + return nil + }, + } + +} + +func tgdhDecryptCmd() *cli.Command { + + var privateFile string + var jwkFile string + var jweFile string + var plaintextFile string + var headersFile string + + return &cli.Command{ + Name: "decrypt", + Usage: "Decrypt a file using a TGDH private key.", + Flags: []cli.Flag{ + &cli.StringFlag{ + Name: "private-file", + Required: false, + Usage: "Input file of private TGDH key", + Destination: &privateFile, + }, + &cli.StringFlag{ + Name: "jwk-file", + Required: false, + Usage: "Input JWK file of the ephemeral AES256 key", + Destination: &jwkFile, + }, + &cli.StringFlag{ + Name: "jwe-file", + Required: true, + Usage: "Input JWE file of the ciphertext", + Destination: &jweFile, + }, + &cli.StringFlag{ + Name: "plaintext-file", + Required: true, + Usage: "Output file for plaintext", + Destination: &plaintextFile, + }, + &cli.StringFlag{ + Name: "headers-file", + Required: false, + Usage: "Output file for encryption headers", + Destination: &headersFile, + }, + }, + Before: func(ctx *cli.Context) error { + hasPrivate := ctx.IsSet("private-file") + hasJwk := ctx.IsSet("jwk-file") + + switch { + case hasPrivate && hasJwk: + return fmt.Errorf("only one of --private-file or --jwk-file may be specified") + case !hasPrivate && !hasJwk: + return fmt.Errorf("one of --private-file or --jwk-file must be specified") + default: + return nil + } + }, + Action: func(ctx *cli.Context) error { + jweBytes, err := os.ReadFile(jweFile) + if err != nil { + return err + } + var headers jwe.Headers + var plaintext []byte + if ctx.IsSet("private-file") { + privateBytes, err := os.ReadFile(privateFile) + if err != nil { + return err + } + private, err := tgdh.UnmarshalJSON(privateBytes) + if err != nil { + return err + } + headers, plaintext, err = private.Decrypt(jweBytes) + if err != nil { + return err + } + } else if ctx.IsSet("jwk-file") { + keyset, err := jwk.ReadFile(jwkFile) + if err != nil { + return nil + } + if len(keyset.Keys()) == 0 { + return fmt.Errorf("JWK file has no keys") + } + key, ok := keyset.Key(0) + if !ok { + return fmt.Errorf("JWK file missing key") + } + var aesKey []byte + err = key.Get("k", &aesKey) + if err != nil { + return err + } + headers, plaintext, err = tgdh.Decrypt(aesKey, jweBytes) + if err != nil { + return err + } + } else { + return fmt.Errorf("exactly one of --private-file or --jwk-file must be specified") + } + err = os.WriteFile(plaintextFile, plaintext, 0644) + if err != nil { + return err + } + if ctx.IsSet("headers-file") { + headersBytes, err := json.Marshal(headers) + if err != nil { + return err + } + err = os.WriteFile(headersFile, headersBytes, 0644) + if err != nil { + return err + } + } + return nil + }, + } + +} diff --git a/go.mod b/go.mod index 8b0f9fb..8b14358 100644 --- a/go.mod +++ b/go.mod @@ -32,15 +32,29 @@ require ( github.com/consensys/gnark-crypto v0.14.0 // indirect github.com/cpuguy83/go-md2man/v2 v2.0.5 // indirect github.com/crackcomm/go-gitignore v0.0.0-20170627025303-887ab5e44cc3 // indirect - github.com/decred/dcrd/dcrec/secp256k1/v4 v4.3.0 // indirect + github.com/decred/dcrd/dcrec/secp256k1/v4 v4.4.0 // indirect github.com/fxamacker/cbor/v2 v2.8.0 // indirect github.com/go-jose/go-jose/v3 v3.0.4 // indirect + github.com/go-jose/go-jose/v4 v4.1.1 // indirect + github.com/goccy/go-json v0.10.3 // indirect github.com/google/uuid v1.6.0 // indirect github.com/hyperledger/fabric-amcl v0.0.0-20230602173724-9e02669dceb2 // indirect github.com/ipfs/boxo v0.12.0 // indirect github.com/jinzhu/copier v0.4.0 // indirect github.com/kilic/bls12-381 v0.1.1-0.20210503002446-7b7597926c69 // indirect github.com/klauspost/cpuid/v2 v2.2.4 // indirect + github.com/leanovate/gopter v0.2.11 // indirect + github.com/lestrrat-go/backoff/v2 v2.0.8 // indirect + github.com/lestrrat-go/blackmagic v1.0.4 // indirect + github.com/lestrrat-go/httpcc v1.0.1 // indirect + github.com/lestrrat-go/httprc v1.0.6 // indirect + github.com/lestrrat-go/httprc/v3 v3.0.0 // indirect + github.com/lestrrat-go/iter v1.0.2 // indirect + github.com/lestrrat-go/jwx v1.2.31 // indirect + github.com/lestrrat-go/jwx/v2 v2.1.6 // indirect + github.com/lestrrat-go/jwx/v3 v3.0.8 // indirect + github.com/lestrrat-go/option v1.0.1 // indirect + github.com/lestrrat-go/option/v2 v2.0.0 // indirect github.com/libp2p/go-buffer-pool v0.1.0 // indirect github.com/libp2p/go-flow-metrics v0.1.0 // indirect github.com/libp2p/go-libp2p v0.27.8 // indirect @@ -59,6 +73,7 @@ require ( github.com/polydawn/refmt v0.89.0 // indirect github.com/pquerna/cachecontrol v0.2.0 // indirect github.com/russross/blackfriday/v2 v2.1.0 // indirect + github.com/segmentio/asm v1.2.0 // indirect github.com/spaolacci/murmur3 v1.1.0 // indirect github.com/teserakt-io/golang-ed25519 v0.0.0-20210104091850-3888c087a4c8 // indirect github.com/trustbloc/bbs-signature-go v1.0.2 // indirect @@ -69,9 +84,10 @@ require ( github.com/xeipuuv/gojsonreference v0.0.0-20180127040603-bd5ef7bd5415 // indirect github.com/xeipuuv/gojsonschema v1.2.0 // indirect github.com/xrash/smetrics v0.0.0-20240521201337-686a1a2994c1 // indirect - golang.org/x/crypto v0.37.0 // indirect - golang.org/x/sys v0.32.0 // indirect + golang.org/x/crypto v0.39.0 // indirect + golang.org/x/sys v0.33.0 // indirect google.golang.org/protobuf v1.36.3 // indirect + gopkg.in/square/go-jose.v2 v2.6.0 // indirect lukechampine.com/blake3 v1.1.7 // indirect rsc.io/tmplfunc v0.0.3 // indirect ) diff --git a/go.sum b/go.sum index 88dc883..e193e9d 100644 --- a/go.sum +++ b/go.sum @@ -1,15 +1,61 @@ +cloud.google.com/go v0.26.0/go.mod h1:aQUYkXzVsufM+DwF1aE+0xfcU+56JwCaLick0ClmMTw= +cloud.google.com/go v0.34.0/go.mod h1:aQUYkXzVsufM+DwF1aE+0xfcU+56JwCaLick0ClmMTw= +cloud.google.com/go v0.38.0/go.mod h1:990N+gfupTy94rShfmMCWGDn0LpTmnzTp2qbd1dvSRU= +cloud.google.com/go v0.44.1/go.mod h1:iSa0KzasP4Uvy3f1mN/7PiObzGgflwredwwASm/v6AU= +cloud.google.com/go v0.44.2/go.mod h1:60680Gw3Yr4ikxnPRS/oxxkBccT6SA1yMk63TGekxKY= +cloud.google.com/go v0.45.1/go.mod h1:RpBamKRgapWJb87xiFSdk4g1CME7QZg3uwTez+TSTjc= +cloud.google.com/go v0.46.3/go.mod h1:a6bKKbmY7er1mI7TEI4lsAkts/mkhTSZK8w33B4RAg0= +cloud.google.com/go v0.50.0/go.mod h1:r9sluTvynVuxRIOHXQEHMFffphuXHOMZMycpNR5e6To= +cloud.google.com/go v0.52.0/go.mod h1:pXajvRH/6o3+F9jDHZWQ5PbGhn+o8w9qiu/CffaVdO4= +cloud.google.com/go v0.53.0/go.mod h1:fp/UouUEsRkN6ryDKNW/Upv/JBKnv6WDthjR6+vze6M= +cloud.google.com/go v0.54.0/go.mod h1:1rq2OEkV3YMf6n/9ZvGWI3GWw0VoqH/1x2nd8Is/bPc= +cloud.google.com/go v0.56.0/go.mod h1:jr7tqZxxKOVYizybht9+26Z/gUq7tiRzu+ACVAMbKVk= +cloud.google.com/go v0.57.0/go.mod h1:oXiQ6Rzq3RAkkY7N6t3TcE6jE+CIBBbA36lwQ1JyzZs= +cloud.google.com/go v0.62.0/go.mod h1:jmCYTdRCQuc1PHIIJ/maLInMho30T/Y0M4hTdTShOYc= +cloud.google.com/go v0.65.0/go.mod h1:O5N8zS7uWy9vkA9vayVHs65eM1ubvY4h553ofrNHObY= +cloud.google.com/go v0.72.0/go.mod h1:M+5Vjvlc2wnp6tjzE102Dw08nGShTscUx2nZMufOKPI= +cloud.google.com/go v0.74.0/go.mod h1:VV1xSbzvo+9QJOxLDaJfTjx5e+MePCpCWwvftOeQmWk= +cloud.google.com/go v0.78.0/go.mod h1:QjdrLG0uq+YwhjoVOLsS1t7TW8fs36kLs4XO5R5ECHg= +cloud.google.com/go v0.79.0/go.mod h1:3bzgcEeQlzbuEAYu4mrWhKqWjmpprinYgKJLgKHnbb8= +cloud.google.com/go v0.81.0/go.mod h1:mk/AM35KwGk/Nm2YSeZbxXdrNK3KZOYHmLkOqC2V6E0= +cloud.google.com/go/bigquery v1.0.1/go.mod h1:i/xbL2UlR5RvWAURpBYZTtm/cXjCha9lbfbpx4poX+o= +cloud.google.com/go/bigquery v1.3.0/go.mod h1:PjpwJnslEMmckchkHFfq+HTD2DmtT67aNFKH1/VBDHE= +cloud.google.com/go/bigquery v1.4.0/go.mod h1:S8dzgnTigyfTmLBfrtrhyYhwRxG72rYxvftPBK2Dvzc= +cloud.google.com/go/bigquery v1.5.0/go.mod h1:snEHRnqQbz117VIFhE8bmtwIDY80NLUZUMb4Nv6dBIg= +cloud.google.com/go/bigquery v1.7.0/go.mod h1://okPTzCYNXSlb24MZs83e2Do+h+VXtc4gLoIoXIAPc= +cloud.google.com/go/bigquery v1.8.0/go.mod h1:J5hqkt3O0uAFnINi6JXValWIb1v0goeZM77hZzJN/fQ= +cloud.google.com/go/datastore v1.0.0/go.mod h1:LXYbyblFSglQ5pkeyhO+Qmw7ukd3C+pD7TKLgZqpHYE= +cloud.google.com/go/datastore v1.1.0/go.mod h1:umbIZjpQpHh4hmRpGhH4tLFup+FVzqBi1b3c64qFpCk= +cloud.google.com/go/firestore v1.1.0/go.mod h1:ulACoGHTpvq5r8rxGJ4ddJZBZqakUQqClKRT5SZwBmk= +cloud.google.com/go/pubsub v1.0.1/go.mod h1:R0Gpsv3s54REJCy4fxDixWD93lHJMoZTyQ2kNxGRt3I= +cloud.google.com/go/pubsub v1.1.0/go.mod h1:EwwdRX2sKPjnvnqCa270oGRyludottCI76h+R3AArQw= +cloud.google.com/go/pubsub v1.2.0/go.mod h1:jhfEVHT8odbXTkndysNHCcx0awwzvfOlguIAii9o8iA= +cloud.google.com/go/pubsub v1.3.1/go.mod h1:i+ucay31+CNRpDW4Lu78I4xXG+O1r/MAHgjpRVR+TSU= +cloud.google.com/go/storage v1.0.0/go.mod h1:IhtSnM/ZTZV8YYJWCY8RULGVqBDmpoyjwiyrjsg+URw= +cloud.google.com/go/storage v1.5.0/go.mod h1:tpKbwo567HUNpVclU5sGELwQWBDZ8gh0ZeosJ0Rtdos= +cloud.google.com/go/storage v1.6.0/go.mod h1:N7U0C8pVQ/+NIKOBQyamJIeKQKkZ+mxpohlUTyfDhBk= +cloud.google.com/go/storage v1.8.0/go.mod h1:Wv1Oy7z6Yz3DshWRJFhqM/UCfaWIRTdp0RXyy7KQOVs= +cloud.google.com/go/storage v1.10.0/go.mod h1:FLPqc6j+Ki4BU591ie1oL6qBQGu2Bl/tZ9ullr3+Kg0= +dmitri.shuralyov.com/gpu/mtl v0.0.0-20190408044501-666a987793e9/go.mod h1:H6x//7gZCb22OMCxBHrMx7a5I7Hp++hsVxbQ4BYO7hU= filippo.io/edwards25519 v1.1.0 h1:FNf4tywRC1HmFuKW5xopWpigGjJKiJSV0Cqo0cJWDaA= filippo.io/edwards25519 v1.1.0/go.mod h1:BxyFTGdWcka3PhytdK4V28tE5sGfRvvvRV7EaN4VDT4= github.com/BurntSushi/toml v0.3.1/go.mod h1:xHWCNGjB5oqiDr8zfno3MHue2Ht5sIBksp03qcyfWMU= +github.com/BurntSushi/xgb v0.0.0-20160522181843-27f122750802/go.mod h1:IVnqGOEym/WlBOVXweHU+Q+/VP0lqqI8lqeDx9IjBqo= github.com/IBM/fp-go v1.0.152 h1:OhRB7PAIzgNjCqVjq6PE41VJb3dYEfuRInIUFAHahY4= github.com/IBM/fp-go v1.0.152/go.mod h1:jgx1QhmnKj93JMeZQEL3HDXoibDqGPIx+yIg2hBbvhw= github.com/IBM/mathlib v0.0.3-0.20231011094432-44ee0eb539da h1:qqGozq4tF6EOVnWoTgBoJGudRKKZXSAYnEtDggzTnsw= github.com/IBM/mathlib v0.0.3-0.20231011094432-44ee0eb539da/go.mod h1:Tco9QzE3fQzjMS7nPbHDeFfydAzctStf1Pa8hsh6Hjs= github.com/aead/siphash v1.0.1/go.mod h1:Nywa3cDsYNNK3gaciGTWPwHt0wlpNV15vwmswBAUSII= +github.com/antihax/optional v1.0.0/go.mod h1:uupD/76wgC+ih3iEmQUL+0Ugr19nfwCT1kdvxnR2qWY= +github.com/armon/circbuf v0.0.0-20150827004946-bbbad097214e/go.mod h1:3U/XgcO3hCbHZ8TKRvWD2dDTCfh9M9ya+I9JpbB7O8o= +github.com/armon/go-metrics v0.0.0-20180917152333-f0300d1749da/go.mod h1:Q73ZrmVTwzkszR9V5SSuryQ31EELlFMUz1kKyl939pY= +github.com/armon/go-radix v0.0.0-20180808171621-7fddfc383310/go.mod h1:ufUuZ+zHj4x4TnLV4JWEpy2hxWSpsRywHrMgIH9cCH8= github.com/benbjohnson/clock v1.3.0 h1:ip6w0uFQkncKQ979AypyG0ER7mqUSBdKLOgAle/AT8A= github.com/benbjohnson/clock v1.3.0/go.mod h1:J11/hYXuz8f4ySSvYwY0FKfm+ezbsZBKZxNJlLklBHA= +github.com/bgentry/speakeasy v0.1.0/go.mod h1:+zsyZBPWlz7T6j88CTgSN5bM796AkVf0kBD4zp0CCIs= github.com/bits-and-blooms/bitset v1.17.0 h1:1X2TS7aHz1ELcC0yU1y2stUs/0ig5oMU6STFZGrhvHI= github.com/bits-and-blooms/bitset v1.17.0/go.mod h1:7hO7Gc7Pp1vODcmWvKMRA9BNmbv6a/7QIWpPxHddWR8= +github.com/bketelsen/crypt v0.0.4/go.mod h1:aI6NrJ0pMGgvZKL1iVgXLnfIFJtfV+bKCoqOes/6LfM= github.com/blang/semver/v4 v4.0.0 h1:1PFHFE6yCCTv8C1TeyNNarDzntLi7wMI5i/pzqYIsAM= github.com/blang/semver/v4 v4.0.0/go.mod h1:IbckMUScFkM3pff0VJDNKRiT6TG/YpiHIM2yvyW5YoQ= github.com/blinklabs-io/gouroboros v0.120.1 h1:WcYVOwxQm/6E93qI3apCO2IPFQNoGlQIi34R58tya2Y= @@ -47,13 +93,24 @@ github.com/cayleygraph/quad v1.3.0 h1:xg7HOLWWPgvZ4CcvzEpfCwq42L8mzYUR+8V0jtYoBz github.com/cayleygraph/quad v1.3.0/go.mod h1:NadtM7uMm78FskmX++XiOOrNvgkq0E1KvvhQdMseMz4= github.com/cenkalti/backoff/v4 v4.2.0 h1:HN5dHm3WBOgndBH6E8V0q2jIYIR3s9yglV8k/+MN3u4= github.com/cenkalti/backoff/v4 v4.2.0/go.mod h1:Y3VNntkOUPxTVeUxJ/G5vcM//AlwfmyYozVcomhLiZE= +github.com/census-instrumentation/opencensus-proto v0.2.1/go.mod h1:f6KPmirojxKA12rnyqOA5BBL4O983OfeGPqjHWSTneU= github.com/cheekybits/is v0.0.0-20150225183255-68e9c0620927 h1:SKI1/fuSdodxmNNyVBR8d7X/HuLnRpvvFO0AgyQk764= github.com/cheekybits/is v0.0.0-20150225183255-68e9c0620927/go.mod h1:h/aW8ynjgkuj+NQRlZcDbAbM1ORAbXjXX77sX7T289U= +github.com/chzyer/logex v1.1.10/go.mod h1:+Ywpsq7O8HXn0nuIou7OrIPyXbp3wmkHB+jjWRnGsAI= +github.com/chzyer/readline v0.0.0-20180603132655-2972be24d48e/go.mod h1:nSuG5e5PlCu98SY8svDHJxuZscDgtXS6KTTbou5AhLI= +github.com/chzyer/test v0.0.0-20180213035817-a1ea475d72b1/go.mod h1:Q3SI9o4m/ZMnBNeIyt5eFwwo7qiLfzFZmjNmxjkiQlU= +github.com/client9/misspell v0.3.4/go.mod h1:qj6jICC3Q7zFZvVWo7KLAzC3yx5G7kyvSDkc90ppPyw= +github.com/cncf/udpa/go v0.0.0-20191209042840-269d4d468f6f/go.mod h1:M8M6+tZqaGXZJjfX53e64911xZQV5JYwmTeXPW+k8Sc= +github.com/cncf/udpa/go v0.0.0-20200629203442-efcf912fb354/go.mod h1:WmhPx2Nbnhtbo57+VJT5O0JRkEi1Wbu0z5j0R8u5Hbk= +github.com/cncf/udpa/go v0.0.0-20201120205902-5459f2c99403/go.mod h1:WmhPx2Nbnhtbo57+VJT5O0JRkEi1Wbu0z5j0R8u5Hbk= github.com/consensys/bavard v0.1.22 h1:Uw2CGvbXSZWhqK59X0VG/zOjpTFuOMcPLStrp1ihI0A= github.com/consensys/bavard v0.1.22/go.mod h1:k/zVjHHC4B+PQy1Pg7fgvG3ALicQw540Crag8qx+dZs= github.com/consensys/gnark-crypto v0.14.0 h1:DDBdl4HaBtdQsq/wfMwJvZNE80sHidrK3Nfrefatm0E= github.com/consensys/gnark-crypto v0.14.0/go.mod h1:CU4UijNPsHawiVGNxe9co07FkzCeWHHrb1li/n1XoU0= +github.com/coreos/go-semver v0.3.0/go.mod h1:nnelYz7RCh+5ahJtPPxZlU+153eP4D4r3EedlOD2RNk= +github.com/coreos/go-systemd/v22 v22.3.2/go.mod h1:Y58oyj3AT4RCenI/lSvhwexgC+NSVTIJ3seZv2GcEnc= github.com/cpuguy83/go-md2man/v2 v2.0.0-20190314233015-f79a8a8ca69d/go.mod h1:maD7wRr/U5Z6m/iR4s+kqSMx2CaBsrgA7czyZG/E6dU= +github.com/cpuguy83/go-md2man/v2 v2.0.0/go.mod h1:maD7wRr/U5Z6m/iR4s+kqSMx2CaBsrgA7czyZG/E6dU= github.com/cpuguy83/go-md2man/v2 v2.0.5 h1:ZtcqGrnekaHpVLArFSe4HK5DoKx1T0rq2DwVB0alcyc= github.com/cpuguy83/go-md2man/v2 v2.0.5/go.mod h1:tgQtvFlXSQOSOSIRvRPT7W67SCa46tRHOmNcaadrF8o= github.com/crackcomm/go-gitignore v0.0.0-20170627025303-887ab5e44cc3 h1:HVTnpeuvF6Owjd5mniCL8DEXo7uYXdQEmOP4FJbV5tg= @@ -66,43 +123,142 @@ github.com/davecgh/go-spew v1.1.2-0.20180830191138-d8f796af33cc/go.mod h1:J7Y8Yc github.com/decred/dcrd/crypto/blake256 v1.0.0/go.mod h1:sQl2p6Y26YV+ZOcSTP6thNdn47hh8kt6rqSlvmrXFAc= github.com/decred/dcrd/crypto/blake256 v1.0.1 h1:7PltbUIQB7u/FfZ39+DGa/ShuMyJ5ilcvdfma9wOH6Y= github.com/decred/dcrd/crypto/blake256 v1.0.1/go.mod h1:2OfgNZ5wDpcsFmHmCK5gZTPcCXqlm2ArzUIkw9czNJo= +github.com/decred/dcrd/crypto/blake256 v1.1.0 h1:zPMNGQCm0g4QTY27fOCorQW7EryeQ/U0x++OzVrdms8= github.com/decred/dcrd/dcrec/secp256k1/v4 v4.0.1/go.mod h1:hyedUtir6IdtD/7lIxGeCxkaw7y45JueMRL4DIyJDKs= github.com/decred/dcrd/dcrec/secp256k1/v4 v4.3.0 h1:rpfIENRNNilwHwZeG5+P150SMrnNEcHYvcCuK6dPZSg= github.com/decred/dcrd/dcrec/secp256k1/v4 v4.3.0/go.mod h1:v57UDF4pDQJcEfFUCRop3lJL149eHGSe9Jvczhzjo/0= +github.com/decred/dcrd/dcrec/secp256k1/v4 v4.4.0 h1:NMZiJj8QnKe1LgsbDayM4UoHwbvwDRwnI3hwNaAHRnc= +github.com/decred/dcrd/dcrec/secp256k1/v4 v4.4.0/go.mod h1:ZXNYxsqcloTdSy/rNShjYzMhyjf0LaoftYK0p+A3h40= github.com/decred/dcrd/lru v1.0.0/go.mod h1:mxKOwFd7lFjN2GZYsiz/ecgqR6kkYAl+0pz0tEMk218= +github.com/envoyproxy/go-control-plane v0.9.0/go.mod h1:YTl/9mNaCwkRvm6d1a2C3ymFceY/DCBVvsKhRF0iEA4= +github.com/envoyproxy/go-control-plane v0.9.1-0.20191026205805-5f8ba28d4473/go.mod h1:YTl/9mNaCwkRvm6d1a2C3ymFceY/DCBVvsKhRF0iEA4= +github.com/envoyproxy/go-control-plane v0.9.4/go.mod h1:6rpuAdCZL397s3pYoYcLgu1mIlRU8Am5FuJP05cCM98= +github.com/envoyproxy/go-control-plane v0.9.7/go.mod h1:cwu0lG7PUMfa9snN8LXBig5ynNVH9qI8YYLbd1fK2po= +github.com/envoyproxy/go-control-plane v0.9.9-0.20201210154907-fd9021fe5dad/go.mod h1:cXg6YxExXjJnVBQHBLXeUAgxn2UodCpnH306RInaBQk= +github.com/envoyproxy/go-control-plane v0.9.9-0.20210217033140-668b12f5399d/go.mod h1:cXg6YxExXjJnVBQHBLXeUAgxn2UodCpnH306RInaBQk= +github.com/envoyproxy/protoc-gen-validate v0.1.0/go.mod h1:iSmxcyjqTsJpI2R4NaDN7+kN2VEUnK/pcBlmesArF7c= +github.com/fatih/color v1.7.0/go.mod h1:Zm6kSWBoL9eyXnKyktHP6abPY2pDugNf5KwzbycvMj4= github.com/frankban/quicktest v1.14.6 h1:7Xjx+VpznH+oBnejlPUj8oUpdxnVs4f8XU8WnHkI4W8= github.com/frankban/quicktest v1.14.6/go.mod h1:4ptaffx2x8+WTWXmUCuVU6aPUX1/Mz7zb5vbUoiM6w0= github.com/fsnotify/fsnotify v1.4.7/go.mod h1:jwhsz4b93w/PPRr/qN1Yymfu8t87LnFCMoQvtojpjFo= github.com/fsnotify/fsnotify v1.4.9/go.mod h1:znqG4EE+3YCdAaPaxE2ZRY/06pZUdp0tY4IgpuI1SZQ= github.com/fxamacker/cbor/v2 v2.8.0 h1:fFtUGXUzXPHTIUdne5+zzMPTfffl3RD5qYnkY40vtxU= github.com/fxamacker/cbor/v2 v2.8.0/go.mod h1:vM4b+DJCtHn+zz7h3FFp/hDAI9WNWCsZj23V5ytsSxQ= +github.com/ghodss/yaml v1.0.0/go.mod h1:4dBDuWmgqj2HViK6kFavaiC9ZROes6MMH2rRYeMEF04= +github.com/go-gl/glfw v0.0.0-20190409004039-e6da0acd62b1/go.mod h1:vR7hzQXu2zJy9AVAgeJqvqgH9Q5CA+iKCZ2gyEVpxRU= +github.com/go-gl/glfw/v3.3/glfw v0.0.0-20191125211704-12ad95a8df72/go.mod h1:tQ2UAYgL5IevRw8kRxooKSPJfGvJ9fJQFa0TUsXzTg8= +github.com/go-gl/glfw/v3.3/glfw v0.0.0-20200222043503-6f7a984d4dc4/go.mod h1:tQ2UAYgL5IevRw8kRxooKSPJfGvJ9fJQFa0TUsXzTg8= github.com/go-jose/go-jose/v3 v3.0.4 h1:Wp5HA7bLQcKnf6YYao/4kpRpVMp/yf6+pJKV8WFSaNY= github.com/go-jose/go-jose/v3 v3.0.4/go.mod h1:5b+7YgP7ZICgJDBdfjZaIt+H/9L9T/YQrVfLAMboGkQ= +github.com/go-jose/go-jose/v4 v4.1.1 h1:JYhSgy4mXXzAdF3nUx3ygx347LRXJRrpgyU3adRmkAI= +github.com/go-jose/go-jose/v4 v4.1.1/go.mod h1:BdsZGqgdO3b6tTc6LSE56wcDbMMLuPsw5d4ZD5f94kA= github.com/go-yaml/yaml v2.1.0+incompatible/go.mod h1:w2MrLa16VYP0jy6N7M5kHaCkaLENm+P+Tv+MfurjSw0= +github.com/goccy/go-json v0.10.3 h1:KZ5WoDbxAIgm2HNbYckL0se1fHD6rz5j4ywS6ebzDqA= +github.com/goccy/go-json v0.10.3/go.mod h1:oq7eo15ShAhp70Anwd5lgX2pLfOS3QCiwU/PULtXL6M= +github.com/godbus/dbus/v5 v5.0.4/go.mod h1:xhWf0FNVPg57R7Z0UbKHbJfkEywrmjJnf7w5xrFpKfA= +github.com/gogo/protobuf v1.3.2/go.mod h1:P1XiOD3dCwIKUDQYPy72D8LYyHL2YPYrpS2s69NZV8Q= +github.com/golang/glog v0.0.0-20160126235308-23def4e6c14b/go.mod h1:SBH7ygxi8pfUlaOkMMuAQtPIUF8ecWP5IEl/CR7VP2Q= +github.com/golang/groupcache v0.0.0-20190702054246-869f871628b6/go.mod h1:cIg4eruTrX1D+g88fzRXU5OdNfaM+9IcxsU14FzY7Hc= +github.com/golang/groupcache v0.0.0-20191227052852-215e87163ea7/go.mod h1:cIg4eruTrX1D+g88fzRXU5OdNfaM+9IcxsU14FzY7Hc= +github.com/golang/groupcache v0.0.0-20200121045136-8c9f03a8e57e/go.mod h1:cIg4eruTrX1D+g88fzRXU5OdNfaM+9IcxsU14FzY7Hc= +github.com/golang/mock v1.1.1/go.mod h1:oTYuIxOrZwtPieC+H1uAHpcLFnEyAGVDL/k47Jfbm0A= +github.com/golang/mock v1.2.0/go.mod h1:oTYuIxOrZwtPieC+H1uAHpcLFnEyAGVDL/k47Jfbm0A= +github.com/golang/mock v1.3.1/go.mod h1:sBzyDLLjw3U8JLTeZvSv8jJB+tU5PVekmnlKIyFUx0Y= +github.com/golang/mock v1.4.0/go.mod h1:UOMv5ysSaYNkG+OFQykRIcU/QvvxJf3p21QfJ2Bt3cw= +github.com/golang/mock v1.4.1/go.mod h1:UOMv5ysSaYNkG+OFQykRIcU/QvvxJf3p21QfJ2Bt3cw= +github.com/golang/mock v1.4.3/go.mod h1:UOMv5ysSaYNkG+OFQykRIcU/QvvxJf3p21QfJ2Bt3cw= +github.com/golang/mock v1.4.4/go.mod h1:l3mdAwkq5BuhzHwde/uurv3sEJeZMXNpwsxVWU71h+4= +github.com/golang/mock v1.5.0/go.mod h1:CWnOUgYIOo4TcNZ0wHX3YZCqsaM1I1Jvs6v3mP3KVu8= github.com/golang/protobuf v1.2.0/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U= +github.com/golang/protobuf v1.3.1/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U= +github.com/golang/protobuf v1.3.2/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U= +github.com/golang/protobuf v1.3.3/go.mod h1:vzj43D7+SQXF/4pzW/hwtAqwc6iTitCiVSaWz5lYuqw= +github.com/golang/protobuf v1.3.4/go.mod h1:vzj43D7+SQXF/4pzW/hwtAqwc6iTitCiVSaWz5lYuqw= +github.com/golang/protobuf v1.3.5/go.mod h1:6O5/vntMXwX2lRkT1hjjk0nAC1IDOTvTlVgjlRvqsdk= github.com/golang/protobuf v1.4.0-rc.1/go.mod h1:ceaxUfeHdC40wWswd/P6IGgMaK3YpKi5j83Wpe3EHw8= github.com/golang/protobuf v1.4.0-rc.1.0.20200221234624-67d41d38c208/go.mod h1:xKAWHe0F5eneWXFV3EuXVDTCmh+JuBKY0li0aMyXATA= github.com/golang/protobuf v1.4.0-rc.2/go.mod h1:LlEzMj4AhA7rCAGe4KMBDvJI+AwstrUpVNzEA03Pprs= github.com/golang/protobuf v1.4.0-rc.4.0.20200313231945-b860323f09d0/go.mod h1:WU3c8KckQ9AFe+yFwt9sWVRKCVIyN9cPHBJSNnbL67w= github.com/golang/protobuf v1.4.0/go.mod h1:jodUvKwWbYaEsadDk5Fwe5c77LiNKVO9IDvqG2KuDX0= +github.com/golang/protobuf v1.4.1/go.mod h1:U8fpvMrcmy5pZrNK1lt4xCsGvpyWQ/VVv6QDs8UjoX8= github.com/golang/protobuf v1.4.2/go.mod h1:oDoupMAO8OvCJWAcko0GGGIgR6R6ocIYbsSw735rRwI= +github.com/golang/protobuf v1.4.3/go.mod h1:oDoupMAO8OvCJWAcko0GGGIgR6R6ocIYbsSw735rRwI= +github.com/golang/protobuf v1.5.0/go.mod h1:FsONVRAS9T7sI+LIUmWTfcYkHO4aIWwzhcaSAoJOfIk= +github.com/golang/protobuf v1.5.1/go.mod h1:DopwsBzvsk0Fs44TXzsVbJyPhcCPeIwnvohx4u74HPM= +github.com/golang/protobuf v1.5.2/go.mod h1:XVQd3VNwM+JqD3oG2Ue2ip4fOMUkwXdXDdiuN0vRsmY= github.com/golang/snappy v0.0.4/go.mod h1:/XxbfmMg8lxefKM7IXC3fBNl/7bRcc72aCRzEWrmP2Q= +github.com/google/btree v0.0.0-20180813153112-4030bb1f1f0c/go.mod h1:lNA+9X1NB3Zf8V7Ke586lFgjr2dZNuvo3lPJSGZ5JPQ= +github.com/google/btree v1.0.0/go.mod h1:lNA+9X1NB3Zf8V7Ke586lFgjr2dZNuvo3lPJSGZ5JPQ= +github.com/google/go-cmp v0.2.0/go.mod h1:oXzfMopK8JAjlY9xF4vHSVASa0yLyX7SntLO5aqRK0M= github.com/google/go-cmp v0.3.0/go.mod h1:8QqcDgzrUqlUb/G2PQTWiueGozuR1884gddMywk6iLU= github.com/google/go-cmp v0.3.1/go.mod h1:8QqcDgzrUqlUb/G2PQTWiueGozuR1884gddMywk6iLU= github.com/google/go-cmp v0.4.0/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= +github.com/google/go-cmp v0.4.1/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= +github.com/google/go-cmp v0.5.0/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= +github.com/google/go-cmp v0.5.1/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= +github.com/google/go-cmp v0.5.2/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= +github.com/google/go-cmp v0.5.3/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= +github.com/google/go-cmp v0.5.4/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= +github.com/google/go-cmp v0.5.5/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= +github.com/google/go-cmp v0.5.6/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= github.com/google/go-cmp v0.5.9/go.mod h1:17dUlkBOakJ0+DkrSSNjCkIjxS6bF9zb3elmeNGIjoY= github.com/google/go-cmp v0.6.0 h1:ofyhxvXcZhMsU5ulbFiLKl/XBFqE1GSq7atu8tAmTRI= github.com/google/go-cmp v0.6.0/go.mod h1:17dUlkBOakJ0+DkrSSNjCkIjxS6bF9zb3elmeNGIjoY= +github.com/google/gofuzz v1.0.0/go.mod h1:dBl0BpW6vV/+mYPU4Po3pmUjxk6FQPldtuIdl/M65Eg= +github.com/google/martian v2.1.0+incompatible/go.mod h1:9I4somxYTbIHy5NJKHRl3wXiIaQGbYVAs8BPL6v8lEs= +github.com/google/martian/v3 v3.0.0/go.mod h1:y5Zk1BBys9G+gd6Jrk0W3cC1+ELVxBWuIGO+w/tUAp0= +github.com/google/martian/v3 v3.1.0/go.mod h1:y5Zk1BBys9G+gd6Jrk0W3cC1+ELVxBWuIGO+w/tUAp0= +github.com/google/pprof v0.0.0-20181206194817-3ea8567a2e57/go.mod h1:zfwlbNMJ+OItoe0UupaVj+oy1omPYYDuagoSzA8v9mc= +github.com/google/pprof v0.0.0-20190515194954-54271f7e092f/go.mod h1:zfwlbNMJ+OItoe0UupaVj+oy1omPYYDuagoSzA8v9mc= +github.com/google/pprof v0.0.0-20191218002539-d4f498aebedc/go.mod h1:ZgVRPoUq/hfqzAqh7sHMqb3I9Rq5C59dIz2SbBwJ4eM= +github.com/google/pprof v0.0.0-20200212024743-f11f1df84d12/go.mod h1:ZgVRPoUq/hfqzAqh7sHMqb3I9Rq5C59dIz2SbBwJ4eM= +github.com/google/pprof v0.0.0-20200229191704-1ebb73c60ed3/go.mod h1:ZgVRPoUq/hfqzAqh7sHMqb3I9Rq5C59dIz2SbBwJ4eM= +github.com/google/pprof v0.0.0-20200430221834-fc25d7d30c6d/go.mod h1:ZgVRPoUq/hfqzAqh7sHMqb3I9Rq5C59dIz2SbBwJ4eM= +github.com/google/pprof v0.0.0-20200708004538-1a94d8640e99/go.mod h1:ZgVRPoUq/hfqzAqh7sHMqb3I9Rq5C59dIz2SbBwJ4eM= +github.com/google/pprof v0.0.0-20201023163331-3e6fc7fc9c4c/go.mod h1:kpwsk12EmLew5upagYY7GY0pfYCcupk39gWOCRROcvE= +github.com/google/pprof v0.0.0-20201203190320-1bf35d6f28c2/go.mod h1:kpwsk12EmLew5upagYY7GY0pfYCcupk39gWOCRROcvE= +github.com/google/pprof v0.0.0-20210122040257-d980be63207e/go.mod h1:kpwsk12EmLew5upagYY7GY0pfYCcupk39gWOCRROcvE= +github.com/google/pprof v0.0.0-20210226084205-cbba55b83ad5/go.mod h1:kpwsk12EmLew5upagYY7GY0pfYCcupk39gWOCRROcvE= +github.com/google/renameio v0.1.0/go.mod h1:KWCgfxg9yswjAJkECMjeO8J8rahYeXnNhOm40UhjYkI= github.com/google/subcommands v1.2.0/go.mod h1:ZjhPrFU+Olkh9WazFPsl27BQ4UPiG37m3yTrtFlrHVk= +github.com/google/uuid v1.1.2/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo= github.com/google/uuid v1.6.0 h1:NIvaJDMOsjHA8n1jAhLSgzrAzy1Hgr+hNrb57e+94F0= github.com/google/uuid v1.6.0/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo= +github.com/googleapis/gax-go/v2 v2.0.4/go.mod h1:0Wqv26UfaUD9n4G6kQubkQ+KchISgw+vpHVxEJEs9eg= +github.com/googleapis/gax-go/v2 v2.0.5/go.mod h1:DWXyrwAJ9X0FpwwEdw+IPEYBICEFu5mhpdKc/us6bOk= github.com/gopherjs/gopherjs v0.0.0-20181017120253-0766667cb4d1/go.mod h1:wJfORRmW1u3UXTncJ5qlYoELFm8eSnnEO6hX4iZ3EWY= github.com/gopherjs/gopherjs v0.0.0-20190430165422-3e4dfb77656c h1:7lF+Vz0LqiRidnzC1Oq86fpX1q/iEv2KJdrCtttYjT4= github.com/gopherjs/gopherjs v0.0.0-20190430165422-3e4dfb77656c/go.mod h1:wJfORRmW1u3UXTncJ5qlYoELFm8eSnnEO6hX4iZ3EWY= +github.com/gopherjs/gopherjs v1.17.2 h1:fQnZVsXk8uxXIStYb0N4bGk7jeyTalG/wsZjQ25dO0g= +github.com/gopherjs/gopherjs v1.17.2/go.mod h1:pRRIvn/QzFLrKfvEz3qUuEhtE/zLCWfreZ6J5gM2i+k= github.com/gorilla/websocket v1.5.0/go.mod h1:YR8l580nyteQvAITg2hZ9XVh4b55+EU/adAjf1fMHhE= +github.com/grpc-ecosystem/grpc-gateway v1.16.0/go.mod h1:BDjrQk3hbvj6Nolgz8mAMFbcEtjT1g+wF4CSlocrBnw= +github.com/hashicorp/consul/api v1.1.0/go.mod h1:VmuI/Lkw1nC05EYQWNKwWGbkg+FbDBtguAZLlVdkD9Q= +github.com/hashicorp/consul/sdk v0.1.1/go.mod h1:VKf9jXwCTEY1QZP2MOLRhb5i/I/ssyNV1vwHyQBF0x8= +github.com/hashicorp/errwrap v1.0.0/go.mod h1:YH+1FKiLXxHSkmPseP+kNlulaMuP3n2brvKWEqk/Jc4= +github.com/hashicorp/go-cleanhttp v0.5.1/go.mod h1:JpRdi6/HCYpAwUzNwuwqhbovhLtngrth3wmdIIUrZ80= +github.com/hashicorp/go-immutable-radix v1.0.0/go.mod h1:0y9vanUI8NX6FsYoO3zeMjhV/C5i9g4Q3DwcSNZ4P60= +github.com/hashicorp/go-msgpack v0.5.3/go.mod h1:ahLV/dePpqEmjfWmKiqvPkv/twdG7iPBM1vqhUKIvfM= +github.com/hashicorp/go-multierror v1.0.0/go.mod h1:dHtQlpGsu+cZNNAkkCN/P3hoUDHhCYQXV3UM06sGGrk= +github.com/hashicorp/go-rootcerts v1.0.0/go.mod h1:K6zTfqpRlCUIjkwsN4Z+hiSfzSTQa6eBIzfwKfwNnHU= +github.com/hashicorp/go-sockaddr v1.0.0/go.mod h1:7Xibr9yA9JjQq1JpNB2Vw7kxv8xerXegt+ozgdvDeDU= +github.com/hashicorp/go-syslog v1.0.0/go.mod h1:qPfqrKkXGihmCqbJM2mZgkZGvKG1dFdvsLplgctolz4= +github.com/hashicorp/go-uuid v1.0.0/go.mod h1:6SBZvOh/SIDV7/2o3Jml5SYk/TvGqwFJ/bN7x4byOro= +github.com/hashicorp/go-uuid v1.0.1/go.mod h1:6SBZvOh/SIDV7/2o3Jml5SYk/TvGqwFJ/bN7x4byOro= +github.com/hashicorp/go.net v0.0.1/go.mod h1:hjKkEWcCURg++eb33jQU7oqQcI9XDCnUzHA0oac0k90= +github.com/hashicorp/golang-lru v0.5.0/go.mod h1:/m3WP610KZHVQ1SGc6re/UDhFvYD7pJ4Ao+sR/qLZy8= +github.com/hashicorp/golang-lru v0.5.1/go.mod h1:/m3WP610KZHVQ1SGc6re/UDhFvYD7pJ4Ao+sR/qLZy8= +github.com/hashicorp/hcl v1.0.0/go.mod h1:E5yfLk+7swimpb2L/Alb/PJmXilQ/rhwaUYs4T20WEQ= +github.com/hashicorp/logutils v1.0.0/go.mod h1:QIAnNjmIWmVIIkWDTG1z5v++HQmx9WQRO+LraFDTW64= +github.com/hashicorp/mdns v1.0.0/go.mod h1:tL+uN++7HEJ6SQLQ2/p+z2pH24WQKWjBPkE0mNTz8vQ= +github.com/hashicorp/memberlist v0.1.3/go.mod h1:ajVTdAv/9Im8oMAAj5G31PhhMCZJV2pPBoIllUwCN7I= +github.com/hashicorp/serf v0.8.2/go.mod h1:6hOLApaqBFA1NXqRQAsxw9QxuDEvNxSQRwA/JwenrHc= github.com/hpcloud/tail v1.0.0/go.mod h1:ab1qPbhIpdTxEkNHXyeSf5vhxWSCs/tWer42PpOxQnU= github.com/hyperledger/fabric-amcl v0.0.0-20230602173724-9e02669dceb2 h1:B1Nt8hKb//KvgGRprk0h1t4lCnwhE9/ryb1WqfZbV+M= github.com/hyperledger/fabric-amcl v0.0.0-20230602173724-9e02669dceb2/go.mod h1:X+DIyUsaTmalOpmpQfIvFZjKHQedrURQ5t4YqquX7lE= +github.com/ianlancetaylor/demangle v0.0.0-20181102032728-5e5cf60278f6/go.mod h1:aSSvb/t6k1mPoxDqO4vJh6VOCGPwU4O0C2/Eqndh1Sc= +github.com/ianlancetaylor/demangle v0.0.0-20200824232613-28f6c0f3b639/go.mod h1:aSSvb/t6k1mPoxDqO4vJh6VOCGPwU4O0C2/Eqndh1Sc= +github.com/inconshreveable/mousetrap v1.0.0/go.mod h1:PxqpIevigyE2G7u3NXJIT2ANytuPF1OarO4DADm73n8= github.com/ipfs/boxo v0.12.0 h1:AXHg/1ONZdRQHQLgG5JHsSC3XoE4DjCAMgK+asZvUcQ= github.com/ipfs/boxo v0.12.0/go.mod h1:xAnfiU6PtxWCnRqu7dcXQ10bB5/kvI1kXRotuGqGBhg= github.com/ipfs/go-cid v0.5.0 h1:goEKKhaGm0ul11IHA7I6p1GmKz8kEYniqFopaB5Otwg= @@ -116,36 +272,83 @@ github.com/jessevdk/go-flags v1.4.0/go.mod h1:4FA24M0QyGHXBuZZK/XkWh8h0e1EYbRYJS github.com/jinzhu/copier v0.4.0 h1:w3ciUoD19shMCRargcpm0cm91ytaBhDvuRpz1ODO/U8= github.com/jinzhu/copier v0.4.0/go.mod h1:DfbEm0FYsaqBcKcFuvmOZb218JkPGtvSHsKg8S8hyyg= github.com/jrick/logrotate v1.0.0/go.mod h1:LNinyqDIJnpAur+b8yyulnQw/wDuN1+BYKlTRt3OuAQ= +github.com/json-iterator/go v1.1.11/go.mod h1:KdQUCv79m/52Kvf8AW2vK1V8akMuk1QjK/uOdHXbAo4= +github.com/jstemmer/go-junit-report v0.0.0-20190106144839-af01ea7f8024/go.mod h1:6v2b51hI/fHJwM22ozAgKL4VKDeJcHhJFhtBdhmNjmU= +github.com/jstemmer/go-junit-report v0.9.1/go.mod h1:Brl9GWCQeLvo8nXZwPNNblvFj/XSXhF0NWZEnDohbsk= github.com/jtolds/gls v4.20.0+incompatible h1:xdiiI2gbIgH/gLH7ADydsJ1uDOEzR8yvV7C0MuV77Wo= github.com/jtolds/gls v4.20.0+incompatible/go.mod h1:QJZ7F/aHp+rZTRtaJ1ow/lLfFfVYBRgL+9YlvaHOwJU= github.com/kilic/bls12-381 v0.1.1-0.20210503002446-7b7597926c69 h1:kMJlf8z8wUcpyI+FQJIdGjAhfTww1y0AbQEv86bpVQI= github.com/kilic/bls12-381 v0.1.1-0.20210503002446-7b7597926c69/go.mod h1:tlkavyke+Ac7h8R3gZIjI5LKBcvMlSWnXNMgT3vZXo8= +github.com/kisielk/errcheck v1.5.0/go.mod h1:pFxgyoBC7bSaBwPgfKdkLd5X25qrDl4LWUI2bnpBCr8= +github.com/kisielk/gotool v1.0.0/go.mod h1:XhKaO+MFFWcvkIS/tQcRk01m1F5IRFswLeQ+oQHNcck= github.com/kkdai/bstream v0.0.0-20161212061736-f391b8402d23/go.mod h1:J+Gs4SYgM6CZQHDETBtE9HaSEkGmuNXF86RwHhHUvq4= github.com/klauspost/cpuid/v2 v2.0.4/go.mod h1:FInQzS24/EEf25PyTYn52gqo7WaD8xa0213Md/qVLRg= github.com/klauspost/cpuid/v2 v2.0.9/go.mod h1:FInQzS24/EEf25PyTYn52gqo7WaD8xa0213Md/qVLRg= github.com/klauspost/cpuid/v2 v2.2.4 h1:acbojRNwl3o09bUq+yDCtZFc1aiwaAAxtcn8YkZXnvk= github.com/klauspost/cpuid/v2 v2.2.4/go.mod h1:RVVoqg1df56z8g3pUjL/3lE5UfnlrJX8tyFgg4nqhuY= +github.com/kr/fs v0.1.0/go.mod h1:FFnZGqtBN9Gxj7eW1uZ42v5BccTP0vu6NEaFoC2HwRg= +github.com/kr/pretty v0.1.0/go.mod h1:dAy3ld7l9f0ibDNOQOHHMYYIIbhfbHSm3C4ZsoJORNo= github.com/kr/pretty v0.3.1 h1:flRD4NNwYAUpkphVc1HcthR4KEIFJ65n8Mw5qdRn3LE= github.com/kr/pretty v0.3.1/go.mod h1:hoEshYVHaxMs3cyo3Yncou5ZscifuDolrwPKZanG3xk= +github.com/kr/pty v1.1.1/go.mod h1:pFQYn66WHrOpPYNljwOMqo10TkYh1fy3cYio2l3bCsQ= +github.com/kr/text v0.1.0/go.mod h1:4Jbv+DJW3UT/LiOwJeYQe1efqtUx/iVham/4vfdArNI= github.com/kr/text v0.2.0 h1:5Nx0Ya0ZqY2ygV366QzturHI13Jq95ApcVaJBhpS+AY= github.com/kr/text v0.2.0/go.mod h1:eLer722TekiGuMkidMxC/pM04lWEeraHUUmBw8l2grE= github.com/leanovate/gopter v0.2.11 h1:vRjThO1EKPb/1NsDXuDrzldR28RLkBflWYcU9CvzWu4= github.com/leanovate/gopter v0.2.11/go.mod h1:aK3tzZP/C+p1m3SPRE4SYZFGP7jjkuSI4f7Xvpt0S9c= +github.com/lestrrat-go/backoff/v2 v2.0.8 h1:oNb5E5isby2kiro9AgdHLv5N5tint1AnDVVf2E2un5A= +github.com/lestrrat-go/backoff/v2 v2.0.8/go.mod h1:rHP/q/r9aT27n24JQLa7JhSQZCKBBOiM/uP402WwN8Y= +github.com/lestrrat-go/blackmagic v1.0.4 h1:IwQibdnf8l2KoO+qC3uT4OaTWsW7tuRQXy9TRN9QanA= +github.com/lestrrat-go/blackmagic v1.0.4/go.mod h1:6AWFyKNNj0zEXQYfTMPfZrAXUWUfTIZ5ECEUEJaijtw= +github.com/lestrrat-go/httpcc v1.0.1 h1:ydWCStUeJLkpYyjLDHihupbn2tYmZ7m22BGkcvZZrIE= +github.com/lestrrat-go/httpcc v1.0.1/go.mod h1:qiltp3Mt56+55GPVCbTdM9MlqhvzyuL6W/NMDA8vA5E= +github.com/lestrrat-go/httprc v1.0.6 h1:qgmgIRhpvBqexMJjA/PmwSvhNk679oqD1RbovdCGW8k= +github.com/lestrrat-go/httprc v1.0.6/go.mod h1:mwwz3JMTPBjHUkkDv/IGJ39aALInZLrhBp0X7KGUZlo= +github.com/lestrrat-go/httprc/v3 v3.0.0 h1:nZUx/zFg5uc2rhlu1L1DidGr5Sj02JbXvGSpnY4LMrc= +github.com/lestrrat-go/httprc/v3 v3.0.0/go.mod h1:k2U1QIiyVqAKtkffbg+cUmsyiPGQsb9aAfNQiNFuQ9Q= +github.com/lestrrat-go/iter v1.0.2 h1:gMXo1q4c2pHmC3dn8LzRhJfP1ceCbgSiT9lUydIzltI= +github.com/lestrrat-go/iter v1.0.2/go.mod h1:Momfcq3AnRlRjI5b5O8/G5/BvpzrhoFTZcn06fEOPt4= +github.com/lestrrat-go/jwx v1.2.31 h1:/OM9oNl/fzyldpv5HKZ9m7bTywa7COUfg8gujd9nJ54= +github.com/lestrrat-go/jwx v1.2.31/go.mod h1:eQJKoRwWcLg4PfD5CFA5gIZGxhPgoPYq9pZISdxLf0c= +github.com/lestrrat-go/jwx/v2 v2.1.6 h1:hxM1gfDILk/l5ylers6BX/Eq1m/pnxe9NBwW6lVfecA= +github.com/lestrrat-go/jwx/v2 v2.1.6/go.mod h1:Y722kU5r/8mV7fYDifjug0r8FK8mZdw0K0GpJw/l8pU= +github.com/lestrrat-go/jwx/v3 v3.0.8 h1:lOCHy+k4/mgRI8FkgkHO+NsUx1GXHHktGx0CIkFToyI= +github.com/lestrrat-go/jwx/v3 v3.0.8/go.mod h1:0P9rjqNMDOspNSetpKX86Go54jLSEwCh8ax4jQRGYL0= +github.com/lestrrat-go/option v1.0.0/go.mod h1:5ZHFbivi4xwXxhxY9XHDe2FHo6/Z7WWmtT7T5nBBp3I= +github.com/lestrrat-go/option v1.0.1 h1:oAzP2fvZGQKWkvHa1/SAcFolBEca1oN+mQ7eooNBEYU= +github.com/lestrrat-go/option v1.0.1/go.mod h1:5ZHFbivi4xwXxhxY9XHDe2FHo6/Z7WWmtT7T5nBBp3I= +github.com/lestrrat-go/option/v2 v2.0.0 h1:XxrcaJESE1fokHy3FpaQ/cXW8ZsIdWcdFzzLOcID3Ss= +github.com/lestrrat-go/option/v2 v2.0.0/go.mod h1:oSySsmzMoR0iRzCDCaUfsCzxQHUEuhOViQObyy7S6Vg= github.com/libp2p/go-buffer-pool v0.1.0 h1:oK4mSFcQz7cTQIfqbe4MIj9gLW+mnanjyFtc6cdF0Y8= github.com/libp2p/go-buffer-pool v0.1.0/go.mod h1:N+vh8gMqimBzdKkSMVuydVDq+UV5QTWy5HSiZacSbPg= github.com/libp2p/go-flow-metrics v0.1.0 h1:0iPhMI8PskQwzh57jB9WxIuIOQ0r+15PChFGkx3Q3WM= github.com/libp2p/go-flow-metrics v0.1.0/go.mod h1:4Xi8MX8wj5aWNDAZttg6UPmc0ZrnFNsMtpsYUClFtro= github.com/libp2p/go-libp2p v0.27.8 h1:IX5x/4yKwyPQeVS2AXHZ3J4YATM9oHBGH1gBc23jBAI= github.com/libp2p/go-libp2p v0.27.8/go.mod h1:eCFFtd0s5i/EVKR7+5Ki8bM7qwkNW3TPTTSSW9sz8NE= +github.com/magiconair/properties v1.8.5/go.mod h1:y3VJvCyxH9uVvJTWEGAELF3aiYNyPKd5NZ3oSwXrF60= +github.com/mattn/go-colorable v0.0.9/go.mod h1:9vuHe8Xs5qXnSaW/c/ABM9alt+Vo+STaOChaDxuIBZU= +github.com/mattn/go-isatty v0.0.3/go.mod h1:M+lRXTBqGeGNdLjl/ufCoiOlB5xdOkqRJdNxMWT7Zi4= +github.com/miekg/dns v1.0.14/go.mod h1:W1PPwlIAgtquWBMBEV9nkV9Cazfe8ScdGz/Lj7v3Nrg= github.com/minio/sha256-simd v1.0.0 h1:v1ta+49hkWZyvaKwrQB8elexRqm6Y0aMLjCNsrYxo6g= github.com/minio/sha256-simd v1.0.0/go.mod h1:OuYzVNI5vcoYIAmbIvHPl3N3jUzVedXbKy5RFepssQM= +github.com/mitchellh/cli v1.0.0/go.mod h1:hNIlj7HEI86fIcpObd7a0FcrxTWetlwJDGcceTlRvqc= +github.com/mitchellh/go-homedir v1.0.0/go.mod h1:SfyaCUpYCn1Vlf4IUYiD9fPX4A5wJrkLzIz1N1q0pr0= github.com/mitchellh/go-homedir v1.1.0 h1:lukF9ziXFxDFPkA1vsr5zpc1XuPDn/wFntq5mG+4E0Y= github.com/mitchellh/go-homedir v1.1.0/go.mod h1:SfyaCUpYCn1Vlf4IUYiD9fPX4A5wJrkLzIz1N1q0pr0= +github.com/mitchellh/go-testing-interface v1.0.0/go.mod h1:kRemZodwjscx+RGhAo8eIhFbs2+BFgRtFPeD/KE+zxI= +github.com/mitchellh/gox v0.4.0/go.mod h1:Sd9lOJ0+aimLBi73mGofS1ycjY8lL3uZM3JPS42BGNg= +github.com/mitchellh/iochan v1.0.0/go.mod h1:JwYml1nuB7xOzsp52dPpHFffvOCDupsG0QubkSMEySY= +github.com/mitchellh/mapstructure v0.0.0-20160808181253-ca63d7c062ee/go.mod h1:FVVH3fgwuzCH5S8UJGiWEs2h04kUh9fWfEaFds41c1Y= +github.com/mitchellh/mapstructure v1.1.2/go.mod h1:FVVH3fgwuzCH5S8UJGiWEs2h04kUh9fWfEaFds41c1Y= +github.com/mitchellh/mapstructure v1.4.1/go.mod h1:bFUtVrKA4DC2yAKiSyO/QUcy7e+RRV2QTWOzhPopBRo= github.com/mitchellh/mapstructure v1.5.0 h1:jeMsZIYE/09sWLaz43PL7Gy6RuMjD2eJVyuac5Z2hdY= github.com/mitchellh/mapstructure v1.5.0/go.mod h1:bFUtVrKA4DC2yAKiSyO/QUcy7e+RRV2QTWOzhPopBRo= github.com/mmcloughlin/addchain v0.4.0 h1:SobOdjm2xLj1KkXN5/n0xTIWyZA2+s99UCY1iPfkHRY= github.com/mmcloughlin/addchain v0.4.0/go.mod h1:A86O+tHqZLMNO4w6ZZ4FlVQEadcoqkyU72HC5wJ4RlU= github.com/mmcloughlin/profile v0.1.1/go.mod h1:IhHD7q1ooxgwTgjxQYkACGA77oFTDdFVejUS1/tS/qU= +github.com/modern-go/concurrent v0.0.0-20180228061459-e0a39a4cb421/go.mod h1:6dJC0mAP4ikYIbvyc7fijjWJddQyLn8Ig3JB5CqoB9Q= +github.com/modern-go/reflect2 v0.0.0-20180701023420-4b7aa43c6742/go.mod h1:bx2lNnkwVCuqBIxFjflWJWanXIb3RllmbCylyMrvgv0= +github.com/modern-go/reflect2 v1.0.1/go.mod h1:bx2lNnkwVCuqBIxFjflWJWanXIb3RllmbCylyMrvgv0= github.com/mr-tron/base58 v1.2.0 h1:T/HDJBh4ZCPbU39/+c3rRvE0uKBQlU27+QI8LJ4t64o= github.com/mr-tron/base58 v1.2.0/go.mod h1:BinMc/sQntlIE1frQmRFPUoPA1Zkr8VRgBdjWI2mNwc= github.com/multiformats/go-base32 v0.1.0 h1:pVx9xoSPqEIQG8o+UbAe7DNi51oej1NtK+aGkbLYxPE= @@ -164,6 +367,8 @@ github.com/multiformats/go-multistream v0.4.1 h1:rFy0Iiyn3YT0asivDUIR05leAdwZq3d github.com/multiformats/go-multistream v0.4.1/go.mod h1:Mz5eykRVAjJWckE2U78c6xqdtyNUEhKSM0Lwar2p77Q= github.com/multiformats/go-varint v0.0.7 h1:sWSGR+f/eu5ABZA2ZpYKBILXTTs9JWpdEM/nEGOHFS8= github.com/multiformats/go-varint v0.0.7/go.mod h1:r8PUYw/fD/SjBCiKOoDlGF6QawOELpZAu9eioSos/OU= +github.com/neelance/astrewrite v0.0.0-20160511093645-99348263ae86/go.mod h1:kHJEU3ofeGjhHklVoIGuVj85JJwZ6kWPaJwCIxgnFmo= +github.com/neelance/sourcemap v0.0.0-20200213170602-2833bce08e4c/go.mod h1:Qr6/a/Q4r9LP1IltGz7tA7iOK1WonHEYhu1HRBA7ZiM= github.com/nxadm/tail v1.4.4/go.mod h1:kenIhsEOeOJmVchQTgglprH7qJGnHDVpk1VPCcaMI8A= github.com/onsi/ginkgo v1.6.0/go.mod h1:lLunBs/Ym6LB5Z9jYTR76FiuTmxDTDusOGeTQH+WWjE= github.com/onsi/ginkgo v1.7.0/go.mod h1:lLunBs/Ym6LB5Z9jYTR76FiuTmxDTDusOGeTQH+WWjE= @@ -173,33 +378,63 @@ github.com/onsi/gomega v1.4.1/go.mod h1:C1qb7wdrVGGVU+Z6iS04AVkA3Q65CEZX59MT0QO5 github.com/onsi/gomega v1.4.3/go.mod h1:ex+gbHU/CVuBBDIJjb2X0qEXbFg53c61hWP/1CpauHY= github.com/onsi/gomega v1.7.1/go.mod h1:XdKZgCCFLUoM/7CFJVPcG8C1xQ1AJ0vpAezJrB7JYyY= github.com/onsi/gomega v1.10.1/go.mod h1:iN09h71vgCQne3DLsj+A5owkum+a2tYe+TOCB1ybHNo= +github.com/pascaldekloe/goe v0.0.0-20180627143212-57f6aae5913c/go.mod h1:lzWF7FIEvWOWxwDKqyGYQf6ZUaNfKdP144TG7ZOy1lc= +github.com/pelletier/go-toml v1.9.3/go.mod h1:u1nR/EPcESfeI/szUZKdtJ0xRNbUoANCkoOuaOx1Y+c= github.com/piprate/json-gold v0.5.1-0.20230111113000-6ddbe6e6f19f h1:HlPa7RcxTCrva5izPfTEfvYecO7LTahgmMRD1Qp13xg= github.com/piprate/json-gold v0.5.1-0.20230111113000-6ddbe6e6f19f/go.mod h1:WZ501QQMbZZ+3pXFPhQKzNwS1+jls0oqov3uQ2WasLs= +github.com/pkg/errors v0.8.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0= github.com/pkg/errors v0.9.1 h1:FEBLx1zS214owpjy7qsBeixbURkuhQAwrK5UwLGTwt4= github.com/pkg/errors v0.9.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0= +github.com/pkg/sftp v1.10.1/go.mod h1:lYOWFsE0bwd1+KfKJaKeuokY15vzFx25BLbzYYoAxZI= github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4= github.com/pmezard/go-difflib v1.0.1-0.20181226105442-5d4384ee4fb2 h1:Jamvg5psRIccs7FGNTlIRMkT8wgtp5eCXdBlqhYGL6U= github.com/pmezard/go-difflib v1.0.1-0.20181226105442-5d4384ee4fb2/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4= github.com/polydawn/refmt v0.89.0 h1:ADJTApkvkeBZsN0tBTx8QjpD9JkmxbKp0cxfr9qszm4= github.com/polydawn/refmt v0.89.0/go.mod h1:/zvteZs/GwLtCgZ4BL6CBsk9IKIlexP43ObX9AxTqTw= +github.com/posener/complete v1.1.1/go.mod h1:em0nMJCgc9GFtwrmVmEMR/ZL6WyhyjMBndrE9hABlRI= github.com/pquerna/cachecontrol v0.2.0 h1:vBXSNuE5MYP9IJ5kjsdo8uq+w41jSPgvba2DEnkRx9k= github.com/pquerna/cachecontrol v0.2.0/go.mod h1:NrUG3Z7Rdu85UNR3vm7SOsl1nFIeSiQnrHV5K9mBcUI= +github.com/prometheus/client_model v0.0.0-20190812154241-14fe0d1b01d4/go.mod h1:xMI15A0UPsDsEKsMN9yxemIoYk6Tm2C1GtYGdfGttqA= +github.com/rogpeppe/fastuuid v1.2.0/go.mod h1:jVj6XXZzXRy/MSR5jhDC/2q6DgLz+nrA6LYCDYWNEvQ= +github.com/rogpeppe/go-internal v1.3.0/go.mod h1:M8bDsm7K2OlrFYOpmOWEs/qY81heoFRclV5y23lUDJ4= github.com/rogpeppe/go-internal v1.11.0 h1:cWPaGQEPrBb5/AsnsZesgZZ9yb1OQ+GOISoDNXVBh4M= github.com/rogpeppe/go-internal v1.11.0/go.mod h1:ddIwULY96R17DhadqLgMfk9H9tvdUzkipdSkR5nkCZA= github.com/russross/blackfriday/v2 v2.0.1/go.mod h1:+Rmxgy9KzJVeS9/2gXHxylqXiyQDYRxCVz55jmeOWTM= github.com/russross/blackfriday/v2 v2.1.0 h1:JIOH55/0cWyOuilr9/qlrm0BSXldqnqwMsf35Ld67mk= github.com/russross/blackfriday/v2 v2.1.0/go.mod h1:+Rmxgy9KzJVeS9/2gXHxylqXiyQDYRxCVz55jmeOWTM= +github.com/ryanuber/columnize v0.0.0-20160712163229-9b3edd62028f/go.mod h1:sm1tb6uqfes/u+d4ooFouqFdy9/2g9QGwK3SQygK0Ts= +github.com/sean-/seed v0.0.0-20170313163322-e2103e2c3529/go.mod h1:DxrIzT+xaE7yg65j358z/aeFdxmN0P9QXhEzd20vsDc= +github.com/segmentio/asm v1.2.0 h1:9BQrFxC+YOHJlTlHGkTrFWf59nbL3XnCoFLTwDCI7ys= +github.com/segmentio/asm v1.2.0/go.mod h1:BqMnlJP91P8d+4ibuonYZw9mfnzI9HfxselHZr5aAcs= +github.com/shurcooL/go v0.0.0-20200502201357-93f07166e636/go.mod h1:TDJrrUr11Vxrven61rcy3hJMUqaf/CLWYhHNPmT14Lk= +github.com/shurcooL/httpfs v0.0.0-20190707220628-8d4bc4ba7749/go.mod h1:ZY1cvUeJuFPAdZ/B6v7RHavJWZn2YPVFQ1OSXhCGOkg= github.com/shurcooL/sanitized_anchor_name v1.0.0/go.mod h1:1NzhyTcUVG4SuEtjjoZeVRXNmyL/1OwPU0+IJeTBvfc= +github.com/shurcooL/vfsgen v0.0.0-20200824052919-0d455de96546/go.mod h1:TrYk7fJVaAttu97ZZKrO9UbRa8izdowaMIZcxYMbVaw= +github.com/sirupsen/logrus v1.8.1/go.mod h1:yWOB1SBYBC5VeMP7gHvWumXLIWorT60ONWic61uBYv0= +github.com/smarty/assertions v1.15.0/go.mod h1:yABtdzeQs6l1brC900WlRNwj6ZR55d7B+E8C6HtKdec= +github.com/smartystreets/assertions v0.0.0-20180927180507-b2de0cb4f26d/go.mod h1:OnSkiWE9lh6wB0YB77sQom3nweQdgAjqCqsofrRNTgc= github.com/smartystreets/assertions v1.2.0 h1:42S6lae5dvLc7BrLu/0ugRtcFVjoJNMC/N3yZFZkDFs= github.com/smartystreets/assertions v1.2.0/go.mod h1:tcbTF8ujkAEcZ8TElKY+i30BzYlVhC/LOxJk7iOWnoo= +github.com/smartystreets/goconvey v1.6.4/go.mod h1:syvi0/a8iFYH4r/RixwvyeAJjdLS9QV7WQ/tjFTllLA= github.com/smartystreets/goconvey v1.7.2 h1:9RBaZCeXEQ3UselpuwUQHltGVXvdwm6cv1hgR6gDIPg= github.com/smartystreets/goconvey v1.7.2/go.mod h1:Vw0tHAZW6lzCRk3xgdin6fKYcG+G3Pg9vgXWeJpQFMM= +github.com/smartystreets/goconvey v1.8.1 h1:qGjIddxOk4grTu9JPOU31tVfq3cNdBlNa5sSznIX1xY= +github.com/smartystreets/goconvey v1.8.1/go.mod h1:+/u4qLyY6x1jReYOp7GOM2FSt8aP9CzCZL03bI28W60= github.com/spaolacci/murmur3 v1.1.0 h1:7c1g84S4BPRrfL5Xrdp6fOJ206sU9y293DDHaoy0bLI= github.com/spaolacci/murmur3 v1.1.0/go.mod h1:JwIasOWyU6f++ZhiEuf87xNszmSA2myDM2Kzu9HwQUA= +github.com/spf13/afero v1.6.0/go.mod h1:Ai8FlHk4v/PARR026UzYexafAt9roJ7LcLMAmO6Z93I= +github.com/spf13/cast v1.3.1/go.mod h1:Qx5cxh0v+4UWYiBimWS+eyWzqEqokIECu5etghLkUJE= +github.com/spf13/cobra v1.2.1/go.mod h1:ExllRjgxM/piMAM+3tAZvg8fsklGAf3tPfi+i8t68Nk= +github.com/spf13/jwalterweatherman v1.1.0/go.mod h1:aNWZUN0dPAAO/Ljvb5BEdw96iTZ0EXowPYD95IqWIGo= +github.com/spf13/pflag v1.0.5/go.mod h1:McXfInJRrz4CZXVZOBLb0bTZqETkiAhM9Iw0y3An2Bg= +github.com/spf13/viper v1.8.1/go.mod h1:o0Pch8wJ9BVSWGQMbra6iw0oQ5oktSIBaujf1rJH9Ns= github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME= github.com/stretchr/objx v0.4.0/go.mod h1:YvHI0jy2hoMjB+UWwv71VJQ9isScKT/TqJzVSSt89Yw= github.com/stretchr/objx v0.5.0/go.mod h1:Yh+to48EsGEfYuaHDzXPcE3xhTkx73EhmCGUpEOglKo= +github.com/stretchr/testify v1.2.2/go.mod h1:a8OnRcib4nhh0OaRAV+Yts87kKdq0PP7pXfy6kDkUVs= github.com/stretchr/testify v1.3.0/go.mod h1:M5WIy9Dh21IEIfnGCwXGc5bZfKNJtfHm1UVUgZn+9EI= +github.com/stretchr/testify v1.4.0/go.mod h1:j7eGeouHqKxXV5pUuKE4zz7dFj8WfuZ+81PSLYec5m4= +github.com/stretchr/testify v1.5.1/go.mod h1:5W2xD1RspED5o8YsWQXVCued0rvSQ+mT+I5cxcmMvtA= github.com/stretchr/testify v1.6.1/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg= github.com/stretchr/testify v1.7.0/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg= github.com/stretchr/testify v1.7.1/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg= @@ -207,6 +442,7 @@ github.com/stretchr/testify v1.8.0/go.mod h1:yNjHg4UonilssWZ8iaSj1OCr/vHnekPRkoO github.com/stretchr/testify v1.8.4/go.mod h1:sz/lmYIOXD/1dqDmKjjqLyZ2RngseejIcXlSw2iwfAo= github.com/stretchr/testify v1.10.0 h1:Xv5erBjTwe/5IxqUQTdXv5kgmIvbHo3QQyRwhJsOfJA= github.com/stretchr/testify v1.10.0/go.mod h1:r2ic/lqez/lEtzL7wO/rwa5dbSLXVDPFyf8C91i36aY= +github.com/subosito/gotenv v1.2.0/go.mod h1:N0PQaV/YGNqwC0u51sEeR/aUtSLEXKX9iv69rRypqCw= github.com/syndtr/goleveldb v1.0.1-0.20210819022825-2ae1ddf74ef7/go.mod h1:q4W45IWZaF22tdD+VEXcAWRA037jwmWEB5VWYORlTpc= github.com/teserakt-io/golang-ed25519 v0.0.0-20210104091850-3888c087a4c8 h1:RBkacARv7qY5laaXGlF4wFB/tk5rnthhPb8oIBGoagY= github.com/teserakt-io/golang-ed25519 v0.0.0-20210104091850-3888c087a4c8/go.mod h1:9PdLyPiZIiW3UopXyRnPYyjUXSpiQNHRLu8fOsR3o8M= @@ -234,98 +470,429 @@ github.com/xeipuuv/gojsonschema v1.2.0 h1:LhYJRs+L4fBtjZUfuSZIKGeVu0QRy8e5Xi7D17 github.com/xeipuuv/gojsonschema v1.2.0/go.mod h1:anYRn/JVcOK2ZgGU+IjEV4nwlhoK5sQluxsYJ78Id3Y= github.com/xrash/smetrics v0.0.0-20240521201337-686a1a2994c1 h1:gEOO8jv9F4OT7lGCjxCBTO/36wtF6j2nSip77qHd4x4= github.com/xrash/smetrics v0.0.0-20240521201337-686a1a2994c1/go.mod h1:Ohn+xnUBiLI6FVj/9LpzZWtj1/D6lUovWYBkxHVV3aM= +github.com/yuin/goldmark v1.1.25/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74= +github.com/yuin/goldmark v1.1.27/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74= +github.com/yuin/goldmark v1.1.32/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74= +github.com/yuin/goldmark v1.2.1/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74= +github.com/yuin/goldmark v1.3.5/go.mod h1:mwnBkeHKe2W/ZEtQ+71ViKU8L12m81fl3OWwC1Zlc8k= github.com/yuin/goldmark v1.4.13/go.mod h1:6yULJ656Px+3vBD8DxQVa3kxgyrAnzto9xy5taEt/CY= +go.etcd.io/etcd/api/v3 v3.5.0/go.mod h1:cbVKeC6lCfl7j/8jBhAK6aIYO9XOjdptoxU/nLQcPvs= +go.etcd.io/etcd/client/pkg/v3 v3.5.0/go.mod h1:IJHfcCEKxYu1Os13ZdwCwIUTUVGYTSAM3YSwc9/Ac1g= +go.etcd.io/etcd/client/v2 v2.305.0/go.mod h1:h9puh54ZTgAKtEbut2oe9P4L/oqKCVB6xsXlzd7alYQ= +go.opencensus.io v0.21.0/go.mod h1:mSImk1erAIZhrmZN+AvHh14ztQfjbGwt4TtuofqLduU= +go.opencensus.io v0.22.0/go.mod h1:+kGneAE2xo2IficOXnaByMWTGM9T73dGwxeWcUqIpI8= +go.opencensus.io v0.22.2/go.mod h1:yxeiOL68Rb0Xd1ddK5vPZ/oVn4vY4Ynel7k9FzqtOIw= +go.opencensus.io v0.22.3/go.mod h1:yxeiOL68Rb0Xd1ddK5vPZ/oVn4vY4Ynel7k9FzqtOIw= +go.opencensus.io v0.22.4/go.mod h1:yxeiOL68Rb0Xd1ddK5vPZ/oVn4vY4Ynel7k9FzqtOIw= +go.opencensus.io v0.22.5/go.mod h1:5pWMHQbX5EPX2/62yrJeAkowc+lfs/XD7Uxpq3pI6kk= +go.opencensus.io v0.23.0/go.mod h1:XItmlyltB5F7CS4xOC1DcqMoFqwtC6OG2xF7mCv7P7E= +go.uber.org/atomic v1.7.0/go.mod h1:fEN4uk6kAWBTFdckzkM89CLk9XfWZrxpCo0nPH17wJc= go.uber.org/goleak v1.3.0 h1:2K3zAYmnTNqV73imy9J1T3WC+gmCePx2hEGkimedGto= go.uber.org/goleak v1.3.0/go.mod h1:CoHD4mav9JJNrW/WLlf7HGZPjdw8EucARQHekz1X6bE= +go.uber.org/multierr v1.6.0/go.mod h1:cdWPpRnG4AhwMwsgIHip0KRBQjJy5kYEpYjJxpXp9iU= +go.uber.org/zap v1.17.0/go.mod h1:MXVU+bhUf/A7Xi2HNOnopQOrmycQ5Ih87HtOu4q5SSo= golang.org/x/crypto v0.0.0-20170930174604-9419663f5a44/go.mod h1:6SG95UA2DQfeDnfUPMdvaQW0Q7yPrPDi9nlGo2tz2b4= +golang.org/x/crypto v0.0.0-20181029021203-45a5f77698d3/go.mod h1:6SG95UA2DQfeDnfUPMdvaQW0Q7yPrPDi9nlGo2tz2b4= golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w= +golang.org/x/crypto v0.0.0-20190510104115-cbcb75029529/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI= +golang.org/x/crypto v0.0.0-20190605123033-f99c8df09eb5/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI= +golang.org/x/crypto v0.0.0-20190820162420-60c769a6c586/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI= +golang.org/x/crypto v0.0.0-20191011191535-87dc89f01550/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI= golang.org/x/crypto v0.0.0-20200115085410-6d4e4cb37c7d/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto= golang.org/x/crypto v0.0.0-20200302210943-78000ba7a073/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto= golang.org/x/crypto v0.0.0-20200622213623-75b288015ac9/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto= +golang.org/x/crypto v0.0.0-20210711020723-a769d52b0f97/go.mod h1:GvvjBRRGRdwPK5ydBHafDWAxML/pGHZbMvKqRZ5+Abc= golang.org/x/crypto v0.0.0-20210921155107-089bfa567519/go.mod h1:GvvjBRRGRdwPK5ydBHafDWAxML/pGHZbMvKqRZ5+Abc= golang.org/x/crypto v0.19.0/go.mod h1:Iy9bg/ha4yyC70EfRS8jz+B6ybOBKMaSxLj6P6oBDfU= golang.org/x/crypto v0.37.0 h1:kJNSjF/Xp7kU0iB2Z+9viTPMW4EqqsrywMXLJOOsXSE= golang.org/x/crypto v0.37.0/go.mod h1:vg+k43peMZ0pUMhYmVAWysMK35e6ioLh3wB8ZCAfbVc= +golang.org/x/crypto v0.39.0 h1:SHs+kF4LP+f+p14esP5jAoDpHU8Gu/v9lFRK6IT5imM= +golang.org/x/crypto v0.39.0/go.mod h1:L+Xg3Wf6HoL4Bn4238Z6ft6KfEpN0tJGo53AAPC632U= +golang.org/x/exp v0.0.0-20190121172915-509febef88a4/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA= +golang.org/x/exp v0.0.0-20190306152737-a1d7652674e8/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA= +golang.org/x/exp v0.0.0-20190510132918-efd6b22b2522/go.mod h1:ZjyILWgesfNpC6sMxTJOJm9Kp84zZh5NQWvqDGG3Qr8= +golang.org/x/exp v0.0.0-20190829153037-c13cbed26979/go.mod h1:86+5VVa7VpoJ4kLfm080zCjGlMRFzhUhsZKEZO7MGek= +golang.org/x/exp v0.0.0-20191030013958-a1ab85dbe136/go.mod h1:JXzH8nQsPlswgeRAPE3MuO9GYsAcnJvJ4vnMwN/5qkY= +golang.org/x/exp v0.0.0-20191129062945-2f5052295587/go.mod h1:2RIsYlXP63K8oxa1u096TMicItID8zy7Y6sNkU49FU4= +golang.org/x/exp v0.0.0-20191227195350-da58074b4299/go.mod h1:2RIsYlXP63K8oxa1u096TMicItID8zy7Y6sNkU49FU4= +golang.org/x/exp v0.0.0-20200119233911-0405dc783f0a/go.mod h1:2RIsYlXP63K8oxa1u096TMicItID8zy7Y6sNkU49FU4= +golang.org/x/exp v0.0.0-20200207192155-f17229e696bd/go.mod h1:J/WKrq2StrnmMY6+EHIKF9dgMWnmCNThgcyBT1FY9mM= +golang.org/x/exp v0.0.0-20200224162631-6cc2880d07d6/go.mod h1:3jZMyOhIsHpP37uCMkUooju7aAi5cS1Q23tOzKc+0MU= +golang.org/x/image v0.0.0-20190227222117-0694c2d4d067/go.mod h1:kZ7UVZpmo3dzQBMxlp+ypCbDeSB+sBbTgSJuh5dn5js= +golang.org/x/image v0.0.0-20190802002840-cff245a6509b/go.mod h1:FeLwcggjj3mMvU+oOTbSwawSJRM1uh48EjtB4UJZlP0= +golang.org/x/lint v0.0.0-20181026193005-c67002cb31c3/go.mod h1:UVdnD1Gm6xHRNCYTkRU2/jEulfH38KcIWyp/GAMgvoE= +golang.org/x/lint v0.0.0-20190227174305-5b3e6a55c961/go.mod h1:wehouNa3lNwaWXcvxsM5YxQ5yQlVC4a0KAMCusXpPoU= +golang.org/x/lint v0.0.0-20190301231843-5614ed5bae6f/go.mod h1:UVdnD1Gm6xHRNCYTkRU2/jEulfH38KcIWyp/GAMgvoE= +golang.org/x/lint v0.0.0-20190313153728-d0100b6bd8b3/go.mod h1:6SW0HCj/g11FgYtHlgUYUwCkIfeOF89ocIRzGO/8vkc= +golang.org/x/lint v0.0.0-20190409202823-959b441ac422/go.mod h1:6SW0HCj/g11FgYtHlgUYUwCkIfeOF89ocIRzGO/8vkc= +golang.org/x/lint v0.0.0-20190909230951-414d861bb4ac/go.mod h1:6SW0HCj/g11FgYtHlgUYUwCkIfeOF89ocIRzGO/8vkc= +golang.org/x/lint v0.0.0-20190930215403-16217165b5de/go.mod h1:6SW0HCj/g11FgYtHlgUYUwCkIfeOF89ocIRzGO/8vkc= +golang.org/x/lint v0.0.0-20191125180803-fdd1cda4f05f/go.mod h1:5qLYkcX4OjUUV8bRuDixDT3tpyyb+LUpUlRWLxfhWrs= +golang.org/x/lint v0.0.0-20200130185559-910be7a94367/go.mod h1:3xt1FjdF8hUf6vQPIChWIBhFzV8gjjsPE/fR3IyQdNY= +golang.org/x/lint v0.0.0-20200302205851-738671d3881b/go.mod h1:3xt1FjdF8hUf6vQPIChWIBhFzV8gjjsPE/fR3IyQdNY= +golang.org/x/lint v0.0.0-20201208152925-83fdc39ff7b5/go.mod h1:3xt1FjdF8hUf6vQPIChWIBhFzV8gjjsPE/fR3IyQdNY= +golang.org/x/lint v0.0.0-20210508222113-6edffad5e616/go.mod h1:3xt1FjdF8hUf6vQPIChWIBhFzV8gjjsPE/fR3IyQdNY= +golang.org/x/mobile v0.0.0-20190312151609-d3739f865fa6/go.mod h1:z+o9i4GpDbdi3rU15maQ/Ox0txvL9dWGYEHz965HBQE= +golang.org/x/mobile v0.0.0-20190719004257-d2bd2a29d028/go.mod h1:E/iHnbuqvinMTCcRqshq8CkpyQDoeVncDDYHnLhea+o= +golang.org/x/mod v0.0.0-20190513183733-4bf6d317e70e/go.mod h1:mXi4GBBbnImb6dmsKGUJ2LatrhH/nqhxcFungHvyanc= +golang.org/x/mod v0.1.0/go.mod h1:0QHyrYULN0/3qlju5TqG8bIK38QM8yzMo5ekMj3DlcY= +golang.org/x/mod v0.1.1-0.20191105210325-c90efee705ee/go.mod h1:QqPTAvyqsEbceGzBzNggFXnrqF1CaUcvgkdR5Ot7KZg= +golang.org/x/mod v0.1.1-0.20191107180719-034126e5016b/go.mod h1:QqPTAvyqsEbceGzBzNggFXnrqF1CaUcvgkdR5Ot7KZg= +golang.org/x/mod v0.2.0/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA= +golang.org/x/mod v0.3.0/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA= +golang.org/x/mod v0.4.0/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA= +golang.org/x/mod v0.4.1/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA= +golang.org/x/mod v0.4.2/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA= golang.org/x/mod v0.6.0-dev.0.20220419223038-86c51ed26bb4/go.mod h1:jJ57K6gSWd91VN4djpZkiMVwK6gcyfeH4XE8wZrZaV4= golang.org/x/mod v0.8.0/go.mod h1:iBbtSCu2XBx23ZKBPSOrRkjjQPZFPuis4dIYUhu/chs= +golang.org/x/mod v0.9.0/go.mod h1:iBbtSCu2XBx23ZKBPSOrRkjjQPZFPuis4dIYUhu/chs= golang.org/x/net v0.0.0-20180719180050-a680a1efc54d/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= +golang.org/x/net v0.0.0-20180724234803-3673e40ba225/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= +golang.org/x/net v0.0.0-20180826012351-8a410e7b638d/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= golang.org/x/net v0.0.0-20180906233101-161cd47e91fd/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= +golang.org/x/net v0.0.0-20181023162649-9b4f9f5ad519/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= +golang.org/x/net v0.0.0-20181201002055-351d144fa1fc/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= +golang.org/x/net v0.0.0-20190108225652-1e06a53dbb7e/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= +golang.org/x/net v0.0.0-20190213061140-3a22650c66bd/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= golang.org/x/net v0.0.0-20190311183353-d8887717615a/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg= golang.org/x/net v0.0.0-20190404232315-eb5bcb51f2a3/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg= +golang.org/x/net v0.0.0-20190501004415-9ce7a6920f09/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg= +golang.org/x/net v0.0.0-20190503192946-f4e77d36d62c/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg= +golang.org/x/net v0.0.0-20190603091049-60506f45cf65/go.mod h1:HSz+uSET+XFnRR8LxR5pz3Of3rY3CfYBVs4xY44aLks= golang.org/x/net v0.0.0-20190620200207-3b0461eec859/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= +golang.org/x/net v0.0.0-20190628185345-da137c7871d7/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= +golang.org/x/net v0.0.0-20190724013045-ca1201d0de80/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= +golang.org/x/net v0.0.0-20191209160850-c0dbc17a3553/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= +golang.org/x/net v0.0.0-20200114155413-6afb5195e5aa/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= +golang.org/x/net v0.0.0-20200202094626-16171245cfb2/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= +golang.org/x/net v0.0.0-20200222125558-5a598a2470a0/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= +golang.org/x/net v0.0.0-20200226121028-0de0cce0169b/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= +golang.org/x/net v0.0.0-20200301022130-244492dfa37a/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= +golang.org/x/net v0.0.0-20200324143707-d3edc9973b7e/go.mod h1:qpuaurCH72eLCgpAm/N6yyVIVM9cpaDIP3A8BGJEC5A= +golang.org/x/net v0.0.0-20200501053045-e0ff5e5a1de5/go.mod h1:qpuaurCH72eLCgpAm/N6yyVIVM9cpaDIP3A8BGJEC5A= +golang.org/x/net v0.0.0-20200506145744-7e3656a0809f/go.mod h1:qpuaurCH72eLCgpAm/N6yyVIVM9cpaDIP3A8BGJEC5A= +golang.org/x/net v0.0.0-20200513185701-a91f0712d120/go.mod h1:qpuaurCH72eLCgpAm/N6yyVIVM9cpaDIP3A8BGJEC5A= golang.org/x/net v0.0.0-20200520004742-59133d7f0dd7/go.mod h1:qpuaurCH72eLCgpAm/N6yyVIVM9cpaDIP3A8BGJEC5A= +golang.org/x/net v0.0.0-20200520182314-0ba52f642ac2/go.mod h1:qpuaurCH72eLCgpAm/N6yyVIVM9cpaDIP3A8BGJEC5A= +golang.org/x/net v0.0.0-20200625001655-4c5254603344/go.mod h1:/O7V0waA8r7cgGh81Ro3o1hOxt32SMVPicZroKQ2sZA= +golang.org/x/net v0.0.0-20200707034311-ab3426394381/go.mod h1:/O7V0waA8r7cgGh81Ro3o1hOxt32SMVPicZroKQ2sZA= golang.org/x/net v0.0.0-20200813134508-3edf25e44fcc/go.mod h1:/O7V0waA8r7cgGh81Ro3o1hOxt32SMVPicZroKQ2sZA= +golang.org/x/net v0.0.0-20200822124328-c89045814202/go.mod h1:/O7V0waA8r7cgGh81Ro3o1hOxt32SMVPicZroKQ2sZA= +golang.org/x/net v0.0.0-20201021035429-f5854403a974/go.mod h1:sp8m0HH+o8qH0wwXwYZr8TS3Oi6o0r6Gce1SSxlDquU= +golang.org/x/net v0.0.0-20201031054903-ff519b6c9102/go.mod h1:sp8m0HH+o8qH0wwXwYZr8TS3Oi6o0r6Gce1SSxlDquU= +golang.org/x/net v0.0.0-20201110031124-69a78807bb2b/go.mod h1:sp8m0HH+o8qH0wwXwYZr8TS3Oi6o0r6Gce1SSxlDquU= +golang.org/x/net v0.0.0-20201209123823-ac852fbbde11/go.mod h1:m0MpNAwzfU5UDzcl9v0D8zg8gWTRqZa9RBIspLL5mdg= +golang.org/x/net v0.0.0-20210119194325-5f4716e94777/go.mod h1:m0MpNAwzfU5UDzcl9v0D8zg8gWTRqZa9RBIspLL5mdg= golang.org/x/net v0.0.0-20210226172049-e18ecbb05110/go.mod h1:m0MpNAwzfU5UDzcl9v0D8zg8gWTRqZa9RBIspLL5mdg= +golang.org/x/net v0.0.0-20210316092652-d523dce5a7f4/go.mod h1:RBQZq4jEuRlivfhVLdyRGr576XBO4/greRjx4P4O3yc= +golang.org/x/net v0.0.0-20210405180319-a5a99cb37ef4/go.mod h1:p54w0d4576C0XHj96bSt6lcn1PtDYWL6XObtHCRCNQM= golang.org/x/net v0.0.0-20220722155237-a158d28d115b/go.mod h1:XRhObCWvk6IyKnWLug+ECip1KBveYUHfp+8e9klMJ9c= golang.org/x/net v0.6.0/go.mod h1:2Tu9+aMcznHK/AK1HMvgo6xiTLG5rD5rZLDS+rp2Bjs= +golang.org/x/net v0.8.0/go.mod h1:QVkue5JL9kW//ek3r6jTKnTFis1tRmNAW2P1shuFdJc= golang.org/x/net v0.10.0/go.mod h1:0qNGK6F8kojg2nk9dLZ2mShWaEBan6FAoqfSigmmuDg= +golang.org/x/oauth2 v0.0.0-20180821212333-d2e6202438be/go.mod h1:N/0e6XlmueqKjAGxoOufVs8QHGRruUQn6yWY3a++T0U= +golang.org/x/oauth2 v0.0.0-20190226205417-e64efc72b421/go.mod h1:gOpvHmFTYa4IltrdGE7lF6nIHvwfUNPOp7c8zoXwtLw= +golang.org/x/oauth2 v0.0.0-20190604053449-0f29369cfe45/go.mod h1:gOpvHmFTYa4IltrdGE7lF6nIHvwfUNPOp7c8zoXwtLw= +golang.org/x/oauth2 v0.0.0-20191202225959-858c2ad4c8b6/go.mod h1:gOpvHmFTYa4IltrdGE7lF6nIHvwfUNPOp7c8zoXwtLw= +golang.org/x/oauth2 v0.0.0-20200107190931-bf48bf16ab8d/go.mod h1:gOpvHmFTYa4IltrdGE7lF6nIHvwfUNPOp7c8zoXwtLw= +golang.org/x/oauth2 v0.0.0-20200902213428-5d25da1a8d43/go.mod h1:KelEdhl1UZF7XfJ4dDtk6s++YSgaE7mD/BuKKDLBl4A= +golang.org/x/oauth2 v0.0.0-20201109201403-9fd604954f58/go.mod h1:KelEdhl1UZF7XfJ4dDtk6s++YSgaE7mD/BuKKDLBl4A= +golang.org/x/oauth2 v0.0.0-20201208152858-08078c50e5b5/go.mod h1:KelEdhl1UZF7XfJ4dDtk6s++YSgaE7mD/BuKKDLBl4A= +golang.org/x/oauth2 v0.0.0-20210218202405-ba52d332ba99/go.mod h1:KelEdhl1UZF7XfJ4dDtk6s++YSgaE7mD/BuKKDLBl4A= +golang.org/x/oauth2 v0.0.0-20210220000619-9bb904979d93/go.mod h1:KelEdhl1UZF7XfJ4dDtk6s++YSgaE7mD/BuKKDLBl4A= +golang.org/x/oauth2 v0.0.0-20210313182246-cd4f82c27b84/go.mod h1:KelEdhl1UZF7XfJ4dDtk6s++YSgaE7mD/BuKKDLBl4A= +golang.org/x/oauth2 v0.0.0-20210402161424-2e8d93401602/go.mod h1:KelEdhl1UZF7XfJ4dDtk6s++YSgaE7mD/BuKKDLBl4A= golang.org/x/sync v0.0.0-20180314180146-1d60e4601c6f/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= +golang.org/x/sync v0.0.0-20181108010431-42b317875d0f/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= +golang.org/x/sync v0.0.0-20181221193216-37e7f081c4d4/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= +golang.org/x/sync v0.0.0-20190227155943-e225da77a7e6/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sync v0.0.0-20190423024810-112230192c58/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= +golang.org/x/sync v0.0.0-20190911185100-cd5d95a43a6e/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= +golang.org/x/sync v0.0.0-20200317015054-43a5402ce75a/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= +golang.org/x/sync v0.0.0-20200625203802-6e8e738ad208/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= +golang.org/x/sync v0.0.0-20201020160332-67f06af15bc9/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= +golang.org/x/sync v0.0.0-20201207232520-09787c993a3a/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= +golang.org/x/sync v0.0.0-20210220032951-036812b2e83c/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sync v0.0.0-20220722155255-886fb9371eb4/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sync v0.1.0/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= +golang.org/x/sys v0.0.0-20180823144017-11551d06cbcc/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= +golang.org/x/sys v0.0.0-20180830151530-49385e6e1522/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= golang.org/x/sys v0.0.0-20180909124046-d0be0721c37e/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= +golang.org/x/sys v0.0.0-20181026203630-95b1ffbd15a5/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= +golang.org/x/sys v0.0.0-20190312061237-fead79001313/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20190412213103-97732733099d/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20190502145724-3ef323f4f1fd/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20190507160741-ecd444e8653b/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20190606165138-5da285871e9c/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20190624142023-c5567b49c5d0/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20190726091711-fc99dfbffb4e/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20190904154756-749cb33beabd/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20191001151750-bb3f8db39f24/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20191005200804-aed5e4c7ecf9/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20191026070338-33540a1f6037/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20191120155948-bd437916bb0e/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20191204072324-ce4227a45e2e/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20191228213918-04cbcbbfeed8/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20200113162924-86b910548bc1/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20200122134326-e047566fdf82/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20200202164722-d101bd2416d5/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20200212091648-12a6c2dcc1e4/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20200223170610-d5e6a3e2c0ae/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20200302150141-5c8b2ff67527/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20200323222414-85ca7c5b95cd/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20200331124033-c3d80250170d/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20200501052902-10377860bb8e/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20200511232937-7e40ca221e25/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20200515095857-1151b9dac4a9/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20200519105757-fe76b779f299/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20200523222454-059865788121/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20200803210538-64077c9b5642/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20200814200057-3d37ad5750ed/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20200905004654-be1d3432aa8f/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20200930185726-fdedc70b468f/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20201119102817-f84b799fce68/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20201201145000-ef89a241ccb3/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20210104204734-6f8348627aad/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20210119212857-b64e53b001e4/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20210124154548-22da62e12c0c/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20210220050731-9a76102bfb43/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20210305230114-8fe3ee5dd75b/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20210315160823-c6e025ad8005/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20210320140829-1e4c9ba3b0c4/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20210330210617-4fbd30eecc44/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20210403161142-5e06dd20ab57/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20210510120138-977fb7262007/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.0.0-20210615035016-665e8c7367d1/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.0.0-20210630005230-0f9fa26af87c/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.0.0-20220520151302-bc2c85ada10a/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.0.0-20220704084225-05e143d24a9e/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.0.0-20220722155257-8c9f86f7a55f/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.5.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.6.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.8.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.17.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA= golang.org/x/sys v0.32.0 h1:s77OFDvIQeibCmezSnk/q6iAfkdiQaJi4VzroCFrN20= golang.org/x/sys v0.32.0/go.mod h1:BJP2sWEmIv4KK5OTEluFJCKSidICx8ciO85XgH3Ak8k= +golang.org/x/sys v0.33.0 h1:q3i8TbbEz+JRD9ywIRlyRAQbM0qF7hu24q3teo2hbuw= +golang.org/x/sys v0.33.0/go.mod h1:BJP2sWEmIv4KK5OTEluFJCKSidICx8ciO85XgH3Ak8k= golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo= golang.org/x/term v0.0.0-20210927222741-03fcf44c2211/go.mod h1:jbD1KX2456YbFQfuXm/mYQcufACuNUgVhRMnK/tPxf8= golang.org/x/term v0.5.0/go.mod h1:jMB1sMXY+tzblOD4FWmEbocvup2/aLOaQEp7JmGp78k= +golang.org/x/term v0.6.0/go.mod h1:m6U89DPEgQRMq3DNkDClhWw02AUbt2daBVO4cn4Hv9U= golang.org/x/term v0.8.0/go.mod h1:xPskH00ivmX89bAKVGSKKtLOWNx2+17Eiy94tnKShWo= golang.org/x/term v0.17.0/go.mod h1:lLRBjIVuehSbZlaOtGMbcMncT+aqLLLmKrsjNrUguwk= +golang.org/x/text v0.0.0-20170915032832-14c0d48ead0c/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= +golang.org/x/text v0.3.1-0.20180807135948-17ff2d5776d2/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= golang.org/x/text v0.3.2/go.mod h1:bEr9sfX3Q8Zfm5fL9x+3itogRgK3+ptLWKqgva+5dAk= golang.org/x/text v0.3.3/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ= +golang.org/x/text v0.3.4/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ= +golang.org/x/text v0.3.5/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ= golang.org/x/text v0.3.7/go.mod h1:u+2+/6zg+i71rQMx5EYifcz6MCKuco9NR6JIITiCfzQ= golang.org/x/text v0.7.0/go.mod h1:mrYo+phRRbMaCq/xk9113O4dZlRixOauAjOtrjsXDZ8= +golang.org/x/text v0.8.0/go.mod h1:e1OnstbJyHTd6l/uOt8jFFHp6TRDWZR/bV3emEE/zU8= golang.org/x/text v0.9.0/go.mod h1:e1OnstbJyHTd6l/uOt8jFFHp6TRDWZR/bV3emEE/zU8= golang.org/x/text v0.14.0/go.mod h1:18ZOQIKpY8NJVqYksKHtTdi31H5itFRjB5/qKTNYzSU= +golang.org/x/time v0.0.0-20181108054448-85acf8d2951c/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ= +golang.org/x/time v0.0.0-20190308202827-9d24e82272b4/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ= +golang.org/x/time v0.0.0-20191024005414-555d28b269f0/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ= golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= +golang.org/x/tools v0.0.0-20190114222345-bf090417da8b/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= +golang.org/x/tools v0.0.0-20190226205152-f727befe758c/go.mod h1:9Yl7xja0Znq3iFh3HoIrodX9oNMXvdceNzlUR8zjMvY= +golang.org/x/tools v0.0.0-20190311212946-11955173bddd/go.mod h1:LCzVGOaR6xXOjkQ3onu1FJEFr0SW1gC7cKk1uF8kGRs= +golang.org/x/tools v0.0.0-20190312151545-0bb0c0a6e846/go.mod h1:LCzVGOaR6xXOjkQ3onu1FJEFr0SW1gC7cKk1uF8kGRs= +golang.org/x/tools v0.0.0-20190312170243-e65039ee4138/go.mod h1:LCzVGOaR6xXOjkQ3onu1FJEFr0SW1gC7cKk1uF8kGRs= golang.org/x/tools v0.0.0-20190328211700-ab21143f2384/go.mod h1:LCzVGOaR6xXOjkQ3onu1FJEFr0SW1gC7cKk1uF8kGRs= +golang.org/x/tools v0.0.0-20190425150028-36563e24a262/go.mod h1:RgjU9mgBXZiqYHBnxXauZ1Gv1EHHAz9KjViQ78xBX0Q= +golang.org/x/tools v0.0.0-20190506145303-2d16b83fe98c/go.mod h1:RgjU9mgBXZiqYHBnxXauZ1Gv1EHHAz9KjViQ78xBX0Q= +golang.org/x/tools v0.0.0-20190524140312-2c0ae7006135/go.mod h1:RgjU9mgBXZiqYHBnxXauZ1Gv1EHHAz9KjViQ78xBX0Q= +golang.org/x/tools v0.0.0-20190606124116-d0a3d012864b/go.mod h1:/rFqwRUd4F7ZHNgwSSTFct+R/Kf4OFW1sUzUTQQTgfc= +golang.org/x/tools v0.0.0-20190621195816-6e04913cbbac/go.mod h1:/rFqwRUd4F7ZHNgwSSTFct+R/Kf4OFW1sUzUTQQTgfc= +golang.org/x/tools v0.0.0-20190628153133-6cdbf07be9d0/go.mod h1:/rFqwRUd4F7ZHNgwSSTFct+R/Kf4OFW1sUzUTQQTgfc= +golang.org/x/tools v0.0.0-20190816200558-6889da9d5479/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= +golang.org/x/tools v0.0.0-20190911174233-4f2ddba30aff/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= +golang.org/x/tools v0.0.0-20191012152004-8de300cfc20a/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= +golang.org/x/tools v0.0.0-20191112195655-aa38f8e97acc/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= +golang.org/x/tools v0.0.0-20191113191852-77e3bb0ad9e7/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= +golang.org/x/tools v0.0.0-20191115202509-3a792d9c32b2/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= golang.org/x/tools v0.0.0-20191119224855-298f0cb1881e/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= +golang.org/x/tools v0.0.0-20191125144606-a911d9008d1f/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= +golang.org/x/tools v0.0.0-20191130070609-6e064ea0cf2d/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= +golang.org/x/tools v0.0.0-20191216173652-a0e659d51361/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28= +golang.org/x/tools v0.0.0-20191227053925-7b8e75db28f4/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28= +golang.org/x/tools v0.0.0-20200117161641-43d50277825c/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28= +golang.org/x/tools v0.0.0-20200122220014-bf1340f18c4a/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28= +golang.org/x/tools v0.0.0-20200130002326-2f3ba24bd6e7/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28= +golang.org/x/tools v0.0.0-20200204074204-1cc6d1ef6c74/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28= +golang.org/x/tools v0.0.0-20200207183749-b753a1ba74fa/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28= +golang.org/x/tools v0.0.0-20200212150539-ea181f53ac56/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28= +golang.org/x/tools v0.0.0-20200224181240-023911ca70b2/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28= +golang.org/x/tools v0.0.0-20200227222343-706bc42d1f0d/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28= +golang.org/x/tools v0.0.0-20200304193943-95d2e580d8eb/go.mod h1:o4KQGtdN14AW+yjsvvwRTJJuXz8XRtIHtEnmAXLyFUw= +golang.org/x/tools v0.0.0-20200312045724-11d5b4c81c7d/go.mod h1:o4KQGtdN14AW+yjsvvwRTJJuXz8XRtIHtEnmAXLyFUw= +golang.org/x/tools v0.0.0-20200331025713-a30bf2db82d4/go.mod h1:Sl4aGygMT6LrqrWclx+PTx3U+LnKx/seiNR+3G19Ar8= +golang.org/x/tools v0.0.0-20200501065659-ab2804fb9c9d/go.mod h1:EkVYQZoAsY45+roYkvgYkIh4xh/qjgUK9TdY2XT94GE= +golang.org/x/tools v0.0.0-20200512131952-2bc93b1c0c88/go.mod h1:EkVYQZoAsY45+roYkvgYkIh4xh/qjgUK9TdY2XT94GE= +golang.org/x/tools v0.0.0-20200515010526-7d3b6ebf133d/go.mod h1:EkVYQZoAsY45+roYkvgYkIh4xh/qjgUK9TdY2XT94GE= +golang.org/x/tools v0.0.0-20200618134242-20370b0cb4b2/go.mod h1:EkVYQZoAsY45+roYkvgYkIh4xh/qjgUK9TdY2XT94GE= +golang.org/x/tools v0.0.0-20200619180055-7c47624df98f/go.mod h1:EkVYQZoAsY45+roYkvgYkIh4xh/qjgUK9TdY2XT94GE= +golang.org/x/tools v0.0.0-20200729194436-6467de6f59a7/go.mod h1:njjCfa9FT2d7l9Bc6FUM5FLjQPp3cFF28FI3qnDFljA= +golang.org/x/tools v0.0.0-20200804011535-6c149bb5ef0d/go.mod h1:njjCfa9FT2d7l9Bc6FUM5FLjQPp3cFF28FI3qnDFljA= +golang.org/x/tools v0.0.0-20200825202427-b303f430e36d/go.mod h1:njjCfa9FT2d7l9Bc6FUM5FLjQPp3cFF28FI3qnDFljA= +golang.org/x/tools v0.0.0-20200904185747-39188db58858/go.mod h1:Cj7w3i3Rnn0Xh82ur9kSqwfTHTeVxaDqrfMjpcNT6bE= +golang.org/x/tools v0.0.0-20201110124207-079ba7bd75cd/go.mod h1:emZCQorbCU4vsT4fOWvOPXz4eW1wZW4PmDk9uLelYpA= +golang.org/x/tools v0.0.0-20201201161351-ac6f37ff4c2a/go.mod h1:emZCQorbCU4vsT4fOWvOPXz4eW1wZW4PmDk9uLelYpA= +golang.org/x/tools v0.0.0-20201208233053-a543418bbed2/go.mod h1:emZCQorbCU4vsT4fOWvOPXz4eW1wZW4PmDk9uLelYpA= +golang.org/x/tools v0.0.0-20210105154028-b0ab187a4818/go.mod h1:emZCQorbCU4vsT4fOWvOPXz4eW1wZW4PmDk9uLelYpA= +golang.org/x/tools v0.0.0-20210106214847-113979e3529a/go.mod h1:emZCQorbCU4vsT4fOWvOPXz4eW1wZW4PmDk9uLelYpA= +golang.org/x/tools v0.1.0/go.mod h1:xkSsbof2nBLbhDlRMhhhyNLN/zl3eTqcnHD5viDpcZ0= +golang.org/x/tools v0.1.2/go.mod h1:o0xws9oXOQQZyjljx8fwUC0k7L1pTE6eaCbjGeHmOkk= +golang.org/x/tools v0.1.5/go.mod h1:o0xws9oXOQQZyjljx8fwUC0k7L1pTE6eaCbjGeHmOkk= golang.org/x/tools v0.1.12/go.mod h1:hNGJHUnrk76NpqgfD5Aqm5Crs+Hm0VOH/i9J2+nxYbc= golang.org/x/tools v0.6.0/go.mod h1:Xwgl3UAJ/d3gWutnCtw505GrjyAbvKui8lOU390QaIU= +golang.org/x/tools v0.7.0/go.mod h1:4pg6aUX35JBAogB10C9AtvVL+qowtN4pT3CGSQex14s= golang.org/x/xerrors v0.0.0-20190717185122-a985d3407aa7/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= +golang.org/x/xerrors v0.0.0-20191011141410-1b5146add898/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= golang.org/x/xerrors v0.0.0-20200804184101-5ec99f83aff1/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= gonum.org/v1/gonum v0.16.0 h1:5+ul4Swaf3ESvrOnidPp4GZbzf0mxVQpDCYUQE7OJfk= gonum.org/v1/gonum v0.16.0/go.mod h1:fef3am4MQ93R2HHpKnLk4/Tbh/s0+wqD5nfa6Pnwy4E= +google.golang.org/api v0.4.0/go.mod h1:8k5glujaEP+g9n7WNsDg8QP6cUVNI86fCNMcbazEtwE= +google.golang.org/api v0.7.0/go.mod h1:WtwebWUNSVBH/HAw79HIFXZNqEvBhG+Ra+ax0hx3E3M= +google.golang.org/api v0.8.0/go.mod h1:o4eAsZoiT+ibD93RtjEohWalFOjRDx6CVaqeizhEnKg= +google.golang.org/api v0.9.0/go.mod h1:o4eAsZoiT+ibD93RtjEohWalFOjRDx6CVaqeizhEnKg= +google.golang.org/api v0.13.0/go.mod h1:iLdEw5Ide6rF15KTC1Kkl0iskquN2gFfn9o9XIsbkAI= +google.golang.org/api v0.14.0/go.mod h1:iLdEw5Ide6rF15KTC1Kkl0iskquN2gFfn9o9XIsbkAI= +google.golang.org/api v0.15.0/go.mod h1:iLdEw5Ide6rF15KTC1Kkl0iskquN2gFfn9o9XIsbkAI= +google.golang.org/api v0.17.0/go.mod h1:BwFmGc8tA3vsd7r/7kR8DY7iEEGSU04BFxCo5jP/sfE= +google.golang.org/api v0.18.0/go.mod h1:BwFmGc8tA3vsd7r/7kR8DY7iEEGSU04BFxCo5jP/sfE= +google.golang.org/api v0.19.0/go.mod h1:BwFmGc8tA3vsd7r/7kR8DY7iEEGSU04BFxCo5jP/sfE= +google.golang.org/api v0.20.0/go.mod h1:BwFmGc8tA3vsd7r/7kR8DY7iEEGSU04BFxCo5jP/sfE= +google.golang.org/api v0.22.0/go.mod h1:BwFmGc8tA3vsd7r/7kR8DY7iEEGSU04BFxCo5jP/sfE= +google.golang.org/api v0.24.0/go.mod h1:lIXQywCXRcnZPGlsd8NbLnOjtAoL6em04bJ9+z0MncE= +google.golang.org/api v0.28.0/go.mod h1:lIXQywCXRcnZPGlsd8NbLnOjtAoL6em04bJ9+z0MncE= +google.golang.org/api v0.29.0/go.mod h1:Lcubydp8VUV7KeIHD9z2Bys/sm/vGKnG1UHuDBSrHWM= +google.golang.org/api v0.30.0/go.mod h1:QGmEvQ87FHZNiUVJkT14jQNYJ4ZJjdRF23ZXz5138Fc= +google.golang.org/api v0.35.0/go.mod h1:/XrVsuzM0rZmrsbjJutiuftIzeuTQcEeaYcSk/mQ1dg= +google.golang.org/api v0.36.0/go.mod h1:+z5ficQTmoYpPn8LCUNVpK5I7hwkpjbcgqA7I34qYtE= +google.golang.org/api v0.40.0/go.mod h1:fYKFpnQN0DsDSKRVRcQSDQNtqWPfM9i+zNPxepjRCQ8= +google.golang.org/api v0.41.0/go.mod h1:RkxM5lITDfTzmyKFPt+wGrCJbVfniCr2ool8kTBzRTU= +google.golang.org/api v0.43.0/go.mod h1:nQsDGjRXMo4lvh5hP0TKqF244gqhGcr/YSIykhUk/94= +google.golang.org/api v0.44.0/go.mod h1:EBOGZqzyhtvMDoxwS97ctnh0zUmYY6CxqXsc1AvkYD8= +google.golang.org/appengine v1.1.0/go.mod h1:EbEs0AVv82hx2wNQdGPgUI5lhzA/G0D9YwlJXL52JkM= +google.golang.org/appengine v1.4.0/go.mod h1:xpcJRLb0r/rnEns0DIKYYv+WjYCduHsrkT7/EB5XEv4= +google.golang.org/appengine v1.5.0/go.mod h1:xpcJRLb0r/rnEns0DIKYYv+WjYCduHsrkT7/EB5XEv4= +google.golang.org/appengine v1.6.1/go.mod h1:i06prIuMbXzDqacNJfV5OdTW448YApPu5ww/cMBSeb0= +google.golang.org/appengine v1.6.5/go.mod h1:8WjMMxjGQR8xUklV/ARdw2HLXBOI7O7uCIDZVag1xfc= +google.golang.org/appengine v1.6.6/go.mod h1:8WjMMxjGQR8xUklV/ARdw2HLXBOI7O7uCIDZVag1xfc= +google.golang.org/appengine v1.6.7/go.mod h1:8WjMMxjGQR8xUklV/ARdw2HLXBOI7O7uCIDZVag1xfc= +google.golang.org/genproto v0.0.0-20180817151627-c66870c02cf8/go.mod h1:JiN7NxoALGmiZfu7CAH4rXhgtRTLTxftemlI0sWmxmc= +google.golang.org/genproto v0.0.0-20190307195333-5fe7a883aa19/go.mod h1:VzzqZJRnGkLBvHegQrXjBqPurQTc5/KpmUdxsrq26oE= +google.golang.org/genproto v0.0.0-20190418145605-e7d98fc518a7/go.mod h1:VzzqZJRnGkLBvHegQrXjBqPurQTc5/KpmUdxsrq26oE= +google.golang.org/genproto v0.0.0-20190425155659-357c62f0e4bb/go.mod h1:VzzqZJRnGkLBvHegQrXjBqPurQTc5/KpmUdxsrq26oE= +google.golang.org/genproto v0.0.0-20190502173448-54afdca5d873/go.mod h1:VzzqZJRnGkLBvHegQrXjBqPurQTc5/KpmUdxsrq26oE= +google.golang.org/genproto v0.0.0-20190801165951-fa694d86fc64/go.mod h1:DMBHOl98Agz4BDEuKkezgsaosCRResVns1a3J2ZsMNc= +google.golang.org/genproto v0.0.0-20190819201941-24fa4b261c55/go.mod h1:DMBHOl98Agz4BDEuKkezgsaosCRResVns1a3J2ZsMNc= +google.golang.org/genproto v0.0.0-20190911173649-1774047e7e51/go.mod h1:IbNlFCBrqXvoKpeg0TB2l7cyZUmoaFKYIwrEpbDKLA8= +google.golang.org/genproto v0.0.0-20191108220845-16a3f7862a1a/go.mod h1:n3cpQtvxv34hfy77yVDNjmbRyujviMdxYliBSkLhpCc= +google.golang.org/genproto v0.0.0-20191115194625-c23dd37a84c9/go.mod h1:n3cpQtvxv34hfy77yVDNjmbRyujviMdxYliBSkLhpCc= +google.golang.org/genproto v0.0.0-20191216164720-4f79533eabd1/go.mod h1:n3cpQtvxv34hfy77yVDNjmbRyujviMdxYliBSkLhpCc= +google.golang.org/genproto v0.0.0-20191230161307-f3c370f40bfb/go.mod h1:n3cpQtvxv34hfy77yVDNjmbRyujviMdxYliBSkLhpCc= +google.golang.org/genproto v0.0.0-20200115191322-ca5a22157cba/go.mod h1:n3cpQtvxv34hfy77yVDNjmbRyujviMdxYliBSkLhpCc= +google.golang.org/genproto v0.0.0-20200122232147-0452cf42e150/go.mod h1:n3cpQtvxv34hfy77yVDNjmbRyujviMdxYliBSkLhpCc= +google.golang.org/genproto v0.0.0-20200204135345-fa8e72b47b90/go.mod h1:GmwEX6Z4W5gMy59cAlVYjN9JhxgbQH6Gn+gFDQe2lzA= +google.golang.org/genproto v0.0.0-20200212174721-66ed5ce911ce/go.mod h1:55QSHmfGQM9UVYDPBsyGGes0y52j32PQ3BqQfXhyH3c= +google.golang.org/genproto v0.0.0-20200224152610-e50cd9704f63/go.mod h1:55QSHmfGQM9UVYDPBsyGGes0y52j32PQ3BqQfXhyH3c= +google.golang.org/genproto v0.0.0-20200228133532-8c2c7df3a383/go.mod h1:55QSHmfGQM9UVYDPBsyGGes0y52j32PQ3BqQfXhyH3c= +google.golang.org/genproto v0.0.0-20200305110556-506484158171/go.mod h1:55QSHmfGQM9UVYDPBsyGGes0y52j32PQ3BqQfXhyH3c= +google.golang.org/genproto v0.0.0-20200312145019-da6875a35672/go.mod h1:55QSHmfGQM9UVYDPBsyGGes0y52j32PQ3BqQfXhyH3c= +google.golang.org/genproto v0.0.0-20200331122359-1ee6d9798940/go.mod h1:55QSHmfGQM9UVYDPBsyGGes0y52j32PQ3BqQfXhyH3c= +google.golang.org/genproto v0.0.0-20200430143042-b979b6f78d84/go.mod h1:55QSHmfGQM9UVYDPBsyGGes0y52j32PQ3BqQfXhyH3c= +google.golang.org/genproto v0.0.0-20200511104702-f5ebc3bea380/go.mod h1:55QSHmfGQM9UVYDPBsyGGes0y52j32PQ3BqQfXhyH3c= +google.golang.org/genproto v0.0.0-20200513103714-09dca8ec2884/go.mod h1:55QSHmfGQM9UVYDPBsyGGes0y52j32PQ3BqQfXhyH3c= +google.golang.org/genproto v0.0.0-20200515170657-fc4c6c6a6587/go.mod h1:YsZOwe1myG/8QRHRsmBRE1LrgQY60beZKjly0O1fX9U= +google.golang.org/genproto v0.0.0-20200526211855-cb27e3aa2013/go.mod h1:NbSheEEYHJ7i3ixzK3sjbqSGDJWnxyFXZblF3eUsNvo= +google.golang.org/genproto v0.0.0-20200618031413-b414f8b61790/go.mod h1:jDfRM7FcilCzHH/e9qn6dsT145K34l5v+OpcnNgKAAA= +google.golang.org/genproto v0.0.0-20200729003335-053ba62fc06f/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no= +google.golang.org/genproto v0.0.0-20200804131852-c06518451d9c/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no= +google.golang.org/genproto v0.0.0-20200825200019-8632dd797987/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no= +google.golang.org/genproto v0.0.0-20200904004341-0bd0a958aa1d/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no= +google.golang.org/genproto v0.0.0-20201109203340-2640f1f9cdfb/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no= +google.golang.org/genproto v0.0.0-20201201144952-b05cb90ed32e/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no= +google.golang.org/genproto v0.0.0-20201210142538-e3217bee35cc/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no= +google.golang.org/genproto v0.0.0-20201214200347-8c77b98c765d/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no= +google.golang.org/genproto v0.0.0-20210222152913-aa3ee6e6a81c/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no= +google.golang.org/genproto v0.0.0-20210303154014-9728d6b83eeb/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no= +google.golang.org/genproto v0.0.0-20210310155132-4ce2db91004e/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no= +google.golang.org/genproto v0.0.0-20210319143718-93e7006c17a6/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no= +google.golang.org/genproto v0.0.0-20210402141018-6c239bbf2bb1/go.mod h1:9lPAdzaEmUacj36I+k7YKbEc5CXzPIeORRgDAUOu28A= +google.golang.org/genproto v0.0.0-20210602131652-f16073e35f0c/go.mod h1:UODoCrxHCcBojKKwX1terBiRUaqAsFqJiF615XL43r0= +google.golang.org/grpc v1.19.0/go.mod h1:mqu4LbDTu4XGKhr4mRzUsmM4RtVoemTSY81AxZiDr8c= +google.golang.org/grpc v1.20.1/go.mod h1:10oTOabMzJvdu6/UiuZezV6QK5dSlG84ov/aaiqXj38= +google.golang.org/grpc v1.21.1/go.mod h1:oYelfM1adQP15Ek0mdvEgi9Df8B9CZIaU1084ijfRaM= +google.golang.org/grpc v1.23.0/go.mod h1:Y5yQAOtifL1yxbo5wqy6BxZv8vAUGQwXBOALyacEbxg= +google.golang.org/grpc v1.25.1/go.mod h1:c3i+UQWmh7LiEpx4sFZnkU36qjEYZ0imhYfXVyQciAY= +google.golang.org/grpc v1.26.0/go.mod h1:qbnxyOmOxrQa7FizSgH+ReBfzJrCY1pSN7KXBS8abTk= +google.golang.org/grpc v1.27.0/go.mod h1:qbnxyOmOxrQa7FizSgH+ReBfzJrCY1pSN7KXBS8abTk= +google.golang.org/grpc v1.27.1/go.mod h1:qbnxyOmOxrQa7FizSgH+ReBfzJrCY1pSN7KXBS8abTk= +google.golang.org/grpc v1.28.0/go.mod h1:rpkK4SK4GF4Ach/+MFLZUBavHOvF2JJB5uozKKal+60= +google.golang.org/grpc v1.29.1/go.mod h1:itym6AZVZYACWQqET3MqgPpjcuV5QH3BxFS3IjizoKk= +google.golang.org/grpc v1.30.0/go.mod h1:N36X2cJ7JwdamYAgDz+s+rVMFjt3numwzf/HckM8pak= +google.golang.org/grpc v1.31.0/go.mod h1:N36X2cJ7JwdamYAgDz+s+rVMFjt3numwzf/HckM8pak= +google.golang.org/grpc v1.31.1/go.mod h1:N36X2cJ7JwdamYAgDz+s+rVMFjt3numwzf/HckM8pak= +google.golang.org/grpc v1.33.1/go.mod h1:fr5YgcSWrqhRRxogOsw7RzIpsmvOZ6IcH4kBYTpR3n0= +google.golang.org/grpc v1.33.2/go.mod h1:JMHMWHQWaTccqQQlmk3MJZS+GWXOdAesneDmEnv2fbc= +google.golang.org/grpc v1.34.0/go.mod h1:WotjhfgOW/POjDeRt8vscBtXq+2VjORFy659qA51WJ8= +google.golang.org/grpc v1.35.0/go.mod h1:qjiiYl8FncCW8feJPdyg3v6XW24KsRHe+dy9BAGRRjU= +google.golang.org/grpc v1.36.0/go.mod h1:qjiiYl8FncCW8feJPdyg3v6XW24KsRHe+dy9BAGRRjU= +google.golang.org/grpc v1.36.1/go.mod h1:qjiiYl8FncCW8feJPdyg3v6XW24KsRHe+dy9BAGRRjU= +google.golang.org/grpc v1.38.0/go.mod h1:NREThFqKR1f3iQ6oBuvc5LadQuXVGo9rkm5ZGrQdJfM= google.golang.org/protobuf v0.0.0-20200109180630-ec00e32a8dfd/go.mod h1:DFci5gLYBciE7Vtevhsrf46CRTquxDuWsQurQQe4oz8= google.golang.org/protobuf v0.0.0-20200221191635-4d8936d0db64/go.mod h1:kwYJMbMJ01Woi6D6+Kah6886xMZcty6N08ah7+eCXa0= google.golang.org/protobuf v0.0.0-20200228230310-ab0ca4ff8a60/go.mod h1:cfTl7dwQJ+fmap5saPgwCLgHXTUD7jkjRqWcaiX5VyM= google.golang.org/protobuf v1.20.1-0.20200309200217-e05f789c0967/go.mod h1:A+miEFZTKqfCUM6K7xSMQL9OKL/b6hQv+e19PK+JZNE= google.golang.org/protobuf v1.21.0/go.mod h1:47Nbq4nVaFHyn7ilMalzfO3qCViNmqZ2kzikPIcrTAo= +google.golang.org/protobuf v1.22.0/go.mod h1:EGpADcykh3NcUnDUJcl1+ZksZNG86OlYog2l/sGQquU= google.golang.org/protobuf v1.23.0/go.mod h1:EGpADcykh3NcUnDUJcl1+ZksZNG86OlYog2l/sGQquU= +google.golang.org/protobuf v1.23.1-0.20200526195155-81db48ad09cc/go.mod h1:EGpADcykh3NcUnDUJcl1+ZksZNG86OlYog2l/sGQquU= +google.golang.org/protobuf v1.24.0/go.mod h1:r/3tXBNzIEhYS9I1OUVjXDlt8tc493IdKGjtUeSXeh4= +google.golang.org/protobuf v1.25.0/go.mod h1:9JNX74DMeImyA3h4bdi1ymwjUzf21/xIlbajtzgsN7c= +google.golang.org/protobuf v1.26.0-rc.1/go.mod h1:jlhhOSvTdKEhbULTjvd4ARK9grFBp09yW+WbY/TyQbw= +google.golang.org/protobuf v1.26.0/go.mod h1:9q0QmTI4eRPtz6boOQmLYwt+qCgq0jsYwAQnmE0givc= google.golang.org/protobuf v1.36.3 h1:82DV7MYdb8anAVi3qge1wSnMDrnKK7ebr+I0hHRN1BU= google.golang.org/protobuf v1.36.3/go.mod h1:9fA7Ob0pmnwhb644+1+CVWFRbNajQ6iRojtC/QF5bRE= gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= +gopkg.in/check.v1 v1.0.0-20180628173108-788fd7840127/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= +gopkg.in/errgo.v2 v2.1.0/go.mod h1:hNsd1EY+bozCKY1Ytp96fpM3vjJbqLJn88ws8XvfDNI= gopkg.in/fsnotify.v1 v1.4.7/go.mod h1:Tz8NjZHkW78fSQdbUxIjBTcgA1z1m8ZHf0WmKUhAMys= +gopkg.in/ini.v1 v1.62.0/go.mod h1:pNLf8WUiyNEtQjuu5G5vTm06TEv9tsIgeAvK8hOrP4k= +gopkg.in/square/go-jose.v2 v2.6.0 h1:NGk74WTnPKBNUhNzQX7PYcTLUjoq7mzKk2OKbvwk2iI= +gopkg.in/square/go-jose.v2 v2.6.0/go.mod h1:M9dMgbHiYLoDGQrXy7OpJDJWiKiU//h+vD76mk0e1AI= gopkg.in/tomb.v1 v1.0.0-20141024135613-dd632973f1e7/go.mod h1:dt/ZhP58zS4L8KSrWDmTeBkI65Dw0HsyUHuEVlX15mw= gopkg.in/yaml.v2 v2.2.1/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= gopkg.in/yaml.v2 v2.2.2/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= +gopkg.in/yaml.v2 v2.2.3/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= gopkg.in/yaml.v2 v2.2.4/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= +gopkg.in/yaml.v2 v2.2.8/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= gopkg.in/yaml.v2 v2.3.0/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= gopkg.in/yaml.v2 v2.4.0 h1:D8xgwECY7CYvx+Y2n4sBz93Jn9JRvxdiyyo8CTfuKaY= gopkg.in/yaml.v2 v2.4.0/go.mod h1:RDklbk79AGWmwhnvt/jBztapEOGDOx6ZbXqjP6csGnQ= gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= +gopkg.in/yaml.v3 v3.0.0-20210107192922-496545a6307b/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= gopkg.in/yaml.v3 v3.0.1 h1:fxVm/GzAzEWqLHuvctI91KS9hhNmmWOoWu0XTYJS7CA= gopkg.in/yaml.v3 v3.0.1/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= +honnef.co/go/tools v0.0.0-20190102054323-c2f93a96b099/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4= +honnef.co/go/tools v0.0.0-20190106161140-3f1c8253044a/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4= +honnef.co/go/tools v0.0.0-20190418001031-e561f6794a2a/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4= +honnef.co/go/tools v0.0.0-20190523083050-ea95bdfd59fc/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4= +honnef.co/go/tools v0.0.1-2019.2.3/go.mod h1:a3bituU0lyd329TUQxRnasdCoJDkEUEAqEt0JzvZhAg= +honnef.co/go/tools v0.0.1-2020.1.3/go.mod h1:X/FiERA/W4tHapMX5mGpAtMSVEeEUOyHaw9vFzvIQ3k= +honnef.co/go/tools v0.0.1-2020.1.4/go.mod h1:X/FiERA/W4tHapMX5mGpAtMSVEeEUOyHaw9vFzvIQ3k= lukechampine.com/blake3 v1.1.7 h1:GgRMhmdsuK8+ii6UZFDL8Nb+VyMwadAgcJyfYHxG6n0= lukechampine.com/blake3 v1.1.7/go.mod h1:tkKEOtDkNtklkXtLNEOGNq5tcV90tJiA1vAA12R78LA= +rsc.io/binaryregexp v0.2.0/go.mod h1:qTv7/COck+e2FymRvadv62gMdZztPaShugOCi3I+8D8= +rsc.io/quote/v3 v3.1.0/go.mod h1:yEA65RcK8LyAZtP9Kv3t0HmxON59tX3rD+tICJqUlj0= +rsc.io/sampler v1.3.0/go.mod h1:T1hPZKmBbMNahiBKFy5HrXp6adAjACjK9JXDnKaTXpA= rsc.io/tmplfunc v0.0.3 h1:53XFQh69AfOa8Tw0Jm7t+GV7KZhOi6jzsCzTtKbMvzU= rsc.io/tmplfunc v0.0.3/go.mod h1:AG3sTPzElb1Io3Yg4voV9AGZJuleGAwaVRxL9M49PhA= diff --git a/header/header.go b/header/header.go index 401d2b5..d127bc8 100644 --- a/header/header.go +++ b/header/header.go @@ -2,7 +2,6 @@ package header import ( "bytes" - "crypto/ed25519" "github.com/ipld/go-ipld-prime" "github.com/ipld/go-ipld-prime/codec/dagcbor" @@ -79,12 +78,6 @@ func (header *Header) Verify() (bool, error) { if err != nil { return false, err } - pub, err := key.PublicKeyFromDid(header.Issuer) - if err != nil { - return false, err - } - err = ed25519.VerifyWithOptions(pub, bytes, header.Signature, &ed25519.Options{ - Context: header.Issuer, - }) + err = key.Verify(header.Issuer, bytes, header.Signature, header.Issuer) return err == nil, err } diff --git a/header/payload.go b/header/payload.go index a20ea37..3a4a275 100644 --- a/header/payload.go +++ b/header/payload.go @@ -2,7 +2,6 @@ package header import ( "bytes" - "crypto/ed25519" "github.com/ipfs/go-cid" "github.com/ipld/go-ipld-prime" @@ -52,20 +51,19 @@ func (payload *Payload) Marshal() ([]byte, error) { return buffer.Bytes(), err } -func (payload *Payload) Sign(key *key.Key) (*Header, error) { +func (payload *Payload) Sign(k key.Key) (*Header, error) { bytes, err := payload.Marshal() if err != nil { return nil, err } - s, err := key.Private.Sign(nil, bytes, &ed25519.Options{ - Context: key.Did, - }) + did := key.Did(k) + s, err := k.Sign(bytes, did) if err != nil { return nil, err } return &Header{ Payload: *payload, - Issuer: key.Did, + Issuer: did, Signature: s, }, nil } diff --git a/key/bls12381.go b/key/bls12381.go new file mode 100644 index 0000000..47f166d --- /dev/null +++ b/key/bls12381.go @@ -0,0 +1,91 @@ +package key + +import ( + "crypto/rand" + "fmt" + + bls12381 "github.com/kilic/bls12-381" +) + +type KeyBls12381 struct { + Private bls12381.Fr + Public bls12381.PointG2 +} + +func makeBls12381(pri *bls12381.Fr) (*KeyBls12381, error) { + g2 := bls12381.NewG2() + return &KeyBls12381{ + Private: *pri, + Public: *g2.MulScalar(g2.New(), g2.One(), pri), + }, nil +} + +func generateBls12381() (*KeyBls12381, error) { + pri, err := bls12381.NewFr().Rand(rand.Reader) + if err != nil { + return nil, err + } + return makeBls12381(pri) +} + +func fromBytesBls12381(priBytes []byte) (*KeyBls12381, error) { + if len(priBytes) != 32 { + return nil, fmt.Errorf("incorrect length of BLS-12381 private key: %v", len(priBytes)) + } + return makeBls12381(bls12381.NewFr().FromBytes(priBytes)) +} + +func (k *KeyBls12381) keyType() KeyType { + return Bls12381 +} + +func (k *KeyBls12381) PrivateBytes() []byte { + return k.Private.ToBytes() +} + +func (k *KeyBls12381) PublicBytes() []byte { + return bls12381.NewG2().ToCompressed(&k.Public) +} + +func (k *KeyBls12381) Sign(message []byte, context string) ([]byte, error) { + g1 := bls12381.NewG1() + point, err := hashToCurveBls12381(message, context) + if err != nil { + return nil, err + } + sig := g1.New() + g1.MulScalar(sig, point, &k.Private) + return g1.ToCompressed(sig), nil +} + +func pointG1FromBytesBls12381(bytes []byte) (*bls12381.PointG1, error) { + g1 := bls12381.NewG1() + return g1.FromCompressed(bytes) +} + +func pointG2FromBytesBls12381(bytes []byte) (*bls12381.PointG2, error) { + g2 := bls12381.NewG2() + return g2.FromCompressed(bytes) +} + +func verifyBls12381(pub *bls12381.PointG2, sig *bls12381.PointG1, message []byte, context string) error { + g2 := bls12381.NewG2() + point, err := hashToCurveBls12381(message, context) + if err != nil { + return err + } + engine := bls12381.NewEngine() + engine.AddPair(point, pub) + engine.AddPairInv(sig, g2.One()) + okay := engine.Check() + if !okay { + return fmt.Errorf("signature verification failed") + } + return nil +} + +func hashToCurveBls12381(message []byte, context string) (*bls12381.PointG1, error) { + g1 := bls12381.NewG1() + dst := []byte("BLS_SIG_" + context + "_XMD:SHA-256_SSWU_RO_NUL_") + return g1.HashToCurve(message, dst) +} diff --git a/key/bls12381_test.go b/key/bls12381_test.go new file mode 100644 index 0000000..fb80c0d --- /dev/null +++ b/key/bls12381_test.go @@ -0,0 +1,49 @@ +package key + +import ( + "reflect" + "testing" +) + +func TestGenerateKey_Bls12381(t *testing.T) { + testGenerateKey(Bls12381, reflect.TypeOf(&KeyBls12381{}), t) +} + +func TestDid_Bls12381(t *testing.T) { + testDid(Bls12381, "did:key:zUC7", t) +} + +func TestPubFromDid_Bls12381(t *testing.T) { + testPubFromDid(Bls12381, t) +} + +func TestDidResolution_Bls12381(t *testing.T) { + testDidResolution(Bls12381, "Bls12381G2Key2020", t) +} + +func TestIO_Bls12381(t *testing.T) { + testIO( + Bls12381, + func(kx Key, ky Key) { + kx1, ok := kx.(*KeyBls12381) + if !ok { + t.Errorf("incorrect key type generated: %T", kx1) + } + ky1, ok := ky.(*KeyBls12381) + if !ok { + t.Errorf("incorrect key type read: %T", ky1) + } + if kx1.Private != ky1.Private { + t.Error("private key does not match") + } + if kx1.Public != ky1.Public { + t.Error("public key does not match") + } + }, + t, + ) +} + +func TestVerify_Bls12381(t *testing.T) { + testVerify(Bls12381, t) +} diff --git a/key/ed25519.go b/key/ed25519.go new file mode 100644 index 0000000..cdea2fb --- /dev/null +++ b/key/ed25519.go @@ -0,0 +1,55 @@ +package key + +import ( + "crypto/ed25519" + "fmt" +) + +type KeyEd25519 struct { + Private ed25519.PrivateKey +} + +func generateEd25519() (*KeyEd25519, error) { + _, pri, err := ed25519.GenerateKey(nil) + if err != nil { + return nil, err + } + return makeEd25519(pri) +} + +func makeEd25519(pri ed25519.PrivateKey) (*KeyEd25519, error) { + return &KeyEd25519{ + Private: pri, + }, nil +} + +func fromBytesEd25519(priBytes []byte) (*KeyEd25519, error) { + if len(priBytes) != 32 { + return nil, fmt.Errorf("incorrect length of Ed25519 private key: %v", len(priBytes)) + } + return makeEd25519(priBytes) +} + +func (k *KeyEd25519) keyType() KeyType { + return Ed25519 +} + +func (k *KeyEd25519) PrivateBytes() []byte { + return k.Private +} + +func (k *KeyEd25519) PublicBytes() []byte { + return k.Private[32:] +} + +func (k *KeyEd25519) Sign(message []byte, context string) ([]byte, error) { + return k.Private.Sign(nil, message, &ed25519.Options{ + Context: context, + }) +} + +func verifyEd25519(pub ed25519.PublicKey, sig []byte, message []byte, context string) error { + return ed25519.VerifyWithOptions(pub, message, sig, &ed25519.Options{ + Context: context, + }) +} diff --git a/key/ed25519_test.go b/key/ed25519_test.go new file mode 100644 index 0000000..8c07201 --- /dev/null +++ b/key/ed25519_test.go @@ -0,0 +1,47 @@ +package key + +import ( + "bytes" + "reflect" + "testing" +) + +func TestGenerateKey_Ed25519(t *testing.T) { + testGenerateKey(Ed25519, reflect.TypeOf(&KeyEd25519{}), t) +} + +func TestDid_Ed25519(t *testing.T) { + testDid(Ed25519, "did:key:z6M", t) +} + +func TestPubFromDid_Ed25519(t *testing.T) { + testPubFromDid(Ed25519, t) +} + +func TestDidResolution_Ed25519(t *testing.T) { + testDidResolution(Ed25519, "Ed25519VerificationKey2018", t) +} + +func TestIO_Ed25519(t *testing.T) { + testIO( + Ed25519, + func(kx Key, ky Key) { + kx1, ok := kx.(*KeyEd25519) + if !ok { + t.Errorf("incorrect key type generated: %T", kx1) + } + ky1, ok := ky.(*KeyEd25519) + if !ok { + t.Errorf("incorrect key type read: %T", ky1) + } + if !bytes.Equal(kx1.Private, ky1.Private) { + t.Error("private key does not match") + } + }, + t, + ) +} + +func TestVerify_Ed25519(t *testing.T) { + testVerify(Ed25519, t) +} diff --git a/key/key.go b/key/key.go index fb233a5..f261e1e 100644 --- a/key/key.go +++ b/key/key.go @@ -13,66 +13,82 @@ import ( "github.com/trustbloc/did-go/method/key" ) -type Key struct { - Private ed25519.PrivateKey - Public ed25519.PublicKey - Did string - Resolution did.DocResolution +type Key interface { + keyType() KeyType + PrivateBytes() []byte + PublicBytes() []byte + Sign(message []byte, context string) ([]byte, error) } -func GenerateKey() (*Key, error) { - _, pri, err := ed25519.GenerateKey(nil) - if err != nil { - return nil, err +type KeyType int + +const ( + UnknownKeyType KeyType = iota + Ed25519 + Bls12381 +) + +func prefixBytes(keyType KeyType) []byte { + // See . + switch keyType { + case Ed25519: + return []byte{0xED, 0x01} + case Bls12381: + return []byte{0xEB, 0x01} + default: + panic(fmt.Errorf("invalid key type: %v", keyType)) } - return makeKey(pri) } -func makeKey(pri []byte) (*Key, error) { - pub := pri[32:] - prefixedKey := append([]byte{0xED, 0x01}, pub...) - str, err := multibase.Encode(multibase.Base58BTC, prefixedKey) - if err != nil { - return nil, err - } - did := "did:key:" + str - resolution, err := key.New().Read(did) - if err != nil { - return nil, err +func blockType(keyType KeyType) string { + switch keyType { + case Ed25519: + return "ED25519 PRIVATE KEY" + case Bls12381: + return "BLS12-381 PRIVATE KEY" + default: + panic(fmt.Errorf("invalid key type: %v", keyType)) } - return &Key{ - Private: pri, - Public: pub, - Did: did, - Resolution: *resolution, - }, nil } -func (key *Key) Sign(message []byte) ([]byte, error) { - return key.Private.Sign(nil, message, nil) +func GenerateKey(keyType KeyType) (Key, error) { + switch keyType { + case Ed25519: + return generateEd25519() + case Bls12381: + return generateBls12381() + default: + return nil, fmt.Errorf("invalid key type: %v", keyType) + } } -func (key *Key) WritePrivateKey(filename string) error { - bytes, err := x509.MarshalPKCS8PrivateKey(key.Private) +func Verify(did string, sigBytes []byte, message []byte, context string) error { + keyType, pubBytes, err := PublicKeyFromDid(did) if err != nil { return err } - pemBlock := &pem.Block{ - Type: "ED25519 PRIVATE KEY", - Bytes: bytes, + switch keyType { + case Ed25519: + { + return verifyEd25519(pubBytes, sigBytes, message, context) + } + case Bls12381: + { + pub, err := pointG2FromBytesBls12381(pubBytes) + if err != nil { + return err + } + sig, err := pointG1FromBytesBls12381(sigBytes) + if err != nil { + return err + } + return verifyBls12381(pub, sig, message, context) + } } - handle, err := os.Create(filename) - if err != nil { - return err - } - err = pem.Encode(handle, pemBlock) - if err != nil { - return err - } - return handle.Close() + return fmt.Errorf("invalid key type: %v", keyType) } -func ReadPrivateKey(filename string) (*Key, error) { +func ReadPrivateKey(filename string) (Key, error) { pemBytes, err := os.ReadFile(filename) if err != nil { return nil, err @@ -82,31 +98,84 @@ func ReadPrivateKey(filename string) (*Key, error) { return nil, fmt.Errorf("no PEM data present") } else if len(rest) > 0 { return nil, fmt.Errorf("extra PEM data present") - } else if block.Type != "ED25519 PRIVATE KEY" { - return nil, fmt.Errorf("wrong PEM block type") + } else if block.Type == blockType(Ed25519) { + pri, err := x509.ParsePKCS8PrivateKey(block.Bytes) + if err == nil { + keyEd25519, okay := pri.(ed25519.PrivateKey) + if okay { + return makeEd25519(keyEd25519) + } else { + return fromBytesEd25519(block.Bytes) + } + } else { + return fromBytesEd25519(block.Bytes) + } + } else if block.Type == blockType(Bls12381) { + return fromBytesBls12381(block.Bytes) + } + return nil, fmt.Errorf("wrong PEM block type") +} + +func WritePrivateKey(k Key, filename string) error { + var bytes []byte + keyEd25519, okay := k.(*KeyEd25519) + if okay { + var err error + bytes, err = x509.MarshalPKCS8PrivateKey(keyEd25519.Private) + if err != nil { + bytes = k.PrivateBytes() + } + } else { + bytes = k.PrivateBytes() } - pri, err := x509.ParsePKCS8PrivateKey(block.Bytes) + block := &pem.Block{ + Type: blockType(k.keyType()), + Bytes: bytes, + } + handle, err := os.Create(filename) if err != nil { - return nil, err + return err + } + err = pem.Encode(handle, block) + if err != nil { + return err + } + return handle.Close() +} + +func Did(k Key) string { + prefixedKey := append(prefixBytes(k.keyType()), k.PublicBytes()...) + str, err := multibase.Encode(multibase.Base58BTC, prefixedKey) + if err != nil { + panic(err) } - return makeKey(pri.(ed25519.PrivateKey)) + return "did:key:" + str +} + +func ResolveDid(did string) (*did.DocResolution, error) { + return key.New().Read(did) } -func PublicKeyFromDid(did string) ([]byte, error) { +func PublicKeyFromDid(did string) (KeyType, []byte, error) { if !strings.HasPrefix(did, "did:key:") { - return nil, fmt.Errorf("invalid DID format") + return UnknownKeyType, nil, fmt.Errorf("invalid DID format") } str := strings.TrimPrefix(did, "did:key:") _, data, err := multibase.Decode(str) if err != nil { - return nil, fmt.Errorf("multibase decode error: %v", err) + return UnknownKeyType, nil, fmt.Errorf("multibase decode error: %v", err) } - if len(data) != 34 || data[0] != 0xED || data[1] != 0x01 { - return nil, fmt.Errorf("not a valid ed25519 multicodec key") + if len(data) < 2 { + return UnknownKeyType, nil, fmt.Errorf("invalid multicodec: %x", data) } - return data[2:], nil -} - -func ResolveDid(did string) (*did.DocResolution, error) { - return key.New().Read(did) + firstTwoMatch := func(x []byte, y []byte) bool { + return x[0] == y[0] && x[1] == y[1] + } + if firstTwoMatch(data, prefixBytes(Ed25519)) { + return Ed25519, data[2:], nil + } + if firstTwoMatch(data, prefixBytes(Bls12381)) { + return Bls12381, data[2:], nil + } + return UnknownKeyType, nil, fmt.Errorf("unsupported multicodec key: %x", data[:2]) } diff --git a/key/key_test.go b/key/key_test.go new file mode 100644 index 0000000..54440d8 --- /dev/null +++ b/key/key_test.go @@ -0,0 +1,151 @@ +package key + +import ( + "bytes" + "os" + "reflect" + "testing" + + "github.com/leanovate/gopter" + "github.com/leanovate/gopter/gen" + "github.com/leanovate/gopter/prop" +) + +func testGenerateKey(keyType KeyType, kT reflect.Type, t *testing.T) { + k0, err := GenerateKey(keyType) + if err != nil { + t.Error(err) + } + if reflect.TypeOf(k0) != kT { + t.Errorf("incorrect key type generated: %T", k0) + } +} + +func testDid(keyType KeyType, prefix string, t *testing.T) { + k0, err := GenerateKey(keyType) + if err != nil { + t.Error(err) + } + d0 := Did(k0) + if d0[:len(prefix)] != prefix { + t.Errorf("incorrect DID encoding: %v", d0) + } +} + +func testDidResolution(keyType KeyType, keyTypeName string, t *testing.T) { + k0, err := GenerateKey(keyType) + if err != nil { + t.Error(err) + } + d0 := Did(k0) + r1, err := ResolveDid(d0) + if err != nil { + t.Error(err) + } + if r1.DIDDocument.VerificationMethod[0].Type != keyTypeName { + t.Errorf("incorrect verification method type: %v", r1.DIDDocument.VerificationMethod[0].Type) + } +} + +func testPubFromDid(keyType KeyType, t *testing.T) { + k0, err := GenerateKey(keyType) + if err != nil { + t.Error(err) + } + d0 := Did(k0) + t1, p1, err := PublicKeyFromDid(d0) + if err != nil { + t.Error(err) + } + if t1 != keyType { + t.Errorf("incorrect key type: %v", t1) + } + if !bytes.Equal(k0.PublicBytes(), p1) { + t.Error("public key does not match") + } +} + +func testIO(keyType KeyType, equals func(kx Key, ky Key), t *testing.T) { + k0, err := GenerateKey(keyType) + if err != nil { + t.Error(err) + } + kFile, err := os.CreateTemp(".", "tmp-*.pem") + if err != nil { + t.Error(err) + } + defer os.Remove(kFile.Name()) + kFile.Close() + err = WritePrivateKey(k0, kFile.Name()) + if err != nil { + t.Error(err) + } + k1, err := ReadPrivateKey(kFile.Name()) + if err != nil { + t.Error(err) + } + if reflect.TypeOf(k0) != reflect.TypeOf(k1) { + t.Errorf("invalid key type read: %T", k1) + } + equals(k0, k1) +} + +func testVerify(keyType KeyType, t *testing.T) { + parameters := gopter.DefaultTestParameters() + properties := gopter.NewProperties(parameters) + k0, err := GenerateKey(keyType) + if err != nil { + t.Error(err) + } + d0 := Did(k0) + properties.Property("sign and verify", prop.ForAll( + func(ctx string, msg []byte) bool { + if len(ctx) > 255 { + return true + } + sig, err := k0.Sign(msg, ctx) + if err != nil { + return false + } + z := Verify(d0, sig, msg, ctx) + return z == nil + }, + genContext(), + genBytes(0, 1000), + )) + properties.Property("sign and not verify", prop.ForAll( + func(ctx string, msg0 []byte, msg1 []byte) bool { + if len(ctx) > 255 { + return true + } + sig, err := k0.Sign(msg0, ctx) + if err != nil { + return false + } + return bytes.Equal(msg0, msg1) || Verify(d0, sig, msg1, ctx) != nil + }, + genContext(), + genBytes(0, 1000), + genBytes(0, 1000), + )) + properties.TestingRun(t) +} + +func genBytes(minLen int, maxLen int) gopter.Gen { + return gen.IntRange(minLen, maxLen).FlatMap( + func(n interface{}) gopter.Gen { + return gen.SliceOfN( + n.(int), + gen.UInt8()).Map(func(v []uint8) []byte { return []byte(v) }) + }, + reflect.TypeOf([]byte{}), + ) +} + +func genContext() gopter.Gen { + return genString(0, 255) +} + +func genString(minLen int, maxLen int) gopter.Gen { + return genBytes(minLen, maxLen).Map(func(v []uint8) string { return string(v) }) +} diff --git a/ledger/ledger_test.go b/ledger/ledger_test.go index d8aad20..9314ae6 100644 --- a/ledger/ledger_test.go +++ b/ledger/ledger_test.go @@ -20,7 +20,7 @@ func makeHeader(accept []cid.Cid, reject []cid.Cid) (cid.Cid, *header.Header) { MediaType: "application/vnd.ipld.dag-cbor", Comment: "", } - ky, _ := key.GenerateKey() + ky, _ := key.GenerateKey(key.Ed25519) hdr, _ := payload.Sign(ky) hdrBytes, _ := hdr.Marshal() hdrCid, _ := ipfs.CidV1(hdrBytes) diff --git a/onchain/tx.sh b/onchain/tx.sh index c8fe606..55d453d 100644 --- a/onchain/tx.sh +++ b/onchain/tx.sh @@ -13,13 +13,11 @@ cardano-cli conway query utxo --address $(cat controllers.$NETWORK.address) cardano-cli conway query utxo --address $(cat script-0.$NETWORK.address) -cardano-cli conway query utxo --address $(cat script-0.$NETWORK.address) - cardano-cli conway transaction build \ --tx-in-collateral 8042f83c9c52ce173750f79d0163b70ad127ee6c225cd2a57b1249689c1cf164#0 \ - --tx-in 8407a3e624750ed035525e2e37c286eb33c9dd9ca95b14a504be481cc91f26c4#1 \ + --tx-in 374f1b03cd416aafd29ca33fe97734df603607fcc63bfe7177ad92e2952bd6eb#1 \ --tx-in-script-file controllers.script \ - --tx-in 8407a3e624750ed035525e2e37c286eb33c9dd9ca95b14a504be481cc91f26c4#0 \ + --tx-in 374f1b03cd416aafd29ca33fe97734df603607fcc63bfe7177ad92e2952bd6eb#0 \ --tx-in-script-file script-0.plutus \ --tx-in-inline-datum-present \ --tx-in-redeemer-file script-0.redeemer \ @@ -42,4 +40,6 @@ cardano-cli conway transaction submit \ cardano-cli conway transaction txid \ --tx-file tx-$SUFFIX.signed -cardano-cli conway query utxo --address $(cat script-0.$NETWORK.address) +cardano-cli conway query utxo \ + --address $(cat script-0.$NETWORK.address) + diff --git a/tgdh/aes256gcm.go b/tgdh/aes256gcm.go new file mode 100644 index 0000000..7673cda --- /dev/null +++ b/tgdh/aes256gcm.go @@ -0,0 +1,100 @@ +package tgdh + +import ( + "crypto/rand" + "encoding/base64" + "encoding/json" + + "github.com/lestrrat-go/jwx/v3/jwa" + "github.com/lestrrat-go/jwx/v3/jwe" + "github.com/lestrrat-go/jwx/v3/jwk" +) + +func (root *Node) DeriveAesKey(salt []byte) ([]byte, error) { + aesKey := make([]byte, 32) + err := root.DeriveSeed(aesKey, salt, []byte("nacatgunma-tgdh-aes256gcm")) + return aesKey, err +} + +func (root *Node) Encrypt(plainText []byte, contentType string) ([]byte, []byte, error) { + salt := make([]byte, 32) + rand.Read(salt) + aesKey, err := root.DeriveAesKey(salt) + if err != nil { + return nil, nil, err + } + did := root.Did() + protected := jwe.NewHeaders() + protected.Set(jwe.TypeKey, "nacatgunma-tgdh+salt") + protected.Set(jwe.KeyIDKey, did) + protected.Set(jwe.SaltKey, salt) + if contentType != "" { + protected.Set(jwe.ContentTypeKey, contentType) + } + jweBytes, err := jwe.Encrypt( + plainText, + jwe.WithKey(jwa.DIRECT(), aesKey), + jwe.WithContentEncryption(jwa.A256GCM()), + jwe.WithProtectedHeaders(protected), + jwe.WithJSON(), + ) + if err != nil { + return nil, nil, err + } + jwkKey, err := jwk.Import(aesKey) + if err != nil { + return nil, nil, err + } + jwkKey.Set(jwk.KeyTypeKey, jwa.OctetSeq()) + jwkKey.Set(jwk.AlgorithmKey, jwa.DIRECT()) + jwkKey.Set(jwk.KeyOpsKey, []jwk.KeyOperation{ + jwk.KeyOpEncrypt, + jwk.KeyOpDecrypt, + }) + jwkKey.Set(jwk.KeyIDKey, did) + jwkKey.Set(jwk.KeyUsageKey, jwk.ForEncryption) + jwkBytes, err := json.Marshal(jwkKey) + if err != nil { + return nil, nil, err + } + return jwkBytes, jweBytes, nil +} + +func Decrypt(aesKey []byte, cipherText []byte) (jwe.Headers, []byte, error) { + message, err := jwe.Parse(cipherText) + if err != nil { + return nil, nil, err + } + protected := message.ProtectedHeaders() + plainText, err := jwe.Decrypt( + cipherText, + jwe.WithKey(jwa.DIRECT(), aesKey), + ) + return protected, plainText, err +} + +func (root *Node) Decrypt(cipherText []byte) (jwe.Headers, []byte, error) { + message, err := jwe.Parse(cipherText) + if err != nil { + return nil, nil, err + } + protected := message.ProtectedHeaders() + var saltString string + err = protected.Get(jwe.SaltKey, &saltString) + if err != nil { + return protected, nil, err + } + salt, err := base64.RawURLEncoding.DecodeString(saltString) + if err != nil { + return protected, nil, err + } + aesKey, err := root.DeriveAesKey(salt) + if err != nil { + return protected, nil, err + } + plainText, err := jwe.Decrypt( + cipherText, + jwe.WithKey(jwa.DIRECT(), aesKey), + ) + return protected, plainText, err +} diff --git a/tgdh/aes256gcm_test.go b/tgdh/aes256gcm_test.go new file mode 100644 index 0000000..283f776 --- /dev/null +++ b/tgdh/aes256gcm_test.go @@ -0,0 +1,52 @@ +package tgdh + +import ( + "bytes" + "testing" + + "github.com/lestrrat-go/jwx/v3/jwe" +) + +func TestEncrypt(t *testing.T) { + root, err := GenerateLeaf() + if err != nil { + t.Error(err) + } + plainText := []byte("Nacatgunma TGDH encryption test") + contentType := "text/plain" + _, cipherText, err := root.Encrypt(plainText, contentType) + if err != nil { + t.Error(err) + } + protected, plainText1, err := root.Decrypt(cipherText) + if err != nil { + t.Error(err) + } + if !bytes.Equal(plainText, plainText1) { + t.Error("plain text does not match") + } + var contentType1 string + err = protected.Get(jwe.ContentTypeKey, &contentType1) + if err != nil { + t.Error(err) + } + if contentType1 != contentType { + t.Error("content type does not match") + } + var kid1 string + err = protected.Get(jwe.KeyIDKey, &kid1) + if err != nil { + t.Error(err) + } + if kid1 != root.Did() { + t.Error("key ID does not match") + } + var type1 string + err = protected.Get(jwe.TypeKey, &type1) + if err != nil { + t.Error(err) + } + if type1 != "nacatgunma-tgdh+salt" { + t.Error("type does not match") + } +} diff --git a/tgdh/tgdh.go b/tgdh/tgdh.go new file mode 100644 index 0000000..8ac31fc --- /dev/null +++ b/tgdh/tgdh.go @@ -0,0 +1,315 @@ +package tgdh + +import ( + "crypto/rand" + "crypto/sha256" + "encoding/hex" + "encoding/json" + "fmt" + "io" + + bls12381 "github.com/kilic/bls12-381" + "github.com/multiformats/go-multibase" + "golang.org/x/crypto/hkdf" +) + +type Node struct { + Private *bls12381.Fr + Public bls12381.PointG1 + Left *Node + Right *Node +} + +func (node *Node) Strip() *Node { + return &Node{ + Private: nil, + Public: node.Public, + Left: node.Left, + Right: node.Right, + } +} + +func (node *Node) DeepStrip() *Node { + var left *Node + if node.Left != nil { + left = node.Left.DeepStrip() + } + var right *Node + if node.Right != nil { + right = node.Right.DeepStrip() + } + return &Node{ + Private: nil, + Public: node.Public, + Left: left, + Right: right, + } +} + +func GenerateLeaf() (*Node, error) { + pri, err := bls12381.NewFr().Rand(rand.Reader) + if err != nil { + return nil, err + } + return Leaf(pri), nil +} + +func makeNode(pri *bls12381.Fr, left *Node, right *Node) *Node { + g1 := bls12381.NewG1() + return &Node{ + Private: pri, + Public: *g1.MulScalar(g1.New(), g1.One(), pri), + Left: left, + Right: right, + } +} + +func Leaf(pri *bls12381.Fr) *Node { + return makeNode(pri, nil, nil) +} + +func hashToFr(secret *bls12381.PointG1, salt []byte, info []byte) (*bls12381.Fr, error) { + hashReader := hkdf.New(sha256.New, bls12381.NewG1().ToCompressed(secret), salt, info) + hashBytes := make([]byte, 32) + _, err := io.ReadFull(hashReader, hashBytes) + if err != nil { + return nil, err + } + return bls12381.NewFr().FromBytes(hashBytes), nil +} + +func Join(left *Node, right *Node) (*Node, error) { + g1 := bls12381.NewG1() + prod := g1.New() + if left.Private != nil { + g1.MulScalar(prod, &right.Public, left.Private) + } else if right.Private != nil { + g1.MulScalar(prod, &left.Public, right.Private) + } else { + return nil, fmt.Errorf("one child must have a private key") + } + pri, err := hashToFr(prod, nil, []byte("nacatgunma-tgdh-bls12381g1")) + if err != nil { + return nil, err + } + return makeNode(pri, left, right), nil +} + +func (root *Node) Remove(leaf *Node) (*Node, error) { + if root.Public == leaf.Public { + return nil, fmt.Errorf("cannot remove root") + } + path, err := FindPath(leaf, root) + if err != nil { + return nil, err + } + leaf = path[0] + roots := []*Node{} + for _, node := range path[1:] { + if node.Left == leaf && node.Right != nil { + roots = append(roots, node.Right) + } else if node.Right == leaf && node.Left != nil { + roots = append(roots, node.Left) + } + leaf = node + } + var start *Node + for _, node := range roots { + if node.Private != nil { + start = node + break + } + } + if start == nil { + return nil, fmt.Errorf("root does not contain any private keys") + } + root1 := start + for _, node := range roots { + if node == start { + continue + } + root1, err = Join(root1, node) + if err != nil { + return nil, err + } + } + return root1, nil +} + +func (node *Node) Did() string { + pub := bls12381.NewG1().ToCompressed(&node.Public) + prefixedKey := append([]byte{0xEA, 0x01}, pub...) + str, err := multibase.Encode(multibase.Base58BTC, prefixedKey) + if err != nil { + panic(err) + } + return "did:key:" + str +} + +func visitPath(leaf *Node, root *Node, candidate *Node) ([]*Node, error) { + if candidate == nil { + return nil, fmt.Errorf("path not found") + } + if leaf.Public == candidate.Public { + return []*Node{candidate}, nil + } + path, err := visitPath(leaf, root, candidate.Left) + if err == nil { + return append(path, candidate), nil + } + path, err = visitPath(leaf, root, candidate.Right) + if err == nil { + return append(path, candidate), nil + } + return nil, fmt.Errorf("path not found") +} + +func FindPath(leaf *Node, root *Node) ([]*Node, error) { + return visitPath(leaf, root, root) +} + +func DerivePrivates(leaf *Node, root *Node) (*Node, error) { + path, err := FindPath(leaf, root) + if err != nil { + return nil, err + } + root1 := leaf + for _, node := range path[1:] { + if node.Left == nil || node.Right == nil { + return nil, fmt.Errorf("ill-formed tree") + } + if node.Left.Public == root1.Public { + root1, err = Join(root1, node.Right) + if err != nil { + return nil, err + } + } + if node.Right.Public == root1.Public { + root1, err = Join(node.Left, root1) + if err != nil { + return nil, err + } + } + } + return root1, nil +} + +func (root *Node) DeriveSeed(dst []byte, salt []byte, info []byte) error { + if root.Private == nil { + return fmt.Errorf("missing private key") + } + hashReader := hkdf.New(sha256.New, root.Private.ToBytes(), salt, info) + _, err := io.ReadFull(hashReader, dst) + return err +} + +type jsonNode struct { + Private string `json:"private,omitempty"` + Public string `json:"public"` + Left *jsonNode `json:"left,omitempty"` + Right *jsonNode `json:"right,omitempty"` +} + +func (root *Node) toJsonNode() (*jsonNode, error) { + if root == nil { + return nil, nil + } + var privHex string + if root.Private != nil { + privBytes := root.Private.ToBytes() + privHex = hex.EncodeToString(privBytes[:]) + } + g1 := bls12381.NewG1() + pubBytes := g1.ToCompressed(&root.Public) + pubHex := hex.EncodeToString(pubBytes) + left, err := root.Left.toJsonNode() + if err != nil { + return nil, err + } + right, err := root.Right.toJsonNode() + if err != nil { + return nil, err + } + return &jsonNode{ + Private: privHex, + Public: pubHex, + Left: left, + Right: right, + }, nil +} + +func (root *Node) MarshalJSON() ([]byte, error) { + j, err := root.toJsonNode() + if err != nil { + return nil, err + } + return json.Marshal(j) +} + +func (j *jsonNode) fromJsonNode() (*Node, error) { + if j == nil { + return nil, nil + } + var fr bls12381.Fr + var pri *bls12381.Fr + if j.Private != "" { + privBytes, err := hex.DecodeString(j.Private) + if err != nil { + return nil, err + } + pri = fr.FromBytes(privBytes) + } else { + pri = nil + } + pubBytes, err := hex.DecodeString(j.Public) + if err != nil { + return nil, err + } + g1 := bls12381.NewG1() + pub, err := g1.FromCompressed(pubBytes) + if err != nil { + return nil, err + } + left, err := j.Left.fromJsonNode() + if err != nil { + return nil, err + } + right, err := j.Right.fromJsonNode() + if err != nil { + return nil, err + } + return &Node{ + Private: pri, + Public: *pub, + Left: left, + Right: right, + }, nil +} + +func UnmarshalJSON(data []byte) (*Node, error) { + var j jsonNode + if err := json.Unmarshal(data, &j); err != nil { + return nil, err + } + return j.fromJsonNode() +} + +func Equal(x *Node, y *Node) bool { + if x == nil && y == nil { + return true + } + if (x == nil) != (y == nil) { + return false + } + if (x.Private == nil) != (y.Private == nil) { + return false + } + if x.Private != nil && !x.Private.Equal(y.Private) { + return false + } + g1 := bls12381.NewG1() + if !g1.Equal(&x.Public, &y.Public) { + return false + } + return Equal(x.Left, y.Left) && Equal(x.Right, y.Right) +} diff --git a/tgdh/tgdh_test.go b/tgdh/tgdh_test.go new file mode 100644 index 0000000..ff7bf12 --- /dev/null +++ b/tgdh/tgdh_test.go @@ -0,0 +1,131 @@ +package tgdh + +import ( + "fmt" + "reflect" + "testing" + + "github.com/leanovate/gopter" + "github.com/leanovate/gopter/gen" + "github.com/leanovate/gopter/prop" +) + +func TestGenerateLeaf(t *testing.T) { + _, err := GenerateLeaf() + if err != nil { + t.Error(err) + } +} + +func TestRoot(t *testing.T) { + parameters := gopter.DefaultTestParameters() + properties := gopter.NewProperties(parameters) + leaves := make([]*Node, 8) + for i := range leaves { + leaf, err := GenerateLeaf() + if err != nil { + t.Error(err) + } + leaves[i] = leaf + } + join := func(flag bool, left *Node, right *Node) *Node { + if flag { + node, err := Join(left, right.Strip()) + if err != nil { + t.Error(err) + } + return node + } else { + node, err := Join(left.Strip(), right) + if err != nil { + t.Error(err) + } + return node + } + } + compute := func(flags [7]bool) *Node { + ab := join(flags[0], leaves[0], leaves[1]) + cd := join(flags[1], leaves[2], leaves[3]) + ef := join(flags[2], leaves[4], leaves[5]) + gh := join(flags[3], leaves[6], leaves[7]) + abcd := join(flags[4], ab, cd) + efgh := join(flags[5], ef, gh) + return join(flags[6], abcd, efgh) + } + properties.Property("roots match", prop.ForAll( + func(flags0 [7]bool, flags1 [7]bool) bool { + node0 := compute(flags0) + node1 := compute(flags1) + return node0.Public == node1.Public && *node0.Private == *node1.Private + }, + gen.ArrayOfN(7, gen.Bool(), reflect.TypeOf(true)), + gen.ArrayOfN(7, gen.Bool(), reflect.TypeOf(true)), + )) + properties.TestingRun(t) +} + +func TestFindPath(t *testing.T) { + A, _ := GenerateLeaf() + B, _ := GenerateLeaf() + AB, _ := Join(A, B.Strip()) + path, err := FindPath(A, AB.DeepStrip()) + if err != nil { + t.Error(err) + } + if len(path) != 2 || path[0].Public != A.Public || path[1].Public != AB.Public { + t.Error("incorrect path") + } +} + +func TestRecompute(t *testing.T) { + A, _ := GenerateLeaf() + B, _ := GenerateLeaf() + AB, _ := Join(A, B.Strip()) + root, err := DerivePrivates(A, AB.DeepStrip()) + if err != nil { + t.Error(err) + } + if *AB.Private != *root.Private { + t.Error("incorrect recomputed private key") + } +} + +func TestRemove(t *testing.T) { + A, _ := GenerateLeaf() + B, _ := GenerateLeaf() + AB, _ := Join(A, B.Strip()) + root, err := DerivePrivates(A, AB.DeepStrip()) + if err != nil { + t.Error(err) + } + A1, err := root.Remove(B) + if err != nil { + t.Error(err) + } + fmt.Println(A) + fmt.Println(A1) + if A1.Private != A.Private { + t.Error("removal failure") + } +} + +func TestJson(t *testing.T) { + A, _ := GenerateLeaf() + B, _ := GenerateLeaf() + AB, _ := Join(A, B.Strip()) + root, err := DerivePrivates(A, AB.DeepStrip()) + if err != nil { + t.Error(err) + } + j, err := root.MarshalJSON() + if err != nil { + t.Error(err) + } + root1, err := UnmarshalJSON(j) + if err != nil { + t.Error(err) + } + if !Equal(root1, root) { + t.Error("deserialization does not match") + } +}