Skip to content
Projects
Groups
Snippets
Help
Loading...
Help
Submit feedback
Contribute to GitLab
Sign in
Toggle navigation
G
Geth-Modification
Project
Project
Details
Activity
Releases
Cycle Analytics
Repository
Repository
Files
Commits
Branches
Tags
Contributors
Graph
Compare
Charts
Issues
0
Issues
0
List
Board
Labels
Milestones
Merge Requests
0
Merge Requests
0
CI / CD
CI / CD
Pipelines
Jobs
Schedules
Charts
Wiki
Wiki
Snippets
Snippets
Members
Members
Collapse sidebar
Close sidebar
Activity
Graph
Charts
Create a new issue
Jobs
Commits
Issue Boards
Open sidebar
张蕾
Geth-Modification
Commits
f32fa075
Commit
f32fa075
authored
Sep 28, 2015
by
Gustav Simonsson
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
core/secp256k1: update libsecp256k1 Go wrapper and tests
parent
1d20b024
Changes
3
Hide whitespace changes
Inline
Side-by-side
Showing
3 changed files
with
256 additions
and
249 deletions
+256
-249
crypto.go
crypto/crypto.go
+9
-1
secp256.go
crypto/secp256k1/secp256.go
+109
-87
secp256_test.go
crypto/secp256k1/secp256_test.go
+138
-161
No files found.
crypto/crypto.go
View file @
f32fa075
...
...
@@ -198,7 +198,9 @@ func Sign(hash []byte, prv *ecdsa.PrivateKey) (sig []byte, err error) {
return
nil
,
fmt
.
Errorf
(
"hash is required to be exactly 32 bytes (%d)"
,
len
(
hash
))
}
sig
,
err
=
secp256k1
.
Sign
(
hash
,
common
.
LeftPadBytes
(
prv
.
D
.
Bytes
(),
prv
.
Params
()
.
BitSize
/
8
))
seckey
:=
common
.
LeftPadBytes
(
prv
.
D
.
Bytes
(),
prv
.
Params
()
.
BitSize
/
8
)
defer
zeroBytes
(
seckey
)
sig
,
err
=
secp256k1
.
Sign
(
hash
,
seckey
)
return
}
...
...
@@ -337,3 +339,9 @@ func PubkeyToAddress(p ecdsa.PublicKey) common.Address {
pubBytes
:=
FromECDSAPub
(
&
p
)
return
common
.
BytesToAddress
(
Sha3
(
pubBytes
[
1
:
])[
12
:
])
}
func
zeroBytes
(
bytes
[]
byte
)
{
for
i
:=
range
bytes
{
bytes
[
i
]
=
0
}
}
crypto/secp256k1/secp256.go
View file @
f32fa075
...
...
@@ -19,7 +19,7 @@ package secp256k1
// TODO: set USE_SCALAR_4X64 depending on platform?
/*
#cgo CFLAGS: -I./secp256k1
#cgo CFLAGS: -I./
lib
secp256k1
#cgo darwin CFLAGS: -I/usr/local/include
#cgo freebsd CFLAGS: -I/usr/local/include
#cgo linux,arm CFLAGS: -I/usr/local/arm/include
...
...
@@ -33,7 +33,8 @@ package secp256k1
#define USE_SCALAR_8X32
#define USE_SCALAR_INV_BUILTIN
#define NDEBUG
#include "./secp256k1/src/secp256k1.c"
#include "./libsecp256k1/src/secp256k1.c"
#include "./libsecp256k1/src/modules/recovery/main_impl.h"
*/
import
"C"
...
...
@@ -48,48 +49,51 @@ import (
//#define USE_FIELD_5X64
/*
Todo:
> Centralize key management in module
> add pubkey/private key struct
> Dont let keys leave module; address keys as ints
TODO:
> store private keys in buffer and shuffle (deters persistance on swap disc)
>
B
yte permutation (changing)
>
b
yte permutation (changing)
> xor with chaning random block (to deter scanning memory for 0x63) (stream cipher?)
On Disk
> Store keys in wallets
> use slow key derivation function for wallet encryption key (2 seconds)
> on disk: store keys in wallets
*/
func
init
()
{
//takes 10ms to 100ms
C
.
secp256k1_start
(
3
)
// SECP256K1_START_SIGN | SECP256K1_START_VERIFY
}
// holds ptr to secp256k1_context_struct (see secp256k1/include/secp256k1.h)
var
context
*
C
.
secp256k1_context
func
Stop
()
{
C
.
secp256k1_stop
()
func
init
()
{
// around 20 ms on a modern CPU.
context
=
C
.
secp256k1_context_create
(
3
)
// SECP256K1_START_SIGN | SECP256K1_START_VERIFY
}
func
GenerateKeyPair
()
([]
byte
,
[]
byte
)
{
pubkey_len
:=
C
.
int
(
65
)
const
seckey_len
=
32
var
pubkey
[]
byte
=
make
([]
byte
,
pubkey_len
)
var
seckey
[]
byte
=
randentropy
.
GetEntropyCSPRNG
(
seckey_len
)
var
pubkey_ptr
*
C
.
uchar
=
(
*
C
.
uchar
)(
unsafe
.
Pointer
(
&
pubkey
[
0
]))
var
seckey
[]
byte
=
randentropy
.
GetEntropyCSPRNG
(
32
)
var
seckey_ptr
*
C
.
uchar
=
(
*
C
.
uchar
)(
unsafe
.
Pointer
(
&
seckey
[
0
]))
var
pubkey64
[]
byte
=
make
([]
byte
,
64
)
// secp256k1_pubkey
var
pubkey65
[]
byte
=
make
([]
byte
,
65
)
// 65 byte uncompressed pubkey
pubkey64_ptr
:=
(
*
C
.
secp256k1_pubkey
)(
unsafe
.
Pointer
(
&
pubkey64
[
0
]))
pubkey65_ptr
:=
(
*
C
.
uchar
)(
unsafe
.
Pointer
(
&
pubkey65
[
0
]))
ret
:=
C
.
secp256k1_ec_pubkey_create
(
pubkey_ptr
,
&
pubkey_len
,
seckey_ptr
,
0
)
context
,
pubkey64_ptr
,
seckey_ptr
,
)
if
ret
!=
C
.
int
(
1
)
{
return
GenerateKeyPair
()
//invalid secret, try again
return
GenerateKeyPair
()
//
invalid secret, try again
}
return
pubkey
,
seckey
var
output_len
C
.
size_t
C
.
secp256k1_ec_pubkey_serialize
(
// always returns 1
context
,
pubkey65_ptr
,
&
output_len
,
pubkey64_ptr
,
0
,
// SECP256K1_EC_COMPRESSED
)
return
pubkey65
,
seckey
}
func
GeneratePubKey
(
seckey
[]
byte
)
([]
byte
,
error
)
{
...
...
@@ -97,17 +101,16 @@ func GeneratePubKey(seckey []byte) ([]byte, error) {
return
nil
,
err
}
pubkey_len
:=
C
.
int
(
65
)
const
seckey_len
=
32
var
pubkey
[]
byte
=
make
([]
byte
,
64
)
var
pubkey_ptr
*
C
.
secp256k1_pubkey
=
(
*
C
.
secp256k1_pubkey
)(
unsafe
.
Pointer
(
&
pubkey
[
0
]))
var
pubkey
[]
byte
=
make
([]
byte
,
pubkey_len
)
var
pubkey_ptr
*
C
.
uchar
=
(
*
C
.
uchar
)(
unsafe
.
Pointer
(
&
pubkey
[
0
]))
var
seckey_ptr
*
C
.
uchar
=
(
*
C
.
uchar
)(
unsafe
.
Pointer
(
&
seckey
[
0
]))
ret
:=
C
.
secp256k1_ec_pubkey_create
(
pubkey_ptr
,
&
pubkey_len
,
seckey_ptr
,
0
)
context
,
pubkey_ptr
,
seckey_ptr
,
)
if
ret
!=
C
.
int
(
1
)
{
return
nil
,
errors
.
New
(
"Unable to generate pubkey from seckey"
)
...
...
@@ -117,38 +120,48 @@ func GeneratePubKey(seckey []byte) ([]byte, error) {
}
func
Sign
(
msg
[]
byte
,
seckey
[]
byte
)
([]
byte
,
error
)
{
nonce
:=
randentropy
.
GetEntropyCSPRNG
(
32
)
msg_ptr
:=
(
*
C
.
uchar
)(
unsafe
.
Pointer
(
&
msg
[
0
]))
seckey_ptr
:=
(
*
C
.
uchar
)(
unsafe
.
Pointer
(
&
seckey
[
0
]))
var
sig
[]
byte
=
make
([]
byte
,
65
)
var
recid
C
.
int
sig
:
=
make
([]
byte
,
65
)
sig_ptr
:=
(
*
C
.
secp256k1_ecdsa_recoverable_signature
)(
unsafe
.
Pointer
(
&
sig
[
0
]))
var
msg_ptr
*
C
.
uchar
=
(
*
C
.
uchar
)(
unsafe
.
Pointer
(
&
msg
[
0
]))
var
sig_ptr
*
C
.
uchar
=
(
*
C
.
uchar
)(
unsafe
.
Pointer
(
&
sig
[
0
]))
var
seckey_ptr
*
C
.
uchar
=
(
*
C
.
uchar
)(
unsafe
.
Pointer
(
&
seckey
[
0
]))
nonce
:=
randentropy
.
GetEntropyCSPRNG
(
32
)
ndata_ptr
:=
unsafe
.
Pointer
(
&
nonce
[
0
])
var
noncefp_ptr
=
&
(
*
C
.
secp256k1_nonce_function_default
)
var
ndata_ptr
=
unsafe
.
Pointer
(
&
nonce
[
0
])
noncefp_ptr
:=
&
(
*
C
.
secp256k1_nonce_function_default
)
if
C
.
secp256k1_ec_seckey_verify
(
seckey_ptr
)
!=
C
.
int
(
1
)
{
if
C
.
secp256k1_ec_seckey_verify
(
context
,
seckey_ptr
)
!=
C
.
int
(
1
)
{
return
nil
,
errors
.
New
(
"Invalid secret key"
)
}
ret
:=
C
.
secp256k1_ecdsa_sign_
compact
(
msg_ptr
,
ret
:=
C
.
secp256k1_ecdsa_sign_
recoverable
(
context
,
sig_ptr
,
msg_ptr
,
seckey_ptr
,
noncefp_ptr
,
ndata_ptr
,
&
recid
)
sig
[
64
]
=
byte
(
int
(
recid
))
)
if
ret
!=
C
.
int
(
1
)
{
// nonce invalid, retry
return
Sign
(
msg
,
seckey
)
if
ret
==
C
.
int
(
0
)
{
return
Sign
(
msg
,
seckey
)
//invalid secret, try again
}
return
sig
,
nil
sig_serialized
:=
make
([]
byte
,
65
)
sig_serialized_ptr
:=
(
*
C
.
uchar
)(
unsafe
.
Pointer
(
&
sig_serialized
[
0
]))
var
recid
C
.
int
C
.
secp256k1_ecdsa_recoverable_signature_serialize_compact
(
context
,
sig_serialized_ptr
,
// 64 byte compact signature
&
recid
,
sig_ptr
,
// 65 byte "recoverable" signature
)
sig_serialized
[
64
]
=
byte
(
int
(
recid
))
// add back recid to get 65 bytes sig
return
sig_serialized
,
nil
}
...
...
@@ -157,26 +170,13 @@ func VerifySeckeyValidity(seckey []byte) error {
return
errors
.
New
(
"priv key is not 32 bytes"
)
}
var
seckey_ptr
*
C
.
uchar
=
(
*
C
.
uchar
)(
unsafe
.
Pointer
(
&
seckey
[
0
]))
ret
:=
C
.
secp256k1_ec_seckey_verify
(
seckey_ptr
)
ret
:=
C
.
secp256k1_ec_seckey_verify
(
context
,
seckey_ptr
)
if
int
(
ret
)
!=
1
{
return
errors
.
New
(
"invalid seckey"
)
}
return
nil
}
func
VerifyPubkeyValidity
(
pubkey
[]
byte
)
error
{
if
len
(
pubkey
)
!=
65
{
return
errors
.
New
(
"pub key is not 65 bytes"
)
}
var
pubkey_ptr
*
C
.
uchar
=
(
*
C
.
uchar
)(
unsafe
.
Pointer
(
&
pubkey
[
0
]))
ret
:=
C
.
secp256k1_ec_pubkey_verify
(
pubkey_ptr
,
65
)
if
int
(
ret
)
!=
1
{
return
errors
.
New
(
"invalid pubkey"
)
}
return
nil
}
func
VerifySignatureValidity
(
sig
[]
byte
)
bool
{
//64+1
if
len
(
sig
)
!=
65
{
...
...
@@ -231,36 +231,58 @@ func VerifySignature(msg []byte, sig []byte, pubkey1 []byte) error {
return
nil
}
//recovers the public key from the signature
//recovery of pubkey means correct signature
// recovers a public key from the signature
func
RecoverPubkey
(
msg
[]
byte
,
sig
[]
byte
)
([]
byte
,
error
)
{
if
len
(
sig
)
!=
65
{
return
nil
,
errors
.
New
(
"Invalid signature length"
)
}
var
pubkey
[]
byte
=
make
([]
byte
,
65
)
var
msg_ptr
*
C
.
uchar
=
(
*
C
.
uchar
)(
unsafe
.
Pointer
(
&
msg
[
0
]))
var
sig_ptr
*
C
.
uchar
=
(
*
C
.
uchar
)(
unsafe
.
Pointer
(
&
sig
[
0
]))
var
pubkey_ptr
*
C
.
uchar
=
(
*
C
.
uchar
)(
unsafe
.
Pointer
(
&
pubkey
[
0
]))
msg_ptr
:=
(
*
C
.
uchar
)(
unsafe
.
Pointer
(
&
msg
[
0
]))
sig_ptr
:=
(
*
C
.
uchar
)(
unsafe
.
Pointer
(
&
sig
[
0
]))
pubkey
:=
make
([]
byte
,
64
)
/*
this slice is used for both the recoverable signature and the
resulting serialized pubkey (both types in libsecp256k1 are 65
bytes). this saves one allocation of 65 bytes, which is nice as
pubkey recovery is one bottleneck during load in Ethereum
*/
bytes65
:=
make
([]
byte
,
65
)
pubkey_ptr
:=
(
*
C
.
secp256k1_pubkey
)(
unsafe
.
Pointer
(
&
pubkey
[
0
]))
recoverable_sig_ptr
:=
(
*
C
.
secp256k1_ecdsa_recoverable_signature
)(
unsafe
.
Pointer
(
&
bytes65
[
0
]))
recid
:=
C
.
int
(
sig
[
64
])
ret
:=
C
.
secp256k1_ecdsa_recoverable_signature_parse_compact
(
context
,
recoverable_sig_ptr
,
sig_ptr
,
recid
)
var
pubkeylen
C
.
int
if
ret
==
C
.
int
(
0
)
{
return
nil
,
errors
.
New
(
"Failed to parse signature"
)
}
ret
:=
C
.
secp256k1_ecdsa_recover_compact
(
msg_ptr
,
sig_ptr
,
ret
=
C
.
secp256k1_ecdsa_recover
(
context
,
pubkey_ptr
,
&
pubkeylen
,
C
.
int
(
0
),
C
.
int
(
sig
[
64
]),
recoverable_sig_ptr
,
msg_ptr
,
)
if
ret
==
C
.
int
(
0
)
{
return
nil
,
errors
.
New
(
"Failed to recover public key"
)
}
else
if
pubkeylen
!=
C
.
int
(
65
)
{
return
nil
,
errors
.
New
(
"Impossible Error: Invalid recovered public key length"
)
}
else
{
return
pubkey
,
nil
serialized_pubkey_ptr
:=
(
*
C
.
uchar
)(
unsafe
.
Pointer
(
&
bytes65
[
0
]))
var
output_len
C
.
size_t
C
.
secp256k1_ec_pubkey_serialize
(
// always returns 1
context
,
serialized_pubkey_ptr
,
&
output_len
,
pubkey_ptr
,
0
,
// SECP256K1_EC_COMPRESSED
)
return
bytes65
,
nil
}
return
nil
,
errors
.
New
(
"Impossible Error: func RecoverPubkey has reached an unreachable state"
)
}
crypto/secp256k1/secp256_test.go
View file @
f32fa075
...
...
@@ -18,169 +18,130 @@ package secp256k1
import
(
"bytes"
"fmt"
"log"
"encoding/hex"
"testing"
"github.com/ethereum/go-ethereum/crypto/randentropy"
)
const
TESTS
=
10000
// how many tests
const
SigSize
=
65
//64+1
const
TestCount
=
10000
func
Test_Secp256_00
(
t
*
testing
.
T
)
{
var
nonce
[]
byte
=
randentropy
.
GetEntropyCSPRNG
(
32
)
//going to get bitcoins stolen!
if
len
(
nonce
)
!=
32
{
t
.
Fatal
()
}
}
//tests for Malleability
//highest bit of S must be 0; 32nd byte
func
CompactSigTest
(
sig
[]
byte
)
{
var
b
int
=
int
(
sig
[
32
])
if
b
<
0
{
log
.
Panic
()
}
if
((
b
>>
7
)
==
1
)
!=
((
b
&
0x80
)
==
0x80
)
{
log
.
Panic
(
"b= %v b2= %v
\n
"
,
b
,
b
>>
7
)
}
if
(
b
&
0x80
)
==
0x80
{
log
.
Panic
(
"b= %v b2= %v
\n
"
,
b
,
b
&
0x80
)
}
}
//test pubkey/private generation
func
Test_Secp256_01
(
t
*
testing
.
T
)
{
pubkey
,
seckey
:=
GenerateKeyPair
()
func
TestPrivkeyGenerate
(
t
*
testing
.
T
)
{
_
,
seckey
:=
GenerateKeyPair
()
if
err
:=
VerifySeckeyValidity
(
seckey
);
err
!=
nil
{
t
.
Fatal
()
}
if
err
:=
VerifyPubkeyValidity
(
pubkey
);
err
!=
nil
{
t
.
Fatal
()
t
.
Errorf
(
"seckey not valid: %s"
,
err
)
}
}
//test size of messages
func
Test_Secp256_02s
(
t
*
testing
.
T
)
{
func
TestSignatureValidity
(
t
*
testing
.
T
)
{
pubkey
,
seckey
:=
GenerateKeyPair
()
msg
:=
randentropy
.
GetEntropyCSPRNG
(
32
)
sig
,
_
:=
Sign
(
msg
,
seckey
)
CompactSigTest
(
sig
)
if
sig
==
nil
{
t
.
Fatal
(
"Signature nil"
)
sig
,
err
:=
Sign
(
msg
,
seckey
)
if
err
!=
nil
{
t
.
Errorf
(
"signature error: %s"
,
err
)
}
compactSigCheck
(
t
,
sig
)
if
len
(
pubkey
)
!=
65
{
t
.
Fail
(
)
t
.
Errorf
(
"pubkey length mismatch: want: 65 have: %d"
,
len
(
pubkey
)
)
}
if
len
(
seckey
)
!=
32
{
t
.
Fail
(
)
t
.
Errorf
(
"seckey length mismatch: want: 32 have: %d"
,
len
(
seckey
)
)
}
if
len
(
sig
)
!=
64
+
1
{
t
.
Fail
()
if
len
(
sig
)
!=
65
{
t
.
Errorf
(
"sig length mismatch: want: 65 have: %d"
,
len
(
sig
))
}
recid
:=
int
(
sig
[
64
])
if
recid
>
4
||
recid
<
0
{
t
.
Errorf
(
"sig recid mismatch: want: within 0 to 4 have: %d"
,
int
(
sig
[
64
]))
}
if
int
(
sig
[
64
])
>
4
{
t
.
Fail
()
}
//should be 0 to 4
}
//test signing message
func
Test_Secp256_02
(
t
*
testing
.
T
)
{
func
TestSignAndRecover
(
t
*
testing
.
T
)
{
pubkey1
,
seckey
:=
GenerateKeyPair
()
msg
:=
randentropy
.
GetEntropyCSPRNG
(
32
)
sig
,
_
:=
Sign
(
msg
,
seckey
)
if
sig
=
=
nil
{
t
.
Fatal
(
"Signature nil"
)
sig
,
err
:=
Sign
(
msg
,
seckey
)
if
err
!
=
nil
{
t
.
Errorf
(
"signature error: %s"
,
err
)
}
pubkey2
,
_
:=
RecoverPubkey
(
msg
,
sig
)
if
pubkey2
==
nil
{
t
.
Fatal
(
"Recovered pubkey invalid"
)
pubkey2
,
err
:=
RecoverPubkey
(
msg
,
sig
)
if
err
!=
nil
{
t
.
Errorf
(
"recover error: %s"
,
err
)
}
if
bytes
.
Equal
(
pubkey1
,
pubkey2
)
==
false
{
t
.
Fatal
(
"Recovered pubkey does not match"
)
if
!
bytes
.
Equal
(
pubkey1
,
pubkey2
)
{
t
.
Errorf
(
"pubkey mismatch: want: %x have: %x"
,
pubkey1
,
pubkey2
)
}
err
:=
VerifySignature
(
msg
,
sig
,
pubkey1
)
err
=
VerifySignature
(
msg
,
sig
,
pubkey1
)
if
err
!=
nil
{
t
.
Fatal
(
"Signature invalid"
)
t
.
Errorf
(
"signature verification error: %s"
,
err
)
}
}
//test pubkey recovery
func
Test_Secp256_02a
(
t
*
testing
.
T
)
{
pubkey1
,
seckey1
:=
GenerateKeyPair
()
msg
:=
randentropy
.
GetEntropyCSPRNG
(
32
)
sig
,
_
:=
Sign
(
msg
,
seckey1
)
if
sig
==
nil
{
t
.
Fatal
(
"Signature nil"
)
}
err
:=
VerifySignature
(
msg
,
sig
,
pubkey1
)
if
err
!=
nil
{
t
.
Fatal
(
"Signature invalid"
)
func
TestRandomMessagesWithSameKey
(
t
*
testing
.
T
)
{
pubkey
,
seckey
:=
GenerateKeyPair
()
keys
:=
func
()
([]
byte
,
[]
byte
)
{
// Sign function zeroes the privkey so we need a new one in each call
newkey
:=
make
([]
byte
,
len
(
seckey
))
copy
(
newkey
,
seckey
)
return
pubkey
,
newkey
}
signAndRecoverWithRandomMessages
(
t
,
keys
)
}
pubkey2
,
_
:=
RecoverPubkey
(
msg
,
sig
)
if
len
(
pubkey1
)
!=
len
(
pubkey2
)
{
t
.
Fatal
()
}
for
i
,
_
:=
range
pubkey1
{
if
pubkey1
[
i
]
!=
pubkey2
[
i
]
{
t
.
Fatal
()
}
}
if
bytes
.
Equal
(
pubkey1
,
pubkey2
)
==
false
{
t
.
Fatal
()
func
TestRandomMessagesWithRandomKeys
(
t
*
testing
.
T
)
{
keys
:=
func
()
([]
byte
,
[]
byte
)
{
pubkey
,
seckey
:=
GenerateKeyPair
()
return
pubkey
,
seckey
}
signAndRecoverWithRandomMessages
(
t
,
keys
)
}
//test random messages for the same pub/private key
func
Test_Secp256_03
(
t
*
testing
.
T
)
{
_
,
seckey
:=
GenerateKeyPair
()
for
i
:=
0
;
i
<
TESTS
;
i
++
{
func
signAndRecoverWithRandomMessages
(
t
*
testing
.
T
,
keys
func
()
([]
byte
,
[]
byte
))
{
for
i
:=
0
;
i
<
TestCount
;
i
++
{
pubkey1
,
seckey
:=
keys
()
msg
:=
randentropy
.
GetEntropyCSPRNG
(
32
)
sig
,
_
:=
Sign
(
msg
,
seckey
)
CompactSigTest
(
sig
)
sig
,
err
:=
Sign
(
msg
,
seckey
)
if
err
!=
nil
{
t
.
Fatalf
(
"signature error: %s"
,
err
)
}
if
sig
==
nil
{
t
.
Fatal
(
"signature is nil"
)
}
compactSigCheck
(
t
,
sig
)
// TODO: why do we flip around the recovery id?
sig
[
len
(
sig
)
-
1
]
%=
4
pubkey2
,
_
:=
RecoverPubkey
(
msg
,
sig
)
pubkey2
,
err
:=
RecoverPubkey
(
msg
,
sig
)
if
err
!=
nil
{
t
.
Fatalf
(
"recover error: %s"
,
err
)
}
if
pubkey2
==
nil
{
t
.
Fail
()
t
.
Error
(
"pubkey is nil"
)
}
if
!
bytes
.
Equal
(
pubkey1
,
pubkey2
)
{
t
.
Fatalf
(
"pubkey mismatch: want: %x have: %x"
,
pubkey1
,
pubkey2
)
}
}
}
//test random messages for different pub/private keys
func
Test_Secp256_04
(
t
*
testing
.
T
)
{
for
i
:=
0
;
i
<
TESTS
;
i
++
{
pubkey1
,
seckey
:=
GenerateKeyPair
(
)
msg
:=
randentropy
.
GetEntropyCSPRNG
(
32
)
sig
,
_
:=
Sign
(
msg
,
seckey
)
CompactSigTest
(
sig
)
func
TestRecoveryOfRandomSignature
(
t
*
testing
.
T
)
{
pubkey1
,
seckey
:=
GenerateKeyPair
()
msg
:=
randentropy
.
GetEntropyCSPRNG
(
32
)
sig
,
err
:=
Sign
(
msg
,
seckey
)
if
err
!=
nil
{
t
.
Errorf
(
"signature error: %s"
,
err
)
}
if
sig
[
len
(
sig
)
-
1
]
>=
4
{
t
.
Fail
()
}
for
i
:=
0
;
i
<
TestCount
;
i
++
{
sig
=
randSig
()
pubkey2
,
_
:=
RecoverPubkey
(
msg
,
sig
)
if
pubkey2
==
nil
{
t
.
Fail
()
}
if
bytes
.
Equal
(
pubkey1
,
pubkey2
)
==
false
{
t
.
Fail
()
// recovery can sometimes work, but if so should always give wrong pubkey
if
bytes
.
Equal
(
pubkey1
,
pubkey2
)
{
t
.
Fatalf
(
"iteration: %d: pubkey mismatch: do NOT want %x: "
,
i
,
pubkey2
)
}
}
}
//test random signatures against fixed messages; should fail
//crashes:
// -SIPA look at this
func
randSig
()
[]
byte
{
sig
:=
randentropy
.
GetEntropyCSPRNG
(
65
)
sig
[
32
]
&=
0x70
...
...
@@ -188,67 +149,83 @@ func randSig() []byte {
return
sig
}
func
Test
_Secp256_06a_alt0
(
t
*
testing
.
T
)
{
func
Test
RandomMessagesAgainstValidSig
(
t
*
testing
.
T
)
{
pubkey1
,
seckey
:=
GenerateKeyPair
()
msg
:=
randentropy
.
GetEntropyCSPRNG
(
32
)
sig
,
_
:=
Sign
(
msg
,
seckey
)
if
sig
==
nil
{
t
.
Fail
()
}
if
len
(
sig
)
!=
65
{
t
.
Fail
()
}
for
i
:=
0
;
i
<
TESTS
;
i
++
{
sig
=
randSig
()
for
i
:=
0
;
i
<
TestCount
;
i
++
{
msg
=
randentropy
.
GetEntropyCSPRNG
(
32
)
pubkey2
,
_
:=
RecoverPubkey
(
msg
,
sig
)
if
bytes
.
Equal
(
pubkey1
,
pubkey2
)
==
true
{
t
.
Fail
()
}
if
pubkey2
!=
nil
&&
VerifySignature
(
msg
,
sig
,
pubkey2
)
!=
nil
{
t
.
Fail
()
}
if
VerifySignature
(
msg
,
sig
,
pubkey1
)
==
nil
{
t
.
Fail
()
// recovery can sometimes work, but if so should always give wrong pubkey
if
bytes
.
Equal
(
pubkey1
,
pubkey2
)
{
t
.
Fatalf
(
"iteration: %d: pubkey mismatch: do NOT want %x: "
,
i
,
pubkey2
)
}
}
}
//test random messages against valid signature: should fail
func
Test_Secp256_06b
(
t
*
testing
.
T
)
{
pubkey1
,
seckey
:=
GenerateKeyPair
()
msg
:=
randentropy
.
GetEntropyCSPRNG
(
32
)
sig
,
_
:=
Sign
(
msg
,
seckey
)
func
TestZeroPrivkey
(
t
*
testing
.
T
)
{
zeroedBytes
:=
make
([]
byte
,
32
)
err
:=
VerifySeckeyValidity
(
zeroedBytes
)
if
err
==
nil
{
t
.
Errorf
(
"zeroed bytes should have returned error"
)
}
}
fail_count
:=
0
for
i
:=
0
;
i
<
TESTS
;
i
++
{
msg
=
randentropy
.
GetEntropyCSPRNG
(
32
)
pubkey2
,
_
:=
RecoverPubkey
(
msg
,
sig
)
if
bytes
.
Equal
(
pubkey1
,
pubkey2
)
==
true
{
t
.
Fail
()
}
// Useful when the underlying libsecp256k1 API changes to quickly
// check only recover function without use of signature function
func
TestRecoverSanity
(
t
*
testing
.
T
)
{
msg
,
_
:=
hex
.
DecodeString
(
"ce0677bb30baa8cf067c88db9811f4333d131bf8bcf12fe7065d211dce971008"
)
sig
,
_
:=
hex
.
DecodeString
(
"90f27b8b488db00b00606796d2987f6a5f59ae62ea05effe84fef5b8b0e549984a691139ad57a3f0b906637673aa2f63d1f55cb1a69199d4009eea23ceaddc9301"
)
pubkey1
,
_
:=
hex
.
DecodeString
(
"04e32df42865e97135acfb65f3bae71bdc86f4d49150ad6a440b6f15878109880a0a2b2667f7e725ceea70c673093bf67663e0312623c8e091b13cf2c0f11ef652"
)
pubkey2
,
err
:=
RecoverPubkey
(
msg
,
sig
)
if
err
!=
nil
{
t
.
Fatalf
(
"recover error: %s"
,
err
)
}
if
!
bytes
.
Equal
(
pubkey1
,
pubkey2
)
{
t
.
Errorf
(
"pubkey mismatch: want: %x have: %x"
,
pubkey1
,
pubkey2
)
}
}
if
pubkey2
!=
nil
&&
VerifySignature
(
msg
,
sig
,
pubkey2
)
!=
nil
{
t
.
Fail
()
}
// tests for malleability
// highest bit of signature ECDSA s value must be 0, in the 33th byte
func
compactSigCheck
(
t
*
testing
.
T
,
sig
[]
byte
)
{
var
b
int
=
int
(
sig
[
32
])
if
b
<
0
{
t
.
Errorf
(
"highest bit is negative: %d"
,
b
)
}
if
((
b
>>
7
)
==
1
)
!=
((
b
&
0x80
)
==
0x80
)
{
t
.
Errorf
(
"highest bit: %d bit >> 7: %d"
,
b
,
b
>>
7
)
}
if
(
b
&
0x80
)
==
0x80
{
t
.
Errorf
(
"highest bit: %d bit & 0x80: %d"
,
b
,
b
&
0x80
)
}
}
if
VerifySignature
(
msg
,
sig
,
pubkey1
)
==
nil
{
t
.
Fail
()
// godep go test -v -run=XXX -bench=BenchmarkSignRandomInputEachRound
// add -benchtime=10s to benchmark longer for more accurate average
func
BenchmarkSignRandomInputEachRound
(
b
*
testing
.
B
)
{
for
i
:=
0
;
i
<
b
.
N
;
i
++
{
b
.
StopTimer
()
_
,
seckey
:=
GenerateKeyPair
()
msg
:=
randentropy
.
GetEntropyCSPRNG
(
32
)
b
.
StartTimer
()
if
_
,
err
:=
Sign
(
msg
,
seckey
);
err
!=
nil
{
b
.
Fatal
(
err
)
}
}
if
fail_count
!=
0
{
fmt
.
Printf
(
"ERROR: Accepted signature for %v of %v random messages
\n
"
,
fail_count
,
TESTS
)
}
}
func
TestInvalidKey
(
t
*
testing
.
T
)
{
p1
:=
make
([]
byte
,
32
)
err
:=
VerifySeckeyValidity
(
p1
)
if
err
==
nil
{
t
.
Errorf
(
"pvk %x varify sec key should have returned error"
,
p1
)
//godep go test -v -run=XXX -bench=BenchmarkRecoverRandomInputEachRound
func
BenchmarkRecoverRandomInputEachRound
(
b
*
testing
.
B
)
{
for
i
:=
0
;
i
<
b
.
N
;
i
++
{
b
.
StopTimer
()
_
,
seckey
:=
GenerateKeyPair
()
msg
:=
randentropy
.
GetEntropyCSPRNG
(
32
)
sig
,
_
:=
Sign
(
msg
,
seckey
)
b
.
StartTimer
()
if
_
,
err
:=
RecoverPubkey
(
msg
,
sig
);
err
!=
nil
{
b
.
Fatal
(
err
)
}
}
}
Write
Preview
Markdown
is supported
0%
Try again
or
attach a new file
Attach a file
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Cancel
Please
register
or
sign in
to comment