mirror of
https://github.com/sonr-io/common.git
synced 2026-01-11 20:08:57 +00:00
refactor(common): extract common utilities for IPFS and WebAuthn
This commit is contained in:
100
go.mod
100
go.mod
@@ -1,7 +1,101 @@
|
|||||||
module github.com/sonr-io/common
|
module github.com/sonr-io/common
|
||||||
|
|
||||||
go 1.24.7
|
go 1.25
|
||||||
|
|
||||||
replace (
|
require (
|
||||||
nhooyr.io/websocket => github.com/coder/websocket v1.8.14
|
github.com/biter777/countries v1.7.5
|
||||||
|
github.com/fxamacker/cbor/v2 v2.9.0
|
||||||
|
github.com/golang-jwt/jwt/v5 v5.3.0
|
||||||
|
github.com/google/go-tpm v0.9.6
|
||||||
|
github.com/google/uuid v1.6.0
|
||||||
|
github.com/ipfs/boxo v0.35.0
|
||||||
|
github.com/ipfs/kubo v0.38.1
|
||||||
|
github.com/mitchellh/mapstructure v1.5.0
|
||||||
|
github.com/stretchr/testify v1.11.1
|
||||||
|
golang.org/x/crypto v0.42.0
|
||||||
|
)
|
||||||
|
|
||||||
|
require (
|
||||||
|
github.com/alecthomas/units v0.0.0-20240927000941-0f3dac36c52b // indirect
|
||||||
|
github.com/beorn7/perks v1.0.1 // indirect
|
||||||
|
github.com/blang/semver/v4 v4.0.0 // indirect
|
||||||
|
github.com/cespare/xxhash/v2 v2.3.0 // indirect
|
||||||
|
github.com/crackcomm/go-gitignore v0.0.0-20241020182519-7843d2ba8fdf // indirect
|
||||||
|
github.com/davecgh/go-spew v1.1.2-0.20180830191138-d8f796af33cc // indirect
|
||||||
|
github.com/decred/dcrd/dcrec/secp256k1/v4 v4.4.0 // indirect
|
||||||
|
github.com/gammazero/chanqueue v1.1.1 // indirect
|
||||||
|
github.com/gammazero/deque v1.1.0 // indirect
|
||||||
|
github.com/go-logr/logr v1.4.3 // indirect
|
||||||
|
github.com/go-logr/stdr v1.2.2 // indirect
|
||||||
|
github.com/google/gopacket v1.1.19 // indirect
|
||||||
|
github.com/hashicorp/golang-lru v1.0.2 // indirect
|
||||||
|
github.com/hashicorp/golang-lru/v2 v2.0.7 // indirect
|
||||||
|
github.com/ipfs/bbloom v0.0.4 // indirect
|
||||||
|
github.com/ipfs/go-bitfield v1.1.0 // indirect
|
||||||
|
github.com/ipfs/go-block-format v0.2.3 // indirect
|
||||||
|
github.com/ipfs/go-cid v0.5.0 // indirect
|
||||||
|
github.com/ipfs/go-cidutil v0.1.0 // indirect
|
||||||
|
github.com/ipfs/go-datastore v0.9.0 // indirect
|
||||||
|
github.com/ipfs/go-dsqueue v0.0.5 // indirect
|
||||||
|
github.com/ipfs/go-ipfs-cmds v0.15.0 // indirect
|
||||||
|
github.com/ipfs/go-ipld-format v0.6.3 // indirect
|
||||||
|
github.com/ipfs/go-ipld-legacy v0.2.2 // indirect
|
||||||
|
github.com/ipfs/go-log/v2 v2.8.1 // indirect
|
||||||
|
github.com/ipfs/go-metrics-interface v0.3.0 // indirect
|
||||||
|
github.com/ipld/go-codec-dagpb v1.7.0 // indirect
|
||||||
|
github.com/ipld/go-ipld-prime v0.21.0 // indirect
|
||||||
|
github.com/klauspost/cpuid/v2 v2.3.0 // indirect
|
||||||
|
github.com/libp2p/go-buffer-pool v0.1.0 // indirect
|
||||||
|
github.com/libp2p/go-cidranger v1.1.0 // indirect
|
||||||
|
github.com/libp2p/go-libp2p v0.43.0 // indirect
|
||||||
|
github.com/libp2p/go-libp2p-asn-util v0.4.1 // indirect
|
||||||
|
github.com/libp2p/go-libp2p-kad-dht v0.35.0 // indirect
|
||||||
|
github.com/libp2p/go-libp2p-kbucket v0.8.0 // indirect
|
||||||
|
github.com/libp2p/go-libp2p-record v0.3.1 // indirect
|
||||||
|
github.com/libp2p/go-libp2p-routing-helpers v0.7.5 // indirect
|
||||||
|
github.com/libp2p/go-msgio v0.3.0 // indirect
|
||||||
|
github.com/libp2p/go-netroute v0.2.2 // indirect
|
||||||
|
github.com/mattn/go-isatty v0.0.20 // indirect
|
||||||
|
github.com/miekg/dns v1.1.68 // 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-multiaddr v0.16.1 // indirect
|
||||||
|
github.com/multiformats/go-multiaddr-dns v0.4.1 // indirect
|
||||||
|
github.com/multiformats/go-multibase v0.2.0 // indirect
|
||||||
|
github.com/multiformats/go-multicodec v0.9.2 // indirect
|
||||||
|
github.com/multiformats/go-multihash v0.2.3 // indirect
|
||||||
|
github.com/multiformats/go-multistream v0.6.1 // indirect
|
||||||
|
github.com/multiformats/go-varint v0.1.0 // indirect
|
||||||
|
github.com/munnerz/goautoneg v0.0.0-20191010083416-a7dc8b61c822 // indirect
|
||||||
|
github.com/pmezard/go-difflib v1.0.1-0.20181226105442-5d4384ee4fb2 // indirect
|
||||||
|
github.com/polydawn/refmt v0.89.0 // indirect
|
||||||
|
github.com/prometheus/client_golang v1.23.2 // indirect
|
||||||
|
github.com/prometheus/client_model v0.6.2 // indirect
|
||||||
|
github.com/prometheus/common v0.66.1 // indirect
|
||||||
|
github.com/prometheus/procfs v0.17.0 // indirect
|
||||||
|
github.com/rs/cors v1.11.1 // indirect
|
||||||
|
github.com/spaolacci/murmur3 v1.1.0 // indirect
|
||||||
|
github.com/whyrusleeping/base32 v0.0.0-20170828182744-c30ac30633cc // indirect
|
||||||
|
github.com/whyrusleeping/chunker v0.0.0-20181014151217-fe64bd25879f // indirect
|
||||||
|
github.com/whyrusleeping/go-keyspace v0.0.0-20160322163242-5b898ac5add1 // indirect
|
||||||
|
github.com/x448/float16 v0.8.4 // indirect
|
||||||
|
go.opentelemetry.io/auto/sdk v1.2.1 // indirect
|
||||||
|
go.opentelemetry.io/otel v1.38.0 // indirect
|
||||||
|
go.opentelemetry.io/otel/metric v1.38.0 // indirect
|
||||||
|
go.opentelemetry.io/otel/trace v1.38.0 // indirect
|
||||||
|
go.uber.org/multierr v1.11.0 // indirect
|
||||||
|
go.uber.org/zap v1.27.0 // indirect
|
||||||
|
go.yaml.in/yaml/v2 v2.4.3 // indirect
|
||||||
|
golang.org/x/exp v0.0.0-20250911091902-df9299821621 // indirect
|
||||||
|
golang.org/x/mod v0.28.0 // indirect
|
||||||
|
golang.org/x/net v0.44.0 // indirect
|
||||||
|
golang.org/x/sync v0.17.0 // indirect
|
||||||
|
golang.org/x/sys v0.36.0 // indirect
|
||||||
|
golang.org/x/tools v0.37.0 // indirect
|
||||||
|
gonum.org/v1/gonum v0.16.0 // indirect
|
||||||
|
google.golang.org/protobuf v1.36.9 // indirect
|
||||||
|
gopkg.in/yaml.v3 v3.0.1 // indirect
|
||||||
|
lukechampine.com/blake3 v1.4.1 // indirect
|
||||||
)
|
)
|
||||||
|
|||||||
438
go.sum
Normal file
438
go.sum
Normal file
@@ -0,0 +1,438 @@
|
|||||||
|
github.com/BurntSushi/toml v0.3.1/go.mod h1:xHWCNGjB5oqiDr8zfno3MHue2Ht5sIBksp03qcyfWMU=
|
||||||
|
github.com/DataDog/zstd v1.5.7 h1:ybO8RBeh29qrxIhCA9E8gKY6xfONU9T6G6aP9DTKfLE=
|
||||||
|
github.com/DataDog/zstd v1.5.7/go.mod h1:g4AWEaM3yOg3HYfnJ3YIawPnVdXJh9QME85blwSAmyw=
|
||||||
|
github.com/Jorropo/jsync v1.0.1 h1:6HgRolFZnsdfzRUj+ImB9og1JYOxQoReSywkHOGSaUU=
|
||||||
|
github.com/Jorropo/jsync v1.0.1/go.mod h1:jCOZj3vrBCri3bSU3ErUYvevKlnbssrXeCivybS5ABQ=
|
||||||
|
github.com/RaduBerinde/axisds v0.0.0-20250419182453-5135a0650657 h1:8XBWWQD+vFF+JqOsm16t0Kab1a7YWV8+GISVEP8AuZ8=
|
||||||
|
github.com/RaduBerinde/axisds v0.0.0-20250419182453-5135a0650657/go.mod h1:UHGJonU9z4YYGKJxSaC6/TNcLOBptpmM5m2Cksbnw0Y=
|
||||||
|
github.com/RaduBerinde/btreemap v0.0.0-20250419174037-3d62b7205d54 h1:bsU8Tzxr/PNz75ayvCnxKZWEYdLMPDkUgticP4a4Bvk=
|
||||||
|
github.com/RaduBerinde/btreemap v0.0.0-20250419174037-3d62b7205d54/go.mod h1:0tr7FllbE9gJkHq7CVeeDDFAFKQVy5RnCSSNBOvdqbc=
|
||||||
|
github.com/alecthomas/units v0.0.0-20240927000941-0f3dac36c52b h1:mimo19zliBX/vSQ6PWWSL9lK8qwHozUj03+zLoEB8O0=
|
||||||
|
github.com/alecthomas/units v0.0.0-20240927000941-0f3dac36c52b/go.mod h1:fvzegU4vN3H1qMT+8wDmzjAcDONcgo2/SZ/TyfdUOFs=
|
||||||
|
github.com/benbjohnson/clock v1.3.5 h1:VvXlSJBzZpA/zum6Sj74hxwYI2DIxRWuNIoXAzHZz5o=
|
||||||
|
github.com/benbjohnson/clock v1.3.5/go.mod h1:J11/hYXuz8f4ySSvYwY0FKfm+ezbsZBKZxNJlLklBHA=
|
||||||
|
github.com/beorn7/perks v1.0.1 h1:VlbKKnNfV8bJzeqoa4cOKqO6bYr3WgKZxO8Z16+hsOM=
|
||||||
|
github.com/beorn7/perks v1.0.1/go.mod h1:G2ZrVWU2WbWT9wwq4/hrbKbnv/1ERSJQ0ibhJ6rlkpw=
|
||||||
|
github.com/biter777/countries v1.7.5 h1:MJ+n3+rSxWQdqVJU8eBy9RqcdH6ePPn4PJHocVWUa+Q=
|
||||||
|
github.com/biter777/countries v1.7.5/go.mod h1:1HSpZ526mYqKJcpT5Ti1kcGQ0L0SrXWIaptUWjFfv2E=
|
||||||
|
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/caddyserver/certmagic v0.23.0 h1:CfpZ/50jMfG4+1J/u2LV6piJq4HOfO6ppOnOf7DkFEU=
|
||||||
|
github.com/caddyserver/certmagic v0.23.0/go.mod h1:9mEZIWqqWoI+Gf+4Trh04MOVPD0tGSxtqsxg87hAIH4=
|
||||||
|
github.com/caddyserver/zerossl v0.1.3 h1:onS+pxp3M8HnHpN5MMbOMyNjmTheJyWRaZYwn+YTAyA=
|
||||||
|
github.com/caddyserver/zerossl v0.1.3/go.mod h1:CxA0acn7oEGO6//4rtrRjYgEoa4MFw/XofZnrYwGqG4=
|
||||||
|
github.com/cespare/xxhash/v2 v2.3.0 h1:UL815xU9SqsFlibzuggzjXhog7bL6oX9BbNZnL2UFvs=
|
||||||
|
github.com/cespare/xxhash/v2 v2.3.0/go.mod h1:VGX0DQ3Q6kWi7AoAeZDth3/j3BFtOZR5XLFGgcrjCOs=
|
||||||
|
github.com/cockroachdb/crlib v0.0.0-20241112164430-1264a2edc35b h1:SHlYZ/bMx7frnmeqCu+xm0TCxXLzX3jQIVuFbnFGtFU=
|
||||||
|
github.com/cockroachdb/crlib v0.0.0-20241112164430-1264a2edc35b/go.mod h1:Gq51ZeKaFCXk6QwuGM0w1dnaOqc/F5zKT2zA9D6Xeac=
|
||||||
|
github.com/cockroachdb/errors v1.11.3 h1:5bA+k2Y6r+oz/6Z/RFlNeVCesGARKuC6YymtcDrbC/I=
|
||||||
|
github.com/cockroachdb/errors v1.11.3/go.mod h1:m4UIW4CDjx+R5cybPsNrRbreomiFqt8o1h1wUVazSd8=
|
||||||
|
github.com/cockroachdb/logtags v0.0.0-20230118201751-21c54148d20b h1:r6VH0faHjZeQy818SGhaone5OnYfxFR/+AzdY3sf5aE=
|
||||||
|
github.com/cockroachdb/logtags v0.0.0-20230118201751-21c54148d20b/go.mod h1:Vz9DsVWQQhf3vs21MhPMZpMGSht7O/2vFW2xusFUVOs=
|
||||||
|
github.com/cockroachdb/pebble/v2 v2.1.0 h1:6KZvjSpWcEXZUvlLzTRC7T1A2G7r+bFskIzggklxixo=
|
||||||
|
github.com/cockroachdb/pebble/v2 v2.1.0/go.mod h1:Aza05DCCc05ghIJZkB4Q/axv/JK9wx5cFwWcnhG0eGw=
|
||||||
|
github.com/cockroachdb/redact v1.1.5 h1:u1PMllDkdFfPWaNGMyLD1+so+aq3uUItthCFqzwPJ30=
|
||||||
|
github.com/cockroachdb/redact v1.1.5/go.mod h1:BVNblN9mBWFyMyqK1k3AAiSxhvhfK2oOZZ2lK+dpvRg=
|
||||||
|
github.com/cockroachdb/swiss v0.0.0-20250624142022-d6e517c1d961 h1:Nua446ru3juLHLZd4AwKNzClZgL1co3pUPGv3o8FlcA=
|
||||||
|
github.com/cockroachdb/swiss v0.0.0-20250624142022-d6e517c1d961/go.mod h1:yBRu/cnL4ks9bgy4vAASdjIW+/xMlFwuHKqtmh3GZQg=
|
||||||
|
github.com/cockroachdb/tokenbucket v0.0.0-20230807174530-cc333fc44b06 h1:zuQyyAKVxetITBuuhv3BI9cMrmStnpT18zmgmTxunpo=
|
||||||
|
github.com/cockroachdb/tokenbucket v0.0.0-20230807174530-cc333fc44b06/go.mod h1:7nc4anLGjupUW/PeY5qiNYsdNXj7zopG+eqsS7To5IQ=
|
||||||
|
github.com/cpuguy83/go-md2man/v2 v2.0.0-20190314233015-f79a8a8ca69d/go.mod h1:maD7wRr/U5Z6m/iR4s+kqSMx2CaBsrgA7czyZG/E6dU=
|
||||||
|
github.com/crackcomm/go-gitignore v0.0.0-20241020182519-7843d2ba8fdf h1:dwGgBWn84wUS1pVikGiruW+x5XM4amhjaZO20vCjay4=
|
||||||
|
github.com/crackcomm/go-gitignore v0.0.0-20241020182519-7843d2ba8fdf/go.mod h1:p1d6YEZWvFzEh4KLyvBcVSnrfNDDvK2zfK/4x2v/4pE=
|
||||||
|
github.com/cskr/pubsub v1.0.2 h1:vlOzMhl6PFn60gRlTQQsIfVwaPB/B/8MziK8FhEPt/0=
|
||||||
|
github.com/cskr/pubsub v1.0.2/go.mod h1:/8MzYXk/NJAz782G8RPkFzXTZVu63VotefPnR9TIRis=
|
||||||
|
github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
|
||||||
|
github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
|
||||||
|
github.com/davecgh/go-spew v1.1.2-0.20180830191138-d8f796af33cc h1:U9qPSI2PIWSS1VwoXQT9A3Wy9MM3WgvqSxFWenqJduM=
|
||||||
|
github.com/davecgh/go-spew v1.1.2-0.20180830191138-d8f796af33cc/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
|
||||||
|
github.com/davidlazar/go-crypto v0.0.0-20200604182044-b73af7476f6c h1:pFUpOrbxDR6AkioZ1ySsx5yxlDQZ8stG2b88gTPxgJU=
|
||||||
|
github.com/davidlazar/go-crypto v0.0.0-20200604182044-b73af7476f6c/go.mod h1:6UhI8N9EjYm1c2odKpFpAYeR8dsBeM7PtzQhRgxRr9U=
|
||||||
|
github.com/decred/dcrd/crypto/blake256 v1.1.0 h1:zPMNGQCm0g4QTY27fOCorQW7EryeQ/U0x++OzVrdms8=
|
||||||
|
github.com/decred/dcrd/crypto/blake256 v1.1.0/go.mod h1:2OfgNZ5wDpcsFmHmCK5gZTPcCXqlm2ArzUIkw9czNJo=
|
||||||
|
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/dustin/go-humanize v1.0.1 h1:GzkhY7T5VNhEkwH0PVJgjz+fX1rhBrR7pRT3mDkpeCY=
|
||||||
|
github.com/dustin/go-humanize v1.0.1/go.mod h1:Mu1zIs6XwVuF/gI1OepvI0qD18qycQx+mFykh5fBlto=
|
||||||
|
github.com/facebookgo/atomicfile v0.0.0-20151019160806-2de1f203e7d5 h1:BBso6MBKW8ncyZLv37o+KNyy0HrrHgfnOaGQC2qvN+A=
|
||||||
|
github.com/facebookgo/atomicfile v0.0.0-20151019160806-2de1f203e7d5/go.mod h1:JpoxHjuQauoxiFMl1ie8Xc/7TfLuMZ5eOCONd1sUBHg=
|
||||||
|
github.com/felixge/httpsnoop v1.0.4 h1:NFTV2Zj1bL4mc9sqWACXbQFVBBg2W3GPvqp8/ESS2Wg=
|
||||||
|
github.com/felixge/httpsnoop v1.0.4/go.mod h1:m8KPJKqk1gH5J9DgRY2ASl2lWCfGKXixSwevea8zH2U=
|
||||||
|
github.com/filecoin-project/go-clock v0.1.0 h1:SFbYIM75M8NnFm1yMHhN9Ahy3W5bEZV9gd6MPfXbKVU=
|
||||||
|
github.com/filecoin-project/go-clock v0.1.0/go.mod h1:4uB/O4PvOjlx1VCMdZ9MyDZXRm//gkj1ELEbxfI1AZs=
|
||||||
|
github.com/flynn/noise v1.1.0 h1:KjPQoQCEFdZDiP03phOvGi11+SVVhBG2wOWAorLsstg=
|
||||||
|
github.com/flynn/noise v1.1.0/go.mod h1:xbMo+0i6+IGbYdJhF31t2eR1BIU0CYc12+BNAKwUTag=
|
||||||
|
github.com/francoispqt/gojay v1.2.13 h1:d2m3sFjloqoIUQU3TsHBgj6qg/BVGlTBeHDUmyJnXKk=
|
||||||
|
github.com/francoispqt/gojay v1.2.13/go.mod h1:ehT5mTG4ua4581f1++1WLG0vPdaA9HaiDsoyrBGkyDY=
|
||||||
|
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/fxamacker/cbor/v2 v2.9.0 h1:NpKPmjDBgUfBms6tr6JZkTHtfFGcMKsw3eGcmD/sapM=
|
||||||
|
github.com/fxamacker/cbor/v2 v2.9.0/go.mod h1:vM4b+DJCtHn+zz7h3FFp/hDAI9WNWCsZj23V5ytsSxQ=
|
||||||
|
github.com/gabriel-vasile/mimetype v1.4.10 h1:zyueNbySn/z8mJZHLt6IPw0KoZsiQNszIpU+bX4+ZK0=
|
||||||
|
github.com/gabriel-vasile/mimetype v1.4.10/go.mod h1:d+9Oxyo1wTzWdyVUPMmXFvp4F9tea18J8ufA774AB3s=
|
||||||
|
github.com/gammazero/chanqueue v1.1.1 h1:n9Y+zbBxw2f7uUE9wpgs0rOSkP/I/yhDLiNuhyVjojQ=
|
||||||
|
github.com/gammazero/chanqueue v1.1.1/go.mod h1:fMwpwEiuUgpab0sH4VHiVcEoji1pSi+EIzeG4TPeKPc=
|
||||||
|
github.com/gammazero/deque v1.1.0 h1:OyiyReBbnEG2PP0Bnv1AASLIYvyKqIFN5xfl1t8oGLo=
|
||||||
|
github.com/gammazero/deque v1.1.0/go.mod h1:JVrR+Bj1NMQbPnYclvDlvSX0nVGReLrQZ0aUMuWLctg=
|
||||||
|
github.com/getsentry/sentry-go v0.27.0 h1:Pv98CIbtB3LkMWmXi4Joa5OOcwbmnX88sF5qbK3r3Ps=
|
||||||
|
github.com/getsentry/sentry-go v0.27.0/go.mod h1:lc76E2QywIyW8WuBnwl8Lc4bkmQH4+w1gwTf25trprY=
|
||||||
|
github.com/go-logr/logr v1.2.2/go.mod h1:jdQByPbusPIv2/zmleS9BjJVeZ6kBagPoEUsqbVz/1A=
|
||||||
|
github.com/go-logr/logr v1.4.3 h1:CjnDlHq8ikf6E492q6eKboGOC0T8CDaOvkHCIg8idEI=
|
||||||
|
github.com/go-logr/logr v1.4.3/go.mod h1:9T104GzyrTigFIr8wt5mBrctHMim0Nb2HLGrmQ40KvY=
|
||||||
|
github.com/go-logr/stdr v1.2.2 h1:hSWxHoqTgW2S2qGc0LTAI563KZ5YKYRhT3MFKZMbjag=
|
||||||
|
github.com/go-logr/stdr v1.2.2/go.mod h1:mMo/vtBO5dYbehREoey6XUKy/eSumjCCveDpRre4VKE=
|
||||||
|
github.com/go-yaml/yaml v2.1.0+incompatible/go.mod h1:w2MrLa16VYP0jy6N7M5kHaCkaLENm+P+Tv+MfurjSw0=
|
||||||
|
github.com/gogo/protobuf v1.3.2 h1:Ov1cvc58UF3b5XjBnZv7+opcTcQFZebYjWzi34vdm4Q=
|
||||||
|
github.com/gogo/protobuf v1.3.2/go.mod h1:P1XiOD3dCwIKUDQYPy72D8LYyHL2YPYrpS2s69NZV8Q=
|
||||||
|
github.com/golang-jwt/jwt/v5 v5.3.0 h1:pv4AsKCKKZuqlgs5sUmn4x8UlGa0kEVt/puTpKx9vvo=
|
||||||
|
github.com/golang-jwt/jwt/v5 v5.3.0/go.mod h1:fxCRLWMO43lRc8nhHWY6LGqRcf+1gQWArsqaEUEa5bE=
|
||||||
|
github.com/golang/snappy v0.0.5-0.20231225225746-43d5d4cd4e0e h1:4bw4WeyTYPp0smaXiJZCNnLrvVBqirQVreixayXezGc=
|
||||||
|
github.com/golang/snappy v0.0.5-0.20231225225746-43d5d4cd4e0e/go.mod h1:/XxbfmMg8lxefKM7IXC3fBNl/7bRcc72aCRzEWrmP2Q=
|
||||||
|
github.com/google/go-cmp v0.7.0 h1:wk8382ETsv4JYUZwIsn6YpYiWiBsYLSJiTsyBybVuN8=
|
||||||
|
github.com/google/go-cmp v0.7.0/go.mod h1:pXiqmnSA92OHEEa9HXL2W4E7lf9JzCmGVUdgjX3N/iU=
|
||||||
|
github.com/google/go-tpm v0.9.6 h1:Ku42PT4LmjDu1H5C5ISWLlpI1mj+Zq7sPGKoRw2XROA=
|
||||||
|
github.com/google/go-tpm v0.9.6/go.mod h1:h9jEsEECg7gtLis0upRBQU+GhYVH6jMjrFxI8u6bVUY=
|
||||||
|
github.com/google/gopacket v1.1.19 h1:ves8RnFZPGiFnTS0uPQStjwru6uO6h+nlr9j6fL7kF8=
|
||||||
|
github.com/google/gopacket v1.1.19/go.mod h1:iJ8V8n6KS+z2U1A8pUwu8bW5SyEMkXJB8Yo/Vo+TKTo=
|
||||||
|
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/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/gorilla/websocket v1.5.3 h1:saDtZ6Pbx/0u+bgYQ3q96pZgCzfhKXGPqt7kZ72aNNg=
|
||||||
|
github.com/gorilla/websocket v1.5.3/go.mod h1:YR8l580nyteQvAITg2hZ9XVh4b55+EU/adAjf1fMHhE=
|
||||||
|
github.com/hashicorp/golang-lru v1.0.2 h1:dV3g9Z/unq5DpblPpw+Oqcv4dU/1omnb4Ok8iPY6p1c=
|
||||||
|
github.com/hashicorp/golang-lru v1.0.2/go.mod h1:iADmTwqILo4mZ8BN3D2Q6+9jd8WM5uGBxy+E8yxSoD4=
|
||||||
|
github.com/hashicorp/golang-lru/v2 v2.0.7 h1:a+bsQ5rvGLjzHuww6tVxozPZFVghXaHOwFs4luLUK2k=
|
||||||
|
github.com/hashicorp/golang-lru/v2 v2.0.7/go.mod h1:QeFd9opnmA6QUJc5vARoKUSoFhyfM2/ZepoAG6RGpeM=
|
||||||
|
github.com/huin/goupnp v1.3.0 h1:UvLUlWDNpoUdYzb2TCn+MuTWtcjXKSza2n6CBdQ0xXc=
|
||||||
|
github.com/huin/goupnp v1.3.0/go.mod h1:gnGPsThkYa7bFi/KWmEysQRf48l2dvR5bxr2OFckNX8=
|
||||||
|
github.com/ipfs/bbloom v0.0.4 h1:Gi+8EGJ2y5qiD5FbsbpX/TMNcJw8gSqr7eyjHa4Fhvs=
|
||||||
|
github.com/ipfs/bbloom v0.0.4/go.mod h1:cS9YprKXpoZ9lT0n/Mw/a6/aFV6DTjTLYHeA+gyqMG0=
|
||||||
|
github.com/ipfs/boxo v0.35.0 h1:3Mku5arSbAZz0dvb4goXRsQuZkFkPrGr5yYdu0YM1pY=
|
||||||
|
github.com/ipfs/boxo v0.35.0/go.mod h1:uhaF0DGnbgEiXDTmD249jCGbxVkMm6+Ew85q6Uub7lo=
|
||||||
|
github.com/ipfs/go-bitfield v1.1.0 h1:fh7FIo8bSwaJEh6DdTWbCeZ1eqOaOkKFI74SCnsWbGA=
|
||||||
|
github.com/ipfs/go-bitfield v1.1.0/go.mod h1:paqf1wjq/D2BBmzfTVFlJQ9IlFOZpg422HL0HqsGWHU=
|
||||||
|
github.com/ipfs/go-block-format v0.2.3 h1:mpCuDaNXJ4wrBJLrtEaGFGXkferrw5eqVvzaHhtFKQk=
|
||||||
|
github.com/ipfs/go-block-format v0.2.3/go.mod h1:WJaQmPAKhD3LspLixqlqNFxiZ3BZ3xgqxxoSR/76pnA=
|
||||||
|
github.com/ipfs/go-cid v0.5.0 h1:goEKKhaGm0ul11IHA7I6p1GmKz8kEYniqFopaB5Otwg=
|
||||||
|
github.com/ipfs/go-cid v0.5.0/go.mod h1:0L7vmeNXpQpUS9vt+yEARkJ8rOg43DF3iPgn4GIN0mk=
|
||||||
|
github.com/ipfs/go-cidutil v0.1.0 h1:RW5hO7Vcf16dplUU60Hs0AKDkQAVPVplr7lk97CFL+Q=
|
||||||
|
github.com/ipfs/go-cidutil v0.1.0/go.mod h1:e7OEVBMIv9JaOxt9zaGEmAoSlXW9jdFZ5lP/0PwcfpA=
|
||||||
|
github.com/ipfs/go-datastore v0.9.0 h1:WocriPOayqalEsueHv6SdD4nPVl4rYMfYGLD4bqCZ+w=
|
||||||
|
github.com/ipfs/go-datastore v0.9.0/go.mod h1:uT77w/XEGrvJWwHgdrMr8bqCN6ZTW9gzmi+3uK+ouHg=
|
||||||
|
github.com/ipfs/go-detect-race v0.0.1 h1:qX/xay2W3E4Q1U7d9lNs1sU9nvguX0a7319XbyQ6cOk=
|
||||||
|
github.com/ipfs/go-detect-race v0.0.1/go.mod h1:8BNT7shDZPo99Q74BpGMK+4D8Mn4j46UU0LZ723meps=
|
||||||
|
github.com/ipfs/go-dsqueue v0.0.5 h1:TUOk15TlCJ/NKV8Yk2W5wgkEjDa44Nem7a7FGIjsMNU=
|
||||||
|
github.com/ipfs/go-dsqueue v0.0.5/go.mod h1:i/jAlpZjBbQJLioN+XKbFgnd+u9eAhGZs9IrqIzTd9g=
|
||||||
|
github.com/ipfs/go-ipfs-cmds v0.15.0 h1:nQDgKadrzyiFyYoZMARMIoVoSwe3gGTAfGvrWLeAQbQ=
|
||||||
|
github.com/ipfs/go-ipfs-cmds v0.15.0/go.mod h1:VABf/mv/wqvYX6hLG6Z+40eNAEw3FQO0bSm370Or3Wk=
|
||||||
|
github.com/ipfs/go-ipfs-delay v0.0.1 h1:r/UXYyRcddO6thwOnhiznIAiSvxMECGgtv35Xs1IeRQ=
|
||||||
|
github.com/ipfs/go-ipfs-delay v0.0.1/go.mod h1:8SP1YXK1M1kXuc4KJZINY3TQQ03J2rwBG9QfXmbRPrw=
|
||||||
|
github.com/ipfs/go-ipfs-pq v0.0.3 h1:YpoHVJB+jzK15mr/xsWC574tyDLkezVrDNeaalQBsTE=
|
||||||
|
github.com/ipfs/go-ipfs-pq v0.0.3/go.mod h1:btNw5hsHBpRcSSgZtiNm/SLj5gYIZ18AKtv3kERkRb4=
|
||||||
|
github.com/ipfs/go-ipfs-redirects-file v0.1.2 h1:QCK7VtL91FH17KROVVy5KrzDx2hu68QvB2FTWk08ZQk=
|
||||||
|
github.com/ipfs/go-ipfs-redirects-file v0.1.2/go.mod h1:yIiTlLcDEM/8lS6T3FlCEXZktPPqSOyuY6dEzVqw7Fw=
|
||||||
|
github.com/ipfs/go-ipld-cbor v0.2.1 h1:H05yEJbK/hxg0uf2AJhyerBDbjOuHX4yi+1U/ogRa7E=
|
||||||
|
github.com/ipfs/go-ipld-cbor v0.2.1/go.mod h1:x9Zbeq8CoE5R2WicYgBMcr/9mnkQ0lHddYWJP2sMV3A=
|
||||||
|
github.com/ipfs/go-ipld-format v0.6.3 h1:9/lurLDTotJpZSuL++gh3sTdmcFhVkCwsgx2+rAh4j8=
|
||||||
|
github.com/ipfs/go-ipld-format v0.6.3/go.mod h1:74ilVN12NXVMIV+SrBAyC05UJRk0jVvGqdmrcYZvCBk=
|
||||||
|
github.com/ipfs/go-ipld-legacy v0.2.2 h1:DThbqCPVLpWBcGtU23KDLiY2YRZZnTkXQyfz8aOfBkQ=
|
||||||
|
github.com/ipfs/go-ipld-legacy v0.2.2/go.mod h1:hhkj+b3kG9b2BcUNw8IFYAsfeNo8E3U7eYlWeAOPyDU=
|
||||||
|
github.com/ipfs/go-log/v2 v2.8.1 h1:Y/X36z7ASoLJaYIJAL4xITXgwf7RVeqb1+/25aq/Xk0=
|
||||||
|
github.com/ipfs/go-log/v2 v2.8.1/go.mod h1:NyhTBcZmh2Y55eWVjOeKf8M7e4pnJYM3yDZNxQBWEEY=
|
||||||
|
github.com/ipfs/go-metrics-interface v0.3.0 h1:YwG7/Cy4R94mYDUuwsBfeziJCVm9pBMJ6q/JR9V40TU=
|
||||||
|
github.com/ipfs/go-metrics-interface v0.3.0/go.mod h1:OxxQjZDGocXVdyTPocns6cOLwHieqej/jos7H4POwoY=
|
||||||
|
github.com/ipfs/go-peertaskqueue v0.8.2 h1:PaHFRaVFdxQk1Qo3OKiHPYjmmusQy7gKQUaL8JDszAU=
|
||||||
|
github.com/ipfs/go-peertaskqueue v0.8.2/go.mod h1:L6QPvou0346c2qPJNiJa6BvOibxDfaiPlqHInmzg0FA=
|
||||||
|
github.com/ipfs/go-test v0.2.3 h1:Z/jXNAReQFtCYyn7bsv/ZqUwS6E7iIcSpJ2CuzCvnrc=
|
||||||
|
github.com/ipfs/go-test v0.2.3/go.mod h1:QW8vSKkwYvWFwIZQLGQXdkt9Ud76eQXRQ9Ao2H+cA1o=
|
||||||
|
github.com/ipfs/go-unixfsnode v1.10.2 h1:TREegX1J4X+k1w4AhoDuxxFvVcS9SegMRvrmxF6Tca8=
|
||||||
|
github.com/ipfs/go-unixfsnode v1.10.2/go.mod h1:ImDPTSiKZ+2h4UVdkSDITJHk87bUAp7kX/lgifjRicg=
|
||||||
|
github.com/ipfs/kubo v0.38.1 h1:y8GYMY8R4nFYzQfchPmYrVdC2F7RvK1YTpmqhZNlSF4=
|
||||||
|
github.com/ipfs/kubo v0.38.1/go.mod h1:lTCedbpplztHA/spUWG2E1F5eQSITwPVC4zT1MiB/eI=
|
||||||
|
github.com/ipld/go-car/v2 v2.15.0 h1:RxtZcGXFx72zFESl+UUsCNQV2YMcy3gEMYx9M3uio24=
|
||||||
|
github.com/ipld/go-car/v2 v2.15.0/go.mod h1:ovlq/n3xlVJDmoiN3Kd/Z7kIzQbdTIFSwltfOP+qIgk=
|
||||||
|
github.com/ipld/go-codec-dagpb v1.7.0 h1:hpuvQjCSVSLnTnHXn+QAMR0mLmb1gA6wl10LExo2Ts0=
|
||||||
|
github.com/ipld/go-codec-dagpb v1.7.0/go.mod h1:rD3Zg+zub9ZnxcLwfol/OTQRVjaLzXypgy4UqHQvilM=
|
||||||
|
github.com/ipld/go-ipld-prime v0.21.0 h1:n4JmcpOlPDIxBcY037SVfpd1G+Sj1nKZah0m6QH9C2E=
|
||||||
|
github.com/ipld/go-ipld-prime v0.21.0/go.mod h1:3RLqy//ERg/y5oShXXdx5YIp50cFGOanyMctpPjsvxQ=
|
||||||
|
github.com/ipshipyard/p2p-forge v0.6.1 h1:987/hUC1YxI56CcMX6iTB+9BLjFV0d2SJnig9Z1pf8A=
|
||||||
|
github.com/ipshipyard/p2p-forge v0.6.1/go.mod h1:pj8Zcs+ex5OMq5a1bFLHqW0oL3qYO0v5eGLZmit0l7U=
|
||||||
|
github.com/jackpal/go-nat-pmp v1.0.2 h1:KzKSgb7qkJvOUTqYl9/Hg/me3pWgBmERKrTGD7BdWus=
|
||||||
|
github.com/jackpal/go-nat-pmp v1.0.2/go.mod h1:QPH045xvCAeXUZOxsnwmrtiCoxIr9eob+4orBN1SBKc=
|
||||||
|
github.com/jbenet/go-temp-err-catcher v0.1.0 h1:zpb3ZH6wIE8Shj2sKS+khgRvf7T7RABoLk/+KKHggpk=
|
||||||
|
github.com/jbenet/go-temp-err-catcher v0.1.0/go.mod h1:0kJRvmDZXNMIiJirNPEYfhpPwbGVtZVWC34vc5WLsDk=
|
||||||
|
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/klauspost/compress v1.18.0 h1:c/Cqfb0r+Yi+JtIEq73FWXVkRonBlf0CRNYc8Zttxdo=
|
||||||
|
github.com/klauspost/compress v1.18.0/go.mod h1:2Pp+KzxcywXVXMr50+X0Q/Lsb43OQHYWRCY2AiWywWQ=
|
||||||
|
github.com/klauspost/cpuid/v2 v2.3.0 h1:S4CRMLnYUhGeDFDqkGriYKdfoFlDnMtqTiI/sFzhA9Y=
|
||||||
|
github.com/klauspost/cpuid/v2 v2.3.0/go.mod h1:hqwkgyIinND0mEev00jJYCxPNVRVXFQeu1XKlok6oO0=
|
||||||
|
github.com/koron/go-ssdp v0.0.6 h1:Jb0h04599eq/CY7rB5YEqPS83HmRfHP2azkxMN2rFtU=
|
||||||
|
github.com/koron/go-ssdp v0.0.6/go.mod h1:0R9LfRJGek1zWTjN3JUNlm5INCDYGpRDfAptnct63fI=
|
||||||
|
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/libdns/libdns v1.0.0-beta.1 h1:KIf4wLfsrEpXpZ3vmc/poM8zCATXT2klbdPe6hyOBjQ=
|
||||||
|
github.com/libdns/libdns v1.0.0-beta.1/go.mod h1:4Bj9+5CQiNMVGf87wjX4CY3HQJypUHRuLvlsfsZqLWQ=
|
||||||
|
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-cidranger v1.1.0 h1:ewPN8EZ0dd1LSnrtuwd4709PXVcITVeuwbag38yPW7c=
|
||||||
|
github.com/libp2p/go-cidranger v1.1.0/go.mod h1:KWZTfSr+r9qEo9OkI9/SIEeAtw+NNoU0dXIXt15Okic=
|
||||||
|
github.com/libp2p/go-doh-resolver v0.5.0 h1:4h7plVVW+XTS+oUBw2+8KfoM1jF6w8XmO7+skhePFdE=
|
||||||
|
github.com/libp2p/go-doh-resolver v0.5.0/go.mod h1:aPDxfiD2hNURgd13+hfo29z9IC22fv30ee5iM31RzxU=
|
||||||
|
github.com/libp2p/go-flow-metrics v0.3.0 h1:q31zcHUvHnwDO0SHaukewPYgwOBSxtt830uJtUx6784=
|
||||||
|
github.com/libp2p/go-flow-metrics v0.3.0/go.mod h1:nuhlreIwEguM1IvHAew3ij7A8BMlyHQJ279ao24eZZo=
|
||||||
|
github.com/libp2p/go-libp2p v0.43.0 h1:b2bg2cRNmY4HpLK8VHYQXLX2d3iND95OjodLFymvqXU=
|
||||||
|
github.com/libp2p/go-libp2p v0.43.0/go.mod h1:IiSqAXDyP2sWH+J2gs43pNmB/y4FOi2XQPbsb+8qvzc=
|
||||||
|
github.com/libp2p/go-libp2p-asn-util v0.4.1 h1:xqL7++IKD9TBFMgnLPZR6/6iYhawHKHl950SO9L6n94=
|
||||||
|
github.com/libp2p/go-libp2p-asn-util v0.4.1/go.mod h1:d/NI6XZ9qxw67b4e+NgpQexCIiFYJjErASrYW4PFDN8=
|
||||||
|
github.com/libp2p/go-libp2p-kad-dht v0.35.0 h1:pWRC4FKR9ptQjA9DuMSrAn2D3vABE8r58iAeoLoK1Ig=
|
||||||
|
github.com/libp2p/go-libp2p-kad-dht v0.35.0/go.mod h1:s70f017NjhsBx+SVl0/w+x//uyglrFpKLfvuQJj4QAU=
|
||||||
|
github.com/libp2p/go-libp2p-kbucket v0.8.0 h1:QAK7RzKJpYe+EuSEATAaaHYMYLkPDGC18m9jxPLnU8s=
|
||||||
|
github.com/libp2p/go-libp2p-kbucket v0.8.0/go.mod h1:JMlxqcEyKwO6ox716eyC0hmiduSWZZl6JY93mGaaqc4=
|
||||||
|
github.com/libp2p/go-libp2p-record v0.3.1 h1:cly48Xi5GjNw5Wq+7gmjfBiG9HCzQVkiZOUZ8kUl+Fg=
|
||||||
|
github.com/libp2p/go-libp2p-record v0.3.1/go.mod h1:T8itUkLcWQLCYMqtX7Th6r7SexyUJpIyPgks757td/E=
|
||||||
|
github.com/libp2p/go-libp2p-routing-helpers v0.7.5 h1:HdwZj9NKovMx0vqq6YNPTh6aaNzey5zHD7HeLJtq6fI=
|
||||||
|
github.com/libp2p/go-libp2p-routing-helpers v0.7.5/go.mod h1:3YaxrwP0OBPDD7my3D0KxfR89FlcX/IEbxDEDfAmj98=
|
||||||
|
github.com/libp2p/go-libp2p-testing v0.12.0 h1:EPvBb4kKMWO29qP4mZGyhVzUyR25dvfUIK5WDu6iPUA=
|
||||||
|
github.com/libp2p/go-libp2p-testing v0.12.0/go.mod h1:KcGDRXyN7sQCllucn1cOOS+Dmm7ujhfEyXQL5lvkcPg=
|
||||||
|
github.com/libp2p/go-msgio v0.3.0 h1:mf3Z8B1xcFN314sWX+2vOTShIE0Mmn2TXn3YCUQGNj0=
|
||||||
|
github.com/libp2p/go-msgio v0.3.0/go.mod h1:nyRM819GmVaF9LX3l03RMh10QdOroF++NBbxAb0mmDM=
|
||||||
|
github.com/libp2p/go-netroute v0.2.2 h1:Dejd8cQ47Qx2kRABg6lPwknU7+nBnFRpko45/fFPuZ8=
|
||||||
|
github.com/libp2p/go-netroute v0.2.2/go.mod h1:Rntq6jUAH0l9Gg17w5bFGhcC9a+vk4KNXs6s7IljKYE=
|
||||||
|
github.com/libp2p/go-reuseport v0.4.0 h1:nR5KU7hD0WxXCJbmw7r2rhRYruNRl2koHw8fQscQm2s=
|
||||||
|
github.com/libp2p/go-reuseport v0.4.0/go.mod h1:ZtI03j/wO5hZVDFo2jKywN6bYKWLOy8Se6DrI2E1cLU=
|
||||||
|
github.com/libp2p/go-yamux/v5 v5.0.1 h1:f0WoX/bEF2E8SbE4c/k1Mo+/9z0O4oC/hWEA+nfYRSg=
|
||||||
|
github.com/libp2p/go-yamux/v5 v5.0.1/go.mod h1:en+3cdX51U0ZslwRdRLrvQsdayFt3TSUKvBGErzpWbU=
|
||||||
|
github.com/marten-seemann/tcp v0.0.0-20210406111302-dfbc87cc63fd h1:br0buuQ854V8u83wA0rVZ8ttrq5CpaPZdvrK0LP2lOk=
|
||||||
|
github.com/marten-seemann/tcp v0.0.0-20210406111302-dfbc87cc63fd/go.mod h1:QuCEs1Nt24+FYQEqAAncTDPJIuGs+LxK1MCiFL25pMU=
|
||||||
|
github.com/mattn/go-isatty v0.0.20 h1:xfD0iDuEKnDkl03q4limB+vH+GxLEtL/jb4xVJSWWEY=
|
||||||
|
github.com/mattn/go-isatty v0.0.20/go.mod h1:W+V8PltTTMOvKvAeJH7IuucS94S2C6jfK/D7dTCTo3Y=
|
||||||
|
github.com/mholt/acmez/v3 v3.1.2 h1:auob8J/0FhmdClQicvJvuDavgd5ezwLBfKuYmynhYzc=
|
||||||
|
github.com/mholt/acmez/v3 v3.1.2/go.mod h1:L1wOU06KKvq7tswuMDwKdcHeKpFFgkppZy/y0DFxagQ=
|
||||||
|
github.com/miekg/dns v1.1.68 h1:jsSRkNozw7G/mnmXULynzMNIsgY2dHC8LO6U6Ij2JEA=
|
||||||
|
github.com/miekg/dns v1.1.68/go.mod h1:fujopn7TB3Pu3JM69XaawiU0wqjpL9/8xGop5UrTPps=
|
||||||
|
github.com/mikioh/tcpinfo v0.0.0-20190314235526-30a79bb1804b h1:z78hV3sbSMAUoyUMM0I83AUIT6Hu17AWfgjzIbtrYFc=
|
||||||
|
github.com/mikioh/tcpinfo v0.0.0-20190314235526-30a79bb1804b/go.mod h1:lxPUiZwKoFL8DUUmalo2yJJUCxbPKtm8OKfqr2/FTNU=
|
||||||
|
github.com/mikioh/tcpopt v0.0.0-20190314235656-172688c1accc h1:PTfri+PuQmWDqERdnNMiD9ZejrlswWrCpBEZgWOiTrc=
|
||||||
|
github.com/mikioh/tcpopt v0.0.0-20190314235656-172688c1accc/go.mod h1:cGKTAVKx4SxOuR/czcZ/E2RSJ3sfHs8FpHhQ5CWMf9s=
|
||||||
|
github.com/minio/minlz v1.0.1-0.20250507153514-87eb42fe8882 h1:0lgqHvJWHLGW5TuObJrfyEi6+ASTKDBWikGvPqy9Yiw=
|
||||||
|
github.com/minio/minlz v1.0.1-0.20250507153514-87eb42fe8882/go.mod h1:qT0aEB35q79LLornSzeDH75LBf3aH1MV+jB5w9Wasec=
|
||||||
|
github.com/minio/sha256-simd v1.0.1 h1:6kaan5IFmwTNynnKKpDHe6FWHohJOHhCPchzK49dzMM=
|
||||||
|
github.com/minio/sha256-simd v1.0.1/go.mod h1:Pz6AKMiUdngCLpeTL/RJY1M9rUuPMYujV5xJjtbRSN8=
|
||||||
|
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/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=
|
||||||
|
github.com/multiformats/go-base32 v0.1.0/go.mod h1:Kj3tFY6zNr+ABYMqeUNeGvkIC/UYgtWibDcT0rExnbI=
|
||||||
|
github.com/multiformats/go-base36 v0.2.0 h1:lFsAbNOGeKtuKozrtBsAkSVhv1p9D0/qedU9rQyccr0=
|
||||||
|
github.com/multiformats/go-base36 v0.2.0/go.mod h1:qvnKE++v+2MWCfePClUEjE78Z7P2a1UV0xHgWc0hkp4=
|
||||||
|
github.com/multiformats/go-multiaddr v0.16.1 h1:fgJ0Pitow+wWXzN9do+1b8Pyjmo8m5WhGfzpL82MpCw=
|
||||||
|
github.com/multiformats/go-multiaddr v0.16.1/go.mod h1:JSVUmXDjsVFiW7RjIFMP7+Ev+h1DTbiJgVeTV/tcmP0=
|
||||||
|
github.com/multiformats/go-multiaddr-dns v0.4.1 h1:whi/uCLbDS3mSEUMb1MsoT4uzUeZB0N32yzufqS0i5M=
|
||||||
|
github.com/multiformats/go-multiaddr-dns v0.4.1/go.mod h1:7hfthtB4E4pQwirrz+J0CcDUfbWzTqEzVyYKKIKpgkc=
|
||||||
|
github.com/multiformats/go-multiaddr-fmt v0.1.0 h1:WLEFClPycPkp4fnIzoFoV9FVd49/eQsuaL3/CWe167E=
|
||||||
|
github.com/multiformats/go-multiaddr-fmt v0.1.0/go.mod h1:hGtDIW4PU4BqJ50gW2quDuPVjyWNZxToGUh/HwTZYJo=
|
||||||
|
github.com/multiformats/go-multibase v0.2.0 h1:isdYCVLvksgWlMW9OZRYJEa9pZETFivncJHmHnnd87g=
|
||||||
|
github.com/multiformats/go-multibase v0.2.0/go.mod h1:bFBZX4lKCA/2lyOFSAoKH5SS6oPyjtnzK/XTFDPkNuk=
|
||||||
|
github.com/multiformats/go-multicodec v0.9.2 h1:YrlXCuqxjqm3bXl+vBq5LKz5pz4mvAsugdqy78k0pXQ=
|
||||||
|
github.com/multiformats/go-multicodec v0.9.2/go.mod h1:LLWNMtyV5ithSBUo3vFIMaeDy+h3EbkMTek1m+Fybbo=
|
||||||
|
github.com/multiformats/go-multihash v0.2.3 h1:7Lyc8XfX/IY2jWb/gI7JP+o7JEq9hOa7BFvVU9RSh+U=
|
||||||
|
github.com/multiformats/go-multihash v0.2.3/go.mod h1:dXgKXCXjBzdscBLk9JkjINiEsCKRVch90MdaGiKsvSM=
|
||||||
|
github.com/multiformats/go-multistream v0.6.1 h1:4aoX5v6T+yWmc2raBHsTvzmFhOI8WVOer28DeBBEYdQ=
|
||||||
|
github.com/multiformats/go-multistream v0.6.1/go.mod h1:ksQf6kqHAb6zIsyw7Zm+gAuVo57Qbq84E27YlYqavqw=
|
||||||
|
github.com/multiformats/go-varint v0.1.0 h1:i2wqFp4sdl3IcIxfAonHQV9qU5OsZ4Ts9IOoETFs5dI=
|
||||||
|
github.com/multiformats/go-varint v0.1.0/go.mod h1:5KVAVXegtfmNQQm/lCY+ATvDzvJJhSkUlGQV9wgObdI=
|
||||||
|
github.com/munnerz/goautoneg v0.0.0-20191010083416-a7dc8b61c822 h1:C3w9PqII01/Oq1c1nUAm88MOHcQC9l5mIlSMApZMrHA=
|
||||||
|
github.com/munnerz/goautoneg v0.0.0-20191010083416-a7dc8b61c822/go.mod h1:+n7T8mK8HuQTcFwEeznm/DIxMOiR9yIdICNftLE1DvQ=
|
||||||
|
github.com/pbnjay/memory v0.0.0-20210728143218-7b4eea64cf58 h1:onHthvaw9LFnH4t2DcNVpwGmV9E1BkGknEliJkfwQj0=
|
||||||
|
github.com/pbnjay/memory v0.0.0-20210728143218-7b4eea64cf58/go.mod h1:DXv8WO4yhMYhSNPKjeNKa5WY9YCIEBRbNzFFPJbWO6Y=
|
||||||
|
github.com/petar/GoLLRB v0.0.0-20210522233825-ae3b015fd3e9 h1:1/WtZae0yGtPq+TI6+Tv1WTxkukpXeMlviSxvL7SRgk=
|
||||||
|
github.com/petar/GoLLRB v0.0.0-20210522233825-ae3b015fd3e9/go.mod h1:x3N5drFsm2uilKKuuYo6LdyD8vZAW55sH/9w+pbo1sw=
|
||||||
|
github.com/pion/datachannel v1.5.10 h1:ly0Q26K1i6ZkGf42W7D4hQYR90pZwzFOjTq5AuCKk4o=
|
||||||
|
github.com/pion/datachannel v1.5.10/go.mod h1:p/jJfC9arb29W7WrxyKbepTU20CFgyx5oLo8Rs4Py/M=
|
||||||
|
github.com/pion/dtls/v2 v2.2.12 h1:KP7H5/c1EiVAAKUmXyCzPiQe5+bCJrpOeKg/L05dunk=
|
||||||
|
github.com/pion/dtls/v2 v2.2.12/go.mod h1:d9SYc9fch0CqK90mRk1dC7AkzzpwJj6u2GU3u+9pqFE=
|
||||||
|
github.com/pion/dtls/v3 v3.0.6 h1:7Hkd8WhAJNbRgq9RgdNh1aaWlZlGpYTzdqjy9x9sK2E=
|
||||||
|
github.com/pion/dtls/v3 v3.0.6/go.mod h1:iJxNQ3Uhn1NZWOMWlLxEEHAN5yX7GyPvvKw04v9bzYU=
|
||||||
|
github.com/pion/ice/v4 v4.0.10 h1:P59w1iauC/wPk9PdY8Vjl4fOFL5B+USq1+xbDcN6gT4=
|
||||||
|
github.com/pion/ice/v4 v4.0.10/go.mod h1:y3M18aPhIxLlcO/4dn9X8LzLLSma84cx6emMSu14FGw=
|
||||||
|
github.com/pion/interceptor v0.1.40 h1:e0BjnPcGpr2CFQgKhrQisBU7V3GXK6wrfYrGYaU6Jq4=
|
||||||
|
github.com/pion/interceptor v0.1.40/go.mod h1:Z6kqH7M/FYirg3frjGJ21VLSRJGBXB/KqaTIrdqnOic=
|
||||||
|
github.com/pion/logging v0.2.3 h1:gHuf0zpoh1GW67Nr6Gj4cv5Z9ZscU7g/EaoC/Ke/igI=
|
||||||
|
github.com/pion/logging v0.2.3/go.mod h1:z8YfknkquMe1csOrxK5kc+5/ZPAzMxbKLX5aXpbpC90=
|
||||||
|
github.com/pion/mdns/v2 v2.0.7 h1:c9kM8ewCgjslaAmicYMFQIde2H9/lrZpjBkN8VwoVtM=
|
||||||
|
github.com/pion/mdns/v2 v2.0.7/go.mod h1:vAdSYNAT0Jy3Ru0zl2YiW3Rm/fJCwIeM0nToenfOJKA=
|
||||||
|
github.com/pion/randutil v0.1.0 h1:CFG1UdESneORglEsnimhUjf33Rwjubwj6xfiOXBa3mA=
|
||||||
|
github.com/pion/randutil v0.1.0/go.mod h1:XcJrSMMbbMRhASFVOlj/5hQial/Y8oH/HVo7TBZq+j8=
|
||||||
|
github.com/pion/rtcp v1.2.15 h1:LZQi2JbdipLOj4eBjK4wlVoQWfrZbh3Q6eHtWtJBZBo=
|
||||||
|
github.com/pion/rtcp v1.2.15/go.mod h1:jlGuAjHMEXwMUHK78RgX0UmEJFV4zUKOFHR7OP+D3D0=
|
||||||
|
github.com/pion/rtp v1.8.19 h1:jhdO/3XhL/aKm/wARFVmvTfq0lC/CvN1xwYKmduly3c=
|
||||||
|
github.com/pion/rtp v1.8.19/go.mod h1:bAu2UFKScgzyFqvUKmbvzSdPr+NGbZtv6UB2hesqXBk=
|
||||||
|
github.com/pion/sctp v1.8.39 h1:PJma40vRHa3UTO3C4MyeJDQ+KIobVYRZQZ0Nt7SjQnE=
|
||||||
|
github.com/pion/sctp v1.8.39/go.mod h1:cNiLdchXra8fHQwmIoqw0MbLLMs+f7uQ+dGMG2gWebE=
|
||||||
|
github.com/pion/sdp/v3 v3.0.13 h1:uN3SS2b+QDZnWXgdr69SM8KB4EbcnPnPf2Laxhty/l4=
|
||||||
|
github.com/pion/sdp/v3 v3.0.13/go.mod h1:88GMahN5xnScv1hIMTqLdu/cOcUkj6a9ytbncwMCq2E=
|
||||||
|
github.com/pion/srtp/v3 v3.0.6 h1:E2gyj1f5X10sB/qILUGIkL4C2CqK269Xq167PbGCc/4=
|
||||||
|
github.com/pion/srtp/v3 v3.0.6/go.mod h1:BxvziG3v/armJHAaJ87euvkhHqWe9I7iiOy50K2QkhY=
|
||||||
|
github.com/pion/stun v0.6.1 h1:8lp6YejULeHBF8NmV8e2787BogQhduZugh5PdhDyyN4=
|
||||||
|
github.com/pion/stun v0.6.1/go.mod h1:/hO7APkX4hZKu/D0f2lHzNyvdkTGtIy3NDmLR7kSz/8=
|
||||||
|
github.com/pion/stun/v3 v3.0.0 h1:4h1gwhWLWuZWOJIJR9s2ferRO+W3zA/b6ijOI6mKzUw=
|
||||||
|
github.com/pion/stun/v3 v3.0.0/go.mod h1:HvCN8txt8mwi4FBvS3EmDghW6aQJ24T+y+1TKjB5jyU=
|
||||||
|
github.com/pion/transport/v2 v2.2.10 h1:ucLBLE8nuxiHfvkFKnkDQRYWYfp8ejf4YBOPfaQpw6Q=
|
||||||
|
github.com/pion/transport/v2 v2.2.10/go.mod h1:sq1kSLWs+cHW9E+2fJP95QudkzbK7wscs8yYgQToO5E=
|
||||||
|
github.com/pion/transport/v3 v3.0.7 h1:iRbMH05BzSNwhILHoBoAPxoB9xQgOaJk+591KC9P1o0=
|
||||||
|
github.com/pion/transport/v3 v3.0.7/go.mod h1:YleKiTZ4vqNxVwh77Z0zytYi7rXHl7j6uPLGhhz9rwo=
|
||||||
|
github.com/pion/turn/v4 v4.0.2 h1:ZqgQ3+MjP32ug30xAbD6Mn+/K4Sxi3SdNOTFf+7mpps=
|
||||||
|
github.com/pion/turn/v4 v4.0.2/go.mod h1:pMMKP/ieNAG/fN5cZiN4SDuyKsXtNTr0ccN7IToA1zs=
|
||||||
|
github.com/pion/webrtc/v4 v4.1.2 h1:mpuUo/EJ1zMNKGE79fAdYNFZBX790KE7kQQpLMjjR54=
|
||||||
|
github.com/pion/webrtc/v4 v4.1.2/go.mod h1:xsCXiNAmMEjIdFxAYU0MbB3RwRieJsegSB2JZsGN+8U=
|
||||||
|
github.com/pkg/errors v0.9.1 h1:FEBLx1zS214owpjy7qsBeixbURkuhQAwrK5UwLGTwt4=
|
||||||
|
github.com/pkg/errors v0.9.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0=
|
||||||
|
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/prometheus/client_golang v1.23.2 h1:Je96obch5RDVy3FDMndoUsjAhG5Edi49h0RJWRi/o0o=
|
||||||
|
github.com/prometheus/client_golang v1.23.2/go.mod h1:Tb1a6LWHB3/SPIzCoaDXI4I8UHKeFTEQ1YCr+0Gyqmg=
|
||||||
|
github.com/prometheus/client_model v0.6.2 h1:oBsgwpGs7iVziMvrGhE53c/GrLUsZdHnqNwqPLxwZyk=
|
||||||
|
github.com/prometheus/client_model v0.6.2/go.mod h1:y3m2F6Gdpfy6Ut/GBsUqTWZqCUvMVzSfMLjcu6wAwpE=
|
||||||
|
github.com/prometheus/common v0.66.1 h1:h5E0h5/Y8niHc5DlaLlWLArTQI7tMrsfQjHV+d9ZoGs=
|
||||||
|
github.com/prometheus/common v0.66.1/go.mod h1:gcaUsgf3KfRSwHY4dIMXLPV0K/Wg1oZ8+SbZk/HH/dA=
|
||||||
|
github.com/prometheus/procfs v0.17.0 h1:FuLQ+05u4ZI+SS/w9+BWEM2TXiHKsUQ9TADiRH7DuK0=
|
||||||
|
github.com/prometheus/procfs v0.17.0/go.mod h1:oPQLaDAMRbA+u8H5Pbfq+dl3VDAvHxMUOVhe0wYB2zw=
|
||||||
|
github.com/quic-go/qpack v0.5.1 h1:giqksBPnT/HDtZ6VhtFKgoLOWmlyo9Ei6u9PqzIMbhI=
|
||||||
|
github.com/quic-go/qpack v0.5.1/go.mod h1:+PC4XFrEskIVkcLzpEkbLqq1uCoxPhQuvK5rH1ZgaEg=
|
||||||
|
github.com/quic-go/quic-go v0.54.0 h1:6s1YB9QotYI6Ospeiguknbp2Znb/jZYjZLRXn9kMQBg=
|
||||||
|
github.com/quic-go/quic-go v0.54.0/go.mod h1:e68ZEaCdyviluZmy44P6Iey98v/Wfz6HCjQEm+l8zTY=
|
||||||
|
github.com/quic-go/webtransport-go v0.9.0 h1:jgys+7/wm6JarGDrW+lD/r9BGqBAmqY/ssklE09bA70=
|
||||||
|
github.com/quic-go/webtransport-go v0.9.0/go.mod h1:4FUYIiUc75XSsF6HShcLeXXYZJ9AGwo/xh3L8M/P1ao=
|
||||||
|
github.com/rogpeppe/go-internal v1.14.1 h1:UQB4HGPB6osV0SQTLymcB4TgvyWu6ZyliaW0tI/otEQ=
|
||||||
|
github.com/rogpeppe/go-internal v1.14.1/go.mod h1:MaRKkUm5W0goXpeCfT7UZI6fk/L7L7so1lCWt35ZSgc=
|
||||||
|
github.com/rs/cors v1.11.1 h1:eU3gRzXLRK57F5rKMGMZURNdIG4EoAmX8k94r9wXWHA=
|
||||||
|
github.com/rs/cors v1.11.1/go.mod h1:XyqrcTp5zjWr1wsJ8PIRZssZ8b/WMcMf71DJnit4EMU=
|
||||||
|
github.com/russross/blackfriday/v2 v2.0.1/go.mod h1:+Rmxgy9KzJVeS9/2gXHxylqXiyQDYRxCVz55jmeOWTM=
|
||||||
|
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=
|
||||||
|
github.com/smartystreets/goconvey v1.7.2 h1:9RBaZCeXEQ3UselpuwUQHltGVXvdwm6cv1hgR6gDIPg=
|
||||||
|
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/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/objx v0.5.2/go.mod h1:FRsXN1f5AsAjCGJKqEizvkpNtU+EGNCLh3NxZ/8L+MA=
|
||||||
|
github.com/stretchr/testify v1.4.0/go.mod h1:j7eGeouHqKxXV5pUuKE4zz7dFj8WfuZ+81PSLYec5m4=
|
||||||
|
github.com/stretchr/testify v1.7.1/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg=
|
||||||
|
github.com/stretchr/testify v1.8.0/go.mod h1:yNjHg4UonilssWZ8iaSj1OCr/vHnekPRkoO+kdMU+MU=
|
||||||
|
github.com/stretchr/testify v1.8.4/go.mod h1:sz/lmYIOXD/1dqDmKjjqLyZ2RngseejIcXlSw2iwfAo=
|
||||||
|
github.com/stretchr/testify v1.9.0/go.mod h1:r2ic/lqez/lEtzL7wO/rwa5dbSLXVDPFyf8C91i36aY=
|
||||||
|
github.com/stretchr/testify v1.11.1 h1:7s2iGBzp5EwR7/aIZr8ao5+dra3wiQyKjjFuvgVKu7U=
|
||||||
|
github.com/stretchr/testify v1.11.1/go.mod h1:wZwfW3scLgRK+23gO65QZefKpKQRnfz6sD981Nm4B6U=
|
||||||
|
github.com/ucarion/urlpath v0.0.0-20200424170820-7ccc79b76bbb h1:Ywfo8sUltxogBpFuMOFRrrSifO788kAFxmvVw31PtQQ=
|
||||||
|
github.com/ucarion/urlpath v0.0.0-20200424170820-7ccc79b76bbb/go.mod h1:ikPs9bRWicNw3S7XpJ8sK/smGwU9WcSVU3dy9qahYBM=
|
||||||
|
github.com/urfave/cli v1.22.10/go.mod h1:Gos4lmkARVdJ6EkW0WaNv/tZAAMe9V7XWyB60NtXRu0=
|
||||||
|
github.com/warpfork/go-testmark v0.12.1 h1:rMgCpJfwy1sJ50x0M0NgyphxYYPMOODIJHhsXyEHU0s=
|
||||||
|
github.com/warpfork/go-testmark v0.12.1/go.mod h1:kHwy7wfvGSPh1rQJYKayD4AbtNaeyZdcGi9tNJTaa5Y=
|
||||||
|
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/whyrusleeping/base32 v0.0.0-20170828182744-c30ac30633cc h1:BCPnHtcboadS0DvysUuJXZ4lWVv5Bh5i7+tbIyi+ck4=
|
||||||
|
github.com/whyrusleeping/base32 v0.0.0-20170828182744-c30ac30633cc/go.mod h1:r45hJU7yEoA81k6MWNhpMj/kms0n14dkzkxYHoB96UM=
|
||||||
|
github.com/whyrusleeping/cbor v0.0.0-20171005072247-63513f603b11 h1:5HZfQkwe0mIfyDmc1Em5GqlNRzcdtlv4HTNmdpt7XH0=
|
||||||
|
github.com/whyrusleeping/cbor v0.0.0-20171005072247-63513f603b11/go.mod h1:Wlo/SzPmxVp6vXpGt/zaXhHH0fn4IxgqZc82aKg6bpQ=
|
||||||
|
github.com/whyrusleeping/cbor-gen v0.3.1 h1:82ioxmhEYut7LBVGhGq8xoRkXPLElVuh5mV67AFfdv0=
|
||||||
|
github.com/whyrusleeping/cbor-gen v0.3.1/go.mod h1:pM99HXyEbSQHcosHc0iW7YFmwnscr+t9Te4ibko05so=
|
||||||
|
github.com/whyrusleeping/chunker v0.0.0-20181014151217-fe64bd25879f h1:jQa4QT2UP9WYv2nzyawpKMOCl+Z/jW7djv2/J50lj9E=
|
||||||
|
github.com/whyrusleeping/chunker v0.0.0-20181014151217-fe64bd25879f/go.mod h1:p9UJB6dDgdPgMJZs7UjUOdulKyRr9fqkS+6JKAInPy8=
|
||||||
|
github.com/whyrusleeping/go-keyspace v0.0.0-20160322163242-5b898ac5add1 h1:EKhdznlJHPMoKr0XTrX+IlJs1LH3lyx2nfr1dOlZ79k=
|
||||||
|
github.com/whyrusleeping/go-keyspace v0.0.0-20160322163242-5b898ac5add1/go.mod h1:8UvriyWtv5Q5EOgjHaSseUEdkQfvwFv1I/In/O2M9gc=
|
||||||
|
github.com/wlynxg/anet v0.0.5 h1:J3VJGi1gvo0JwZ/P1/Yc/8p63SoW98B5dHkYDmpgvvU=
|
||||||
|
github.com/wlynxg/anet v0.0.5/go.mod h1:eay5PRQr7fIVAMbTbchTnO9gG65Hg/uYGdc7mguHxoA=
|
||||||
|
github.com/x448/float16 v0.8.4 h1:qLwI1I70+NjRFUR3zs1JPUCgaCXSh3SW62uAKT1mSBM=
|
||||||
|
github.com/x448/float16 v0.8.4/go.mod h1:14CWIYCyZA/cWjXOioeEpHeN/83MdbZDRQHoFcYsOfg=
|
||||||
|
github.com/zeebo/blake3 v0.2.4 h1:KYQPkhpRtcqh0ssGYcKLG1JYvddkEA8QwCM/yBqhaZI=
|
||||||
|
github.com/zeebo/blake3 v0.2.4/go.mod h1:7eeQ6d2iXWRGF6npfaxl2CU+xy2Fjo2gxeyZGCRUjcE=
|
||||||
|
go.opentelemetry.io/auto/sdk v1.2.1 h1:jXsnJ4Lmnqd11kwkBV2LgLoFMZKizbCi5fNZ/ipaZ64=
|
||||||
|
go.opentelemetry.io/auto/sdk v1.2.1/go.mod h1:KRTj+aOaElaLi+wW1kO/DZRXwkF4C5xPbEe3ZiIhN7Y=
|
||||||
|
go.opentelemetry.io/contrib/instrumentation/net/http/otelhttp v0.63.0 h1:RbKq8BG0FI8OiXhBfcRtqqHcZcka+gU3cskNuf05R18=
|
||||||
|
go.opentelemetry.io/contrib/instrumentation/net/http/otelhttp v0.63.0/go.mod h1:h06DGIukJOevXaj/xrNjhi/2098RZzcLTbc0jDAUbsg=
|
||||||
|
go.opentelemetry.io/otel v1.38.0 h1:RkfdswUDRimDg0m2Az18RKOsnI8UDzppJAtj01/Ymk8=
|
||||||
|
go.opentelemetry.io/otel v1.38.0/go.mod h1:zcmtmQ1+YmQM9wrNsTGV/q/uyusom3P8RxwExxkZhjM=
|
||||||
|
go.opentelemetry.io/otel/metric v1.38.0 h1:Kl6lzIYGAh5M159u9NgiRkmoMKjvbsKtYRwgfrA6WpA=
|
||||||
|
go.opentelemetry.io/otel/metric v1.38.0/go.mod h1:kB5n/QoRM8YwmUahxvI3bO34eVtQf2i4utNVLr9gEmI=
|
||||||
|
go.opentelemetry.io/otel/trace v1.38.0 h1:Fxk5bKrDZJUH+AMyyIXGcFAPah0oRcT+LuNtJrmcNLE=
|
||||||
|
go.opentelemetry.io/otel/trace v1.38.0/go.mod h1:j1P9ivuFsTceSWe1oY+EeW3sc+Pp42sO++GHkg4wwhs=
|
||||||
|
go.uber.org/dig v1.19.0 h1:BACLhebsYdpQ7IROQ1AGPjrXcP5dF80U3gKoFzbaq/4=
|
||||||
|
go.uber.org/dig v1.19.0/go.mod h1:Us0rSJiThwCv2GteUN0Q7OKvU7n5J4dxZ9JKUXozFdE=
|
||||||
|
go.uber.org/fx v1.24.0 h1:wE8mruvpg2kiiL1Vqd0CC+tr0/24XIB10Iwp2lLWzkg=
|
||||||
|
go.uber.org/fx v1.24.0/go.mod h1:AmDeGyS+ZARGKM4tlH4FY2Jr63VjbEDJHtqXTGP5hbo=
|
||||||
|
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/mock v0.5.2 h1:LbtPTcP8A5k9WPXj54PPPbjcI4Y6lhyOZXn+VS7wNko=
|
||||||
|
go.uber.org/mock v0.5.2/go.mod h1:wLlUxC2vVTPTaE3UD51E0BGOAElKrILxhVSDYQLld5o=
|
||||||
|
go.uber.org/multierr v1.11.0 h1:blXXJkSxSSfBVBlC76pxqeO+LN3aDfLQo+309xJstO0=
|
||||||
|
go.uber.org/multierr v1.11.0/go.mod h1:20+QtiLqy0Nd6FdQB9TLXag12DsQkrbs3htMFfDN80Y=
|
||||||
|
go.uber.org/zap v1.27.0 h1:aJMhYGrd5QSmlpLMr2MftRKl7t8J8PTZPA732ud/XR8=
|
||||||
|
go.uber.org/zap v1.27.0/go.mod h1:GB2qFLM7cTU87MWRP2mPIjqfIDnGu+VIO4V/SdhGo2E=
|
||||||
|
go.uber.org/zap/exp v0.3.0 h1:6JYzdifzYkGmTdRR59oYH+Ng7k49H9qVpWwNSsGJj3U=
|
||||||
|
go.uber.org/zap/exp v0.3.0/go.mod h1:5I384qq7XGxYyByIhHm6jg5CHkGY0nsTfbDLgDDlgJQ=
|
||||||
|
go.yaml.in/yaml/v2 v2.4.3 h1:6gvOSjQoTB3vt1l+CU+tSyi/HOjfOjRLJ4YwYZGwRO0=
|
||||||
|
go.yaml.in/yaml/v2 v2.4.3/go.mod h1:zSxWcmIDjOzPXpjlTTbAsKokqkDNAVtZO0WOMiT90s8=
|
||||||
|
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.42.0 h1:chiH31gIWm57EkTXpwnqf8qeuMUi0yekh6mT2AvFlqI=
|
||||||
|
golang.org/x/crypto v0.42.0/go.mod h1:4+rDnOTJhQCx2q7/j6rAN5XDw8kPjeaXEUR2eL94ix8=
|
||||||
|
golang.org/x/exp v0.0.0-20250911091902-df9299821621 h1:2id6c1/gto0kaHYyrixvknJ8tUK/Qs5IsmBtrc+FtgU=
|
||||||
|
golang.org/x/exp v0.0.0-20250911091902-df9299821621/go.mod h1:TwQYMMnGpvZyc+JpB/UAuTNIsVJifOlSkrZkhcvpVUk=
|
||||||
|
golang.org/x/lint v0.0.0-20200302205851-738671d3881b/go.mod h1:3xt1FjdF8hUf6vQPIChWIBhFzV8gjjsPE/fR3IyQdNY=
|
||||||
|
golang.org/x/mod v0.1.1-0.20191105210325-c90efee705ee/go.mod h1:QqPTAvyqsEbceGzBzNggFXnrqF1CaUcvgkdR5Ot7KZg=
|
||||||
|
golang.org/x/mod v0.28.0 h1:gQBtGhjxykdjY9YhZpSlZIsbnaE2+PgjfLWUQTnoZ1U=
|
||||||
|
golang.org/x/mod v0.28.0/go.mod h1:yfB/L0NOf/kmEbXjzCPOx1iK1fRutOydrCMsqRhEBxI=
|
||||||
|
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.44.0 h1:evd8IRDyfNBMBTTY5XRF1vaZlD+EmWx6x8PkhR04H/I=
|
||||||
|
golang.org/x/net v0.44.0/go.mod h1:ECOoLqd5U3Lhyeyo/QDCEVQ4sNgYsqvCZ722XogGieY=
|
||||||
|
golang.org/x/sync v0.0.0-20190423024810-112230192c58/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
|
||||||
|
golang.org/x/sync v0.17.0 h1:l60nONMj9l5drqw6jlhIELNv9I0A4OFgRsG9k2oT9Ug=
|
||||||
|
golang.org/x/sync v0.17.0/go.mod h1:9KTHXmSnoGruLpwFjVSX0lNNA75CykiMECbovNTZqGI=
|
||||||
|
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.6.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||||
|
golang.org/x/sys v0.36.0 h1:KVRy2GtZBrk1cBYA7MKu5bEZFxQk4NIDV6RLVcC8o0k=
|
||||||
|
golang.org/x/sys v0.36.0/go.mod h1:OgkHotnGiDImocRcuBABYBEXf8A9a87e/uXjp9XT3ks=
|
||||||
|
golang.org/x/telemetry v0.0.0-20250908211612-aef8a434d053 h1:dHQOQddU4YHS5gY33/6klKjq7Gp3WwMyOXGNp5nzRj8=
|
||||||
|
golang.org/x/telemetry v0.0.0-20250908211612-aef8a434d053/go.mod h1:+nZKN+XVh4LCiA9DV3ywrzN4gumyCnKjau3NGb9SGoE=
|
||||||
|
golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=
|
||||||
|
golang.org/x/text v0.29.0 h1:1neNs90w9YzJ9BocxfsQNHKuAT4pkghyXc4nhZ6sJvk=
|
||||||
|
golang.org/x/text v0.29.0/go.mod h1:7MhJOA9CD2qZyOKYazxdYMF85OwPdEr9jTtBpO7ydH4=
|
||||||
|
golang.org/x/time v0.12.0 h1:ScB/8o8olJvc+CQPWrK3fPZNfh7qgwCrY0zJmoEQLSE=
|
||||||
|
golang.org/x/time v0.12.0/go.mod h1:CDIdPxbZBQxdj6cxyCIdrNogrJKMJ7pr37NYpMcMDSg=
|
||||||
|
golang.org/x/tools v0.0.0-20190328211700-ab21143f2384/go.mod h1:LCzVGOaR6xXOjkQ3onu1FJEFr0SW1gC7cKk1uF8kGRs=
|
||||||
|
golang.org/x/tools v0.0.0-20200130002326-2f3ba24bd6e7/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28=
|
||||||
|
golang.org/x/tools v0.37.0 h1:DVSRzp7FwePZW356yEAChSdNcQo6Nsp+fex1SUW09lE=
|
||||||
|
golang.org/x/tools v0.37.0/go.mod h1:MBN5QPQtLMHVdvsbtarmTNukZDdgwdwlO5qGacAzF0w=
|
||||||
|
golang.org/x/xerrors v0.0.0-20191011141410-1b5146add898/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
|
||||||
|
golang.org/x/xerrors v0.0.0-20240903120638-7835f813f4da h1:noIWHXmPHxILtqtCOPIhSt0ABwskkZKjD3bXGnZGpNY=
|
||||||
|
golang.org/x/xerrors v0.0.0-20240903120638-7835f813f4da/go.mod h1:NDW/Ps6MPRej6fsCIbMTohpP40sJ/P/vI1MoTEGwX90=
|
||||||
|
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/protobuf v1.36.9 h1:w2gp2mA27hUeUzj9Ex9FBjsBm40zfaDtEWow293U7Iw=
|
||||||
|
google.golang.org/protobuf v1.36.9/go.mod h1:fuxRtAxBytpl4zzqUh6/eyUujkJdNiuEkXntxiD/uRU=
|
||||||
|
gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
|
||||||
|
gopkg.in/check.v1 v1.0.0-20201130134442-10cb98267c6c h1:Hei/4ADfdWqJk1ZMxUNpqntNwaWcugrBjAiHlqqRiVk=
|
||||||
|
gopkg.in/check.v1 v1.0.0-20201130134442-10cb98267c6c/go.mod h1:JHkPIbrfpd72SG/EVd6muEfDQjcINNoR0C8j2r3qZ4Q=
|
||||||
|
gopkg.in/yaml.v2 v2.2.2/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.1 h1:fxVm/GzAzEWqLHuvctI91KS9hhNmmWOoWu0XTYJS7CA=
|
||||||
|
gopkg.in/yaml.v3 v3.0.1/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=
|
||||||
|
lukechampine.com/blake3 v1.4.1 h1:I3Smz7gso8w4/TunLKec6K2fn+kyKtDxr/xcQEN84Wg=
|
||||||
|
lukechampine.com/blake3 v1.4.1/go.mod h1:QFosUxmjB8mnrWFSNwKmvxHpfY72bmD2tQ0kBMM3kwo=
|
||||||
@@ -1,310 +0,0 @@
|
|||||||
// Package webauthn provides Sonr-specific WebAuthn service binding functionality
|
|
||||||
// that integrates with the x/svc module for domain-verified WebAuthn credentials.
|
|
||||||
//
|
|
||||||
// This package contains service-related WebAuthn operations that enable binding
|
|
||||||
// WebAuthn credentials to verified domains for capability-based access control.
|
|
||||||
package webauthn
|
|
||||||
|
|
||||||
import (
|
|
||||||
"fmt"
|
|
||||||
"net/url"
|
|
||||||
"strings"
|
|
||||||
)
|
|
||||||
|
|
||||||
// ServiceBinding represents a binding between a WebAuthn credential and a verified service domain.
|
|
||||||
type ServiceBinding struct {
|
|
||||||
// CredentialID is the WebAuthn credential identifier
|
|
||||||
CredentialID string
|
|
||||||
|
|
||||||
// Domain is the verified domain this credential is bound to
|
|
||||||
Domain string
|
|
||||||
|
|
||||||
// ServiceID is the unique identifier for the registered service
|
|
||||||
ServiceID string
|
|
||||||
|
|
||||||
// Permissions are the specific permissions granted to this credential
|
|
||||||
Permissions []string
|
|
||||||
|
|
||||||
// Origin is the WebAuthn origin for this service binding
|
|
||||||
Origin string
|
|
||||||
|
|
||||||
// CreatedAt timestamp when the binding was created
|
|
||||||
CreatedAt int64
|
|
||||||
|
|
||||||
// ExpiresAt timestamp when the binding expires (optional, 0 = no expiry)
|
|
||||||
ExpiresAt int64
|
|
||||||
}
|
|
||||||
|
|
||||||
// ValidateServiceBinding validates a WebAuthn credential for service binding.
|
|
||||||
// This ensures that the credential is legitimate and the service domain is verified.
|
|
||||||
func ValidateServiceBinding(
|
|
||||||
credential WebAuthnCredential,
|
|
||||||
domain string,
|
|
||||||
permissions []string,
|
|
||||||
) error {
|
|
||||||
if credential == nil {
|
|
||||||
return fmt.Errorf("credential cannot be nil")
|
|
||||||
}
|
|
||||||
|
|
||||||
if domain == "" {
|
|
||||||
return fmt.Errorf("domain cannot be empty")
|
|
||||||
}
|
|
||||||
|
|
||||||
// Validate credential structure first
|
|
||||||
if err := ValidateStructure(credential); err != nil {
|
|
||||||
return fmt.Errorf("credential validation failed: %w", err)
|
|
||||||
}
|
|
||||||
|
|
||||||
// Validate domain format
|
|
||||||
if err := validateServiceDomain(domain); err != nil {
|
|
||||||
return fmt.Errorf("invalid service domain: %w", err)
|
|
||||||
}
|
|
||||||
|
|
||||||
// Validate permissions
|
|
||||||
if err := validateServicePermissions(permissions); err != nil {
|
|
||||||
return fmt.Errorf("invalid service permissions: %w", err)
|
|
||||||
}
|
|
||||||
|
|
||||||
// Validate origin matches domain
|
|
||||||
if credential.GetOrigin() != "" {
|
|
||||||
expectedOrigin := fmt.Sprintf("https://%s", domain)
|
|
||||||
if credential.GetOrigin() != expectedOrigin {
|
|
||||||
return fmt.Errorf("credential origin %s does not match expected service origin %s",
|
|
||||||
credential.GetOrigin(), expectedOrigin)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
|
|
||||||
// validateServiceDomain validates that a domain meets service binding requirements.
|
|
||||||
func validateServiceDomain(domain string) error {
|
|
||||||
if domain == "" {
|
|
||||||
return fmt.Errorf("domain cannot be empty")
|
|
||||||
}
|
|
||||||
|
|
||||||
// Basic domain validation - should not include protocol or path
|
|
||||||
if strings.Contains(domain, "://") {
|
|
||||||
return fmt.Errorf("domain should not include protocol (https://)")
|
|
||||||
}
|
|
||||||
|
|
||||||
if strings.Contains(domain, "/") {
|
|
||||||
return fmt.Errorf("domain should not include path")
|
|
||||||
}
|
|
||||||
|
|
||||||
// Check domain format using URL parsing
|
|
||||||
testURL := "https://" + domain
|
|
||||||
parsedURL, err := url.Parse(testURL)
|
|
||||||
if err != nil {
|
|
||||||
return fmt.Errorf("invalid domain format: %w", err)
|
|
||||||
}
|
|
||||||
|
|
||||||
if parsedURL.Hostname() != domain {
|
|
||||||
return fmt.Errorf("invalid domain format")
|
|
||||||
}
|
|
||||||
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
|
|
||||||
// validateServicePermissions validates the permissions granted to a service-bound credential.
|
|
||||||
func validateServicePermissions(permissions []string) error {
|
|
||||||
if len(permissions) == 0 {
|
|
||||||
return fmt.Errorf("at least one permission must be specified")
|
|
||||||
}
|
|
||||||
|
|
||||||
validPermissions := map[string]bool{
|
|
||||||
"read": true,
|
|
||||||
"write": true,
|
|
||||||
"execute": true,
|
|
||||||
"admin": true,
|
|
||||||
"delegate": true,
|
|
||||||
}
|
|
||||||
|
|
||||||
for _, perm := range permissions {
|
|
||||||
if !validPermissions[perm] {
|
|
||||||
return fmt.Errorf("invalid permission: %s", perm)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
|
|
||||||
// GenerateServiceOrigin generates the expected WebAuthn origin for a service domain.
|
|
||||||
func GenerateServiceOrigin(domain string) (string, error) {
|
|
||||||
if err := validateServiceDomain(domain); err != nil {
|
|
||||||
return "", fmt.Errorf("invalid domain: %w", err)
|
|
||||||
}
|
|
||||||
|
|
||||||
return fmt.Sprintf("https://%s", domain), nil
|
|
||||||
}
|
|
||||||
|
|
||||||
// ValidateCredentialForDomain validates that a WebAuthn credential is valid for a specific domain.
|
|
||||||
// This includes checking the origin and ensuring the credential can be bound to the domain.
|
|
||||||
func ValidateCredentialForDomain(
|
|
||||||
credential WebAuthnCredential,
|
|
||||||
domain string,
|
|
||||||
challengeToken string,
|
|
||||||
) error {
|
|
||||||
if credential == nil {
|
|
||||||
return fmt.Errorf("credential cannot be nil")
|
|
||||||
}
|
|
||||||
|
|
||||||
// Generate expected origin for the domain
|
|
||||||
expectedOrigin, err := GenerateServiceOrigin(domain)
|
|
||||||
if err != nil {
|
|
||||||
return fmt.Errorf("failed to generate origin: %w", err)
|
|
||||||
}
|
|
||||||
|
|
||||||
// Validate the credential with domain-specific requirements
|
|
||||||
if err := ValidateForGaslessRegistration(credential, challengeToken, expectedOrigin); err != nil {
|
|
||||||
return fmt.Errorf("credential validation failed for domain %s: %w", domain, err)
|
|
||||||
}
|
|
||||||
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
|
|
||||||
// CreateServiceBinding creates a new service binding for a WebAuthn credential.
|
|
||||||
func CreateServiceBinding(
|
|
||||||
credentialID string,
|
|
||||||
domain string,
|
|
||||||
serviceID string,
|
|
||||||
permissions []string,
|
|
||||||
createdAt int64,
|
|
||||||
) (*ServiceBinding, error) {
|
|
||||||
if credentialID == "" {
|
|
||||||
return nil, fmt.Errorf("credential ID cannot be empty")
|
|
||||||
}
|
|
||||||
|
|
||||||
if err := validateServiceDomain(domain); err != nil {
|
|
||||||
return nil, fmt.Errorf("invalid domain: %w", err)
|
|
||||||
}
|
|
||||||
|
|
||||||
if serviceID == "" {
|
|
||||||
return nil, fmt.Errorf("service ID cannot be empty")
|
|
||||||
}
|
|
||||||
|
|
||||||
if err := validateServicePermissions(permissions); err != nil {
|
|
||||||
return nil, fmt.Errorf("invalid permissions: %w", err)
|
|
||||||
}
|
|
||||||
|
|
||||||
origin, err := GenerateServiceOrigin(domain)
|
|
||||||
if err != nil {
|
|
||||||
return nil, fmt.Errorf("failed to generate origin: %w", err)
|
|
||||||
}
|
|
||||||
|
|
||||||
return &ServiceBinding{
|
|
||||||
CredentialID: credentialID,
|
|
||||||
Domain: domain,
|
|
||||||
ServiceID: serviceID,
|
|
||||||
Permissions: permissions,
|
|
||||||
Origin: origin,
|
|
||||||
CreatedAt: createdAt,
|
|
||||||
ExpiresAt: 0, // No expiration by default
|
|
||||||
}, nil
|
|
||||||
}
|
|
||||||
|
|
||||||
// ValidateServiceBindingPermission checks if a service binding has a specific permission.
|
|
||||||
func ValidateServiceBindingPermission(binding *ServiceBinding, requiredPermission string) error {
|
|
||||||
if binding == nil {
|
|
||||||
return fmt.Errorf("service binding cannot be nil")
|
|
||||||
}
|
|
||||||
|
|
||||||
// Check if the binding has the required permission
|
|
||||||
for _, perm := range binding.Permissions {
|
|
||||||
if perm == requiredPermission || perm == "admin" {
|
|
||||||
return nil // Permission granted
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return fmt.Errorf("permission denied: %s not granted to credential %s for domain %s",
|
|
||||||
requiredPermission, binding.CredentialID, binding.Domain)
|
|
||||||
}
|
|
||||||
|
|
||||||
// IsServiceBindingExpired checks if a service binding has expired.
|
|
||||||
func IsServiceBindingExpired(binding *ServiceBinding, currentTime int64) bool {
|
|
||||||
if binding == nil {
|
|
||||||
return true
|
|
||||||
}
|
|
||||||
|
|
||||||
// If ExpiresAt is 0, the binding never expires
|
|
||||||
if binding.ExpiresAt == 0 {
|
|
||||||
return false
|
|
||||||
}
|
|
||||||
|
|
||||||
return currentTime >= binding.ExpiresAt
|
|
||||||
}
|
|
||||||
|
|
||||||
// ValidateServiceBindingAccess validates that a credential can access a service with specific permissions.
|
|
||||||
func ValidateServiceBindingAccess(
|
|
||||||
binding *ServiceBinding,
|
|
||||||
requiredPermission string,
|
|
||||||
currentTime int64,
|
|
||||||
) error {
|
|
||||||
if binding == nil {
|
|
||||||
return fmt.Errorf("no service binding found")
|
|
||||||
}
|
|
||||||
|
|
||||||
// Check if binding is expired
|
|
||||||
if IsServiceBindingExpired(binding, currentTime) {
|
|
||||||
return fmt.Errorf("service binding expired at %d", binding.ExpiresAt)
|
|
||||||
}
|
|
||||||
|
|
||||||
// Check permission
|
|
||||||
if err := ValidateServiceBindingPermission(binding, requiredPermission); err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
|
|
||||||
// GenerateServiceBindingID generates a unique ID for a service binding.
|
|
||||||
func GenerateServiceBindingID(credentialID, domain, serviceID string) string {
|
|
||||||
return fmt.Sprintf("%s:%s:%s", credentialID, domain, serviceID)
|
|
||||||
}
|
|
||||||
|
|
||||||
// ValidateDomainVerificationForBinding ensures that a domain is properly verified
|
|
||||||
// before allowing WebAuthn credential binding.
|
|
||||||
func ValidateDomainVerificationForBinding(
|
|
||||||
domain string,
|
|
||||||
verificationStatus string,
|
|
||||||
verifiedAt int64,
|
|
||||||
currentTime int64,
|
|
||||||
) error {
|
|
||||||
if domain == "" {
|
|
||||||
return fmt.Errorf("domain cannot be empty")
|
|
||||||
}
|
|
||||||
|
|
||||||
// Check verification status
|
|
||||||
if verificationStatus != "DOMAIN_VERIFICATION_STATUS_VERIFIED" {
|
|
||||||
return fmt.Errorf("domain %s is not verified (status: %s)", domain, verificationStatus)
|
|
||||||
}
|
|
||||||
|
|
||||||
// Ensure verification is not too old (e.g., within 30 days)
|
|
||||||
const maxVerificationAge = 30 * 24 * 60 * 60 // 30 days in seconds
|
|
||||||
if currentTime-verifiedAt > maxVerificationAge {
|
|
||||||
return fmt.Errorf(
|
|
||||||
"domain verification is too old (verified %d seconds ago)",
|
|
||||||
currentTime-verifiedAt,
|
|
||||||
)
|
|
||||||
}
|
|
||||||
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
|
|
||||||
// ExtractDomainFromOrigin extracts the domain from a WebAuthn origin.
|
|
||||||
func ExtractDomainFromOrigin(origin string) (string, error) {
|
|
||||||
if origin == "" {
|
|
||||||
return "", fmt.Errorf("origin cannot be empty")
|
|
||||||
}
|
|
||||||
|
|
||||||
parsedURL, err := url.Parse(origin)
|
|
||||||
if err != nil {
|
|
||||||
return "", fmt.Errorf("invalid origin format: %w", err)
|
|
||||||
}
|
|
||||||
|
|
||||||
if parsedURL.Scheme != "https" {
|
|
||||||
return "", fmt.Errorf("origin must use HTTPS")
|
|
||||||
}
|
|
||||||
|
|
||||||
return parsedURL.Hostname(), nil
|
|
||||||
}
|
|
||||||
@@ -1,188 +0,0 @@
|
|||||||
// Package webauthn provides Sonr-specific WebAuthn utility functions
|
|
||||||
// that support gasless transaction processing and DID generation.
|
|
||||||
//
|
|
||||||
// This package contains utility functions moved from app/ante/webauthn_gasless.go
|
|
||||||
// to eliminate circular dependencies while providing core WebAuthn functionality.
|
|
||||||
package webauthn
|
|
||||||
|
|
||||||
import (
|
|
||||||
"crypto/sha256"
|
|
||||||
"encoding/hex"
|
|
||||||
"fmt"
|
|
||||||
|
|
||||||
sdk "github.com/cosmos/cosmos-sdk/types"
|
|
||||||
)
|
|
||||||
|
|
||||||
// GenerateAddressFromCredential generates a deterministic address from a WebAuthn credential ID.
|
|
||||||
// This ensures the same credential always generates the same address, allowing for
|
|
||||||
// predictable account creation without requiring pre-existing blockchain state.
|
|
||||||
//
|
|
||||||
// This function is used by the gasless WebAuthn registration system to create
|
|
||||||
// controller addresses automatically when users don't have existing accounts.
|
|
||||||
func GenerateAddressFromCredential(credentialID string) sdk.AccAddress {
|
|
||||||
// Create a deterministic hash from the credential ID
|
|
||||||
// Add a domain separator to prevent collisions with other address generation methods
|
|
||||||
domainSeparator := "webauthn_gasless_v1"
|
|
||||||
data := domainSeparator + credentialID
|
|
||||||
|
|
||||||
// Generate SHA256 hash
|
|
||||||
hash := sha256.Sum256([]byte(data))
|
|
||||||
|
|
||||||
// Take the first 20 bytes for the address (Ethereum-compatible)
|
|
||||||
return sdk.AccAddress(hash[:20])
|
|
||||||
}
|
|
||||||
|
|
||||||
// GenerateDIDFromCredential generates a deterministic DID from a WebAuthn credential.
|
|
||||||
// This creates a unique, reproducible DID for each WebAuthn credential.
|
|
||||||
//
|
|
||||||
// The generated DID follows the format: did:sonr:<hex-encoded-hash-prefix>
|
|
||||||
// where the hash is derived from the credential ID and username.
|
|
||||||
func GenerateDIDFromCredential(credentialID string, username string) string {
|
|
||||||
// Create a deterministic hash from credential ID and username
|
|
||||||
data := credentialID + ":" + username
|
|
||||||
hash := sha256.Sum256([]byte(data))
|
|
||||||
|
|
||||||
// Create a DID with the sonr method
|
|
||||||
// Format: did:sonr:<hex-encoded-hash-prefix>
|
|
||||||
didSuffix := hex.EncodeToString(hash[:16]) // Use first 16 bytes for shorter DIDs
|
|
||||||
return fmt.Sprintf("did:sonr:%s", didSuffix)
|
|
||||||
}
|
|
||||||
|
|
||||||
// GenerateVerificationMethodID creates a verification method ID for WebAuthn credentials.
|
|
||||||
// This follows DID standards for verification method identifiers.
|
|
||||||
func GenerateVerificationMethodID(did, credentialID string) string {
|
|
||||||
// Create a short hash from the credential ID for uniqueness
|
|
||||||
hash := sha256.Sum256([]byte(credentialID))
|
|
||||||
hashSuffix := hex.EncodeToString(hash[:8]) // Use first 8 bytes for compactness
|
|
||||||
|
|
||||||
return fmt.Sprintf("%s#webauthn-%s", did, hashSuffix)
|
|
||||||
}
|
|
||||||
|
|
||||||
// IsValidCredentialID validates that a credential ID meets Sonr's requirements.
|
|
||||||
// WebAuthn credential IDs should be base64url-encoded and of reasonable length.
|
|
||||||
func IsValidCredentialID(credentialID string) bool {
|
|
||||||
if credentialID == "" {
|
|
||||||
return false
|
|
||||||
}
|
|
||||||
|
|
||||||
// Credential IDs should be at least 16 characters (reasonable minimum)
|
|
||||||
// and not exceed 1024 characters (reasonable maximum)
|
|
||||||
if len(credentialID) < 16 || len(credentialID) > 1024 {
|
|
||||||
return false
|
|
||||||
}
|
|
||||||
|
|
||||||
// Basic check for base64url characters
|
|
||||||
// WebAuthn credential IDs are typically base64url encoded
|
|
||||||
for _, r := range credentialID {
|
|
||||||
if !((r >= 'A' && r <= 'Z') ||
|
|
||||||
(r >= 'a' && r <= 'z') ||
|
|
||||||
(r >= '0' && r <= '9') ||
|
|
||||||
r == '-' || r == '_') {
|
|
||||||
return false
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return true
|
|
||||||
}
|
|
||||||
|
|
||||||
// GenerateChallengeHash creates a deterministic challenge hash for WebAuthn operations.
|
|
||||||
// This can be used for challenge generation in situations where deterministic challenges are needed.
|
|
||||||
func GenerateChallengeHash(input string) string {
|
|
||||||
hash := sha256.Sum256([]byte(input))
|
|
||||||
return hex.EncodeToString(hash[:])
|
|
||||||
}
|
|
||||||
|
|
||||||
// ExtractOriginFromURL extracts the origin from a URL for WebAuthn origin validation.
|
|
||||||
// Returns the origin in the format expected by WebAuthn (e.g., "https://example.com").
|
|
||||||
func ExtractOriginFromURL(url string) string {
|
|
||||||
// Simple origin extraction - in production this would use proper URL parsing
|
|
||||||
// For now, return the input assuming it's already a valid origin
|
|
||||||
return url
|
|
||||||
}
|
|
||||||
|
|
||||||
// ValidateOriginFormat validates that an origin meets WebAuthn requirements.
|
|
||||||
func ValidateOriginFormat(origin string) error {
|
|
||||||
if origin == "" {
|
|
||||||
return fmt.Errorf("origin cannot be empty")
|
|
||||||
}
|
|
||||||
|
|
||||||
// WebAuthn origins must be HTTPS (except localhost for development)
|
|
||||||
if origin != "http://localhost" &&
|
|
||||||
origin != "http://127.0.0.1" &&
|
|
||||||
len(origin) >= 8 &&
|
|
||||||
origin[:8] != "https://" {
|
|
||||||
return fmt.Errorf("WebAuthn origins must use HTTPS (or localhost for development)")
|
|
||||||
}
|
|
||||||
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
|
|
||||||
// CreateDeterministicSeed creates a deterministic seed from multiple inputs.
|
|
||||||
// This is useful for generating consistent values across different operations.
|
|
||||||
func CreateDeterministicSeed(inputs ...string) []byte {
|
|
||||||
var combined string
|
|
||||||
for _, input := range inputs {
|
|
||||||
combined += input + ":"
|
|
||||||
}
|
|
||||||
|
|
||||||
hash := sha256.Sum256([]byte(combined))
|
|
||||||
return hash[:]
|
|
||||||
}
|
|
||||||
|
|
||||||
// FormatCredentialForDisplay formats a credential ID for user-friendly display.
|
|
||||||
// Truncates long credential IDs while preserving uniqueness for display purposes.
|
|
||||||
func FormatCredentialForDisplay(credentialID string) string {
|
|
||||||
if len(credentialID) <= 16 {
|
|
||||||
return credentialID
|
|
||||||
}
|
|
||||||
|
|
||||||
// Show first 8 and last 8 characters with ellipsis in between
|
|
||||||
return fmt.Sprintf("%s...%s", credentialID[:8], credentialID[len(credentialID)-8:])
|
|
||||||
}
|
|
||||||
|
|
||||||
// ValidateUsernameFormat validates that a username meets Sonr's requirements.
|
|
||||||
func ValidateUsernameFormat(username string) error {
|
|
||||||
if username == "" {
|
|
||||||
return fmt.Errorf("username cannot be empty")
|
|
||||||
}
|
|
||||||
|
|
||||||
if len(username) < 3 {
|
|
||||||
return fmt.Errorf("username must be at least 3 characters long")
|
|
||||||
}
|
|
||||||
|
|
||||||
if len(username) > 32 {
|
|
||||||
return fmt.Errorf("username cannot exceed 32 characters")
|
|
||||||
}
|
|
||||||
|
|
||||||
// Check for valid characters (alphanumeric and some special characters)
|
|
||||||
for _, r := range username {
|
|
||||||
if !((r >= 'A' && r <= 'Z') ||
|
|
||||||
(r >= 'a' && r <= 'z') ||
|
|
||||||
(r >= '0' && r <= '9') ||
|
|
||||||
r == '-' || r == '_' || r == '.') {
|
|
||||||
return fmt.Errorf("username contains invalid character: %c", r)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
|
|
||||||
// GenerateAccountSeq generates a deterministic account sequence for gasless transactions.
|
|
||||||
// This ensures consistent account sequence handling for WebAuthn gasless transactions.
|
|
||||||
func GenerateAccountSeq(credentialID string, blockHeight int64) uint64 {
|
|
||||||
data := fmt.Sprintf("%s:%d", credentialID, blockHeight)
|
|
||||||
hash := sha256.Sum256([]byte(data))
|
|
||||||
|
|
||||||
// Convert first 8 bytes to uint64
|
|
||||||
var seq uint64
|
|
||||||
for i := 0; i < 8; i++ {
|
|
||||||
seq = seq<<8 + uint64(hash[i])
|
|
||||||
}
|
|
||||||
|
|
||||||
// Ensure it's not zero
|
|
||||||
if seq == 0 {
|
|
||||||
seq = 1
|
|
||||||
}
|
|
||||||
|
|
||||||
return seq
|
|
||||||
}
|
|
||||||
@@ -1,437 +0,0 @@
|
|||||||
// Package webauthn provides Sonr-specific WebAuthn validation extensions
|
|
||||||
// that integrate with the comprehensive WebAuthn protocol implementation.
|
|
||||||
//
|
|
||||||
// This package contains validation methods moved from x/did/types/webauthn.go
|
|
||||||
// to eliminate circular dependencies while leveraging the full WebAuthn protocol stack.
|
|
||||||
package webauthn
|
|
||||||
|
|
||||||
import (
|
|
||||||
"crypto/sha256"
|
|
||||||
"encoding/base64"
|
|
||||||
"encoding/json"
|
|
||||||
"fmt"
|
|
||||||
"slices"
|
|
||||||
|
|
||||||
"github.com/sonr-io/common/webauthn/webauthncbor"
|
|
||||||
"github.com/sonr-io/common/webauthn/webauthncose"
|
|
||||||
)
|
|
||||||
|
|
||||||
// WebAuthnCredential defines the interface that WebAuthn credentials must implement
|
|
||||||
// This avoids circular dependencies while allowing validation of any credential type
|
|
||||||
type WebAuthnCredential interface {
|
|
||||||
GetCredentialId() string
|
|
||||||
GetPublicKey() []byte
|
|
||||||
GetAlgorithm() int32
|
|
||||||
GetRawId() string
|
|
||||||
GetClientDataJson() string
|
|
||||||
GetAttestationObject() string
|
|
||||||
GetOrigin() string
|
|
||||||
}
|
|
||||||
|
|
||||||
// ClientData represents the parsed client data JSON from WebAuthn
|
|
||||||
type ClientData struct {
|
|
||||||
Type string `json:"type"`
|
|
||||||
Challenge string `json:"challenge"`
|
|
||||||
Origin string `json:"origin"`
|
|
||||||
}
|
|
||||||
|
|
||||||
// ValidateStructure validates a WebAuthn credential for gasless transaction processing.
|
|
||||||
// This method performs cryptographic validation to ensure the credential is legitimate
|
|
||||||
// and prevents abuse of the gasless registration system.
|
|
||||||
//
|
|
||||||
// Validation checks:
|
|
||||||
// 1. Required fields are present (credential_id, public_key, algorithm)
|
|
||||||
// 2. Algorithm is supported (ES256, RS256)
|
|
||||||
// 3. Public key can be parsed successfully
|
|
||||||
// 4. Raw ID matches credential ID when base64url decoded
|
|
||||||
func ValidateStructure(c WebAuthnCredential) error {
|
|
||||||
if c == nil {
|
|
||||||
return fmt.Errorf("credential cannot be nil")
|
|
||||||
}
|
|
||||||
|
|
||||||
// Validate required fields
|
|
||||||
if c.GetCredentialId() == "" {
|
|
||||||
return fmt.Errorf("credential_id is required")
|
|
||||||
}
|
|
||||||
|
|
||||||
if len(c.GetPublicKey()) == 0 {
|
|
||||||
return fmt.Errorf("public_key is required")
|
|
||||||
}
|
|
||||||
|
|
||||||
if c.GetAlgorithm() == 0 {
|
|
||||||
return fmt.Errorf("algorithm is required")
|
|
||||||
}
|
|
||||||
|
|
||||||
// Validate supported algorithms
|
|
||||||
switch c.GetAlgorithm() {
|
|
||||||
case -7: // ES256
|
|
||||||
case -257: // RS256
|
|
||||||
default:
|
|
||||||
return fmt.Errorf("unsupported algorithm: %d", c.GetAlgorithm())
|
|
||||||
}
|
|
||||||
|
|
||||||
// Validate public key can be parsed
|
|
||||||
if err := validatePublicKeyFormat(c); err != nil {
|
|
||||||
return fmt.Errorf("invalid public key format: %v", err)
|
|
||||||
}
|
|
||||||
|
|
||||||
// Validate raw_id matches credential_id when decoded
|
|
||||||
if c.GetRawId() != "" {
|
|
||||||
decodedRawID, err := base64.RawURLEncoding.DecodeString(c.GetRawId())
|
|
||||||
if err != nil {
|
|
||||||
return fmt.Errorf("invalid raw_id encoding: %v", err)
|
|
||||||
}
|
|
||||||
|
|
||||||
decodedCredID, err := base64.RawURLEncoding.DecodeString(c.GetCredentialId())
|
|
||||||
if err != nil {
|
|
||||||
return fmt.Errorf("invalid credential_id encoding: %v", err)
|
|
||||||
}
|
|
||||||
|
|
||||||
if string(decodedRawID) != string(decodedCredID) {
|
|
||||||
return fmt.Errorf("raw_id does not match credential_id")
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
|
|
||||||
// validatePublicKeyFormat validates that the public key can be parsed according to the specified algorithm.
|
|
||||||
// WebAuthn public keys are typically in COSE format, so we use the webauthncose package for parsing.
|
|
||||||
func validatePublicKeyFormat(c WebAuthnCredential) error {
|
|
||||||
// Use the comprehensive COSE public key parser from the WebAuthn library
|
|
||||||
parsedKey, err := webauthncose.ParsePublicKey(c.GetPublicKey())
|
|
||||||
if err != nil {
|
|
||||||
return fmt.Errorf("failed to parse COSE public key: %w", err)
|
|
||||||
}
|
|
||||||
|
|
||||||
// Validate the parsed key matches the expected algorithm
|
|
||||||
switch c.GetAlgorithm() {
|
|
||||||
case -7: // ES256 (ECDSA with P-256 and SHA-256)
|
|
||||||
cosePubKey, ok := parsedKey.(webauthncose.EC2PublicKeyData)
|
|
||||||
if !ok {
|
|
||||||
return fmt.Errorf(
|
|
||||||
"public key type mismatch: expected EC2PublicKeyData for ES256 algorithm, got %T",
|
|
||||||
parsedKey,
|
|
||||||
)
|
|
||||||
}
|
|
||||||
|
|
||||||
// Validate that we can construct a valid ECDSA public key from the COSE data
|
|
||||||
if len(cosePubKey.XCoord) != 32 || len(cosePubKey.YCoord) != 32 {
|
|
||||||
return fmt.Errorf(
|
|
||||||
"invalid ECDSA coordinate length: x=%d, y=%d (expected 32 bytes each)",
|
|
||||||
len(cosePubKey.XCoord),
|
|
||||||
len(cosePubKey.YCoord),
|
|
||||||
)
|
|
||||||
}
|
|
||||||
|
|
||||||
// Verify the algorithm matches
|
|
||||||
if cosePubKey.Algorithm != -7 {
|
|
||||||
return fmt.Errorf(
|
|
||||||
"algorithm mismatch: COSE key algorithm %d, expected ES256 (-7)",
|
|
||||||
cosePubKey.Algorithm,
|
|
||||||
)
|
|
||||||
}
|
|
||||||
|
|
||||||
return nil
|
|
||||||
|
|
||||||
case -257: // RS256 (RSASSA-PKCS1-v1_5 with SHA-256)
|
|
||||||
cosePubKey, ok := parsedKey.(webauthncose.RSAPublicKeyData)
|
|
||||||
if !ok {
|
|
||||||
return fmt.Errorf(
|
|
||||||
"public key type mismatch: expected RSAPublicKeyData for RS256 algorithm, got %T",
|
|
||||||
parsedKey,
|
|
||||||
)
|
|
||||||
}
|
|
||||||
|
|
||||||
// Validate RSA key components
|
|
||||||
if len(cosePubKey.Modulus) == 0 || len(cosePubKey.Exponent) == 0 {
|
|
||||||
return fmt.Errorf("invalid RSA key: empty modulus or exponent")
|
|
||||||
}
|
|
||||||
|
|
||||||
// Verify the algorithm matches
|
|
||||||
if cosePubKey.Algorithm != -257 {
|
|
||||||
return fmt.Errorf(
|
|
||||||
"algorithm mismatch: COSE key algorithm %d, expected RS256 (-257)",
|
|
||||||
cosePubKey.Algorithm,
|
|
||||||
)
|
|
||||||
}
|
|
||||||
|
|
||||||
return nil
|
|
||||||
|
|
||||||
default:
|
|
||||||
return fmt.Errorf("unsupported algorithm for validation: %d", c.GetAlgorithm())
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// ValidateAttestation performs security validation of WebAuthn credential data.
|
|
||||||
// This performs essential security checks while leveraging the comprehensive
|
|
||||||
// WebAuthn protocol validation framework where possible.
|
|
||||||
//
|
|
||||||
// Security checks performed:
|
|
||||||
// 1. Challenge verification against provided challenge
|
|
||||||
// 2. Origin validation against expected origin
|
|
||||||
// 3. Client data JSON structure validation
|
|
||||||
// 4. Basic attestation object presence validation
|
|
||||||
func ValidateAttestation(c WebAuthnCredential, challenge, expectedOrigin string) error {
|
|
||||||
if c == nil {
|
|
||||||
return fmt.Errorf("credential cannot be nil")
|
|
||||||
}
|
|
||||||
|
|
||||||
// Validate that we have the required attestation data
|
|
||||||
if c.GetClientDataJson() == "" {
|
|
||||||
return fmt.Errorf("client_data_json is required for attestation validation")
|
|
||||||
}
|
|
||||||
|
|
||||||
if c.GetAttestationObject() == "" {
|
|
||||||
return fmt.Errorf("attestation_object is required for attestation validation")
|
|
||||||
}
|
|
||||||
|
|
||||||
// Parse and validate client data JSON
|
|
||||||
clientData, err := parseClientDataJSON(c.GetClientDataJson())
|
|
||||||
if err != nil {
|
|
||||||
return fmt.Errorf("failed to parse client data JSON: %w", err)
|
|
||||||
}
|
|
||||||
|
|
||||||
// Validate challenge
|
|
||||||
if challenge != "" && clientData.Challenge != challenge {
|
|
||||||
return fmt.Errorf(
|
|
||||||
"challenge mismatch: expected %s, got %s",
|
|
||||||
challenge,
|
|
||||||
clientData.Challenge,
|
|
||||||
)
|
|
||||||
}
|
|
||||||
|
|
||||||
// Validate origin
|
|
||||||
if expectedOrigin != "" && clientData.Origin != expectedOrigin {
|
|
||||||
return fmt.Errorf("origin mismatch: expected %s, got %s", expectedOrigin, clientData.Origin)
|
|
||||||
}
|
|
||||||
|
|
||||||
// Validate type is "webauthn.create" for registration
|
|
||||||
if clientData.Type != "webauthn.create" {
|
|
||||||
return fmt.Errorf(
|
|
||||||
"invalid client data type: expected 'webauthn.create', got %s",
|
|
||||||
clientData.Type,
|
|
||||||
)
|
|
||||||
}
|
|
||||||
|
|
||||||
// Validate attestation object is valid base64url and has reasonable size
|
|
||||||
attestationBytes, err := base64.RawURLEncoding.DecodeString(c.GetAttestationObject())
|
|
||||||
if err != nil {
|
|
||||||
return fmt.Errorf("invalid attestation object encoding: %w", err)
|
|
||||||
}
|
|
||||||
|
|
||||||
// Basic size validation - attestation objects should be at least 100 bytes
|
|
||||||
if len(attestationBytes) < 100 {
|
|
||||||
return fmt.Errorf("attestation object too small: %d bytes", len(attestationBytes))
|
|
||||||
}
|
|
||||||
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
|
|
||||||
// parseClientDataJSON parses the base64url-encoded client data JSON
|
|
||||||
func parseClientDataJSON(clientDataJSON string) (*ClientData, error) {
|
|
||||||
clientDataBytes, err := base64.RawURLEncoding.DecodeString(clientDataJSON)
|
|
||||||
if err != nil {
|
|
||||||
return nil, fmt.Errorf("failed to decode client data JSON: %w", err)
|
|
||||||
}
|
|
||||||
|
|
||||||
var clientData ClientData
|
|
||||||
if err := json.Unmarshal(clientDataBytes, &clientData); err != nil {
|
|
||||||
return nil, fmt.Errorf("failed to unmarshal client data JSON: %w", err)
|
|
||||||
}
|
|
||||||
|
|
||||||
return &clientData, nil
|
|
||||||
}
|
|
||||||
|
|
||||||
// ValidateForGaslessRegistration performs comprehensive validation for gasless WebAuthn registration.
|
|
||||||
// This combines structural validation with cryptographic attestation validation,
|
|
||||||
// leveraging the full WebAuthn protocol capabilities where applicable.
|
|
||||||
func ValidateForGaslessRegistration(
|
|
||||||
c WebAuthnCredential,
|
|
||||||
challenge, expectedOrigin string,
|
|
||||||
) error {
|
|
||||||
// First perform structural validation
|
|
||||||
if err := ValidateStructure(c); err != nil {
|
|
||||||
return fmt.Errorf("structural validation failed: %w", err)
|
|
||||||
}
|
|
||||||
|
|
||||||
// Then perform cryptographic attestation validation
|
|
||||||
// For gasless registration, we require full attestation validation to prevent abuse
|
|
||||||
if challenge != "" || expectedOrigin != "" {
|
|
||||||
if err := ValidateAttestation(c, challenge, expectedOrigin); err != nil {
|
|
||||||
return fmt.Errorf("attestation validation failed: %w", err)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
|
|
||||||
// ValidateCredentialUniqueness validates that a WebAuthn credential is unique
|
|
||||||
// across the entire system to prevent reuse attacks in gasless transactions.
|
|
||||||
func ValidateCredentialUniqueness(credentialID string, existingCredentials []string) error {
|
|
||||||
if credentialID == "" {
|
|
||||||
return fmt.Errorf("credential_id cannot be empty")
|
|
||||||
}
|
|
||||||
|
|
||||||
// Check against all existing credentials
|
|
||||||
if slices.Contains(existingCredentials, credentialID) {
|
|
||||||
return fmt.Errorf("credential_id already exists: %s", credentialID)
|
|
||||||
}
|
|
||||||
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
|
|
||||||
// ValidateAlgorithmSupport validates that the specified algorithm is supported
|
|
||||||
// by the Sonr WebAuthn implementation.
|
|
||||||
func ValidateAlgorithmSupport(algorithm int32) error {
|
|
||||||
switch algorithm {
|
|
||||||
case -7: // ES256 (ECDSA with P-256 and SHA-256)
|
|
||||||
return nil
|
|
||||||
case -257: // RS256 (RSASSA-PKCS1-v1_5 with SHA-256)
|
|
||||||
return nil
|
|
||||||
default:
|
|
||||||
return fmt.Errorf(
|
|
||||||
"unsupported algorithm: %d (only ES256 (-7) and RS256 (-257) are supported)",
|
|
||||||
algorithm,
|
|
||||||
)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// Enhanced validation functions that leverage the full WebAuthn protocol
|
|
||||||
|
|
||||||
// ValidateAttestationObjectFormat validates the attestation object format
|
|
||||||
// using the comprehensive WebAuthn protocol validation framework.
|
|
||||||
func ValidateAttestationObjectFormat(attestationObject string) error {
|
|
||||||
if attestationObject == "" {
|
|
||||||
return fmt.Errorf("attestation_object is required")
|
|
||||||
}
|
|
||||||
|
|
||||||
// Decode the attestation object
|
|
||||||
attestationBytes, err := base64.RawURLEncoding.DecodeString(attestationObject)
|
|
||||||
if err != nil {
|
|
||||||
return fmt.Errorf("invalid attestation object encoding: %w", err)
|
|
||||||
}
|
|
||||||
|
|
||||||
// Validate minimum size
|
|
||||||
if len(attestationBytes) < 100 {
|
|
||||||
return fmt.Errorf("attestation object too small: %d bytes", len(attestationBytes))
|
|
||||||
}
|
|
||||||
|
|
||||||
// Use the existing WebAuthn protocol CBOR unmarshaling for validation
|
|
||||||
var attestationObj AttestationObject
|
|
||||||
if err := webauthncbor.Unmarshal(attestationBytes, &attestationObj); err != nil {
|
|
||||||
return fmt.Errorf("failed to unmarshal attestation object: %w", err)
|
|
||||||
}
|
|
||||||
|
|
||||||
// Validate authenticator data can be unmarshaled
|
|
||||||
if err := attestationObj.AuthData.Unmarshal(attestationObj.RawAuthData); err != nil {
|
|
||||||
return fmt.Errorf("failed to unmarshal authenticator data: %w", err)
|
|
||||||
}
|
|
||||||
|
|
||||||
// Check for attested credential data flag
|
|
||||||
if !attestationObj.AuthData.Flags.HasAttestedCredentialData() {
|
|
||||||
return fmt.Errorf("attestation missing attested credential data flag")
|
|
||||||
}
|
|
||||||
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
|
|
||||||
// ValidateClientDataJSONFormat validates the client data JSON format
|
|
||||||
// and returns the parsed client data using the WebAuthn protocol structures.
|
|
||||||
func ValidateClientDataJSONFormat(clientDataJSON string) (*ClientData, error) {
|
|
||||||
if clientDataJSON == "" {
|
|
||||||
return nil, fmt.Errorf("client_data_json is required")
|
|
||||||
}
|
|
||||||
|
|
||||||
// Use the existing WebAuthn protocol's CollectedClientData for validation
|
|
||||||
clientDataBytes, err := base64.RawURLEncoding.DecodeString(clientDataJSON)
|
|
||||||
if err != nil {
|
|
||||||
return nil, fmt.Errorf("failed to decode client data JSON: %w", err)
|
|
||||||
}
|
|
||||||
|
|
||||||
var collectedData CollectedClientData
|
|
||||||
if err := json.Unmarshal(clientDataBytes, &collectedData); err != nil {
|
|
||||||
return nil, fmt.Errorf("failed to unmarshal client data JSON: %w", err)
|
|
||||||
}
|
|
||||||
|
|
||||||
// Convert to our simple ClientData format for compatibility
|
|
||||||
return &ClientData{
|
|
||||||
Type: string(collectedData.Type),
|
|
||||||
Challenge: collectedData.Challenge,
|
|
||||||
Origin: collectedData.Origin,
|
|
||||||
}, nil
|
|
||||||
}
|
|
||||||
|
|
||||||
// ValidateWithProtocol validates a WebAuthn credential using the full protocol validation.
|
|
||||||
// This leverages the comprehensive attestation and client data validation from the WebAuthn library.
|
|
||||||
func ValidateWithProtocol(
|
|
||||||
c WebAuthnCredential,
|
|
||||||
challenge string,
|
|
||||||
rpOrigins []string,
|
|
||||||
rpID string,
|
|
||||||
userVerificationRequired bool,
|
|
||||||
) error {
|
|
||||||
if c == nil {
|
|
||||||
return fmt.Errorf("credential cannot be nil")
|
|
||||||
}
|
|
||||||
|
|
||||||
// Create a CredentialCreationResponse from our credential data
|
|
||||||
ccr := &CredentialCreationResponse{
|
|
||||||
PublicKeyCredential: PublicKeyCredential{
|
|
||||||
Credential: Credential{
|
|
||||||
ID: c.GetCredentialId(),
|
|
||||||
Type: "public-key",
|
|
||||||
},
|
|
||||||
RawID: URLEncodedBase64(c.GetRawId()),
|
|
||||||
},
|
|
||||||
AttestationResponse: AuthenticatorAttestationResponse{
|
|
||||||
AuthenticatorResponse: AuthenticatorResponse{
|
|
||||||
ClientDataJSON: URLEncodedBase64(c.GetClientDataJson()),
|
|
||||||
},
|
|
||||||
AttestationObject: URLEncodedBase64(c.GetAttestationObject()),
|
|
||||||
},
|
|
||||||
}
|
|
||||||
|
|
||||||
// Parse the credential creation response using the full WebAuthn protocol
|
|
||||||
parsed, err := ccr.Parse()
|
|
||||||
if err != nil {
|
|
||||||
return fmt.Errorf("failed to parse credential with WebAuthn protocol: %w", err)
|
|
||||||
}
|
|
||||||
|
|
||||||
// Validate client data using the full protocol validation
|
|
||||||
err = parsed.Response.CollectedClientData.Verify(
|
|
||||||
challenge,
|
|
||||||
CreateCeremony,
|
|
||||||
rpOrigins,
|
|
||||||
[]string{}, // rpTopOrigins - empty for basic validation
|
|
||||||
TopOriginDefaultVerificationMode,
|
|
||||||
)
|
|
||||||
if err != nil {
|
|
||||||
return fmt.Errorf("client data validation failed: %w", err)
|
|
||||||
}
|
|
||||||
|
|
||||||
// Create client data hash for attestation verification
|
|
||||||
clientDataBytes, err := base64.RawURLEncoding.DecodeString(c.GetClientDataJson())
|
|
||||||
if err != nil {
|
|
||||||
return fmt.Errorf("failed to decode client data JSON: %w", err)
|
|
||||||
}
|
|
||||||
clientDataHash := sha256.Sum256(clientDataBytes)
|
|
||||||
|
|
||||||
// Validate the attestation object
|
|
||||||
err = parsed.Response.AttestationObject.Verify(
|
|
||||||
rpID,
|
|
||||||
clientDataHash[:],
|
|
||||||
userVerificationRequired,
|
|
||||||
true, // user presence required
|
|
||||||
nil, // metadata provider - optional
|
|
||||||
[]CredentialParameter{
|
|
||||||
{Type: "public-key", Algorithm: -7}, // ES256
|
|
||||||
{Type: "public-key", Algorithm: -257}, // RS256
|
|
||||||
},
|
|
||||||
)
|
|
||||||
if err != nil {
|
|
||||||
return fmt.Errorf("attestation validation failed: %w", err)
|
|
||||||
}
|
|
||||||
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
Reference in New Issue
Block a user