Skip to content

Commit

Permalink
Merge pull request #4 from kaspanet/2020-03-setBytes
Browse files Browse the repository at this point in the history
Add constants and implement DeserializeXXXFromSlice for all serialized objects
  • Loading branch information
stasatdaglabs authored Mar 26, 2020
2 parents 0b1b6dd + 53fbb2e commit add33b6
Show file tree
Hide file tree
Showing 4 changed files with 83 additions and 18 deletions.
17 changes: 16 additions & 1 deletion multiset.go
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,9 @@ import (
"github.com/pkg/errors"
)

// SerializedMultiSetSize defines the length in bytes of SerializedMultiSet
const SerializedMultiSetSize = 64

// MultiSet is a type used to create an Elliptic Curve Multiset Hash
// which is a rolling(homomorphic) hash that you can add and remove elements from
// and receiving the same resulting hash as-if you never hashed that element.
Expand All @@ -17,7 +20,7 @@ type MultiSet struct {
}

// SerializedMultiSet is a is a byte array representing the storage representation of a MultiSet
type SerializedMultiSet [64]byte
type SerializedMultiSet [SerializedMultiSetSize]byte

// String returns the SerializedMultiSet as the hexadecimal string
func (serialized *SerializedMultiSet) String() string {
Expand Down Expand Up @@ -114,3 +117,15 @@ func DeserializeMultiSet(serialized *SerializedMultiSet) (multiset *MultiSet, er
}
return
}

// DeserializeMultiSetFromSlice returns a MultiSet type from a from a a serialized multiset slice.
// will verify that it's SerializedMultiSetSize bytes long and a valid multiset.
func DeserializeMultiSetFromSlice(newMultiSet []byte) (multiset *MultiSet, err error) {
if len(newMultiSet) != SerializedMultiSetSize {
return nil, errors.Errorf("invalid multiset length got %d, expected %d", len(newMultiSet),
SerializedMultiSetSize)
}
serializedMultiSet := &SerializedMultiSet{}
copy(serializedMultiSet[:], newMultiSet)
return DeserializeMultiSet(serializedMultiSet)
}
33 changes: 28 additions & 5 deletions oldschnorr.go
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,17 @@ import (
"github.com/pkg/errors"
)

const (
// SerializedSchnorrPublicKeyCompressedSize defines the length in bytes of SerializedSchnorrPublicKeyCompressed
SerializedSchnorrPublicKeyCompressedSize = 33

// SerializedSchnorrPublicKeyUncompressedSize defines the length in bytes of SerializedSchnorrPublicKeyUncompressed
SerializedSchnorrPublicKeyUncompressedSize = 65

// SerializedSchnorrSignatureSize defines the length in bytes of SerializedSchnorrSignature
SerializedSchnorrSignatureSize = 64
)

