Browse Source

Add Signature Compression & Decompression

feature/abstract-curve
arnaucube 3 years ago
parent
commit
ccaa631337
5 changed files with 88 additions and 11 deletions
  1. +1
    -1
      .github/workflows/lint.yml
  2. +12
    -5
      README.md
  3. +25
    -1
      blindsecp256k1.go
  4. +45
    -0
      blindsecp256k1_test.go
  5. +5
    -4
      parsers.go

+ 1
- 1
.github/workflows/lint.yml

@ -14,4 +14,4 @@ jobs:
run: |
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
$(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

+ 12
- 5
README.md

@ -7,17 +7,24 @@ Blind signature over [secp256k1](https://en.bitcoin.it/wiki/Secp256k1), based on
## Usage
```go
import (
[...]
"github.com/arnaucube/go-blindsecp256k1"
)
[...]
// signer: create new signer key pair
sk := NewPrivateKey()
sk := blindsecp256k1.NewPrivateKey()
signerPubK := sk.Public()
// signer: when user requests new R parameter to blind a new msg,
// create new signerR (public) with its secret k
k, signerR := NewRequestParameters()
k, signerR := blindsecp256k1.NewRequestParameters()
// user: blinds the msg using signer's R
msg := new(big.Int).SetBytes([]byte("test"))
msgBlinded, userSecretData, err := Blind(msg, signerR)
msgBlinded, userSecretData, err := blindsecp256k1.Blind(msg, signerR)
require.Nil(t, err)
// 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)
// user: unblinds the blinded signature
sig := Unblind(sBlind, userSecretData)
sig := blindsecp256k1.Unblind(sBlind, userSecretData)
// signature can be verified with signer PublicKey
verified := Verify(msg, sig, signerPubK)
verified := blindsecp256k1.Verify(msg, sig, signerPubK)
assert.True(t, verified)
```

+ 25
- 1
blindsecp256k1.go

@ -86,7 +86,7 @@ func (p *Point) isValid() error {
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 {
xBytes := p.X.Bytes()
odd := byte(0)
@ -264,6 +264,30 @@ type Signature struct {
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
// given the UserSecretData
func Unblind(sBlind *big.Int, u *UserSecretData) *Signature {

+ 45
- 0
blindsecp256k1_test.go

@ -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) {
const n = 256
var points [n]*Point

+ 5
- 4
parsers.go

@ -65,9 +65,9 @@ func (p *Point) Bytes() []byte {
// little-endian.
func NewPointFromBytes(b []byte) (*Point, error) {
if len(b) != 64 { //nolint:gomnd
return nil,
fmt.Errorf("Can not parse bytes to Point, expected byte array of length %d, current %d",
64, len(b))
return nil, fmt.Errorf("Can not parse bytes to Point,"+
" expected byte array of length %d, current %d",
64, len(b))
}
p := &Point{}
p.X = new(big.Int).SetBytes(swapEndianness(b[:32]))
@ -193,7 +193,8 @@ func (sig *Signature) Bytes() []byte {
func NewSignatureFromBytes(b []byte) (*Signature, error) {
if len(b) != 96 { //nolint:gomnd
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))
}
s := new(big.Int).SetBytes(swapEndianness(b[:32]))

Loading…
Cancel
Save