crypto/secp256k1: remove external LGPL dependencies (#17239)
This commit is contained in:
parent
11a402f747
commit
d9575e92fc
@ -28,18 +28,18 @@ package keystore
|
|||||||
import (
|
import (
|
||||||
"bytes"
|
"bytes"
|
||||||
"crypto/aes"
|
"crypto/aes"
|
||||||
crand "crypto/rand"
|
"crypto/rand"
|
||||||
"crypto/sha256"
|
"crypto/sha256"
|
||||||
"encoding/hex"
|
"encoding/hex"
|
||||||
"encoding/json"
|
"encoding/json"
|
||||||
"fmt"
|
"fmt"
|
||||||
|
"io"
|
||||||
"io/ioutil"
|
"io/ioutil"
|
||||||
"path/filepath"
|
"path/filepath"
|
||||||
|
|
||||||
"github.com/ethereum/go-ethereum/common"
|
"github.com/ethereum/go-ethereum/common"
|
||||||
"github.com/ethereum/go-ethereum/common/math"
|
"github.com/ethereum/go-ethereum/common/math"
|
||||||
"github.com/ethereum/go-ethereum/crypto"
|
"github.com/ethereum/go-ethereum/crypto"
|
||||||
"github.com/ethereum/go-ethereum/crypto/randentropy"
|
|
||||||
"github.com/pborman/uuid"
|
"github.com/pborman/uuid"
|
||||||
"golang.org/x/crypto/pbkdf2"
|
"golang.org/x/crypto/pbkdf2"
|
||||||
"golang.org/x/crypto/scrypt"
|
"golang.org/x/crypto/scrypt"
|
||||||
@ -93,7 +93,7 @@ func (ks keyStorePassphrase) GetKey(addr common.Address, filename, auth string)
|
|||||||
|
|
||||||
// StoreKey generates a key, encrypts with 'auth' and stores in the given directory
|
// StoreKey generates a key, encrypts with 'auth' and stores in the given directory
|
||||||
func StoreKey(dir, auth string, scryptN, scryptP int) (common.Address, error) {
|
func StoreKey(dir, auth string, scryptN, scryptP int) (common.Address, error) {
|
||||||
_, a, err := storeNewKey(&keyStorePassphrase{dir, scryptN, scryptP}, crand.Reader, auth)
|
_, a, err := storeNewKey(&keyStorePassphrase{dir, scryptN, scryptP}, rand.Reader, auth)
|
||||||
return a.Address, err
|
return a.Address, err
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -116,7 +116,11 @@ func (ks keyStorePassphrase) JoinPath(filename string) string {
|
|||||||
// blob that can be decrypted later on.
|
// blob that can be decrypted later on.
|
||||||
func EncryptKey(key *Key, auth string, scryptN, scryptP int) ([]byte, error) {
|
func EncryptKey(key *Key, auth string, scryptN, scryptP int) ([]byte, error) {
|
||||||
authArray := []byte(auth)
|
authArray := []byte(auth)
|
||||||
salt := randentropy.GetEntropyCSPRNG(32)
|
|
||||||
|
salt := make([]byte, 32)
|
||||||
|
if _, err := io.ReadFull(rand.Reader, salt); err != nil {
|
||||||
|
panic("reading from crypto/rand failed: " + err.Error())
|
||||||
|
}
|
||||||
derivedKey, err := scrypt.Key(authArray, salt, scryptN, scryptR, scryptP, scryptDKLen)
|
derivedKey, err := scrypt.Key(authArray, salt, scryptN, scryptR, scryptP, scryptDKLen)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
@ -124,7 +128,10 @@ func EncryptKey(key *Key, auth string, scryptN, scryptP int) ([]byte, error) {
|
|||||||
encryptKey := derivedKey[:16]
|
encryptKey := derivedKey[:16]
|
||||||
keyBytes := math.PaddedBigBytes(key.PrivateKey.D, 32)
|
keyBytes := math.PaddedBigBytes(key.PrivateKey.D, 32)
|
||||||
|
|
||||||
iv := randentropy.GetEntropyCSPRNG(aes.BlockSize) // 16
|
iv := make([]byte, aes.BlockSize) // 16
|
||||||
|
if _, err := io.ReadFull(rand.Reader, iv); err != nil {
|
||||||
|
panic("reading from crypto/rand failed: " + err.Error())
|
||||||
|
}
|
||||||
cipherText, err := aesCTRXOR(encryptKey, keyBytes, iv)
|
cipherText, err := aesCTRXOR(encryptKey, keyBytes, iv)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
|
@ -1,42 +0,0 @@
|
|||||||
// Copyright 2015 The go-ethereum Authors
|
|
||||||
// This file is part of the go-ethereum library.
|
|
||||||
//
|
|
||||||
// The go-ethereum library is free software: you can redistribute it and/or modify
|
|
||||||
// it under the terms of the GNU Lesser General Public License as published by
|
|
||||||
// the Free Software Foundation, either version 3 of the License, or
|
|
||||||
// (at your option) any later version.
|
|
||||||
//
|
|
||||||
// The go-ethereum library is distributed in the hope that it will be useful,
|
|
||||||
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
||||||
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
||||||
// GNU Lesser General Public License for more details.
|
|
||||||
//
|
|
||||||
// You should have received a copy of the GNU Lesser General Public License
|
|
||||||
// along with the go-ethereum library. If not, see <http://www.gnu.org/licenses/>.
|
|
||||||
|
|
||||||
package randentropy
|
|
||||||
|
|
||||||
import (
|
|
||||||
crand "crypto/rand"
|
|
||||||
"io"
|
|
||||||
)
|
|
||||||
|
|
||||||
var Reader io.Reader = &randEntropy{}
|
|
||||||
|
|
||||||
type randEntropy struct {
|
|
||||||
}
|
|
||||||
|
|
||||||
func (*randEntropy) Read(bytes []byte) (n int, err error) {
|
|
||||||
readBytes := GetEntropyCSPRNG(len(bytes))
|
|
||||||
copy(bytes, readBytes)
|
|
||||||
return len(bytes), nil
|
|
||||||
}
|
|
||||||
|
|
||||||
func GetEntropyCSPRNG(n int) []byte {
|
|
||||||
mainBuff := make([]byte, n)
|
|
||||||
_, err := io.ReadFull(crand.Reader, mainBuff)
|
|
||||||
if err != nil {
|
|
||||||
panic("reading from crypto/rand failed: " + err.Error())
|
|
||||||
}
|
|
||||||
return mainBuff
|
|
||||||
}
|
|
@ -1,5 +1,6 @@
|
|||||||
// Copyright 2010 The Go Authors. All rights reserved.
|
// Copyright 2010 The Go Authors. All rights reserved.
|
||||||
// Copyright 2011 ThePiachu. All rights reserved.
|
// Copyright 2011 ThePiachu. All rights reserved.
|
||||||
|
// Copyright 2015 Jeffrey Wilcke, Felix Lange, Gustav Simonsson. All rights reserved.
|
||||||
//
|
//
|
||||||
// Redistribution and use in source and binary forms, with or without
|
// Redistribution and use in source and binary forms, with or without
|
||||||
// modification, are permitted provided that the following conditions are
|
// modification, are permitted provided that the following conditions are
|
||||||
@ -35,8 +36,6 @@ import (
|
|||||||
"crypto/elliptic"
|
"crypto/elliptic"
|
||||||
"math/big"
|
"math/big"
|
||||||
"unsafe"
|
"unsafe"
|
||||||
|
|
||||||
"github.com/ethereum/go-ethereum/common/math"
|
|
||||||
)
|
)
|
||||||
|
|
||||||
/*
|
/*
|
||||||
@ -45,6 +44,27 @@ extern int secp256k1_ext_scalar_mul(const secp256k1_context* ctx, const unsigned
|
|||||||
*/
|
*/
|
||||||
import "C"
|
import "C"
|
||||||
|
|
||||||
|
const (
|
||||||
|
// number of bits in a big.Word
|
||||||
|
wordBits = 32 << (uint64(^big.Word(0)) >> 63)
|
||||||
|
// number of bytes in a big.Word
|
||||||
|
wordBytes = wordBits / 8
|
||||||
|
)
|
||||||
|
|
||||||
|
// readBits encodes the absolute value of bigint as big-endian bytes. Callers
|
||||||
|
// must ensure that buf has enough space. If buf is too short the result will
|
||||||
|
// be incomplete.
|
||||||
|
func readBits(bigint *big.Int, buf []byte) {
|
||||||
|
i := len(buf)
|
||||||
|
for _, d := range bigint.Bits() {
|
||||||
|
for j := 0; j < wordBytes && i > 0; j++ {
|
||||||
|
i--
|
||||||
|
buf[i] = byte(d)
|
||||||
|
d >>= 8
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// This code is from https://github.com/ThePiachu/GoBit and implements
|
// This code is from https://github.com/ThePiachu/GoBit and implements
|
||||||
// several Koblitz elliptic curves over prime fields.
|
// several Koblitz elliptic curves over prime fields.
|
||||||
//
|
//
|
||||||
@ -231,8 +251,9 @@ func (BitCurve *BitCurve) ScalarMult(Bx, By *big.Int, scalar []byte) (*big.Int,
|
|||||||
|
|
||||||
// Do the multiplication in C, updating point.
|
// Do the multiplication in C, updating point.
|
||||||
point := make([]byte, 64)
|
point := make([]byte, 64)
|
||||||
math.ReadBits(Bx, point[:32])
|
readBits(Bx, point[:32])
|
||||||
math.ReadBits(By, point[32:])
|
readBits(By, point[32:])
|
||||||
|
|
||||||
pointPtr := (*C.uchar)(unsafe.Pointer(&point[0]))
|
pointPtr := (*C.uchar)(unsafe.Pointer(&point[0]))
|
||||||
scalarPtr := (*C.uchar)(unsafe.Pointer(&scalar[0]))
|
scalarPtr := (*C.uchar)(unsafe.Pointer(&scalar[0]))
|
||||||
res := C.secp256k1_ext_scalar_mul(context, pointPtr, scalarPtr)
|
res := C.secp256k1_ext_scalar_mul(context, pointPtr, scalarPtr)
|
||||||
@ -264,8 +285,8 @@ func (BitCurve *BitCurve) Marshal(x, y *big.Int) []byte {
|
|||||||
byteLen := (BitCurve.BitSize + 7) >> 3
|
byteLen := (BitCurve.BitSize + 7) >> 3
|
||||||
ret := make([]byte, 1+2*byteLen)
|
ret := make([]byte, 1+2*byteLen)
|
||||||
ret[0] = 4 // uncompressed point flag
|
ret[0] = 4 // uncompressed point flag
|
||||||
math.ReadBits(x, ret[1:1+byteLen])
|
readBits(x, ret[1:1+byteLen])
|
||||||
math.ReadBits(y, ret[1+byteLen:])
|
readBits(y, ret[1+byteLen:])
|
||||||
return ret
|
return ret
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -290,11 +311,11 @@ func init() {
|
|||||||
// See SEC 2 section 2.7.1
|
// See SEC 2 section 2.7.1
|
||||||
// curve parameters taken from:
|
// curve parameters taken from:
|
||||||
// http://www.secg.org/collateral/sec2_final.pdf
|
// http://www.secg.org/collateral/sec2_final.pdf
|
||||||
theCurve.P = math.MustParseBig256("0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFEFFFFFC2F")
|
theCurve.P, _ = new(big.Int).SetString("0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFEFFFFFC2F", 0)
|
||||||
theCurve.N = math.MustParseBig256("0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFEBAAEDCE6AF48A03BBFD25E8CD0364141")
|
theCurve.N, _ = new(big.Int).SetString("0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFEBAAEDCE6AF48A03BBFD25E8CD0364141", 0)
|
||||||
theCurve.B = math.MustParseBig256("0x0000000000000000000000000000000000000000000000000000000000000007")
|
theCurve.B, _ = new(big.Int).SetString("0x0000000000000000000000000000000000000000000000000000000000000007", 0)
|
||||||
theCurve.Gx = math.MustParseBig256("0x79BE667EF9DCBBAC55A06295CE870B07029BFCDB2DCE28D959F2815B16F81798")
|
theCurve.Gx, _ = new(big.Int).SetString("0x79BE667EF9DCBBAC55A06295CE870B07029BFCDB2DCE28D959F2815B16F81798", 0)
|
||||||
theCurve.Gy = math.MustParseBig256("0x483ADA7726A3C4655DA4FBFC0E1108A8FD17B448A68554199C47D08FFB10D4B8")
|
theCurve.Gy, _ = new(big.Int).SetString("0x483ADA7726A3C4655DA4FBFC0E1108A8FD17B448A68554199C47D08FFB10D4B8", 0)
|
||||||
theCurve.BitSize = 256
|
theCurve.BitSize = 256
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -10,10 +10,8 @@ import (
|
|||||||
"crypto/elliptic"
|
"crypto/elliptic"
|
||||||
"crypto/rand"
|
"crypto/rand"
|
||||||
"encoding/hex"
|
"encoding/hex"
|
||||||
|
"io"
|
||||||
"testing"
|
"testing"
|
||||||
|
|
||||||
"github.com/ethereum/go-ethereum/common/math"
|
|
||||||
"github.com/ethereum/go-ethereum/crypto/randentropy"
|
|
||||||
)
|
)
|
||||||
|
|
||||||
const TestCount = 1000
|
const TestCount = 1000
|
||||||
@ -24,11 +22,24 @@ func generateKeyPair() (pubkey, privkey []byte) {
|
|||||||
panic(err)
|
panic(err)
|
||||||
}
|
}
|
||||||
pubkey = elliptic.Marshal(S256(), key.X, key.Y)
|
pubkey = elliptic.Marshal(S256(), key.X, key.Y)
|
||||||
return pubkey, math.PaddedBigBytes(key.D, 32)
|
|
||||||
|
privkey = make([]byte, 32)
|
||||||
|
blob := key.D.Bytes()
|
||||||
|
copy(privkey[32-len(blob):], blob)
|
||||||
|
|
||||||
|
return pubkey, privkey
|
||||||
|
}
|
||||||
|
|
||||||
|
func csprngEntropy(n int) []byte {
|
||||||
|
buf := make([]byte, n)
|
||||||
|
if _, err := io.ReadFull(rand.Reader, buf); err != nil {
|
||||||
|
panic("reading from crypto/rand failed: " + err.Error())
|
||||||
|
}
|
||||||
|
return buf
|
||||||
}
|
}
|
||||||
|
|
||||||
func randSig() []byte {
|
func randSig() []byte {
|
||||||
sig := randentropy.GetEntropyCSPRNG(65)
|
sig := csprngEntropy(65)
|
||||||
sig[32] &= 0x70
|
sig[32] &= 0x70
|
||||||
sig[64] %= 4
|
sig[64] %= 4
|
||||||
return sig
|
return sig
|
||||||
@ -51,7 +62,7 @@ func compactSigCheck(t *testing.T, sig []byte) {
|
|||||||
|
|
||||||
func TestSignatureValidity(t *testing.T) {
|
func TestSignatureValidity(t *testing.T) {
|
||||||
pubkey, seckey := generateKeyPair()
|
pubkey, seckey := generateKeyPair()
|
||||||
msg := randentropy.GetEntropyCSPRNG(32)
|
msg := csprngEntropy(32)
|
||||||
sig, err := Sign(msg, seckey)
|
sig, err := Sign(msg, seckey)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
t.Errorf("signature error: %s", err)
|
t.Errorf("signature error: %s", err)
|
||||||
@ -74,7 +85,7 @@ func TestSignatureValidity(t *testing.T) {
|
|||||||
|
|
||||||
func TestInvalidRecoveryID(t *testing.T) {
|
func TestInvalidRecoveryID(t *testing.T) {
|
||||||
_, seckey := generateKeyPair()
|
_, seckey := generateKeyPair()
|
||||||
msg := randentropy.GetEntropyCSPRNG(32)
|
msg := csprngEntropy(32)
|
||||||
sig, _ := Sign(msg, seckey)
|
sig, _ := Sign(msg, seckey)
|
||||||
sig[64] = 99
|
sig[64] = 99
|
||||||
_, err := RecoverPubkey(msg, sig)
|
_, err := RecoverPubkey(msg, sig)
|
||||||
@ -85,7 +96,7 @@ func TestInvalidRecoveryID(t *testing.T) {
|
|||||||
|
|
||||||
func TestSignAndRecover(t *testing.T) {
|
func TestSignAndRecover(t *testing.T) {
|
||||||
pubkey1, seckey := generateKeyPair()
|
pubkey1, seckey := generateKeyPair()
|
||||||
msg := randentropy.GetEntropyCSPRNG(32)
|
msg := csprngEntropy(32)
|
||||||
sig, err := Sign(msg, seckey)
|
sig, err := Sign(msg, seckey)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
t.Errorf("signature error: %s", err)
|
t.Errorf("signature error: %s", err)
|
||||||
@ -136,7 +147,7 @@ func TestRandomMessagesWithRandomKeys(t *testing.T) {
|
|||||||
func signAndRecoverWithRandomMessages(t *testing.T, keys func() ([]byte, []byte)) {
|
func signAndRecoverWithRandomMessages(t *testing.T, keys func() ([]byte, []byte)) {
|
||||||
for i := 0; i < TestCount; i++ {
|
for i := 0; i < TestCount; i++ {
|
||||||
pubkey1, seckey := keys()
|
pubkey1, seckey := keys()
|
||||||
msg := randentropy.GetEntropyCSPRNG(32)
|
msg := csprngEntropy(32)
|
||||||
sig, err := Sign(msg, seckey)
|
sig, err := Sign(msg, seckey)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
t.Fatalf("signature error: %s", err)
|
t.Fatalf("signature error: %s", err)
|
||||||
@ -164,7 +175,7 @@ func signAndRecoverWithRandomMessages(t *testing.T, keys func() ([]byte, []byte)
|
|||||||
|
|
||||||
func TestRecoveryOfRandomSignature(t *testing.T) {
|
func TestRecoveryOfRandomSignature(t *testing.T) {
|
||||||
pubkey1, _ := generateKeyPair()
|
pubkey1, _ := generateKeyPair()
|
||||||
msg := randentropy.GetEntropyCSPRNG(32)
|
msg := csprngEntropy(32)
|
||||||
|
|
||||||
for i := 0; i < TestCount; i++ {
|
for i := 0; i < TestCount; i++ {
|
||||||
// recovery can sometimes work, but if so should always give wrong pubkey
|
// recovery can sometimes work, but if so should always give wrong pubkey
|
||||||
@ -177,11 +188,11 @@ func TestRecoveryOfRandomSignature(t *testing.T) {
|
|||||||
|
|
||||||
func TestRandomMessagesAgainstValidSig(t *testing.T) {
|
func TestRandomMessagesAgainstValidSig(t *testing.T) {
|
||||||
pubkey1, seckey := generateKeyPair()
|
pubkey1, seckey := generateKeyPair()
|
||||||
msg := randentropy.GetEntropyCSPRNG(32)
|
msg := csprngEntropy(32)
|
||||||
sig, _ := Sign(msg, seckey)
|
sig, _ := Sign(msg, seckey)
|
||||||
|
|
||||||
for i := 0; i < TestCount; i++ {
|
for i := 0; i < TestCount; i++ {
|
||||||
msg = randentropy.GetEntropyCSPRNG(32)
|
msg = csprngEntropy(32)
|
||||||
pubkey2, _ := RecoverPubkey(msg, sig)
|
pubkey2, _ := RecoverPubkey(msg, sig)
|
||||||
// recovery can sometimes work, but if so should always give wrong pubkey
|
// recovery can sometimes work, but if so should always give wrong pubkey
|
||||||
if bytes.Equal(pubkey1, pubkey2) {
|
if bytes.Equal(pubkey1, pubkey2) {
|
||||||
@ -207,7 +218,7 @@ func TestRecoverSanity(t *testing.T) {
|
|||||||
|
|
||||||
func BenchmarkSign(b *testing.B) {
|
func BenchmarkSign(b *testing.B) {
|
||||||
_, seckey := generateKeyPair()
|
_, seckey := generateKeyPair()
|
||||||
msg := randentropy.GetEntropyCSPRNG(32)
|
msg := csprngEntropy(32)
|
||||||
b.ResetTimer()
|
b.ResetTimer()
|
||||||
|
|
||||||
for i := 0; i < b.N; i++ {
|
for i := 0; i < b.N; i++ {
|
||||||
@ -216,7 +227,7 @@ func BenchmarkSign(b *testing.B) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func BenchmarkRecover(b *testing.B) {
|
func BenchmarkRecover(b *testing.B) {
|
||||||
msg := randentropy.GetEntropyCSPRNG(32)
|
msg := csprngEntropy(32)
|
||||||
_, seckey := generateKeyPair()
|
_, seckey := generateKeyPair()
|
||||||
sig, _ := Sign(msg, seckey)
|
sig, _ := Sign(msg, seckey)
|
||||||
b.ResetTimer()
|
b.ResetTimer()
|
||||||
|
Loading…
Reference in New Issue
Block a user