mirror of
https://github.com/arnaucube/go-blindsecp256k1.git
synced 2026-02-06 19:16:40 +01:00
Add Signature Compression & Decompression
This commit is contained in:
2
.github/workflows/lint.yml
vendored
2
.github/workflows/lint.yml
vendored
@@ -14,4 +14,4 @@ jobs:
|
|||||||
run: |
|
run: |
|
||||||
curl -sSfL https://raw.githubusercontent.com/golangci/golangci-lint/master/install.sh | sh -s -- -b $(go env GOPATH)/bin v1.30.0
|
curl -sSfL https://raw.githubusercontent.com/golangci/golangci-lint/master/install.sh | sh -s -- -b $(go env GOPATH)/bin v1.30.0
|
||||||
rm -r wasm
|
rm -r wasm
|
||||||
$(go env GOPATH)/bin/golangci-lint run --timeout=5m -c .golangci.yml
|
go list -f '{{.Dir}}' ./... | fgrep -v wasm | xargs realpath --relative-to=. | xargs $(go env GOPATH)/bin/golangci-lint run --timeout=5m -c .golangci.yml
|
||||||
|
|||||||
17
README.md
17
README.md
@@ -7,17 +7,24 @@ Blind signature over [secp256k1](https://en.bitcoin.it/wiki/Secp256k1), based on
|
|||||||
## Usage
|
## Usage
|
||||||
|
|
||||||
```go
|
```go
|
||||||
|
import (
|
||||||
|
[...]
|
||||||
|
"github.com/arnaucube/go-blindsecp256k1"
|
||||||
|
)
|
||||||
|
|
||||||
|
[...]
|
||||||
|
|
||||||
// signer: create new signer key pair
|
// signer: create new signer key pair
|
||||||
sk := NewPrivateKey()
|
sk := blindsecp256k1.NewPrivateKey()
|
||||||
signerPubK := sk.Public()
|
signerPubK := sk.Public()
|
||||||
|
|
||||||
// signer: when user requests new R parameter to blind a new msg,
|
// signer: when user requests new R parameter to blind a new msg,
|
||||||
// create new signerR (public) with its secret k
|
// create new signerR (public) with its secret k
|
||||||
k, signerR := NewRequestParameters()
|
k, signerR := blindsecp256k1.NewRequestParameters()
|
||||||
|
|
||||||
// user: blinds the msg using signer's R
|
// user: blinds the msg using signer's R
|
||||||
msg := new(big.Int).SetBytes([]byte("test"))
|
msg := new(big.Int).SetBytes([]byte("test"))
|
||||||
msgBlinded, userSecretData, err := Blind(msg, signerR)
|
msgBlinded, userSecretData, err := blindsecp256k1.Blind(msg, signerR)
|
||||||
require.Nil(t, err)
|
require.Nil(t, err)
|
||||||
|
|
||||||
// signer: signs the blinded message using its private key & secret k
|
// signer: signs the blinded message using its private key & secret k
|
||||||
@@ -25,10 +32,10 @@ sBlind, err := sk.BlindSign(msgBlinded, k)
|
|||||||
require.Nil(t, err)
|
require.Nil(t, err)
|
||||||
|
|
||||||
// user: unblinds the blinded signature
|
// user: unblinds the blinded signature
|
||||||
sig := Unblind(sBlind, userSecretData)
|
sig := blindsecp256k1.Unblind(sBlind, userSecretData)
|
||||||
|
|
||||||
// signature can be verified with signer PublicKey
|
// signature can be verified with signer PublicKey
|
||||||
verified := Verify(msg, sig, signerPubK)
|
verified := blindsecp256k1.Verify(msg, sig, signerPubK)
|
||||||
assert.True(t, verified)
|
assert.True(t, verified)
|
||||||
```
|
```
|
||||||
|
|
||||||
|
|||||||
@@ -86,7 +86,7 @@ func (p *Point) isValid() error {
|
|||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
// Compress packs a Point to a byte array of 33 bytes
|
// Compress packs a Point to a byte array of 33 bytes, encoded in little-endian.
|
||||||
func (p *Point) Compress() [33]byte {
|
func (p *Point) Compress() [33]byte {
|
||||||
xBytes := p.X.Bytes()
|
xBytes := p.X.Bytes()
|
||||||
odd := byte(0)
|
odd := byte(0)
|
||||||
@@ -264,6 +264,30 @@ type Signature struct {
|
|||||||
F *Point
|
F *Point
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Compress packs a Signature to a byte array of 65 bytes, encoded in
|
||||||
|
// little-endian.
|
||||||
|
func (s *Signature) Compress() [65]byte {
|
||||||
|
var b [65]byte
|
||||||
|
sBytes := s.S.Bytes()
|
||||||
|
fBytes := s.F.Compress()
|
||||||
|
copy(b[:32], swapEndianness(sBytes))
|
||||||
|
copy(b[32:], fBytes[:])
|
||||||
|
return b
|
||||||
|
}
|
||||||
|
|
||||||
|
// DecompressSignature unpacks a Signature from the given byte array of 65 bytes
|
||||||
|
func DecompressSignature(b [65]byte) (*Signature, error) {
|
||||||
|
s := new(big.Int).SetBytes(swapEndianness(b[:32]))
|
||||||
|
var fBytes [33]byte
|
||||||
|
copy(fBytes[:], b[32:])
|
||||||
|
f, err := DecompressPoint(fBytes)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
sig := &Signature{S: s, F: f}
|
||||||
|
return sig, nil
|
||||||
|
}
|
||||||
|
|
||||||
// Unblind performs the unblinding operation of the blinded signature for the
|
// Unblind performs the unblinding operation of the blinded signature for the
|
||||||
// given the UserSecretData
|
// given the UserSecretData
|
||||||
func Unblind(sBlind *big.Int, u *UserSecretData) *Signature {
|
func Unblind(sBlind *big.Int, u *UserSecretData) *Signature {
|
||||||
|
|||||||
@@ -107,6 +107,51 @@ func TestPointCompressDecompress(t *testing.T) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func TestSignatureCompressDecompress(t *testing.T) {
|
||||||
|
f := G
|
||||||
|
sig := &Signature{
|
||||||
|
S: big.NewInt(1),
|
||||||
|
F: f,
|
||||||
|
}
|
||||||
|
b := sig.Compress()
|
||||||
|
assert.Equal(t,
|
||||||
|
"01000000000000000000000000000000000000000000000000000000000000007"+
|
||||||
|
"9be667ef9dcbbac55a06295ce870b07029bfcdb2dce28d959f2815b16f8179800",
|
||||||
|
hex.EncodeToString(b[:]))
|
||||||
|
sig2, err := DecompressSignature(b)
|
||||||
|
require.Nil(t, err)
|
||||||
|
assert.Equal(t, sig, sig2)
|
||||||
|
|
||||||
|
f = G
|
||||||
|
sig = &Signature{
|
||||||
|
S: Q,
|
||||||
|
F: f,
|
||||||
|
}
|
||||||
|
b = sig.Compress()
|
||||||
|
assert.Equal(t,
|
||||||
|
"0cffffbfffffffffffffffffffffffffffffffffffffffffffffffffffffff3f7"+
|
||||||
|
"9be667ef9dcbbac55a06295ce870b07029bfcdb2dce28d959f2815b16f8179800",
|
||||||
|
hex.EncodeToString(b[:]))
|
||||||
|
sig2, err = DecompressSignature(b)
|
||||||
|
require.Nil(t, err)
|
||||||
|
require.Equal(t, sig, sig2)
|
||||||
|
|
||||||
|
for i := 2; i < 10; i++ {
|
||||||
|
s := new(big.Int).Mod(new(big.Int).Mul(Q, big.NewInt(int64(i))), P)
|
||||||
|
f := G.Mul(big.NewInt(int64(i)))
|
||||||
|
sig := &Signature{
|
||||||
|
S: s,
|
||||||
|
F: f,
|
||||||
|
}
|
||||||
|
b := sig.Compress()
|
||||||
|
assert.Equal(t, 65, len(b))
|
||||||
|
|
||||||
|
sig2, err := DecompressSignature(b)
|
||||||
|
require.Nil(t, err)
|
||||||
|
assert.Equal(t, sig, sig2)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
func BenchmarkCompressDecompress(b *testing.B) {
|
func BenchmarkCompressDecompress(b *testing.B) {
|
||||||
const n = 256
|
const n = 256
|
||||||
var points [n]*Point
|
var points [n]*Point
|
||||||
|
|||||||
@@ -65,8 +65,8 @@ func (p *Point) Bytes() []byte {
|
|||||||
// little-endian.
|
// little-endian.
|
||||||
func NewPointFromBytes(b []byte) (*Point, error) {
|
func NewPointFromBytes(b []byte) (*Point, error) {
|
||||||
if len(b) != 64 { //nolint:gomnd
|
if len(b) != 64 { //nolint:gomnd
|
||||||
return nil,
|
return nil, fmt.Errorf("Can not parse bytes to Point,"+
|
||||||
fmt.Errorf("Can not parse bytes to Point, expected byte array of length %d, current %d",
|
" expected byte array of length %d, current %d",
|
||||||
64, len(b))
|
64, len(b))
|
||||||
}
|
}
|
||||||
p := &Point{}
|
p := &Point{}
|
||||||
@@ -193,7 +193,8 @@ func (sig *Signature) Bytes() []byte {
|
|||||||
func NewSignatureFromBytes(b []byte) (*Signature, error) {
|
func NewSignatureFromBytes(b []byte) (*Signature, error) {
|
||||||
if len(b) != 96 { //nolint:gomnd
|
if len(b) != 96 { //nolint:gomnd
|
||||||
return nil,
|
return nil,
|
||||||
fmt.Errorf("Can not parse bytes to Signature, expected byte array of length %d, current %d",
|
fmt.Errorf("Can not parse bytes to Signature,"+
|
||||||
|
" expected byte array of length %d, current %d",
|
||||||
96, len(b))
|
96, len(b))
|
||||||
}
|
}
|
||||||
s := new(big.Int).SetBytes(swapEndianness(b[:32]))
|
s := new(big.Int).SetBytes(swapEndianness(b[:32]))
|
||||||
|
|||||||
Reference in New Issue
Block a user