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
Expand all
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
This diff is collapsed.
Click to expand it.
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