chore(envelope): refactor to decode token.Token to schema.TypedNode

This commit is contained in:
Steve Moyer
2024-09-13 12:01:51 -04:00
parent 16f0f38b43
commit 7cead1bf8d
17 changed files with 369 additions and 297 deletions

18
go.mod
View File

@@ -1,18 +1,19 @@
module github.com/ucan-wg/go-ucan
go 1.21
go 1.22.0
toolchain go1.22.1
toolchain go1.22.4
require (
github.com/gobwas/glob v0.2.3
github.com/ipfs/go-cid v0.4.1
github.com/ipld/go-ipld-prime v0.21.0
github.com/launchdarkly/go-options v1.3.0
github.com/libp2p/go-libp2p v0.36.2
github.com/multiformats/go-multibase v0.2.0
github.com/multiformats/go-multicodec v0.9.0
github.com/multiformats/go-multihash v0.2.3
github.com/multiformats/go-varint v0.0.7
github.com/selesy/go-options v0.0.0-20240912020512-ed2658318e52
github.com/stretchr/testify v1.9.0
gotest.tools/v3 v3.5.1
)
@@ -20,22 +21,21 @@ require (
require (
github.com/davecgh/go-spew v1.1.1 // indirect
github.com/decred/dcrd/dcrec/secp256k1/v4 v4.3.0 // indirect
github.com/fatih/structtag v1.0.0 // indirect
github.com/fatih/structtag v1.2.0 // indirect
github.com/google/go-cmp v0.6.0 // indirect
github.com/klauspost/cpuid/v2 v2.2.8 // indirect
github.com/minio/sha256-simd v1.0.1 // indirect
github.com/mr-tron/base58 v1.2.0 // indirect
github.com/multiformats/go-base32 v0.1.0 // indirect
github.com/multiformats/go-base36 v0.2.0 // indirect
github.com/multiformats/go-multihash v0.2.3 // indirect
github.com/pmezard/go-difflib v1.0.0 // indirect
github.com/polydawn/refmt v0.89.0 // indirect
github.com/spaolacci/murmur3 v1.1.0 // indirect
golang.org/x/crypto v0.25.0 // indirect
golang.org/x/mod v0.19.0 // indirect
golang.org/x/sync v0.7.0 // indirect
golang.org/x/sys v0.22.0 // indirect
golang.org/x/tools v0.23.0 // indirect
golang.org/x/mod v0.21.0 // indirect
golang.org/x/sync v0.8.0 // indirect
golang.org/x/sys v0.25.0 // indirect
golang.org/x/tools v0.25.0 // indirect
google.golang.org/protobuf v1.34.2 // indirect
gopkg.in/yaml.v3 v3.0.1 // indirect
lukechampine.com/blake3 v1.3.0 // indirect

105
go.sum
View File

@@ -1,41 +1,22 @@
github.com/BurntSushi/toml v0.3.1/go.mod h1:xHWCNGjB5oqiDr8zfno3MHue2Ht5sIBksp03qcyfWMU=
github.com/cpuguy83/go-md2man/v2 v2.0.0-20190314233015-f79a8a8ca69d/go.mod h1:maD7wRr/U5Z6m/iR4s+kqSMx2CaBsrgA7czyZG/E6dU=
github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c=
github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
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/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/fatih/structtag v1.0.0 h1:pTHj65+u3RKWYPSGaU290FpI/dXxTaHdVwVwbcPKmEc=
github.com/fatih/structtag v1.0.0/go.mod h1:IKitwq45uXL/yqi5mYghiD3w9H6eTOvI9vnk8tXMphA=
github.com/fatih/structtag v1.2.0 h1:/OdNE99OxoI/PqaW/SuSK9uxxT3f/tcSZgon/ssNSx4=
github.com/fatih/structtag v1.2.0/go.mod h1:mBJUNpUnHmRKrKlQQlmCrh5PuhftFbNv8Ys4/aAZl94=
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/go-task/slim-sprig v0.0.0-20210107165309-348f09dbbbc0/go.mod h1:fyg7847qk6SyHyPtNmDHnmrv/HOrqktSC+C9fM+CJOE=
github.com/go-yaml/yaml v2.1.0+incompatible/go.mod h1:w2MrLa16VYP0jy6N7M5kHaCkaLENm+P+Tv+MfurjSw0=
github.com/gobwas/glob v0.2.3 h1:A4xDbljILXROh+kObIiy5kIaPYD8e96x1tgBhUI5J+Y=
github.com/gobwas/glob v0.2.3/go.mod h1:d3Ez4x06l9bZtSvzIay5+Yzi0fmZzPgnTbPcKjJAkT8=
github.com/golang/protobuf v1.2.0/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U=
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.2/go.mod h1:oDoupMAO8OvCJWAcko0GGGIgR6R6ocIYbsSw735rRwI=
github.com/golang/protobuf v1.5.0/go.mod h1:FsONVRAS9T7sI+LIUmWTfcYkHO4aIWwzhcaSAoJOfIk=
github.com/golang/protobuf v1.5.2/go.mod h1:XVQd3VNwM+JqD3oG2Ue2ip4fOMUkwXdXDdiuN0vRsmY=
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.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.6.0 h1:ofyhxvXcZhMsU5ulbFiLKl/XBFqE1GSq7atu8tAmTRI=
github.com/google/go-cmp v0.6.0/go.mod h1:17dUlkBOakJ0+DkrSSNjCkIjxS6bF9zb3elmeNGIjoY=
github.com/gopherjs/gopherjs v0.0.0-20181017120253-0766667cb4d1 h1:EGx4pi6eqNxGaHF6qqu48+N2wcFQ5qg5FXgOdqsJ5d8=
github.com/gopherjs/gopherjs v0.0.0-20181017120253-0766667cb4d1/go.mod h1:wJfORRmW1u3UXTncJ5qlYoELFm8eSnnEO6hX4iZ3EWY=
github.com/hpcloud/tail v1.0.0/go.mod h1:ab1qPbhIpdTxEkNHXyeSf5vhxWSCs/tWer42PpOxQnU=
github.com/ipfs/go-cid v0.4.1 h1:A/T3qGvxi4kpKWWcPC/PgbvDA2bjVLO7n4UeVwnbs/s=
github.com/ipfs/go-cid v0.4.1/go.mod h1:uQHwDeX4c6CtyrFwdqyhpNcxVewur1M7l7fNU7LKwZk=
github.com/ipld/go-ipld-prime v0.21.0 h1:n4JmcpOlPDIxBcY037SVfpd1G+Sj1nKZah0m6QH9C2E=
@@ -48,8 +29,6 @@ github.com/kr/pretty v0.3.1 h1:flRD4NNwYAUpkphVc1HcthR4KEIFJ65n8Mw5qdRn3LE=
github.com/kr/pretty v0.3.1/go.mod h1:hoEshYVHaxMs3cyo3Yncou5ZscifuDolrwPKZanG3xk=
github.com/kr/text v0.2.0 h1:5Nx0Ya0ZqY2ygV366QzturHI13Jq95ApcVaJBhpS+AY=
github.com/kr/text v0.2.0/go.mod h1:eLer722TekiGuMkidMxC/pM04lWEeraHUUmBw8l2grE=
github.com/launchdarkly/go-options v1.3.0 h1:djG7Jnq5Ypixj4oqPlQOaZZMM54R9DhESyUheNl7Fow=
github.com/launchdarkly/go-options v1.3.0/go.mod h1:M4XaM6jqyeCwQFRKtU4OGepTeWvUF9rDhcggjLLTPvE=
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-libp2p v0.36.2 h1:BbqRkDaGC3/5xfaJakLV/BrpjlAuYqSB0lRvtzL3B/U=
@@ -72,14 +51,6 @@ github.com/multiformats/go-multihash v0.2.3 h1:7Lyc8XfX/IY2jWb/gI7JP+o7JEq9hOa7B
github.com/multiformats/go-multihash v0.2.3/go.mod h1:dXgKXCXjBzdscBLk9JkjINiEsCKRVch90MdaGiKsvSM=
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/nxadm/tail v1.4.4/go.mod h1:kenIhsEOeOJmVchQTgglprH7qJGnHDVpk1VPCcaMI8A=
github.com/nxadm/tail v1.4.8/go.mod h1:+ncqLTQzXmGhMZNUePPaPqPvBxHAIsmXswZKocGu+AU=
github.com/onsi/ginkgo v1.6.0/go.mod h1:lLunBs/Ym6LB5Z9jYTR76FiuTmxDTDusOGeTQH+WWjE=
github.com/onsi/ginkgo v1.12.1/go.mod h1:zj2OWP4+oCPe1qIXoGWkgMRwljMUYCdkwsT2108oapk=
github.com/onsi/ginkgo v1.16.2/go.mod h1:CObGmKUOKaSC0RjmoAK7tKyn4Azo5P2IWuoMnvwxz1E=
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/onsi/gomega v1.13.0/go.mod h1:lRk9szgn8TxENtWd0Tp4c3wjlRfMTMH27I+3Je41yGY=
github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM=
github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4=
github.com/polydawn/refmt v0.89.0 h1:ADJTApkvkeBZsN0tBTx8QjpD9JkmxbKp0cxfr9qszm4=
@@ -87,6 +58,8 @@ github.com/polydawn/refmt v0.89.0/go.mod h1:/zvteZs/GwLtCgZ4BL6CBsk9IKIlexP43ObX
github.com/rogpeppe/go-internal v1.9.0 h1:73kH8U+JUqXU8lRuOHeVHaa/SZPifC7BkcraZVejAe8=
github.com/rogpeppe/go-internal v1.9.0/go.mod h1:WtVeX8xhTBvf0smdhujwtBcq4Qrzq/fJaraNFVN+nFs=
github.com/russross/blackfriday/v2 v2.0.1/go.mod h1:+Rmxgy9KzJVeS9/2gXHxylqXiyQDYRxCVz55jmeOWTM=
github.com/selesy/go-options v0.0.0-20240912020512-ed2658318e52 h1:poNWlojS+o3229ZuatLMzK9wFiLuLxo7O170Edggs0o=
github.com/selesy/go-options v0.0.0-20240912020512-ed2658318e52/go.mod h1:Cn8TrnJWCWd3dAmejFTpLN8tNVNKNoVVlZzL8ux5EWQ=
github.com/shurcooL/sanitized_anchor_name v1.0.0/go.mod h1:1NzhyTcUVG4SuEtjjoZeVRXNmyL/1OwPU0+IJeTBvfc=
github.com/smartystreets/assertions v1.2.0 h1:42S6lae5dvLc7BrLu/0ugRtcFVjoJNMC/N3yZFZkDFs=
github.com/smartystreets/assertions v1.2.0/go.mod h1:tcbTF8ujkAEcZ8TElKY+i30BzYlVhC/LOxJk7iOWnoo=
@@ -94,88 +67,34 @@ github.com/smartystreets/goconvey v1.7.2 h1:9RBaZCeXEQ3UselpuwUQHltGVXvdwm6cv1hg
github.com/smartystreets/goconvey v1.7.2/go.mod h1:Vw0tHAZW6lzCRk3xgdin6fKYcG+G3Pg9vgXWeJpQFMM=
github.com/spaolacci/murmur3 v1.1.0 h1:7c1g84S4BPRrfL5Xrdp6fOJ206sU9y293DDHaoy0bLI=
github.com/spaolacci/murmur3 v1.1.0/go.mod h1:JwIasOWyU6f++ZhiEuf87xNszmSA2myDM2Kzu9HwQUA=
github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME=
github.com/stretchr/testify v1.5.1/go.mod h1:5W2xD1RspED5o8YsWQXVCued0rvSQ+mT+I5cxcmMvtA=
github.com/stretchr/testify v1.9.0 h1:HtqpIVDClZ4nwg75+f6Lvsy/wHu+3BoSGCbBAcpTsTg=
github.com/stretchr/testify v1.9.0/go.mod h1:r2ic/lqez/lEtzL7wO/rwa5dbSLXVDPFyf8C91i36aY=
github.com/urfave/cli v1.22.10/go.mod h1:Gos4lmkARVdJ6EkW0WaNv/tZAAMe9V7XWyB60NtXRu0=
github.com/warpfork/go-wish v0.0.0-20220906213052-39a1cc7a02d0 h1:GDDkbFiaK8jsSDJfjId/PEGEShv6ugrt4kYsC5UIDaQ=
github.com/warpfork/go-wish v0.0.0-20220906213052-39a1cc7a02d0/go.mod h1:x6AKhvSSexNrVSrViXSHUEbICjmGXhtgABaHIySUSGw=
github.com/yuin/goldmark v1.2.1/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74=
github.com/yuin/goldmark v1.3.5/go.mod h1:mwnBkeHKe2W/ZEtQ+71ViKU8L12m81fl3OWwC1Zlc8k=
golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w=
golang.org/x/crypto v0.0.0-20191011191535-87dc89f01550/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI=
golang.org/x/crypto v0.0.0-20200622213623-75b288015ac9/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto=
golang.org/x/crypto v0.25.0 h1:ypSNr+bnYL2YhwoMt2zPxHFmbAN1KZs/njMG3hxUp30=
golang.org/x/crypto v0.25.0/go.mod h1:T+wALwcMOSE0kXgUAnPAHqTLW+XHgcELELW8VaDgm/M=
golang.org/x/exp v0.0.0-20240719175910-8a7402abbf56 h1:2dVuKD2vS7b0QIHQbpyTISPd0LeHDbnYEryqj5Q1ug8=
golang.org/x/exp v0.0.0-20240719175910-8a7402abbf56/go.mod h1:M4RDyNAINzryxdtnbRXRL/OHtkFuWGRjvuhBJpk2IlY=
golang.org/x/mod v0.3.0/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA=
golang.org/x/mod v0.4.2/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA=
golang.org/x/mod v0.19.0 h1:fEdghXQSo20giMthA7cd28ZC+jts4amQ3YMXiP5oMQ8=
golang.org/x/mod v0.19.0/go.mod h1:hTbmBsO62+eylJbnUtE2MGJUyE7QWk4xUqPFrRgJ+7c=
golang.org/x/net v0.0.0-20180906233101-161cd47e91fd/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
golang.org/x/mod v0.21.0 h1:vvrHzRwRfVKSiLrG+d4FMl/Qi4ukBCE6kZlTUkDYRT0=
golang.org/x/mod v0.21.0/go.mod h1:6SkKJ3Xj0I0BrPOZoBy3bdMptDDU9oJrpohJ3eWZ1fY=
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-20190620200207-3b0461eec859/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s=
golang.org/x/net v0.0.0-20200520004742-59133d7f0dd7/go.mod h1:qpuaurCH72eLCgpAm/N6yyVIVM9cpaDIP3A8BGJEC5A=
golang.org/x/net v0.0.0-20201021035429-f5854403a974/go.mod h1:sp8m0HH+o8qH0wwXwYZr8TS3Oi6o0r6Gce1SSxlDquU=
golang.org/x/net v0.0.0-20210405180319-a5a99cb37ef4/go.mod h1:p54w0d4576C0XHj96bSt6lcn1PtDYWL6XObtHCRCNQM=
golang.org/x/net v0.0.0-20210428140749-89ef3d95e781/go.mod h1:OJAsFXCWl8Ukc7SiCT/9KSuxbyM7479/AVlXFRxuMCk=
golang.org/x/sync v0.0.0-20180314180146-1d60e4601c6f/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-20201020160332-67f06af15bc9/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.7.0 h1:YsImfSBoP9QPYL0xyKJPq0gcaJdG3rInoqxTWbfQu9M=
golang.org/x/sync v0.7.0/go.mod h1:Czt+wKu1gCyEFDUtn0jG5QVvpJ6rzVqr5aXyt9drQfk=
golang.org/x/sys v0.0.0-20180909124046-d0be0721c37e/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
golang.org/x/sync v0.8.0 h1:3NFvSEYkUoMifnESzZl15y791HH1qU2xm6eCJU5ZPXQ=
golang.org/x/sync v0.8.0/go.mod h1:Czt+wKu1gCyEFDUtn0jG5QVvpJ6rzVqr5aXyt9drQfk=
golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
golang.org/x/sys v0.0.0-20190412213103-97732733099d/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20190904154756-749cb33beabd/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20191005200804-aed5e4c7ecf9/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20191120155948-bd437916bb0e/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20200323222414-85ca7c5b95cd/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-20210112080510-489259a85091/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20210330210617-4fbd30eecc44/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20210423082822-04245dca01da/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20210510120138-977fb7262007/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.5.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.22.0 h1:RI27ohtqKCnwULzJLqkv897zojh5/DwS/ENaMzUOaWI=
golang.org/x/sys v0.22.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA=
golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo=
golang.org/x/sys v0.25.0 h1:r+8e+loiHxRqhXVl6ML1nO3l1+oFoWbnlu2Ehimmi34=
golang.org/x/sys v0.25.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA=
golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=
golang.org/x/text v0.3.3/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ=
golang.org/x/text v0.3.6/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ=
golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ=
golang.org/x/tools v0.0.0-20190328211700-ab21143f2384/go.mod h1:LCzVGOaR6xXOjkQ3onu1FJEFr0SW1gC7cKk1uF8kGRs=
golang.org/x/tools v0.0.0-20191119224855-298f0cb1881e/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo=
golang.org/x/tools v0.0.0-20201224043029-2b0845dc783e/go.mod h1:emZCQorbCU4vsT4fOWvOPXz4eW1wZW4PmDk9uLelYpA=
golang.org/x/tools v0.1.2/go.mod h1:o0xws9oXOQQZyjljx8fwUC0k7L1pTE6eaCbjGeHmOkk=
golang.org/x/tools v0.23.0 h1:SGsXPZ+2l4JsgaCKkx+FQ9YZ5XEtA1GZYuoDjenLjvg=
golang.org/x/tools v0.23.0/go.mod h1:pnu6ufv6vQkll6szChhK3C3L/ruaIv5eBeztNG8wtsI=
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=
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.23.0/go.mod h1:EGpADcykh3NcUnDUJcl1+ZksZNG86OlYog2l/sGQquU=
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=
golang.org/x/tools v0.25.0 h1:oFU9pkj/iJgs+0DT+VMHrx+oBKs/LJMV+Uvg78sl+fE=
golang.org/x/tools v0.25.0/go.mod h1:/vtpO8WL1N9cQC3FN5zPqb//fRXskFHbLKk4OW1Q7rg=
google.golang.org/protobuf v1.34.2 h1:6xV6lTsCfpGD21XK49h7MhtcApnLqkfYgPcdHftf6hg=
google.golang.org/protobuf v1.34.2/go.mod h1:qYOHts0dSfpeUzUFpOMr/WGzszTmLH+DiWniOlNbLDw=
gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405 h1:yhCVgyC4o1eVCa2tZl7eS0r+SDo693bJlVdllGtEeKM=
gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
gopkg.in/fsnotify.v1 v1.4.7/go.mod h1:Tz8NjZHkW78fSQdbUxIjBTcgA1z1m8ZHf0WmKUhAMys=
gopkg.in/tomb.v1 v1.0.0-20141024135613-dd632973f1e7/go.mod h1:dt/ZhP58zS4L8KSrWDmTeBkI65Dw0HsyUHuEVlX15mw=
gopkg.in/yaml.v2 v2.2.2/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI=
gopkg.in/yaml.v2 v2.2.4/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.1 h1:fxVm/GzAzEWqLHuvctI91KS9hhNmmWOoWu0XTYJS7CA=

View File

@@ -3,24 +3,26 @@ package envelope
import (
"bytes"
"errors"
"fmt"
"strings"
"github.com/ipfs/go-cid"
"github.com/ipld/go-ipld-prime"
"github.com/ipld/go-ipld-prime/codec/dagcbor"
"github.com/ipld/go-ipld-prime/datamodel"
"github.com/ipld/go-ipld-prime/fluent/qp"
"github.com/ipld/go-ipld-prime/node/basicnode"
"github.com/ipld/go-ipld-prime/node/bindnode"
crypto "github.com/libp2p/go-libp2p/core/crypto"
"github.com/libp2p/go-libp2p/core/crypto/pb"
"github.com/multiformats/go-multibase"
"github.com/multiformats/go-multicodec"
"github.com/multiformats/go-multihash"
"github.com/multiformats/go-varint"
"github.com/ucan-wg/go-ucan/did"
"github.com/ucan-wg/go-ucan/internal/token"
"github.com/ucan-wg/go-ucan/internal/varsig"
)
// [Envelope] is a signed enclosure for types implementing Tokener.
// [Envelope] is a signed enclosure for a UCAN v1 Token.
//
// While the types and functions in this package are not exported,
// the names used for types, fields, variables, etc generally use the
// names from the specification
//
// [Envelope]: https://github.com/ucan-wg/spec#envelope
type Envelope struct {
@@ -29,8 +31,8 @@ type Envelope struct {
}
// New creates an Envelope containing a VarsigHeader and Signature for
// the data resulting from wrapping the provided Tokener in and IPLD
// datamodel.Node and encoding it using DAG-CBOR
// the data resulting from wrapping the provided Token in an IPLD
// datamodel.Node and encoding it using DAG-CBOR.
func New(privKey crypto.PrivKey, token *token.Token, tag string) (*Envelope, error) {
sigPayload, err := newSigPayload(privKey.Type(), token, tag)
if err != nil {
@@ -56,7 +58,7 @@ func New(privKey crypto.PrivKey, token *token.Token, tag string) (*Envelope, err
// Wrap is syntactic sugar for creating an Envelope and wrapping it as an
// IPLD datamodel.Node in a single operation.
//
// Since the Envelope itself isn't returned, us this method only when
// Since the Envelope itself isn't returned, use this method only when
// the IPLD datamodel.Node is used directly. If the Envelope is also
// required, use New followed by Envelope.Wrap to avoid the need to
// unwrap the newly created datamodel.Node.
@@ -69,7 +71,13 @@ func Wrap(privKey crypto.PrivKey, token *token.Token, tag string) (datamodel.Nod
return env.Wrap()
}
func Unwrap(node datamodel.Node, tag string) (*Envelope, error) {
// Unwrap attempts to crate an Envelope from a datamodel.Node
//
// There are lots of ways that this can fail and therefore there are
// an almost excessive number of check included here and while
// attempting to extract the token.Token from one of the inner IPLD
// nodes.
func Unwrap(node datamodel.Node) (*Envelope, error) {
signatureNode, err := node.LookupByIndex(0)
if err != nil {
return nil, err
@@ -85,7 +93,7 @@ func Unwrap(node datamodel.Node, tag string) (*Envelope, error) {
return nil, err
}
sigPayload, err := unwrapSigPayload(sigPayloadNode, tag)
sigPayload, err := unwrapSigPayload(sigPayloadNode)
if err != nil {
return nil, err
}
@@ -96,35 +104,20 @@ func Unwrap(node datamodel.Node, tag string) (*Envelope, error) {
}, nil
}
func (e *Envelope) CID() (cid.Cid, error) {
node, err := e.Wrap()
if err != nil {
return cid.Undef, nil
}
cbor, err := ipld.Encode(node, dagcbor.Encode)
if err != nil {
return cid.Undef, nil
}
data := varint.ToUvarint(uint64(multicodec.DagCbor))
data = append(data, cbor...)
hash, err := multihash.Sum(data, uint64(multicodec.Sha2_256), -1)
if err != nil {
return cid.Undef, err
}
return cid.NewCidV1(multibase.Base58BTC, hash), nil
}
// Signature is an accessor that returns the cryptographic signature
// that was created when the Envelope was created or unwrapped.
// Signature returns the cryptographic signature of the Envelope's
// SigPayload.
func (e *Envelope) Signature() []byte {
return e.signature
}
func (e *Envelope) Token() *token.Token {
// Tag returns the key that's used to reference the TokenPayload within
// this Envelope.
func (e *Envelope) Tag() string {
return e.sigPayload.tag
}
// TokenPayload returns the *token.Token enclosed within this Envelope.
func (e *Envelope) TokenPayload() *token.Token {
return e.sigPayload.tokenPayload
}
@@ -142,11 +135,17 @@ func (e *Envelope) VarsigHeader() []byte {
// data created by encoding the SigPayload as DAG-CBOR and the public
// key passed as the only argument.
//
// Note that for Delegation and Invocation Tokeners, the public key
// is retrieved from the DID's method specific identifier.
// Note that for Delegation and Invocation tokens, the public key
// is retrieved from the DID's method specific identifier for the
// Issuer field.
//
// [Envelope]: https://github.com/ucan-wg/spec#envelope
func (e *Envelope) Verify(pubKey crypto.PubKey) (bool, error) {
func (e *Envelope) Verify() (bool, error) {
pubKey, err := did.ToPubKey(e.sigPayload.tokenPayload.Issuer)
if err != nil {
return false, err
}
cbor, err := e.sigPayload.cbor()
if err != nil {
return false, err
@@ -157,35 +156,15 @@ func (e *Envelope) Verify(pubKey crypto.PubKey) (bool, error) {
// Wrap encodes the Envelope as an IPLD datamodel.Node.
func (e *Envelope) Wrap() (datamodel.Node, error) {
sn := bindnode.Wrap(&e.signature, nil)
spn, err := e.sigPayload.wrap()
if err != nil {
return nil, err
}
np := basicnode.Prototype.Any
lb := np.NewBuilder()
la, err := lb.BeginList(2)
if err != nil {
return nil, err
}
if err = la.AssembleValue().AssignNode(sn); err != nil {
return nil, err
}
if err := la.AssembleValue().AssignNode(spn); err != nil {
return nil, err
}
if err := la.Finish(); err != nil {
return nil, err
}
return lb.Build(), nil
return qp.BuildList(basicnode.Prototype.Any, 2, func(la datamodel.ListAssembler) {
qp.ListEntry(la, qp.Bytes(e.signature))
qp.ListEntry(la, qp.Node(spn))
})
}
//
@@ -213,35 +192,90 @@ func newSigPayload(keyType pb.KeyType, token *token.Token, tag string) (*sigPayl
}, nil
}
func unwrapSigPayload(node datamodel.Node, tag string) (*sigPayload, error) {
tokenPayloadNode, err := node.LookupByString(tag)
func unwrapSigPayload(node datamodel.Node) (*sigPayload, error) {
// Normally we could look up the VarsigHeader and TokenPayload using
// node.LookupByString() - this works for the "h" key used for the
// VarsigHeader but not for the TokenPayload's key (tag) as all we
// know is that it starts with "ucan/" and as explained below, must
// decode to a schema.TypedNode for the representation provided by the
// token.Prototype().
// vvv
mi := node.MapIterator()
if mi == nil {
return nil, fmt.Errorf("the SigPayload node is not a map: %s", node.Kind().String())
}
var (
hdrNode datamodel.Node
tknNode datamodel.Node
tag string
)
keyCount := 0
for !mi.Done() {
k, v, err := mi.Next()
if err != nil {
return nil, err
}
kStr, err := k.AsString()
if err != nil {
return nil, fmt.Errorf("the SigPayload keys are not strings: %w", err)
}
keyCount++
if kStr == "h" {
hdrNode = v
continue
}
if strings.HasPrefix(kStr, "ucan/") {
tknNode = v
tag = kStr
}
}
if keyCount != 2 {
return nil, fmt.Errorf("the SigPayload map should have exactly two keys: %d", keyCount)
}
// ^^^
// Replaces the datamodel.Node in tokenPayloadNode with a
// schema.TypedNode so that we can cast it to a *token.Token after
// unwrapping it.
// vvv
nb := token.Prototype().Representation().NewBuilder()
err := nb.AssignNode(tknNode)
if err != nil {
return nil, err
}
tokenPayload := bindnode.Unwrap(tokenPayloadNode)
tknNode = nb.Build()
// ^^^
tokenPayload := bindnode.Unwrap(tknNode)
if tokenPayload == nil {
return nil, errors.New("unexpected type") // TODO
return nil, errors.New("failed to Unwrap the TokenPayload")
}
token, ok := tokenPayload.(*token.Token)
tkn, ok := tokenPayload.(*token.Token)
if !ok {
return nil, errors.New("unexpected type") // TODO
return nil, errors.New("failed to assert the TokenPayload type as *token.Token")
}
headerNode, err := node.LookupByString("h")
if err != nil {
return nil, err
}
header, err := headerNode.AsBytes()
hdr, err := hdrNode.AsBytes()
if err != nil {
return nil, err
}
return &sigPayload{
varsigHeader: header,
tokenPayload: token,
varsigHeader: hdr,
tokenPayload: tkn,
tag: tag,
}, nil
}
@@ -262,29 +296,8 @@ func (sp *sigPayload) cbor() ([]byte, error) {
func (sp *sigPayload) wrap() (datamodel.Node, error) {
tpn := bindnode.Wrap(sp.tokenPayload, token.Prototype().Type())
np := basicnode.Prototype.Any
mb := np.NewBuilder()
ma, err := mb.BeginMap(2)
if err != nil {
return nil, err
}
ha, err := ma.AssembleEntry("h")
if err != nil {
return nil, err
}
ha.AssignBytes(sp.varsigHeader)
ta, err := ma.AssembleEntry(sp.tag)
if err != nil {
return nil, err
}
ta.AssignNode(tpn.Representation())
if err := ma.Finish(); err != nil {
return nil, err
}
return mb.Build(), nil
return qp.BuildMap(basicnode.Prototype.Any, 2, func(ma datamodel.MapAssembler) {
qp.MapEntry(ma, "h", qp.Bytes(sp.varsigHeader))
qp.MapEntry(ma, sp.tag, qp.Node(tpn.Representation()))
})
}

View File

@@ -1,16 +1,16 @@
package envelope_test
import (
"bytes"
"crypto/rand"
"crypto/rsa"
_ "embed"
"encoding/base64"
"testing"
"github.com/ipld/go-ipld-prime"
"github.com/ipld/go-ipld-prime/codec/dagcbor"
"github.com/ipld/go-ipld-prime/codec/dagjson"
"github.com/libp2p/go-libp2p/core/crypto"
"github.com/ipld/go-ipld-prime/datamodel"
"github.com/ipld/go-ipld-prime/fluent/qp"
"github.com/ipld/go-ipld-prime/node/basicnode"
crypto "github.com/libp2p/go-libp2p/core/crypto"
"github.com/stretchr/testify/assert"
"github.com/stretchr/testify/require"
"github.com/ucan-wg/go-ucan/did"
@@ -20,134 +20,181 @@ import (
)
const (
exampleSignature = "G9EFlDm5csIZR+byd5qMFxuaN/gsZmPSeoecW2PqWW8+wYWna9zx0peX1g7mUdo4ZTLTTr8LJSxuF1JFOJR0EsjgM0c8OHuX0WpSv8U+KSNxonbZpZqO8lyI/kW4crl/k9QrWMXtyHLEOS1OD3q9SsNGsf62fk1AMH9W+D2JVBVWdWAYFVXVkXQ+RbJi21lWYc9v/JtHSJbbuCbwhRqEsTBdhcYnyfFLcgLZvR9vqM636gA3ebRjZGZJOiAvxwdTOzlVxtw/552pAx8Od3hRGc5xdG5jGu2/OwIn9UMoXPQl7pMUYqk1nfqN3C7kDelIaQlgoAGyfssepB1tMRH/KA"
exampleTag = "ucan/example@v1.0.0-rc.1"
exampleVarsigHeader = "NIUkEoACcQ"
invalidSignature = "a5BocvMSlifrDzWN7MQpDZ4cEciwe+b9twdQ7d5EZ/LlW3w1VIjk34ci8LqmzMCMwqJsoBqevArUMNS86RrDOLZEl+71+nSf1GJ9fK/E2o7ONSPTQt1wALH1xhJ4S/h5o8v0sWP/PWBvolSfMpro9lN1xCi9zC4iuFmizqdjOd3Ba3txHD5DGAculWBiob3N1mjkXZPbQYEQteCoLwSNDCmmHCE7VpRUkoi832N7UVHlu1FFucENB31qBWZQ+JTj8/oV56Do+LbhrDDiabNkTxulwQ7u+hdKA30vA6FWaA6QW+UE2/mCEKM5wvVAohLPZsapGXP6LoEcbBM3O758dx"
priCfg = "CAASqAkwggSkAgEAAoIBAQDq39Aou82MEteoEz+iKpu7zwJc0dZfomAfB4Zpnl8+WhUOhZyveHDD9lr/UCc/fcN5ufeyZxutDRvIXcmUGG5DNTVRZ10ywT/wN8KO+x/hZ5QIxBAsCFukcyHbAPseLYpAK0J0HNnQhtF6cQcQkuThCnZH/Ofj42d7snuztbBUxwjButvHYHiWwolcJUeb99HCpGwtJYjkp004roFBqjkLayP4AWHrnW4mtCY0rw86gRCT60N1XBZ9zXKw+LJeuQg3RUgZqBL6hvVIs1LAY5ie0LSXVkdjg9bmV7j5SKJBgk9ABoKvt35/KSWA5HW/6g3y/UITCD2DQDrTFv8xzDIvAgMBAAECggEAFoGr6LtWTv3fPHPbvSZoFe8YQty4tiFRJKgL8UMDzW3EZsfW49metKh+v8hmemcKvDddzPKkbEi9SM3z6wUMS9Rlb4+AFsT94370Xc8ilu7d+JkRE6cZYQDHVb0aUyH6BXwfuhCprpm8qQb7rlLlK8tc2jkZ33SDDg9kWywl4XmiDabKm0fOJd68KGuO5FNpCfpipqG3ok/FYuKlSqpCz+7QH2p3z2eVGTa/uIbDMNxkFBoIuhEJT43eDR2elPOrSL9+AYgBPVrzcJoRRxZFVvDDQ+RIwI/A62DvZ3IpFEyzEk2VZwWpLWYKnAUElcSegxx22K7S4BAaWjL86I6cAQKBgQDr8Y1NLYKYffHJAkmWE/ssGcih5C06gOo9WInBU8ZroY4LAhzKLstS0yKsM0OtRSFhZsmCdR3M/IHO94c3KsXu+KtA7r9AG+58LMpmob1mvyGsXIowHFMAd95s3FDd/HOE10tMyrIE1c7eWLfII+s6yGo8MS0WHXOSFBlioukGbwKBgQD+1v3vC+iUNP0FMhVxnhGgONyUb0X+AEw9GOLeCpsugZqRXnharYSiTjGPjwPaT2YBVkyaraoX6VwK+ys3RCngUg4s9IeHUYsR6Xa0oheAlME0ZDtuzi5+lDo+Zpsg8vepgx6v//bKvUcJb+9YDcKlMfQgFnSb3bAwUN9Ru79wQQKBgD7Z/9wZTXq1whzbwSJ7fCNJUwrdL7cv9DYXScr4OBkf1ijUjTrGsF8F42yf011q1vONYAyiiie69BFgGuL1P/jiwSvw7X10c1kczWX9m+is7ZlupVkfknTDebriDaC0yUkP2P1B2Z40HoFYfMyR1O25yaLzLqF/gvPc6s49u3l9AoGBAOZ9d2EdKTfbEToAyYpgyFpc84zBc9G/XTUpbBAeEasnh7CRfFOvezX9eS/5zydGBuGQt2pzRlOoOhqof7bVzPZZ4P5iEK6gXyNNQJMxxAYFBRYozeRzUXQlBuTnksljWAMWV8whu4o1VanAdv7yOymEm+Ply4QqJzAcBU/8erLBAoGBAJ6120n/Q8B7kNW/tZvJ4Xi0u/kSEodNQ9TpF44SB32bn/aWwfe7qFS1x+3omO7XWcx3FLUUPhITQjmQcbNa2yWY0UZoqnzkHhDmJeG2PUILEMCHSLCKQHS+PNJxqEWvwQe2mX/gJIjf14U9983hgLnOL7gH9sVYf9M9yA8NVlem"
exampleDID = "did:key:z6MkpuK2Amsu1RqcLGgmHHQHhvmeXCCBVsM4XFSg2cCyg4Nh"
examplePrivKeyCfg = "CAESQP9v2uqECTuIi45dyg3znQvsryvf2IXmOF/6aws6aCehm0FVrj0zHR5RZSDxWNjcpcJqsGym3sjCungX9Zt5oA4="
exampleSignatureStr = "PZV6A2aI7n+MlyADqcqmWhkuyNrgUCDz+qSLSnI9bpasOwOhKUTx95m5Nu5CO/INa1LqzHGioD9+PVf6qdtTBg"
exampleTag = "ucan/example@v1.0.0-rc.1"
exampleVarsigHeaderStr = "NO0BcQ"
invalidSignatureStr = "PZV6A2aI7n+MlyADqcqmWhkuyNrgUCDz+qSLSnI9bpasOwOhKUTx95m5Nu5CO/INa1LqzHGioD9+PVf6qdtTBK"
exampleDAGCBORFilename = "example.dagcbor"
exampleDAGJSONFilename = "example.dagjson"
)
func TestNew(t *testing.T) {
t.Parallel()
exampleSignature, err := base64.RawStdEncoding.DecodeString(exampleSignature)
require.NoError(t, err)
varsigHeader, err := base64.RawStdEncoding.DecodeString(exampleVarsigHeader)
require.NoError(t, err)
envel := exampleEnvelope(t)
assert.NotZero(t, envel)
env := exampleEnvelope(t)
assert.Equal(t, exampleSignature, env.Signature())
assert.Equal(t, varsigHeader, env.VarsigHeader())
tkn := env.Token()
assert.IsType(t, (*token.Token)(nil), tkn)
// TODO
assert.Equal(t, exampleSignature(t), envel.Signature())
assert.Equal(t, exampleTag, envel.Tag())
assert.Equal(t, exampleVarsigHeader(t), envel.VarsigHeader())
assert.EqualValues(t, exampleGoldenTokenPayload(t), envel.TokenPayload())
}
func TestWrap(t *testing.T) {
t.Parallel()
envNode, err := envelope.Wrap(rsaPrivateKey(t), exampleToken(t), exampleTag)
assert.NoError(t, err)
assert.NotNil(t, envNode)
buf := &bytes.Buffer{}
require.NoError(t, dagcbor.Encode(envNode, buf))
golden.AssertBytes(t, buf.Bytes(), "example.cbor")
// TODO: use golden file
}
func TestEnvelope_Wrap(t *testing.T) {
t.Parallel()
env := exampleEnvelope(t)
envNode, err := env.Wrap()
node, err := envelope.Wrap(examplePrivKey(t), exampleToken(t), exampleTag)
require.NoError(t, err)
buf := &bytes.Buffer{}
require.NoError(t, dagjson.Encode(envNode, buf))
golden.AssertBytes(t, buf.Bytes(), "example.json")
t.Log(buf.String())
env1, err := envelope.Unwrap(envNode, exampleTag)
cbor, err := ipld.Encode(node, dagcbor.Encode)
require.NoError(t, err)
assert.NotNil(t, env1)
t.Log(string(env1.Signature()))
assert.Equal(t, env.Signature(), env1.Signature())
assert.Equal(t, env.VarsigHeader(), env1.VarsigHeader())
assert.Equal(t, env.Token(), env1.Token())
golden.AssertBytes(t, cbor, exampleDAGCBORFilename)
// t.Fail()
json, err := ipld.Encode(node, dagjson.Encode)
require.NoError(t, err)
golden.Assert(t, string(json), exampleDAGJSONFilename)
}
func TestEnvelope_Verify(t *testing.T) {
t.Parallel()
t.Run("true with correct public key", func(t *testing.T) {
t.Run("valid signature by issuer", func(t *testing.T) {
t.Parallel()
env := exampleEnvelope(t)
ok, err := env.Verify(rsaPublicKey(t))
envel := exampleEnvelope(t)
ok, err := envel.Verify()
require.NoError(t, err)
require.True(t, ok)
assert.True(t, ok)
})
t.Run("false with wrong public key", func(t *testing.T) {
t.Run("invalid signature by wrong issuer", func(t *testing.T) {
t.Parallel()
_, pub, err := crypto.GenerateRSAKeyPair(2048, rand.Reader)
envel, err := envelope.Unwrap(invalidNodeFromGolden(t))
require.NoError(t, err)
env := exampleEnvelope(t)
ok, err := env.Verify(pub)
assert.ErrorIs(t, err, rsa.ErrVerification)
ok, _ := envel.Verify()
assert.False(t, ok)
})
}
func TestEnvelope_Wrap(t *testing.T) {
t.Parallel()
envel := exampleEnvelope(t)
node, err := envel.Wrap()
require.NoError(t, err)
cbor, err := ipld.Encode(node, dagcbor.Encode)
require.NoError(t, err)
assert.Equal(t, golden.Get(t, exampleDAGCBORFilename), cbor)
}
func exampleGoldenEnvelope(t *testing.T) *envelope.Envelope {
t.Helper()
envel, err := envelope.Unwrap(exampleGoldenNode(t))
require.NoError(t, err)
return envel
}
func exampleGoldenNode(t *testing.T) datamodel.Node {
t.Helper()
cbor := golden.Get(t, exampleDAGCBORFilename)
node, err := ipld.Decode(cbor, dagcbor.Decode)
require.NoError(t, err)
return node
}
func exampleGoldenTokenPayload(t *testing.T) *token.Token {
t.Helper()
return exampleGoldenEnvelope(t).TokenPayload()
}
func examplePrivKey(t *testing.T) crypto.PrivKey {
t.Helper()
privKeyEnc, err := crypto.ConfigDecodeKey(examplePrivKeyCfg)
require.NoError(t, err)
privKey, err := crypto.UnmarshalPrivateKey(privKeyEnc)
require.NoError(t, err)
return privKey
}
func exampleEnvelope(t *testing.T) *envelope.Envelope {
t.Helper()
env, err := envelope.New(rsaPrivateKey(t), exampleToken(t), exampleTag)
envel, err := envelope.New(examplePrivKey(t), exampleToken(t), exampleTag)
require.NoError(t, err)
t.Log("exampleEnvelope.Signature", base64.RawStdEncoding.EncodeToString(env.Signature()))
return envel
}
return env
func examplePubKey(t *testing.T) crypto.PubKey {
t.Helper()
return examplePrivKey(t).GetPublic()
}
func exampleSignature(t *testing.T) []byte {
t.Helper()
sig, err := base64.RawStdEncoding.DecodeString(exampleSignatureStr)
require.NoError(t, err)
return sig
}
func exampleToken(t *testing.T) *token.Token {
t.Helper()
id, err := did.Parse("did:key:z6MkhaXgBZDvotDkL5257faiztiGiC2QtKLGpbnnEGta2doK")
require.NoError(t, err)
_ = id // TODO:
tkn, err := token.New() // TODO: fields
id, err := did.FromPubKey(examplePubKey(t))
require.NoError(t, err)
return tkn
return &token.Token{
Issuer: id.String(),
}
}
func rsaPrivateKey(t *testing.T) crypto.PrivKey {
func exampleVarsigHeader(t *testing.T) []byte {
t.Helper()
priEnc, err := crypto.ConfigDecodeKey(priCfg)
require.NoError(t, err)
pri, err := crypto.UnmarshalPrivateKey(priEnc)
hdr, err := base64.RawStdEncoding.DecodeString(exampleVarsigHeaderStr)
require.NoError(t, err)
return pri
return hdr
}
func rsaPublicKey(t *testing.T) crypto.PubKey {
func invalidNodeFromGolden(t *testing.T) datamodel.Node {
t.Helper()
return rsaPrivateKey(t).GetPublic()
invalidSig, err := base64.RawStdEncoding.DecodeString(invalidSignatureStr)
require.NoError(t, err)
envelNode := exampleGoldenNode(t)
sigPayloadNode, err := envelNode.LookupByIndex(1)
require.NoError(t, err)
node, err := qp.BuildList(basicnode.Prototype.Any, 2, func(la datamodel.ListAssembler) {
qp.ListEntry(la, qp.Bytes(invalidSig))
qp.ListEntry(la, qp.Node(sigPayloadNode))
})
require.NoError(t, err)
return node
}

Binary file not shown.

View File

@@ -0,0 +1 @@
X@=•zfˆîŒ— ©Ê¦Z.ÈÚàP óú¤Jr=n¬;¡)Dñ÷™¹6îB;ò

View File

@@ -0,0 +1 @@
[{"/":{"bytes":"PZV6A2aI7n+MlyADqcqmWhkuyNrgUCDz+qSLSnI9bpasOwOhKUTx95m5Nu5CO/INa1LqzHGioD9+PVf6qdtTBg"}},{"h":{"/":{"bytes":"NO0BcQ"}},"ucan/example@v1.0.0-rc.1":{"cmd":"","exp":null,"iss":"did:key:z6MkpuK2Amsu1RqcLGgmHHQHhvmeXCCBVsM4XFSg2cCyg4Nh","sub":null}}]

View File

@@ -1 +0,0 @@
[{"/":{"bytes":"G9EFlDm5csIZR+byd5qMFxuaN/gsZmPSeoecW2PqWW8+wYWna9zx0peX1g7mUdo4ZTLTTr8LJSxuF1JFOJR0EsjgM0c8OHuX0WpSv8U+KSNxonbZpZqO8lyI/kW4crl/k9QrWMXtyHLEOS1OD3q9SsNGsf62fk1AMH9W+D2JVBVWdWAYFVXVkXQ+RbJi21lWYc9v/JtHSJbbuCbwhRqEsTBdhcYnyfFLcgLZvR9vqM636gA3ebRjZGZJOiAvxwdTOzlVxtw/552pAx8Od3hRGc5xdG5jGu2/OwIn9UMoXPQl7pMUYqk1nfqN3C7kDelIaQlgoAGyfssepB1tMRH/KA"}},{"h":{"/":{"bytes":"NIUkEoACcQ"}},"ucan/example@v1.0.0-rc.1":{"cmd":"","exp":null,"iss":"","sub":null}}]

View File

@@ -0,0 +1,24 @@
package token
import (
"github.com/ipld/go-ipld-prime/datamodel"
)
func ToIPLDMapStringAny(m map[string]datamodel.Node) Map__String__Any {
keys := make([]string, len(m))
i := 0
for k := range m {
keys[i] = k
i++
}
return Map__String__Any{
Keys: keys,
Values: m,
}
}
func FromIPLDMapStringAny(m Map__String__Any) map[string]datamodel.Node {
return m.Values
}

View File

@@ -0,0 +1,33 @@
// Package token provides a generic model of the [TokenPayload] required
// within an Envelope.
//
// # Field requirements
//
// While the Token object represents the wire format of both a UCAN
// Delegation token and a UCAN Invocation token, the delegation and
// invocation packages are, respectively, responsible for making sure
// required fields are included when creating a new Token or when
// validating the contents of an Envelope as it's received from
// another party. The following table shows the current (as of
// 2024-09-11) relationship between optional and nullable fields in
// the delegation and invocation views and the payload model:
//
// | Name | Delegation | Invocation | Token |
// | | Required | Nullable | Required | Nullable | |
// | ----- | -------- | -------- | -------- | -------- | -------- |
// | iss | Yes | No | Yes | No | |
// | aud | Yes | No | No | N/A | Optional |
// | sub | Yes | Yes | Yes | No | Nullable |
// | cmd | Yes | No | Yes | No | |
// | pol | Yes | No | X | X | Optional |
// | nonce | Yes | No | No | N/A | Optional |
// | meta | No | N/A | No | N/A | Optional |
// | nbf | No | N/A | X | X | Optional |
// | exp | Yes | Yes | Yes | Yes | |
// | args | X | X | Yes | No | Optional |
// | prf | X | X | Yes | No | Optional |
// | iat | X | X | No | N/A | Optional |
// | cause | X | X | No | N/A | Optional |
//
// [TokenPayload]: https://github.com/ucan-wg/spec?tab=readme-ov-file#envelope
package token

View File

@@ -7,3 +7,5 @@ var ErrFailedSchemaLoad = errors.New("failed to load IPLD Schema")
var ErrNoSchemaType = errors.New("schema does not contain type")
var ErrNodeNotToken = errors.New("IPLD node is not a Token")
var ErrMissingRequiredDID = errors.New("a required DID is missing")

View File

@@ -77,6 +77,7 @@ func TestSchemaRoundTrip(t *testing.T) {
func BenchmarkSchemaLoad(b *testing.B) {
b.ReportAllocs()
for i := 0; i < b.N; i++ {
_, _ = ipld.LoadSchemaBytes(schemaBytes)
}

View File

@@ -7,10 +7,12 @@ import (
//go:generate go run ../cmd/token/...
func New() (*Token, error) {
return &Token{}, nil
}
// Unwrap creates a Token from an arbitrary IPLD node or returns an
// error if at least the required model fields are not present.
//
// It is the responsibility of the Delegation and Invocation views
// to further validate the presence of the required fields and the
// content as needed.
func Unwrap(node datamodel.Node) (*Token, error) {
iface := bindnode.Unwrap(node)
if iface == nil {
@@ -25,6 +27,7 @@ func Unwrap(node datamodel.Node) (*Token, error) {
return tkn, nil
}
// Wrap creates an IPLD node representing the Token.
func (t *Token) Wrap() datamodel.Node {
return bindnode.Wrap(t, tokenType())
}

View File

@@ -8,7 +8,7 @@ type DID string
# Field requirements:
#
# | Name | Delegation | Invocation | Token |
# | | Required | Nullable | Required | Nullable | |
# | | Required | Nullable | Required | Nullable | |
# | ----- | -------- | -------- | -------- | -------- | -------- |
# | iss | Yes | No | Yes | No | |
# | aud | Yes | No | No | N/A | Optional |
@@ -18,7 +18,7 @@ type DID string
# | nonce | Yes | No | No | N/A | Optional |
# | meta | No | N/A | No | N/A | Optional |
# | nbf | No | N/A | X | X | Optional |
# | exp | Yes | Yes | Yes | Yes | |
# | exp | Yes | Yes | Yes | Yes | Nullable |
# | args | X | X | Yes | No | Optional |
# | prf | X | X | Yes | No | Optional |
# | iat | X | X | No | N/A | Optional |
@@ -40,10 +40,10 @@ type Token struct {
policy optional Any (rename "pol")
# The invocation's arguments
args optional {String: Any}
arguments optional {String: Any} (rename "args")
# Delegations that prove the chain of authority
prf optional [CID]
Proofs optional [CID] (rename "prf")
# A unique, random nonce
nonce optional Bytes

View File

@@ -20,8 +20,8 @@ type Token struct {
Subject *string
Command string
Policy *datamodel.Node
Args *Map__String__Any
Prf *List__CID
Arguments *Map__String__Any
Proofs *List__CID
Nonce *[]uint8
Meta *Map__String__Any
NotBefore *int

View File

@@ -12,8 +12,7 @@ import (
func TestEncode(t *testing.T) {
t.Parallel()
tkn, err := token.New()
require.NoError(t, err)
tkn := &token.Token{}
node := tkn.Wrap()
@@ -24,3 +23,33 @@ func TestEncode(t *testing.T) {
t.Fail()
}
func TestPrototype(t *testing.T) {
t.Parallel()
tkn := &token.Token{
Issuer: "blah",
}
n1 := tkn.Wrap()
json, err := ipld.Encode(n1, dagjson.Encode)
require.NoError(t, err)
t.Log(string(json))
n2, err := ipld.Decode(json, dagjson.Decode)
require.NoError(t, err)
nb := token.Prototype().Representation().NewBuilder()
require.NoError(t, nb.AssignNode(n2))
n3 := nb.Build()
tkn2, err := token.Unwrap(n3)
require.NoError(t, err)
t.Log(tkn2)
require.Equal(t, tkn, tkn2)
t.Fail()
}

View File

@@ -3,5 +3,5 @@
package tools
import (
_ "github.com/launchdarkly/go-options"
_ "github.com/selesy/go-options"
)