// SchnorrPublicKey is a PublicKey type used to sign and verify Schnorr signatures.
// The struct itself is an opaque data type that should only be created via the supplied methods.
type SchnorrPublicKey struct {
Expand All @@ -17,14 +28,14 @@ type SchnorrPublicKey struct {
// SchnorrSignature is a type representing a Schnorr Signature.
// The struct itself is an opaque data type that should only be created via the supplied methods.
type SchnorrSignature struct {
signature [64]byte
signature [SerializedSchnorrSignatureSize]byte
}

// SerializedSchnorrPublicKey is a is a byte array representing the storage representation of a compressed or uncompressed SchnorrPublicKey
type SerializedSchnorrPublicKey []byte

// SerializedSchnorrSignature is a is a byte array representing the storage representation of a SchnorrSignature
type SerializedSchnorrSignature [64]byte
type SerializedSchnorrSignature [SerializedSchnorrSignatureSize]byte

// IsEqual returns true if target is the same as key.
func (key *SchnorrPublicKey) IsEqual(target *SchnorrPublicKey) bool {
Expand Down Expand Up @@ -83,6 +94,18 @@ func DeserializeSchnorrSignature(serializedSignature *SerializedSchnorrSignature
return &SchnorrSignature{signature: *serializedSignature}
}

// DeserializeSchnorrSignatureFromSlice returns a SchnorrSignature type from a serialized signature slice.
// will verify that it's SerializedSchnorrSignatureSize bytes long
func DeserializeSchnorrSignatureFromSlice(data []byte) (signature *SchnorrSignature, err error) {
if len(data) != SerializedSchnorrSignatureSize {
return nil, errors.Errorf("invalid schnorr signature length got %d, expected %d", len(data),
SerializedSchnorrSignatureSize)
}
signature = &SchnorrSignature{}
copy(signature.signature[:], data)
return
}

// String returns the SchnorrPublicKey as the hexadecimal string
func (key *SchnorrPublicKey) String() string {
serialized, err := key.SerializeCompressed()
Expand Down Expand Up @@ -185,16 +208,16 @@ func (key *SchnorrPublicKey) serializeInternal(flag C.uint) (SerializedSchnorrPu
ret := C.secp256k1_ec_pubkey_serialize(C.secp256k1_context_no_precomp, cPtr, &cLen, &key.pubkey, flag)
if ret != 1 {
panic("failed serializing a pubkey. Should never happen (upstream promise to return 1)")
} else if cLen != 33 && cLen != 65 {
} else if cLen != SerializedSchnorrPublicKeyCompressedSize && cLen != SerializedSchnorrPublicKeyUncompressedSize {
panic("Returned length doesn't match compressed length(33) nor uncompressed length(65), should never happen")
}
return data[:cLen], nil
}

func supportedKey(key []byte) bool {
if len(key) == 33 && (key[0] == 0x02 || key[0] == 0x03) {
if len(key) == SerializedSchnorrPublicKeyCompressedSize && (key[0] == 0x02 || key[0] == 0x03) {
return true
} else if len(key) == 65 && key[0] == 0x04 {
} else if len(key) == SerializedSchnorrPublicKeyUncompressedSize && key[0] == 0x04 {
return true
} else {
return false
Expand Down
26 changes: 22 additions & 4 deletions secp256k1.go
Original file line number Diff line number Diff line change
Expand Up @@ -44,8 +44,13 @@ func init() {
}
}

// HashSize of array used to store hashes. See Hash.
const HashSize = 32
const (
// HashSize of array used to store hashes. See Hash.
HashSize = 32

// SerializedPrivateKeySize defines the length in bytes of SerializedPrivateKey
SerializedPrivateKeySize = 32
)

// Hash is a type encapsulating the result of hashing some unknown sized data.
// it typically represents Sha256 / Double Sha256.
Expand Down Expand Up @@ -81,11 +86,11 @@ func (hash *Hash) String() string {
// PrivateKey is a type representing a Secp256k1 private key.
// This private key can be used to create Schnorr/ECDSA signatures
type PrivateKey struct {
privateKey [32]byte
privateKey [SerializedPrivateKeySize]byte
}

// SerializedPrivateKey is a byte array representing the storage representation of a PrivateKey
type SerializedPrivateKey [32]byte
type SerializedPrivateKey [SerializedPrivateKeySize]byte

// String returns the PrivateKey as the hexadecimal string
func (key *SerializedPrivateKey) String() string {
Expand All @@ -110,6 +115,19 @@ func DeserializePrivateKey(data *SerializedPrivateKey) (key *PrivateKey, err err
return &PrivateKey{*data}, nil
}

// DeserializePrivateKeyFromSlice returns a PrivateKey type from a serialized private key slice.
// will verify that it's 32 byte and it's a valid private key(Group Order > key > 0)
func DeserializePrivateKeyFromSlice(data []byte) (key *PrivateKey, err error) {
if len(data) != SerializedPrivateKeySize {
return nil, errors.Errorf("invalid private key length got %d, expected %d", len(data),
SerializedPrivateKeySize)
}

serializedKey := &SerializedPrivateKey{}
copy(serializedKey[:], data)
return DeserializePrivateKey(serializedKey)
}

// GeneratePrivateKey generates a random valid private key from `crypto/rand`
func GeneratePrivateKey() (key *PrivateKey, err error) {
key = &PrivateKey{}
Expand Down
25 changes: 17 additions & 8 deletions secp256k1_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -464,17 +464,21 @@ func TestSchnorrSignatureVerify(t *testing.T) {
},
}

sig64 := SerializedSchnorrSignature{}
msg32 := Hash{}
for i, test := range tests {
pubkey, err := DeserializeSchnorrPubKey(test.pubKey)
if err != nil {
t.Fatal(err)
}
copy(sig64[:], test.signature)
sig := DeserializeSchnorrSignature(&sig64)
sig, err := DeserializeSchnorrSignatureFromSlice(test.signature)
if err != nil {
t.Fatal(err)
}

copy(msg32[:], test.message)
err = msg32.SetBytes(test.message)
if err != nil {
t.Fatal(err)
}
valid := pubkey.SchnorrVerify(&msg32, sig)
if valid != test.valid {
t.Errorf("Schnorr test vector '%d' expected verification: '%t', got: '%t'", i, valid, test.valid)
Expand All @@ -484,12 +488,17 @@ func TestSchnorrSignatureVerify(t *testing.T) {

func TestDeterministicSchnorrSignatureGen(t *testing.T) {
// Test vector from Bitcoin-ABC
privKeyBytes := SerializedPrivateKey{}
copy(privKeyBytes[:], decodeHex("12b004fff7f4b69ef8650e767f18f11ede158148b425660723b9f9a66e61f747"))
privKey, _ := DeserializePrivateKey(&privKeyBytes)

privKey, err := DeserializePrivateKeyFromSlice(decodeHex("12b004fff7f4b69ef8650e767f18f11ede158148b425660723b9f9a66e61f747"))
if err != nil {
t.Fatal(err)
}

msg := Hash{}
copy(msg[:], decodeHex("5255683da567900bfd3e786ed8836a4e7763c221bf1ac20ece2a5171b9199e8a"))
err = msg.SetBytes(decodeHex("5255683da567900bfd3e786ed8836a4e7763c221bf1ac20ece2a5171b9199e8a"))
if err != nil {
t.Fatal(err)
}
sig, err := privKey.SchnorrSign(&msg)
if err != nil {
t.Fatal(err)
Expand Down

0 comments on commit add33b6

Please sign in to comment.