├── .github └── workflows │ ├── golangci-lint.yml │ └── test.yml ├── LICENSE ├── Makefile ├── README.md ├── bls └── bls.go ├── go.mod ├── go.sum ├── secp256k1 └── secp256k1.go └── wallet ├── keystore.go ├── wallet.go └── wallet_test.go /.github/workflows/golangci-lint.yml: -------------------------------------------------------------------------------- 1 | name: golangci-lint 2 | on: 3 | push: 4 | tags: 5 | - v* 6 | branches: 7 | - main 8 | pull_request: 9 | jobs: 10 | golangci: 11 | name: lint 12 | runs-on: ubuntu-latest 13 | steps: 14 | - uses: actions/checkout@v3 15 | - name: golangci-lint 16 | uses: golangci/golangci-lint-action@v3 17 | with: 18 | version: v1.51.2 19 | -------------------------------------------------------------------------------- /.github/workflows/test.yml: -------------------------------------------------------------------------------- 1 | on: 2 | push: 3 | branches: 4 | - main 5 | pull_request: 6 | branches: 7 | - main 8 | name: Test 9 | jobs: 10 | test: 11 | strategy: 12 | matrix: 13 | go-version: [1.19.x, 1.20.x] 14 | os: [ubuntu-latest, macos-latest, windows-latest] 15 | runs-on: ${{ matrix.os }} 16 | steps: 17 | - name: Install Go 18 | uses: actions/setup-go@v3 19 | with: 20 | go-version: ${{ matrix.go-version }} 21 | - name: Checkout code 22 | uses: actions/checkout@v3 23 | - uses: actions/cache@v3 24 | with: 25 | path: | 26 | ~/go/pkg/mod 27 | ~/.cache/go-build 28 | ~/Library/Caches/go-build 29 | %LocalAppData%\go-build 30 | key: ${{ runner.os }}-go-${{ hashFiles('**/go.sum') }} 31 | restore-keys: | 32 | ${{ runner.os }}-go- 33 | - name: Test CGO free 34 | run: make check-cgo-free 35 | - name: Test 36 | run: make test 37 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (c) 2019 textile.io 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | -------------------------------------------------------------------------------- /Makefile: -------------------------------------------------------------------------------- 1 | GO_FLAGS=CGO_ENABLED=0 2 | 3 | check-cgo-free: 4 | $(GO_FLAGS) go build ./... 5 | .PHONY: check-cgo-free 6 | 7 | test: 8 | $(GO_FLAGS) go test ./... 9 | go test ./... -race # -race requires CGO 10 | .PHONY: test 11 | 12 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # Pure Go Filecoin signer 2 | 3 | 4 | > A pure Go (CGO free) signing library for Filecoin 5 | 6 | Supports both Secp256k1 and BLS signatures. 7 | 8 | An important goal of this library is avoiding CGO dependencies which is very convenient 9 | for simplicity and painless compatibility in multiples OS and CPU architectures. 10 | 11 | ## Roadmap 12 | 13 | - [ ] Provide a Wallet interface that can be a drop-in replacement with Lotus wallets. 14 | - [ ] Include more test vectors for both secp256k1 and BLS signatures. 15 | 16 | ## Contributing 17 | 18 | Contributions are what make the open source community such an amazing place to be learn, inspire, and create. Any contributions you make are **greatly appreciated**. 19 | 20 | 21 | ## License 22 | 23 | Distributed under the MIT License. See `LICENSE` for more information. 24 | 25 | ## Contact 26 | 27 | Ignacio Hagopian - [@jsign](https://github.com/jsign) 28 | 29 | 30 | ## Acknowledgements 31 | * [@xinaxu](https://github.com/xinaxu) 32 | * [@dignifiedquire](https://github.com/dignifiedquire) 33 | * [@nikkolasg](https://github.com/nikkolasg) 34 | * [@ribasushi](https://github.com/ribasushi) 35 | * [@whyrusleeping](https://github.com/whyrusleeping) 36 | 37 | -------------------------------------------------------------------------------- /bls/bls.go: -------------------------------------------------------------------------------- 1 | package bls 2 | 3 | import ( 4 | "fmt" 5 | 6 | curve12381 "github.com/drand/kyber-bls12381" 7 | "github.com/drand/kyber/sign/bls" // nolint:staticcheck 8 | "github.com/filecoin-project/go-address" 9 | ) 10 | 11 | // Sign creates a BLS signature of a message using a private key. 12 | // The private key needs to be in exact format as expected in an official 13 | // Filecoin client, which is a big-endian encoded 32 byte scalar. 14 | // The signature has a format as described in RFC 2.6.1. 15 | func Sign(pk []byte, msg []byte) ([]byte, error) { 16 | // We need to do an endianess conversion considering 17 | // Filecoin assumptions around the private key representation. 18 | var pkrev [32]byte 19 | isZero := true 20 | for i := 0; i < 32; i++ { 21 | pkrev[i] = pk[32-i-1] 22 | if pkrev[i] != 0 { 23 | isZero = false 24 | } 25 | } 26 | if isZero { 27 | return nil, fmt.Errorf("private key is zero point") 28 | } 29 | scalar := curve12381.NewKyberScalar().SetBytes(pkrev[:]) 30 | signer := bls.NewSchemeOnG2(curve12381.NewBLS12381Suite()) 31 | s, err := signer.Sign(scalar, msg) 32 | if err != nil { 33 | return nil, fmt.Errorf("signing: %w", err) 34 | } 35 | return s, nil 36 | } 37 | 38 | // Verify verifies that a message is correctly signed by a public key. 39 | func Verify(pubkey, msg, sig []byte) (bool, error) { 40 | point := curve12381.NewGroupG1().Point() 41 | if err := point.UnmarshalBinary(pubkey); err != nil { 42 | return false, nil 43 | } 44 | if point.Equal(curve12381.NullKyberG1()) { 45 | return false, fmt.Errorf("public key is zero point") 46 | } 47 | signer := bls.NewSchemeOnG2(curve12381.NewBLS12381Suite()) 48 | if err := signer.Verify(point, msg, sig); err != nil { 49 | return false, nil 50 | } 51 | 52 | return true, nil 53 | } 54 | 55 | // GetPubKey returns the public key from the private key. 56 | func GetPubKey(pk []byte) (address.Address, error) { 57 | var pkrev [32]byte 58 | for i := 0; i < 32; i++ { 59 | pkrev[i] = pk[32-i-1] 60 | } 61 | scalar := curve12381.NewKyberScalar().SetBytes(pkrev[:]) 62 | pubPoint := curve12381.NewGroupG1().Point() 63 | pubPoint.Mul(scalar, nil) 64 | 65 | buf, err := pubPoint.MarshalBinary() 66 | if err != nil { 67 | return address.Address{}, fmt.Errorf("marshaling pub: %s", err) 68 | } 69 | addr, err := address.NewBLSAddress(buf) 70 | if err != nil { 71 | return address.Undef, fmt.Errorf("generating public key: %s", err) 72 | } 73 | 74 | return addr, nil 75 | } 76 | -------------------------------------------------------------------------------- /go.mod: -------------------------------------------------------------------------------- 1 | module github.com/jsign/go-filsigner 2 | 3 | go 1.16 4 | 5 | require ( 6 | github.com/dchest/blake2b v1.0.0 7 | github.com/decred/dcrd/dcrec/secp256k1/v4 v4.0.0-20210507181900-4e0be8d2fbb4 8 | github.com/drand/kyber v1.1.4 9 | github.com/drand/kyber-bls12381 v0.2.1 10 | github.com/filecoin-project/go-address v1.1.0 11 | github.com/filecoin-project/go-state-types v0.10.0 12 | github.com/stretchr/testify v1.7.0 13 | ) 14 | -------------------------------------------------------------------------------- /go.sum: -------------------------------------------------------------------------------- 1 | github.com/BurntSushi/toml v0.3.1/go.mod h1:xHWCNGjB5oqiDr8zfno3MHue2Ht5sIBksp03qcyfWMU= 2 | github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= 3 | github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c= 4 | github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= 5 | github.com/dchest/blake2b v1.0.0 h1:KK9LimVmE0MjRl9095XJmKqZ+iLxWATvlcpVFRtaw6s= 6 | github.com/dchest/blake2b v1.0.0/go.mod h1:U034kXgbJpCle2wSk5ybGIVhOSHCVLMDqOzcPEA0F7s= 7 | github.com/decred/dcrd/chaincfg/chainhash v1.0.2 h1:rt5Vlq/jM3ZawwiacWjPa+smINyLRN07EO0cNBV6DGU= 8 | github.com/decred/dcrd/chaincfg/chainhash v1.0.2/go.mod h1:BpbrGgrPTr3YJYRN3Bm+D9NuaFd+zGyNeIKgrhCXK60= 9 | github.com/decred/dcrd/crypto/blake256 v1.0.0 h1:/8DMNYp9SGi5f0w7uCm6d6M4OU2rGFK09Y2A4Xv7EE0= 10 | github.com/decred/dcrd/crypto/blake256 v1.0.0/go.mod h1:sQl2p6Y26YV+ZOcSTP6thNdn47hh8kt6rqSlvmrXFAc= 11 | github.com/decred/dcrd/dcrec/secp256k1/v4 v4.0.0-20210507181900-4e0be8d2fbb4 h1:C3W9QFmRizSpUtcO8fPhQuu5g4IXvj74k05L0gA5mXE= 12 | github.com/decred/dcrd/dcrec/secp256k1/v4 v4.0.0-20210507181900-4e0be8d2fbb4/go.mod h1:UkVqoxmJlLgUvBjJD+GdJz6mgdSdf3UjX83xfwUAYDk= 13 | github.com/drand/bls12-381 v0.3.2/go.mod h1:dtcLgPtYT38L3NO6mPDYH0nbpc5tjPassDqiniuAt4Y= 14 | github.com/drand/kyber v1.0.1-0.20200110225416-8de27ed8c0e2/go.mod h1:UpXoA0Upd1N9l4TvRPHr1qAUBBERj6JQ/mnKI3BPEmw= 15 | github.com/drand/kyber v1.0.2/go.mod h1:x6KOpK7avKj0GJ4emhXFP5n7M7W7ChAPmnQh/OL6vRw= 16 | github.com/drand/kyber v1.1.4 h1:YvKM03QWGvLrdTnYmxxP5iURAX+Gdb6qRDUOgg8i60Q= 17 | github.com/drand/kyber v1.1.4/go.mod h1:9+IgTq7kadePhZg7eRwSD7+bA+bmvqRK+8DtmoV5a3U= 18 | github.com/drand/kyber-bls12381 v0.2.0/go.mod h1:zQip/bHdeEB6HFZSU3v+d3cQE0GaBVQw9aR2E7AdoeI= 19 | github.com/drand/kyber-bls12381 v0.2.1 h1:/d5/YAdaCmHpYjF1NZevOEcKGaq6LBbyvkCTIdGqDjs= 20 | github.com/drand/kyber-bls12381 v0.2.1/go.mod h1:JwWn4nHO9Mp4F5qCie5sVIPQZ0X6cw8XAeMRvc/GXBE= 21 | github.com/filecoin-project/filecoin-ffi v0.30.4-0.20200910194244-f640612a1a1f/go.mod h1:+If3s2VxyjZn+KGGZIoRXBDSFQ9xL404JBJGf4WhEj0= 22 | github.com/filecoin-project/go-address v0.0.3/go.mod h1:jr8JxKsYx+lQlQZmF5i2U0Z+cGQ59wMIps/8YW/lDj8= 23 | github.com/filecoin-project/go-address v0.0.5/go.mod h1:jr8JxKsYx+lQlQZmF5i2U0Z+cGQ59wMIps/8YW/lDj8= 24 | github.com/filecoin-project/go-address v1.1.0 h1:ofdtUtEsNxkIxkDw67ecSmvtzaVSdcea4boAmLbnHfE= 25 | github.com/filecoin-project/go-address v1.1.0/go.mod h1:5t3z6qPmIADZBtuE9EIzi0EwzcRy2nVhpo0I/c1r0OA= 26 | github.com/filecoin-project/go-amt-ipld/v2 v2.1.0/go.mod h1:nfFPoGyX0CU9SkXX8EoCcSuHN1XcbN0c6KBh7yvP5fs= 27 | github.com/filecoin-project/go-amt-ipld/v4 v4.0.0/go.mod h1:gF053YQ4BIpzTNDoEwHZas7U3oAwncDVGvOHyY8oDpE= 28 | github.com/filecoin-project/go-bitfield v0.2.0/go.mod h1:CNl9WG8hgR5mttCnUErjcQjGvuiZjRqK9rHVBsQF4oM= 29 | github.com/filecoin-project/go-bitfield v0.2.4/go.mod h1:CNl9WG8hgR5mttCnUErjcQjGvuiZjRqK9rHVBsQF4oM= 30 | github.com/filecoin-project/go-commp-utils v0.1.3/go.mod h1:3ENlD1pZySaUout0p9ANQrY3fDFoXdqyX04J+dWpK30= 31 | github.com/filecoin-project/go-commp-utils/nonffi v0.0.0-20220905160352-62059082a837/go.mod h1:e2YBjSblNVoBckkbv3PPqsq71q98oFkFqL7s1etViGo= 32 | github.com/filecoin-project/go-crypto v0.0.0-20191218222705-effae4ea9f03 h1:2pMXdBnCiXjfCYx/hLqFxccPoqsSveQFxVLvNxy9bus= 33 | github.com/filecoin-project/go-crypto v0.0.0-20191218222705-effae4ea9f03/go.mod h1:+viYnvGtUTgJRdy6oaeF4MTFKAfatX071MPDPBL11EQ= 34 | github.com/filecoin-project/go-fil-commcid v0.0.0-20200716160307-8f644712406f/go.mod h1:Eaox7Hvus1JgPrL5+M3+h7aSPHc0cVqpSxA+TxIEpZQ= 35 | github.com/filecoin-project/go-fil-commcid v0.0.0-20201016201715-d41df56b4f6a/go.mod h1:Eaox7Hvus1JgPrL5+M3+h7aSPHc0cVqpSxA+TxIEpZQ= 36 | github.com/filecoin-project/go-fil-commcid v0.1.0/go.mod h1:Eaox7Hvus1JgPrL5+M3+h7aSPHc0cVqpSxA+TxIEpZQ= 37 | github.com/filecoin-project/go-hamt-ipld/v3 v3.1.0/go.mod h1:bxmzgT8tmeVQA1/gvBwFmYdT8SOFUwB3ovSUfG1Ux0g= 38 | github.com/filecoin-project/go-padreader v0.0.0-20200903213702-ed5fae088b20/go.mod h1:mPn+LRRd5gEKNAtc+r3ScpW2JRU/pj4NBKdADYWHiak= 39 | github.com/filecoin-project/go-state-types v0.0.0-20200903145444-247639ffa6ad/go.mod h1:IQ0MBPnonv35CJHtWSN3YY1Hz2gkPru1Q9qoaYLxx9I= 40 | github.com/filecoin-project/go-state-types v0.0.0-20200904021452-1883f36ca2f4/go.mod h1:IQ0MBPnonv35CJHtWSN3YY1Hz2gkPru1Q9qoaYLxx9I= 41 | github.com/filecoin-project/go-state-types v0.0.0-20201102161440-c8033295a1fc/go.mod h1:ezYnPf0bNkTsDibL/psSz5dy4B5awOJ/E7P2Saeep8g= 42 | github.com/filecoin-project/go-state-types v0.1.10/go.mod h1:UwGVoMsULoCK+bWjEdd/xLCvLAQFBC7EDT477SKml+Q= 43 | github.com/filecoin-project/go-state-types v0.10.0 h1:vsSThZIaPmOxNGG59+8D/HnlWRtlbdOjduH6ye+v8f0= 44 | github.com/filecoin-project/go-state-types v0.10.0/go.mod h1:aLIas+W8BWAfpLWEPUOGMPBdhcVwoCG4pIQSQk26024= 45 | github.com/filecoin-project/specs-actors v0.9.4/go.mod h1:BStZQzx5x7TmCkLv0Bpa07U6cPKol6fd3w9KjMPZ6Z4= 46 | github.com/gogo/protobuf v1.3.1/go.mod h1:SlYgWuQ5SjCEi6WLHjHCa1yvBfUnHcTbrrZtXPKa29o= 47 | github.com/google/go-cmp v0.4.0/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= 48 | github.com/google/renameio v0.1.0/go.mod h1:KWCgfxg9yswjAJkECMjeO8J8rahYeXnNhOm40UhjYkI= 49 | github.com/gopherjs/gopherjs v0.0.0-20181017120253-0766667cb4d1/go.mod h1:wJfORRmW1u3UXTncJ5qlYoELFm8eSnnEO6hX4iZ3EWY= 50 | github.com/gopherjs/gopherjs v0.0.0-20190812055157-5d271430af9f h1:KMlcu9X58lhTA/KrfX8Bi1LQSO4pzoVjTiL3h4Jk+Zk= 51 | github.com/gopherjs/gopherjs v0.0.0-20190812055157-5d271430af9f/go.mod h1:wJfORRmW1u3UXTncJ5qlYoELFm8eSnnEO6hX4iZ3EWY= 52 | github.com/gxed/hashland/keccakpg v0.0.1/go.mod h1:kRzw3HkwxFU1mpmPP8v1WyQzwdGfmKFJ6tItnhQ67kU= 53 | github.com/gxed/hashland/murmur3 v0.0.1/go.mod h1:KjXop02n4/ckmZSnY2+HKcLud/tcmvhST0bie/0lS48= 54 | github.com/ipfs/go-block-format v0.0.2/go.mod h1:AWR46JfpcObNfg3ok2JHDUfdiHRgWhJgCQF+KIgOPJY= 55 | github.com/ipfs/go-block-format v0.0.3 h1:r8t66QstRp/pd/or4dpnbVfXT5Gt7lOqRvC+/dDTpMc= 56 | github.com/ipfs/go-block-format v0.0.3/go.mod h1:4LmD4ZUw0mhO+JSKdpWwrzATiEfM7WWgQ8H5l6P8MVk= 57 | github.com/ipfs/go-cid v0.0.1/go.mod h1:GHWU/WuQdMPmIosc4Yn1bcCT7dSeX4lBafM7iqUPQvM= 58 | github.com/ipfs/go-cid v0.0.2/go.mod h1:GHWU/WuQdMPmIosc4Yn1bcCT7dSeX4lBafM7iqUPQvM= 59 | github.com/ipfs/go-cid v0.0.3/go.mod h1:GHWU/WuQdMPmIosc4Yn1bcCT7dSeX4lBafM7iqUPQvM= 60 | github.com/ipfs/go-cid v0.0.5/go.mod h1:plgt+Y5MnOey4vO4UlUazGqdbEXuFYitED67FexhXog= 61 | github.com/ipfs/go-cid v0.0.6-0.20200501230655-7c82f3b81c00/go.mod h1:plgt+Y5MnOey4vO4UlUazGqdbEXuFYitED67FexhXog= 62 | github.com/ipfs/go-cid v0.0.6/go.mod h1:6Ux9z5e+HpkQdckYoX1PG/6xqKspzlEIR5SDmgqgC/I= 63 | github.com/ipfs/go-cid v0.0.7/go.mod h1:6Ux9z5e+HpkQdckYoX1PG/6xqKspzlEIR5SDmgqgC/I= 64 | github.com/ipfs/go-cid v0.2.0 h1:01JTiihFq9en9Vz0lc0VDWvZe/uBonGpzo4THP0vcQ0= 65 | github.com/ipfs/go-cid v0.2.0/go.mod h1:P+HXFDF4CVhaVayiEb4wkAy7zBHxBwsJyt0Y5U6MLro= 66 | github.com/ipfs/go-hamt-ipld v0.1.1/go.mod h1:1EZCr2v0jlCnhpa+aZ0JZYp8Tt2w16+JJOAVz17YcDk= 67 | github.com/ipfs/go-ipfs-util v0.0.1/go.mod h1:spsl5z8KUnrve+73pOhSVZND1SIxPW5RyBCNzQxlJBc= 68 | github.com/ipfs/go-ipfs-util v0.0.2 h1:59Sswnk1MFaiq+VcaknX7aYEyGyGDAA73ilhEK2POp8= 69 | github.com/ipfs/go-ipfs-util v0.0.2/go.mod h1:CbPtkWJzjLdEcezDns2XYaehFVNXG9zrdrtMecczcsQ= 70 | github.com/ipfs/go-ipld-cbor v0.0.4/go.mod h1:BkCduEx3XBCO6t2Sfo5BaHzuok7hbhdMm9Oh8B2Ftq4= 71 | github.com/ipfs/go-ipld-cbor v0.0.5/go.mod h1:BkCduEx3XBCO6t2Sfo5BaHzuok7hbhdMm9Oh8B2Ftq4= 72 | github.com/ipfs/go-ipld-cbor v0.0.6-0.20211211231443-5d9b9e1f6fa8/go.mod h1:ssdxxaLJPXH7OjF5V4NSjBbcfh+evoR4ukuru0oPXMA= 73 | github.com/ipfs/go-ipld-cbor v0.0.6 h1:pYuWHyvSpIsOOLw4Jy7NbBkCyzLDcl64Bf/LZW7eBQ0= 74 | github.com/ipfs/go-ipld-cbor v0.0.6/go.mod h1:ssdxxaLJPXH7OjF5V4NSjBbcfh+evoR4ukuru0oPXMA= 75 | github.com/ipfs/go-ipld-format v0.0.1/go.mod h1:kyJtbkDALmFHv3QR6et67i35QzO3S0dCDnkOJhcZkms= 76 | github.com/ipfs/go-ipld-format v0.0.2 h1:OVAGlyYT6JPZ0pEfGntFPS40lfrDmaDbQwNHEY2G9Zs= 77 | github.com/ipfs/go-ipld-format v0.0.2/go.mod h1:4B6+FM2u9OJ9zCV+kSbgFAZlOrv1Hqbf0INGQgiKf9k= 78 | github.com/ipfs/go-log v1.0.4/go.mod h1:oDCg2FkjogeFOhqqb+N39l2RpTNPL6F/StPkB3kPgcs= 79 | github.com/ipfs/go-log/v2 v2.0.5/go.mod h1:eZs4Xt4ZUJQFM3DlanGhy7TkwwawCZcSByscwkWG+dw= 80 | github.com/ipfs/go-log/v2 v2.1.2-0.20200626104915-0016c0b4b3e4/go.mod h1:2v2nsGfZsvvAJz13SyFzf9ObaqwHiHxsPLEHntrv9KM= 81 | github.com/ipsn/go-secp256k1 v0.0.0-20180726113642-9d62b9f0bc52 h1:QG4CGBqCeuBo6aZlGAamSkxWdgWfZGeE49eUOWJPA4c= 82 | github.com/ipsn/go-secp256k1 v0.0.0-20180726113642-9d62b9f0bc52/go.mod h1:fdg+/X9Gg4AsAIzWpEHwnqd+QY3b7lajxyjE1m4hkq4= 83 | github.com/jonboulle/clockwork v0.1.0/go.mod h1:Ii8DK3G1RaLaWxj9trq07+26W01tbo22gdxWY5EU2bo= 84 | github.com/jtolds/gls v4.2.1+incompatible/go.mod h1:QJZ7F/aHp+rZTRtaJ1ow/lLfFfVYBRgL+9YlvaHOwJU= 85 | github.com/jtolds/gls v4.20.0+incompatible h1:xdiiI2gbIgH/gLH7ADydsJ1uDOEzR8yvV7C0MuV77Wo= 86 | github.com/jtolds/gls v4.20.0+incompatible/go.mod h1:QJZ7F/aHp+rZTRtaJ1ow/lLfFfVYBRgL+9YlvaHOwJU= 87 | github.com/kilic/bls12-381 v0.0.0-20200607163746-32e1441c8a9f/go.mod h1:XXfR6YFCRSrkEXbNlIyDsgXVNJWVUV30m/ebkVy9n6s= 88 | github.com/kilic/bls12-381 v0.0.0-20200731194930-64c428e1bff5/go.mod h1:XXfR6YFCRSrkEXbNlIyDsgXVNJWVUV30m/ebkVy9n6s= 89 | github.com/kilic/bls12-381 v0.0.0-20200820230200-6b2c19996391 h1:51kHw7l/dUDdOdW06AlUGT5jnpj6nqQSILebcsikSjA= 90 | github.com/kilic/bls12-381 v0.0.0-20200820230200-6b2c19996391/go.mod h1:XXfR6YFCRSrkEXbNlIyDsgXVNJWVUV30m/ebkVy9n6s= 91 | github.com/kisielk/errcheck v1.2.0/go.mod h1:/BMXB+zMLi60iA8Vv6Ksmxu/1UDYcXs4uQLJ+jE2L00= 92 | github.com/kisielk/gotool v1.0.0/go.mod h1:XhKaO+MFFWcvkIS/tQcRk01m1F5IRFswLeQ+oQHNcck= 93 | github.com/klauspost/cpuid/v2 v2.0.4 h1:g0I61F2K2DjRHz1cnxlkNSBIaePVoJIjjnHui8QHbiw= 94 | github.com/klauspost/cpuid/v2 v2.0.4/go.mod h1:FInQzS24/EEf25PyTYn52gqo7WaD8xa0213Md/qVLRg= 95 | github.com/kr/pretty v0.1.0/go.mod h1:dAy3ld7l9f0ibDNOQOHHMYYIIbhfbHSm3C4ZsoJORNo= 96 | github.com/kr/pretty v0.2.1 h1:Fmg33tUaq4/8ym9TJN1x7sLJnHVwhP33CNkpYV/7rwI= 97 | github.com/kr/pretty v0.2.1/go.mod h1:ipq/a2n7PKx3OHsz4KJII5eveXtPO4qwEXGdVfWzfnI= 98 | github.com/kr/pty v1.1.1/go.mod h1:pFQYn66WHrOpPYNljwOMqo10TkYh1fy3cYio2l3bCsQ= 99 | github.com/kr/text v0.1.0 h1:45sCR5RtlFHMR4UwH9sdQ5TC8v0qDQCHnXt+kaKSTVE= 100 | github.com/kr/text v0.1.0/go.mod h1:4Jbv+DJW3UT/LiOwJeYQe1efqtUx/iVham/4vfdArNI= 101 | github.com/minio/blake2b-simd v0.0.0-20160723061019-3f5f724cb5b1 h1:lYpkrQH5ajf0OXOcUbGjvZxxijuBwbbmlSxLiuofa+g= 102 | github.com/minio/blake2b-simd v0.0.0-20160723061019-3f5f724cb5b1/go.mod h1:pD8RvIylQ358TN4wwqatJ8rNavkEINozVn9DtGI3dfQ= 103 | github.com/minio/sha256-simd v0.0.0-20190131020904-2d45a736cd16/go.mod h1:2FMWW+8GMoPweT6+pI63m9YE3Lmw4J71hV56Chs1E/U= 104 | github.com/minio/sha256-simd v0.1.1-0.20190913151208-6de447530771/go.mod h1:B5e1o+1/KgNmWrSQK08Y6Z1Vb5pwIktudl0J58iy0KM= 105 | github.com/minio/sha256-simd v0.1.1/go.mod h1:B5e1o+1/KgNmWrSQK08Y6Z1Vb5pwIktudl0J58iy0KM= 106 | github.com/minio/sha256-simd v1.0.0 h1:v1ta+49hkWZyvaKwrQB8elexRqm6Y0aMLjCNsrYxo6g= 107 | github.com/minio/sha256-simd v1.0.0/go.mod h1:OuYzVNI5vcoYIAmbIvHPl3N3jUzVedXbKy5RFepssQM= 108 | github.com/mr-tron/base58 v1.1.0/go.mod h1:xcD2VGqlgYjBdcBLw+TuYLr8afG+Hj8g2eTVqeSzSU8= 109 | github.com/mr-tron/base58 v1.1.2/go.mod h1:BinMc/sQntlIE1frQmRFPUoPA1Zkr8VRgBdjWI2mNwc= 110 | github.com/mr-tron/base58 v1.1.3/go.mod h1:BinMc/sQntlIE1frQmRFPUoPA1Zkr8VRgBdjWI2mNwc= 111 | github.com/mr-tron/base58 v1.2.0 h1:T/HDJBh4ZCPbU39/+c3rRvE0uKBQlU27+QI8LJ4t64o= 112 | github.com/mr-tron/base58 v1.2.0/go.mod h1:BinMc/sQntlIE1frQmRFPUoPA1Zkr8VRgBdjWI2mNwc= 113 | github.com/multiformats/go-base32 v0.0.3 h1:tw5+NhuwaOjJCC5Pp82QuXbrmLzWg7uxlMFp8Nq/kkI= 114 | github.com/multiformats/go-base32 v0.0.3/go.mod h1:pLiuGC8y0QR3Ue4Zug5UzK9LjgbkL8NSQj0zQ5Nz/AA= 115 | github.com/multiformats/go-base36 v0.1.0 h1:JR6TyF7JjGd3m6FbLU2cOxhC0Li8z8dLNGQ89tUg4F4= 116 | github.com/multiformats/go-base36 v0.1.0/go.mod h1:kFGE83c6s80PklsHO9sRn2NCoffoRdUUOENyW/Vv6sM= 117 | github.com/multiformats/go-multibase v0.0.1/go.mod h1:bja2MqRZ3ggyXtZSEDKpl0uO/gviWFaSteVbWT51qgs= 118 | github.com/multiformats/go-multibase v0.0.3 h1:l/B6bJDQjvQ5G52jw4QGSYeOTZoAwIO77RblWplfIqk= 119 | github.com/multiformats/go-multibase v0.0.3/go.mod h1:5+1R4eQrT3PkYZ24C3W2Ue2tPwIdYQD509ZjSb5y9Oc= 120 | github.com/multiformats/go-multihash v0.0.1/go.mod h1:w/5tugSrLEbWqlcgJabL3oHFKTwfvkofsjW2Qa1ct4U= 121 | github.com/multiformats/go-multihash v0.0.10/go.mod h1:YSLudS+Pi8NHE7o6tb3D8vrpKa63epEDmG8nTduyAew= 122 | github.com/multiformats/go-multihash v0.0.13/go.mod h1:VdAWLKTwram9oKAatUcLxBNUjdtcVwxObEQBtRfuyjc= 123 | github.com/multiformats/go-multihash v0.0.14/go.mod h1:VdAWLKTwram9oKAatUcLxBNUjdtcVwxObEQBtRfuyjc= 124 | github.com/multiformats/go-multihash v0.0.15 h1:hWOPdrNqDjwHDx82vsYGSDZNyktOJJ2dzZJzFkOV1jM= 125 | github.com/multiformats/go-multihash v0.0.15/go.mod h1:D6aZrWNLFTV/ynMpKsNtB40mJzmCl4jb1alC0OvHiHg= 126 | github.com/multiformats/go-varint v0.0.5/go.mod h1:3Ls8CIEsrijN6+B7PbrXRPxHRPuXSrVKRY101jdMZYE= 127 | github.com/multiformats/go-varint v0.0.6 h1:gk85QWKxh3TazbLxED/NlDVv8+q+ReFJk7Y2W/KhfNY= 128 | github.com/multiformats/go-varint v0.0.6/go.mod h1:3Ls8CIEsrijN6+B7PbrXRPxHRPuXSrVKRY101jdMZYE= 129 | github.com/opentracing/opentracing-go v1.1.0/go.mod h1:UkNAQd3GIcIGf0SeVgPpRdFStlNbqXla1AfSYxPUl2o= 130 | github.com/pkg/errors v0.8.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0= 131 | github.com/pkg/errors v0.9.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0= 132 | github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM= 133 | github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4= 134 | github.com/polydawn/refmt v0.0.0-20190221155625-df39d6c2d992/go.mod h1:uIp+gprXxxrWSjjklXD+mN4wed/tMfjMMmN/9+JsA9o= 135 | github.com/polydawn/refmt v0.0.0-20190807091052-3d65705ee9f1/go.mod h1:uIp+gprXxxrWSjjklXD+mN4wed/tMfjMMmN/9+JsA9o= 136 | github.com/polydawn/refmt v0.0.0-20190809202753-05966cbd336a h1:hjZfReYVLbqFkAtr2us7vdy04YWz3LVAirzP7reh8+M= 137 | github.com/polydawn/refmt v0.0.0-20190809202753-05966cbd336a/go.mod h1:uIp+gprXxxrWSjjklXD+mN4wed/tMfjMMmN/9+JsA9o= 138 | github.com/remyoudompheng/bigfft v0.0.0-20200410134404-eec4a21b6bb0/go.mod h1:qqbHyh8v60DhA7CoWK5oRCqLrMHRGoxYCSS9EjAz6Eo= 139 | github.com/rogpeppe/go-internal v1.3.0/go.mod h1:M8bDsm7K2OlrFYOpmOWEs/qY81heoFRclV5y23lUDJ4= 140 | github.com/smartystreets/assertions v0.0.0-20180927180507-b2de0cb4f26d/go.mod h1:OnSkiWE9lh6wB0YB77sQom3nweQdgAjqCqsofrRNTgc= 141 | github.com/smartystreets/assertions v1.0.1 h1:voD4ITNjPL5jjBfgR/r8fPIIBrliWrWHeiJApdr3r4w= 142 | github.com/smartystreets/assertions v1.0.1/go.mod h1:kHHU4qYBaI3q23Pp3VPrmWhuIUrLW/7eUrw0BU5VaoM= 143 | github.com/smartystreets/goconvey v0.0.0-20190222223459-a17d461953aa/go.mod h1:2RVY1rIf+2J2o/IM9+vPq9RzmHDSseB7FoXiSNIUsoU= 144 | github.com/smartystreets/goconvey v0.0.0-20190731233626-505e41936337 h1:WN9BUFbdyOsSH/XohnWpXOlq9NBD5sGAB2FciQMUEe8= 145 | github.com/smartystreets/goconvey v0.0.0-20190731233626-505e41936337/go.mod h1:syvi0/a8iFYH4r/RixwvyeAJjdLS9QV7WQ/tjFTllLA= 146 | github.com/spaolacci/murmur3 v1.1.0/go.mod h1:JwIasOWyU6f++ZhiEuf87xNszmSA2myDM2Kzu9HwQUA= 147 | github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME= 148 | github.com/stretchr/testify v1.3.0/go.mod h1:M5WIy9Dh21IEIfnGCwXGc5bZfKNJtfHm1UVUgZn+9EI= 149 | github.com/stretchr/testify v1.4.0/go.mod h1:j7eGeouHqKxXV5pUuKE4zz7dFj8WfuZ+81PSLYec5m4= 150 | github.com/stretchr/testify v1.6.1/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg= 151 | github.com/stretchr/testify v1.7.0 h1:nwc3DEeHmmLAfoZucVR881uASk0Mfjw8xYJ99tb5CcY= 152 | github.com/stretchr/testify v1.7.0/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg= 153 | github.com/tj/go-spin v1.1.0/go.mod h1:Mg1mzmePZm4dva8Qz60H2lHwmJ2loum4VIrLgVnKwh4= 154 | github.com/warpfork/go-wish v0.0.0-20180510122957-5ad1f5abf436/go.mod h1:x6AKhvSSexNrVSrViXSHUEbICjmGXhtgABaHIySUSGw= 155 | github.com/warpfork/go-wish v0.0.0-20190328234359-8b3e70f8e830 h1:8kxMKmKzXXL4Ru1nyhvdms/JjWt+3YLpvRb/bAjO/y0= 156 | github.com/warpfork/go-wish v0.0.0-20190328234359-8b3e70f8e830/go.mod h1:x6AKhvSSexNrVSrViXSHUEbICjmGXhtgABaHIySUSGw= 157 | github.com/whyrusleeping/cbor-gen v0.0.0-20200123233031-1cdf64d27158/go.mod h1:Xj/M2wWU+QdTdRbu/L/1dIZY8/Wb2K9pAhtroQuxJJI= 158 | github.com/whyrusleeping/cbor-gen v0.0.0-20200414195334-429a0b5e922e/go.mod h1:Xj/M2wWU+QdTdRbu/L/1dIZY8/Wb2K9pAhtroQuxJJI= 159 | github.com/whyrusleeping/cbor-gen v0.0.0-20200504204219-64967432584d/go.mod h1:W5MvapuoHRP8rz4vxjwCK1pDqF1aQcWsV5PZ+AHbqdg= 160 | github.com/whyrusleeping/cbor-gen v0.0.0-20200715143311-227fab5a2377/go.mod h1:fgkXqYy7bV2cFeIEOkVTZS/WjXARfBqSH6Q2qHL33hQ= 161 | github.com/whyrusleeping/cbor-gen v0.0.0-20200723185710-6a3894a6352b/go.mod h1:fgkXqYy7bV2cFeIEOkVTZS/WjXARfBqSH6Q2qHL33hQ= 162 | github.com/whyrusleeping/cbor-gen v0.0.0-20200806213330-63aa96ca5488/go.mod h1:fgkXqYy7bV2cFeIEOkVTZS/WjXARfBqSH6Q2qHL33hQ= 163 | github.com/whyrusleeping/cbor-gen v0.0.0-20200810223238-211df3b9e24c/go.mod h1:fgkXqYy7bV2cFeIEOkVTZS/WjXARfBqSH6Q2qHL33hQ= 164 | github.com/whyrusleeping/cbor-gen v0.0.0-20200812213548-958ddffe352c/go.mod h1:fgkXqYy7bV2cFeIEOkVTZS/WjXARfBqSH6Q2qHL33hQ= 165 | github.com/whyrusleeping/cbor-gen v0.0.0-20210118024343-169e9d70c0c2/go.mod h1:fgkXqYy7bV2cFeIEOkVTZS/WjXARfBqSH6Q2qHL33hQ= 166 | github.com/whyrusleeping/cbor-gen v0.0.0-20210303213153-67a261a1d291 h1:79Kq0q5yEFiAij/DV5I3N8gp5b1m2vT4xgRBztuqOSU= 167 | github.com/whyrusleeping/cbor-gen v0.0.0-20210303213153-67a261a1d291/go.mod h1:fgkXqYy7bV2cFeIEOkVTZS/WjXARfBqSH6Q2qHL33hQ= 168 | github.com/xlab/c-for-go v0.0.0-20200718154222-87b0065af829/go.mod h1:h/1PEBwj7Ym/8kOuMWvO2ujZ6Lt+TMbySEXNhjjR87I= 169 | github.com/xlab/pkgconfig v0.0.0-20170226114623-cea12a0fd245/go.mod h1:C+diUUz7pxhNY6KAoLgrTYARGWnt82zWTylZlxT92vk= 170 | github.com/xorcare/golden v0.6.0/go.mod h1:7T39/ZMvaSEZlBPoYfVFmsBLmUl3uz9IuzWj/U6FtvQ= 171 | github.com/yuin/goldmark v1.1.32/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74= 172 | go.dedis.ch/fixbuf v1.0.3 h1:hGcV9Cd/znUxlusJ64eAlExS+5cJDIyTyEG+otu5wQs= 173 | go.dedis.ch/fixbuf v1.0.3/go.mod h1:yzJMt34Wa5xD37V5RTdmp38cz3QhMagdGoem9anUalw= 174 | go.dedis.ch/kyber/v3 v3.0.4/go.mod h1:OzvaEnPvKlyrWyp3kGXlFdp7ap1VC6RkZDTaPikqhsQ= 175 | go.dedis.ch/kyber/v3 v3.0.9/go.mod h1:rhNjUUg6ahf8HEg5HUvVBYoWY4boAafX8tYxX+PS+qg= 176 | go.dedis.ch/protobuf v1.0.5/go.mod h1:eIV4wicvi6JK0q/QnfIEGeSFNG0ZeB24kzut5+HaRLo= 177 | go.dedis.ch/protobuf v1.0.7/go.mod h1:pv5ysfkDX/EawiPqcW3ikOxsL5t+BqnV6xHSmE79KI4= 178 | go.dedis.ch/protobuf v1.0.11/go.mod h1:97QR256dnkimeNdfmURz0wAMNVbd1VmLXhG1CrTYrJ4= 179 | go.uber.org/atomic v1.6.0/go.mod h1:sABNBOSYdrvTF6hTgEIbc7YasKWGhgEQZyfxyTvoXHQ= 180 | go.uber.org/multierr v1.5.0/go.mod h1:FeouvMocqHpRaaGuG9EjoKcStLC43Zu/fmqdUMPcKYU= 181 | go.uber.org/tools v0.0.0-20190618225709-2cfd321de3ee/go.mod h1:vJERXedbb3MVM5f9Ejo0C68/HhF8uaILCdgjnY+goOA= 182 | go.uber.org/zap v1.14.1/go.mod h1:Mb2vm2krFEG5DV0W9qcHBYFtp/Wku1cvYaqPsS/WYfc= 183 | golang.org/x/crypto v0.0.0-20190123085648-057139ce5d2b/go.mod h1:6SG95UA2DQfeDnfUPMdvaQW0Q7yPrPDi9nlGo2tz2b4= 184 | golang.org/x/crypto v0.0.0-20190211182817-74369b46fc67/go.mod h1:6SG95UA2DQfeDnfUPMdvaQW0Q7yPrPDi9nlGo2tz2b4= 185 | golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w= 186 | golang.org/x/crypto v0.0.0-20190510104115-cbcb75029529/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI= 187 | golang.org/x/crypto v0.0.0-20190611184440-5c40567a22f8/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI= 188 | golang.org/x/crypto v0.0.0-20191011191535-87dc89f01550/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI= 189 | golang.org/x/crypto v0.0.0-20200128174031-69ecbb4d6d5d/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto= 190 | golang.org/x/crypto v0.0.0-20200604202706-70a84ac30bf9/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto= 191 | golang.org/x/crypto v0.0.0-20200622213623-75b288015ac9/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto= 192 | golang.org/x/crypto v0.0.0-20200728195943-123391ffb6de/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto= 193 | golang.org/x/crypto v0.0.0-20210220033148-5ea612d1eb83/go.mod h1:jdWPYTVW3xRLrWPugEBEK3UY2ZEsg3UU495nc5E+M+I= 194 | golang.org/x/crypto v0.0.0-20210506145944-38f3c27a63bf h1:B2n+Zi5QeYRDAEodEu72OS36gmTWjgpXr2+cWcBW90o= 195 | golang.org/x/crypto v0.0.0-20210506145944-38f3c27a63bf/go.mod h1:P+XmwS30IXTQdn5tA2iutPOUgjI07+tq3H3K9MVA1s8= 196 | golang.org/x/lint v0.0.0-20190930215403-16217165b5de/go.mod h1:6SW0HCj/g11FgYtHlgUYUwCkIfeOF89ocIRzGO/8vkc= 197 | golang.org/x/mod v0.0.0-20190513183733-4bf6d317e70e/go.mod h1:mXi4GBBbnImb6dmsKGUJ2LatrhH/nqhxcFungHvyanc= 198 | golang.org/x/mod v0.3.0/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA= 199 | golang.org/x/net v0.0.0-20190311183353-d8887717615a/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg= 200 | golang.org/x/net v0.0.0-20190404232315-eb5bcb51f2a3/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg= 201 | golang.org/x/net v0.0.0-20190620200207-3b0461eec859/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= 202 | golang.org/x/net v0.0.0-20200625001655-4c5254603344/go.mod h1:/O7V0waA8r7cgGh81Ro3o1hOxt32SMVPicZroKQ2sZA= 203 | golang.org/x/net v0.0.0-20210226172049-e18ecbb05110/go.mod h1:m0MpNAwzfU5UDzcl9v0D8zg8gWTRqZa9RBIspLL5mdg= 204 | golang.org/x/sync v0.0.0-20190423024810-112230192c58/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= 205 | golang.org/x/sync v0.0.0-20200625203802-6e8e738ad208/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= 206 | golang.org/x/sync v0.0.0-20220722155255-886fb9371eb4/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= 207 | golang.org/x/sys v0.0.0-20190124100055-b90733256f2e/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= 208 | golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= 209 | golang.org/x/sys v0.0.0-20190219092855-153ac476189d/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= 210 | golang.org/x/sys v0.0.0-20190412213103-97732733099d/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= 211 | golang.org/x/sys v0.0.0-20190626221950-04f50cda93cb/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= 212 | golang.org/x/sys v0.0.0-20191025090151-53bf42e6b339/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= 213 | golang.org/x/sys v0.0.0-20191026070338-33540a1f6037/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= 214 | golang.org/x/sys v0.0.0-20200124204421-9fbb57f87de9/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= 215 | golang.org/x/sys v0.0.0-20200323222414-85ca7c5b95cd/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= 216 | golang.org/x/sys v0.0.0-20200602225109-6fdc65e7d980/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= 217 | golang.org/x/sys v0.0.0-20200812155832-6a926be9bd1d/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= 218 | golang.org/x/sys v0.0.0-20200926100807-9d91bd62050c/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= 219 | golang.org/x/sys v0.0.0-20201119102817-f84b799fce68/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= 220 | golang.org/x/sys v0.0.0-20210309074719-68d13333faf2 h1:46ULzRKLh1CwgRq2dC5SlBzEqqNCi8rreOZnNrbqcIY= 221 | golang.org/x/sys v0.0.0-20210309074719-68d13333faf2/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= 222 | golang.org/x/term v0.0.0-20201117132131-f5c789dd3221/go.mod h1:Nr5EML6q2oocZ2LXRh80K7BxOlk5/8JxuGnuhpl+muw= 223 | golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo= 224 | golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= 225 | golang.org/x/text v0.3.3/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ= 226 | golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= 227 | golang.org/x/tools v0.0.0-20181030221726-6c7e314b6563/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= 228 | golang.org/x/tools v0.0.0-20190311212946-11955173bddd/go.mod h1:LCzVGOaR6xXOjkQ3onu1FJEFr0SW1gC7cKk1uF8kGRs= 229 | golang.org/x/tools v0.0.0-20190328211700-ab21143f2384/go.mod h1:LCzVGOaR6xXOjkQ3onu1FJEFr0SW1gC7cKk1uF8kGRs= 230 | golang.org/x/tools v0.0.0-20190621195816-6e04913cbbac/go.mod h1:/rFqwRUd4F7ZHNgwSSTFct+R/Kf4OFW1sUzUTQQTgfc= 231 | golang.org/x/tools v0.0.0-20191029041327-9cc4af7d6b2c/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= 232 | golang.org/x/tools v0.0.0-20191029190741-b9c20aec41a5/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= 233 | golang.org/x/tools v0.0.0-20191119224855-298f0cb1881e/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= 234 | golang.org/x/tools v0.0.0-20200711155855-7342f9734a7d/go.mod h1:njjCfa9FT2d7l9Bc6FUM5FLjQPp3cFF28FI3qnDFljA= 235 | golang.org/x/xerrors v0.0.0-20190717185122-a985d3407aa7/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= 236 | golang.org/x/xerrors v0.0.0-20191011141410-1b5146add898/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= 237 | golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= 238 | golang.org/x/xerrors v0.0.0-20200804184101-5ec99f83aff1 h1:go1bK/D/BFZV2I8cIQd1NKEZ+0owSTG1fDTci4IqFcE= 239 | golang.org/x/xerrors v0.0.0-20200804184101-5ec99f83aff1/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= 240 | gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= 241 | gopkg.in/check.v1 v1.0.0-20180628173108-788fd7840127/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= 242 | gopkg.in/check.v1 v1.0.0-20190902080502-41f04d3bba15 h1:YR8cESwS4TdDjEe65xsg0ogRM/Nc3DYOhEAlW+xobZo= 243 | gopkg.in/check.v1 v1.0.0-20190902080502-41f04d3bba15/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= 244 | gopkg.in/errgo.v2 v2.1.0/go.mod h1:hNsd1EY+bozCKY1Ytp96fpM3vjJbqLJn88ws8XvfDNI= 245 | gopkg.in/yaml.v2 v2.2.2/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= 246 | gopkg.in/yaml.v2 v2.2.4/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= 247 | gopkg.in/yaml.v2 v2.3.0/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= 248 | gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c h1:dUUwHk2QECo/6vqA44rthZ8ie2QXMNeKRTHCNY2nXvo= 249 | gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= 250 | honnef.co/go/tools v0.0.1-2019.2.3/go.mod h1:a3bituU0lyd329TUQxRnasdCoJDkEUEAqEt0JzvZhAg= 251 | modernc.org/cc v1.0.0/go.mod h1:1Sk4//wdnYJiUIxnW8ddKpaOJCF37yAdqYnkxUpaYxw= 252 | modernc.org/golex v1.0.0/go.mod h1:b/QX9oBD/LhixY6NDh+IdGv17hgB+51fET1i2kPSmvk= 253 | modernc.org/mathutil v1.1.1/go.mod h1:mZW8CKdRPY1v87qxC/wUdX5O1qDzXMP5TH3wjfpga6E= 254 | modernc.org/strutil v1.1.0/go.mod h1:lstksw84oURvj9y3tn8lGvRxyRC1S2+g5uuIzNfIOBs= 255 | modernc.org/xc v1.0.0/go.mod h1:mRNCo0bvLjGhHO9WsyuKVU4q0ceiDDDoEeWDJHrNx8I= 256 | -------------------------------------------------------------------------------- /secp256k1/secp256k1.go: -------------------------------------------------------------------------------- 1 | package secp256k1 2 | 3 | import ( 4 | "bytes" 5 | "fmt" 6 | 7 | "github.com/dchest/blake2b" 8 | "github.com/decred/dcrd/dcrec/secp256k1/v4" 9 | "github.com/decred/dcrd/dcrec/secp256k1/v4/ecdsa" 10 | "github.com/filecoin-project/go-address" 11 | ) 12 | 13 | // Sign creates a secp256k1 signature of a message using a private key. 14 | // The private byte slice should be exactly as implemented in an 15 | // official Filecoin client. The signature is also compatible with a Filecoin 16 | // client. It has format R|S|V where V is 0 or 1, allowing recovering the 17 | // public key only using the signature. 18 | func Sign(pk []byte, msg []byte) ([]byte, error) { 19 | priv := secp256k1.PrivKeyFromBytes(pk) 20 | msgHash := blake2b.Sum256(msg) 21 | sig := ecdsa.SignCompact(priv, msgHash[:], false) 22 | 23 | // We need to left-rotate by 1 byte, and adjust the 24 | // recovery ID to be zero-centered. 25 | recoveryID := sig[0] 26 | copy(sig, sig[1:]) 27 | sig[64] = recoveryID - 27 28 | 29 | return sig, nil 30 | } 31 | 32 | // Verify verifies that a message is correctly signed by a public key. 33 | func Verify(pubkey, msg, sig []byte) bool { 34 | // We need to do the inverse operation of signatures.b 35 | recoveryID := sig[64] + 27 36 | copy(sig[1:], sig) 37 | sig[0] = recoveryID 38 | 39 | msgHash := blake2b.Sum256(msg) 40 | vpubkey, _, err := ecdsa.RecoverCompact(sig, msgHash[:]) 41 | if err != nil { 42 | return false 43 | } 44 | verifAddr, err := address.NewSecp256k1Address(vpubkey.SerializeUncompressed()) 45 | if err != nil { 46 | return false 47 | } 48 | if !bytes.Equal(verifAddr.Payload(), pubkey) { 49 | return false 50 | } 51 | return true 52 | } 53 | 54 | // GetPubKey returns the public key from the private key. 55 | func GetPubKey(pk []byte) (address.Address, error) { 56 | priv := secp256k1.PrivKeyFromBytes(pk) 57 | pubkey := priv.PubKey() 58 | 59 | addr, err := address.NewSecp256k1Address(pubkey.SerializeUncompressed()) 60 | if err != nil { 61 | return address.Undef, fmt.Errorf("generating public key: %s", err) 62 | } 63 | 64 | return addr, nil 65 | } 66 | -------------------------------------------------------------------------------- /wallet/keystore.go: -------------------------------------------------------------------------------- 1 | package wallet 2 | 3 | type KeyType string 4 | 5 | const ( 6 | KTBLS KeyType = "bls" 7 | KTSecp256k1 KeyType = "secp256k1" 8 | KTSecp256k1Ledger KeyType = "secp256k1-ledger" 9 | ) 10 | 11 | // KeyInfo is used for storing keys in KeyStore 12 | type KeyInfo struct { 13 | Type KeyType 14 | PrivateKey []byte 15 | } 16 | -------------------------------------------------------------------------------- /wallet/wallet.go: -------------------------------------------------------------------------------- 1 | package wallet 2 | 3 | import ( 4 | "encoding/json" 5 | "fmt" 6 | "github.com/filecoin-project/go-address" 7 | "github.com/filecoin-project/go-state-types/crypto" 8 | "github.com/jsign/go-filsigner/bls" 9 | "github.com/jsign/go-filsigner/secp256k1" 10 | 11 | "encoding/hex" 12 | ) 13 | 14 | // WalletSign allows to sign a message using an exported private key. The exported private key 15 | // is a hex-encoded string of a sepc256k1 or BLS private key as exported by a Filecoin 16 | // client (e.g: `lotus wallet export`). It automatically detects the key type and signs 17 | // appropiately. 18 | func WalletSign(exportedPK string, msg []byte) (*crypto.Signature, error) { 19 | ki, err := decodeLotusExportedPK(exportedPK) 20 | if err != nil { 21 | return nil, fmt.Errorf("decoding lotus exported key: %s", err) 22 | } 23 | 24 | switch ki.Type { 25 | case KTSecp256k1: 26 | sig, err := secp256k1.Sign(ki.PrivateKey, msg) 27 | if err != nil { 28 | return nil, fmt.Errorf("generating secp256k1 signature: %w", err) 29 | } 30 | return &crypto.Signature{ 31 | Type: crypto.SigTypeSecp256k1, 32 | Data: sig, 33 | }, nil 34 | case KTBLS: 35 | sig, err := bls.Sign(ki.PrivateKey, msg) 36 | if err != nil { 37 | return nil, fmt.Errorf("generating bls signature: %w", err) 38 | } 39 | return &crypto.Signature{ 40 | Type: crypto.SigTypeBLS, 41 | Data: sig, 42 | }, nil 43 | default: 44 | return nil, fmt.Errorf("signature type not supported") 45 | } 46 | } 47 | 48 | func WalletVerify(publicKey address.Address, msg []byte, sig []byte) (bool, error) { 49 | var signature crypto.Signature 50 | if err := signature.UnmarshalBinary(sig); err != nil { 51 | return false, fmt.Errorf("unmarshaling signature: %s", err) 52 | } 53 | switch publicKey.Protocol() { 54 | case address.SECP256K1: 55 | return secp256k1.Verify(publicKey.Payload(), msg, signature.Data), nil 56 | case address.BLS: 57 | return bls.Verify(publicKey.Payload(), msg, signature.Data) 58 | default: 59 | return false, fmt.Errorf("address type not supported") 60 | } 61 | } 62 | 63 | func PublicKey(lotusExportedPK string) (address.Address, error) { 64 | ki, err := decodeLotusExportedPK(lotusExportedPK) 65 | if err != nil { 66 | return address.Undef, fmt.Errorf("decoding lotus exported key: %s", err) 67 | } 68 | 69 | switch ki.Type { 70 | case KTSecp256k1: 71 | return secp256k1.GetPubKey(ki.PrivateKey) 72 | default: 73 | return bls.GetPubKey(ki.PrivateKey) 74 | } 75 | } 76 | 77 | func decodeLotusExportedPK(lotusExportedPK string) (*KeyInfo, error) { 78 | kiBytes, err := hex.DecodeString(lotusExportedPK) 79 | if err != nil { 80 | return nil, fmt.Errorf("decoding hex: %s", err) 81 | } 82 | var ki KeyInfo 83 | if err := json.Unmarshal(kiBytes, &ki); err != nil { 84 | return nil, fmt.Errorf("unmarshaling exported key: %s", err) 85 | } 86 | 87 | return &ki, nil 88 | } 89 | -------------------------------------------------------------------------------- /wallet/wallet_test.go: -------------------------------------------------------------------------------- 1 | package wallet 2 | 3 | import ( 4 | "encoding/hex" 5 | "encoding/json" 6 | "github.com/filecoin-project/go-state-types/crypto" 7 | "github.com/jsign/go-filsigner/bls" 8 | "testing" 9 | 10 | "github.com/filecoin-project/go-address" 11 | "github.com/stretchr/testify/require" 12 | ) 13 | 14 | var msg = []byte("DUKE") // 44554b45 in hex. 15 | 16 | func TestSecp256k1(t *testing.T) { 17 | address.CurrentNetwork = address.Mainnet 18 | t.Parallel() 19 | 20 | publicAddr := "f1fib3pv7jua2ockdugtz7viz3cyy6lkhh7rfx3sa" 21 | 22 | // lotus wallet export f1fib3pv7jua2ockdugtz7viz3cyy6lkhh7rfx3sa 23 | privateKeyHex := "7b2254797065223a22736563703235366b31222c22507269766174654b6579223a226b35507976337148327349586343595a58594f5775453149326e32554539436861556b6c4e36695a5763453d227d" 24 | 25 | // lotus wallet sign f1fib3pv7jua2ockdugtz7viz3cyy6lkhh7rfx3sa 44554b45 26 | hexSignature := "0103bff286f1371c1a4ce8e33c29d6a20eeb53f17970190d12c5a1c0fc4be9a56e766250d5a82dda2179fa90ae297696d1dfaa9eea8f2f833da0cf87b927294eb700" 27 | 28 | t.Run("sign", func(t *testing.T) { 29 | t.Parallel() 30 | 31 | sig, err := WalletSign(privateKeyHex, msg) 32 | require.NoError(t, err) 33 | sigm, err := sig.MarshalBinary() 34 | require.NoError(t, err) 35 | genHexSignature := hex.EncodeToString(sigm) 36 | 37 | require.Equal(t, hexSignature, genHexSignature) 38 | }) 39 | 40 | t.Run("verify", func(t *testing.T) { 41 | t.Parallel() 42 | 43 | // Check that signature verification succeeds with correct: signature, message, and public key. 44 | sig, err := hex.DecodeString(hexSignature) 45 | require.NoError(t, err) 46 | addr, err := address.NewFromString(publicAddr) 47 | require.NoError(t, err) 48 | okSig, err := WalletVerify(addr, msg, sig) 49 | require.NoError(t, err) 50 | require.True(t, okSig) 51 | 52 | // Check that signature verification fails with incorrect message. 53 | okSig, err = WalletVerify(addr, []byte("DUKEZ"), sig) 54 | require.NoError(t, err) 55 | require.False(t, okSig) 56 | 57 | // Check that address parsing fails with incorrect public key. 58 | _, err = address.NewFromString("f1fib3pv7jua2ockdugtz7viz3cyy6lkhh7rfx3sb") 59 | require.Error(t, err) 60 | }) 61 | 62 | t.Run("gen-pubkey", func(t *testing.T) { 63 | addr, err := PublicKey(privateKeyHex) 64 | require.NoError(t, err) 65 | require.Equal(t, publicAddr, addr.String()) 66 | }) 67 | } 68 | 69 | func checkBlsVerify(t *testing.T, signatureBytes string, addr string, messageBytes string, expectSuccess bool) { 70 | sig, err := hex.DecodeString(signatureBytes) 71 | require.NoError(t, err) 72 | a, err := address.NewFromString(addr) 73 | require.NoError(t, err) 74 | data := []byte(messageBytes) 75 | s := crypto.Signature{ 76 | Type: crypto.SigTypeBLS, 77 | Data: sig, 78 | } 79 | b, err := s.MarshalBinary() 80 | require.NoError(t, err) 81 | okSig, err := WalletVerify(a, data, b) 82 | if expectSuccess { 83 | require.NoError(t, err) 84 | require.True(t, okSig) 85 | } else { 86 | require.NoError(t, err) 87 | require.False(t, okSig) 88 | } 89 | } 90 | 91 | func TestBLSSign(t *testing.T) { 92 | address.CurrentNetwork = address.Mainnet 93 | t.Parallel() 94 | 95 | publicAddr := "f3rpskqryflc2sqzzzu7j2q6fecrkdkv4p2avpf4kyk5u754he7g6cr2rbpmif7pam5oxbme2oyzot4ry3d74q" 96 | 97 | // lotus wallet export f3rpskqryflc2sqzzzu7j2q6fecrkdkv4p2avpf4kyk5u754he7g6cr2rbpmif7pam5oxbme2oyzot4ry3d74q 98 | privateKeyHex := "7b2254797065223a22626c73222c22507269766174654b6579223a226862702f794666527439514c43716b6d566171415752436f50556777314b776971716e73684e49704e57513d227d" 99 | 100 | // lotus wallet sign f3rpskqryflc2sqzzzu7j2q6fecrkdkv4p2avpf4kyk5u754he7g6cr2rbpmif7pam5oxbme2oyzot4ry3d74q 44554b45 101 | hexSignature := "0280cef41af956cf6855725a5af0d8d956ea41f6da2688cc1f436a7ea5ebd15d96ba384746b819c0836c53a54d6d30b0a70b528204e9da92f833031e7a4776f57bad83e033ea0235bad0f8a5337a4eb66870fc0429175ed63f91203ec1b65c6e31" 102 | 103 | t.Run("sign", func(t *testing.T) { 104 | t.Parallel() 105 | 106 | sig, err := WalletSign(privateKeyHex, msg) 107 | require.NoError(t, err) 108 | sigm, err := sig.MarshalBinary() 109 | require.NoError(t, err) 110 | genHexSignature := hex.EncodeToString(sigm) 111 | 112 | require.Equal(t, hexSignature, genHexSignature) 113 | }) 114 | 115 | t.Run("gen-pubkey", func(t *testing.T) { 116 | addr, err := PublicKey(privateKeyHex) 117 | require.NoError(t, err) 118 | require.Equal(t, publicAddr, addr.String()) 119 | }) 120 | 121 | t.Run("verify", func(t *testing.T) { 122 | t.Parallel() 123 | 124 | // Check that signature verification succeeds with correct: signature, message, and public key. 125 | sig, err := hex.DecodeString(hexSignature) 126 | require.NoError(t, err) 127 | addr, err := address.NewFromString(publicAddr) 128 | require.NoError(t, err) 129 | okSig, err := WalletVerify(addr, msg, sig) 130 | require.NoError(t, err) 131 | require.True(t, okSig) 132 | 133 | // Check that signature verification fails with incorrect message. 134 | okSig, err = WalletVerify(addr, []byte("DUKEZ"), sig) 135 | require.NoError(t, err) 136 | require.False(t, okSig) 137 | 138 | // Check that signature verification fails with incorrect public key. 139 | wrongAddr, err := address.NewFromString("f3wmv7nhiqosmlr6mis2mr4xzupdhe3rtvw5ntis4x6yru7jhm35pfla2pkwgwfa3t62kdmoylssczmf74yika") 140 | require.NoError(t, err) 141 | okSig, err = WalletVerify(wrongAddr, msg, sig) 142 | require.NoError(t, err) 143 | require.False(t, okSig) 144 | 145 | }) 146 | 147 | // https://github.com/filecoin-project/lotus/blob/97a9921cdd807278414440dc041f567b6e3fb8d0/lib/sigs/bls/bls_test.go#L39 148 | t.Run("test-uncompressed-fails", func(t *testing.T) { 149 | t.Parallel() 150 | 151 | data := "potato" 152 | addr := "f3tcgq5scpfhdwh4dbalwktzf6mbv3ng2nw7tyzni5cyrsgvineid6jybnweecpa6misa6lk4tvwtxj2gkwpzq" 153 | // compressed 154 | signature := "9927444bfcffdca34af57b78757b9b90f1cd28d2a3aeed2aa6bde299f8bbb9184756f2287b0588e6d3f2860d2bb2066e0c59778c1e644fb2cfb35fba8f09fa824a9ed825108c82ff4bf634c1037eeaf185f45673d4a1c1c6eeb712b7d72a5498" 155 | checkBlsVerify(t, signature, addr, data, true) 156 | // compressed byte changed 157 | signature = "9927444bfcffdca34af57b78757b9b90f1cd28d2a3aeed2aa6bde299f8bbb9184756f2287b0588f6d3f2860d2bb2066e0c59778c1e644fb2cfb35fba8f09fa824a9ed825108c82ff4bf634c1037eeaf185f45673d4a1c1c6eeb712b7d72a5498" 158 | checkBlsVerify(t, signature, addr, data, false) 159 | // compressed with prefix 160 | signature = "9927444bfcffdca34af57b78757b9b90f1cd28d2a3aeed2aa6bde299f8bbb9184756f2287b0588e6d3f2860d2bb2066e0c59778c1e644fb2cfb35fba8f09fa824a9ed825108c82ff4bf634c1037eeaf185f45673d4a1c1c6eeb712b7d72a549855" 161 | checkBlsVerify(t, signature, addr, data, false) 162 | // uncompressed 163 | signature = "1927444bfcffdca34af57b78757b9b90f1cd28d2a3aeed2aa6bde299f8bbb9184756f2287b0588e6d3f2860d2bb2066e0c59778c1e644fb2cfb35fba8f09fa824a9ed825108c82ff4bf634c1037eeaf185f45673d4a1c1c6eeb712b7d72a549808942378dbce2ad72e87df083b66c631c18c582f9f9e104d2a7e13e79cbb22deccf67777b09c255d5de688098c6335d40a85768db766a6c6ece6de2a9f3487281a48fecab14702f6512652709d7edb7e8bc9f641aaa83b7e8afd7ae479e659e4" 164 | checkBlsVerify(t, signature, addr, data, false) 165 | // uncompressed one byte change 166 | signature = "1927444bfcffdca34af57b78757b9b90f1cd28d2a3aeed2aa6bde299f8bbb9184756f2287b0588e6d3f2860d2bb2066e0c59778c1e644fb2cfb35fba8f09fa824a9ed825108c82ff4bf634c1037eeaf185f45673d4a1c1c6eeb712b7d72a549808942378dbce2ad72e87df083b66c631c18c582f9f9e104d2a7e13e79cbb22deccf67777b09c255d5de688098c6335d40a85668db766a6c6ece6de2a9f3487281a48fecab14702f6512652709d7edb7e8bc9f641aaa83b7e8afd7ae479e659e4" 167 | checkBlsVerify(t, signature, addr, data, false) 168 | }) 169 | 170 | t.Run("zero-point", func(t *testing.T) { 171 | t.Parallel() 172 | // Create Zero point private and public key 173 | var key [32]byte 174 | ki := KeyInfo{ 175 | Type: KTBLS, 176 | PrivateKey: key[:], 177 | } 178 | addr, err := bls.GetPubKey(ki.PrivateKey) 179 | require.NoError(t, err) 180 | require.Equal(t, "f3yaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaby2smx7a", addr.String()) 181 | m, err := json.Marshal(ki) 182 | require.NoError(t, err) 183 | pk := hex.EncodeToString([]byte(m)) 184 | 185 | // Sign with Zero point private key should fail 186 | sig, err := WalletSign(pk, []byte("hello")) 187 | require.Error(t, err) 188 | require.Nil(t, sig) 189 | 190 | // Verify signature with Zero point public key should fail 191 | signatureHex := "02c00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000" 192 | sigBytes, err := hex.DecodeString(signatureHex) 193 | require.NoError(t, err) 194 | result, err := WalletVerify(addr, []byte("hello"), sigBytes) 195 | require.Error(t, err) 196 | require.False(t, result) 197 | }) 198 | } 199 | --------------------------------------------------------------------------------