Prechádzať zdrojové kódy

crypto/secp256k1: remove external LGPL dependencies (#17239)

Péter Szilágyi 7 rokov pred
rodič
commit
d9575e92fc

+ 12 - 5
accounts/keystore/keystore_passphrase.go

@@ -28,18 +28,18 @@ package keystore
 import (
 	"bytes"
 	"crypto/aes"
-	crand "crypto/rand"
+	"crypto/rand"
 	"crypto/sha256"
 	"encoding/hex"
 	"encoding/json"
 	"fmt"
+	"io"
 	"io/ioutil"
 	"path/filepath"
 
 	"github.com/ethereum/go-ethereum/common"
 	"github.com/ethereum/go-ethereum/common/math"
 	"github.com/ethereum/go-ethereum/crypto"
-	"github.com/ethereum/go-ethereum/crypto/randentropy"
 	"github.com/pborman/uuid"
 	"golang.org/x/crypto/pbkdf2"
 	"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
 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
 }
 
@@ -116,7 +116,11 @@ func (ks keyStorePassphrase) JoinPath(filename string) string {
 // blob that can be decrypted later on.
 func EncryptKey(key *Key, auth string, scryptN, scryptP int) ([]byte, error) {
 	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)
 	if err != nil {
 		return nil, err
@@ -124,7 +128,10 @@ func EncryptKey(key *Key, auth string, scryptN, scryptP int) ([]byte, error) {
 	encryptKey := derivedKey[:16]
 	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)
 	if err != nil {
 		return nil, err

+ 0 - 42
crypto/randentropy/rand_entropy.go

@@ -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
-}

+ 32 - 11
crypto/secp256k1/curve.go

@@ -1,5 +1,6 @@
 // Copyright 2010 The Go Authors. 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
 // modification, are permitted provided that the following conditions are
@@ -35,8 +36,6 @@ import (
 	"crypto/elliptic"
 	"math/big"
 	"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"
 
+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
 // 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.
 	point := make([]byte, 64)
-	math.ReadBits(Bx, point[:32])
-	math.ReadBits(By, point[32:])
+	readBits(Bx, point[:32])
+	readBits(By, point[32:])
+
 	pointPtr := (*C.uchar)(unsafe.Pointer(&point[0]))
 	scalarPtr := (*C.uchar)(unsafe.Pointer(&scalar[0]))
 	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
 	ret := make([]byte, 1+2*byteLen)
 	ret[0] = 4 // uncompressed point flag
-	math.ReadBits(x, ret[1:1+byteLen])
-	math.ReadBits(y, ret[1+byteLen:])
+	readBits(x, ret[1:1+byteLen])
+	readBits(y, ret[1+byteLen:])
 	return ret
 }
 
@@ -290,11 +311,11 @@ func init() {
 	// See SEC 2 section 2.7.1
 	// curve parameters taken from:
 	// http://www.secg.org/collateral/sec2_final.pdf
-	theCurve.P = math.MustParseBig256("0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFEFFFFFC2F")
-	theCurve.N = math.MustParseBig256("0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFEBAAEDCE6AF48A03BBFD25E8CD0364141")
-	theCurve.B = math.MustParseBig256("0x0000000000000000000000000000000000000000000000000000000000000007")
-	theCurve.Gx = math.MustParseBig256("0x79BE667EF9DCBBAC55A06295CE870B07029BFCDB2DCE28D959F2815B16F81798")
-	theCurve.Gy = math.MustParseBig256("0x483ADA7726A3C4655DA4FBFC0E1108A8FD17B448A68554199C47D08FFB10D4B8")
+	theCurve.P, _ = new(big.Int).SetString("0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFEFFFFFC2F", 0)
+	theCurve.N, _ = new(big.Int).SetString("0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFEBAAEDCE6AF48A03BBFD25E8CD0364141", 0)
+	theCurve.B, _ = new(big.Int).SetString("0x0000000000000000000000000000000000000000000000000000000000000007", 0)
+	theCurve.Gx, _ = new(big.Int).SetString("0x79BE667EF9DCBBAC55A06295CE870B07029BFCDB2DCE28D959F2815B16F81798", 0)
+	theCurve.Gy, _ = new(big.Int).SetString("0x483ADA7726A3C4655DA4FBFC0E1108A8FD17B448A68554199C47D08FFB10D4B8", 0)
 	theCurve.BitSize = 256
 }
 

+ 25 - 14
crypto/secp256k1/secp256_test.go

@@ -10,10 +10,8 @@ import (
 	"crypto/elliptic"
 	"crypto/rand"
 	"encoding/hex"
+	"io"
 	"testing"
-
-	"github.com/ethereum/go-ethereum/common/math"
-	"github.com/ethereum/go-ethereum/crypto/randentropy"
 )
 
 const TestCount = 1000
@@ -24,11 +22,24 @@ func generateKeyPair() (pubkey, privkey []byte) {
 		panic(err)
 	}
 	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 {
-	sig := randentropy.GetEntropyCSPRNG(65)
+	sig := csprngEntropy(65)
 	sig[32] &= 0x70
 	sig[64] %= 4
 	return sig
@@ -51,7 +62,7 @@ func compactSigCheck(t *testing.T, sig []byte) {
 
 func TestSignatureValidity(t *testing.T) {
 	pubkey, seckey := generateKeyPair()
-	msg := randentropy.GetEntropyCSPRNG(32)
+	msg := csprngEntropy(32)
 	sig, err := Sign(msg, seckey)
 	if err != nil {
 		t.Errorf("signature error: %s", err)
@@ -74,7 +85,7 @@ func TestSignatureValidity(t *testing.T) {
 
 func TestInvalidRecoveryID(t *testing.T) {
 	_, seckey := generateKeyPair()
-	msg := randentropy.GetEntropyCSPRNG(32)
+	msg := csprngEntropy(32)
 	sig, _ := Sign(msg, seckey)
 	sig[64] = 99
 	_, err := RecoverPubkey(msg, sig)
@@ -85,7 +96,7 @@ func TestInvalidRecoveryID(t *testing.T) {
 
 func TestSignAndRecover(t *testing.T) {
 	pubkey1, seckey := generateKeyPair()
-	msg := randentropy.GetEntropyCSPRNG(32)
+	msg := csprngEntropy(32)
 	sig, err := Sign(msg, seckey)
 	if err != nil {
 		t.Errorf("signature error: %s", err)
@@ -136,7 +147,7 @@ func TestRandomMessagesWithRandomKeys(t *testing.T) {
 func signAndRecoverWithRandomMessages(t *testing.T, keys func() ([]byte, []byte)) {
 	for i := 0; i < TestCount; i++ {
 		pubkey1, seckey := keys()
-		msg := randentropy.GetEntropyCSPRNG(32)
+		msg := csprngEntropy(32)
 		sig, err := Sign(msg, seckey)
 		if err != nil {
 			t.Fatalf("signature error: %s", err)
@@ -164,7 +175,7 @@ func signAndRecoverWithRandomMessages(t *testing.T, keys func() ([]byte, []byte)
 
 func TestRecoveryOfRandomSignature(t *testing.T) {
 	pubkey1, _ := generateKeyPair()
-	msg := randentropy.GetEntropyCSPRNG(32)
+	msg := csprngEntropy(32)
 
 	for i := 0; i < TestCount; i++ {
 		// 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) {
 	pubkey1, seckey := generateKeyPair()
-	msg := randentropy.GetEntropyCSPRNG(32)
+	msg := csprngEntropy(32)
 	sig, _ := Sign(msg, seckey)
 
 	for i := 0; i < TestCount; i++ {
-		msg = randentropy.GetEntropyCSPRNG(32)
+		msg = csprngEntropy(32)
 		pubkey2, _ := RecoverPubkey(msg, sig)
 		// recovery can sometimes work, but if so should always give wrong pubkey
 		if bytes.Equal(pubkey1, pubkey2) {
@@ -207,7 +218,7 @@ func TestRecoverSanity(t *testing.T) {
 
 func BenchmarkSign(b *testing.B) {
 	_, seckey := generateKeyPair()
-	msg := randentropy.GetEntropyCSPRNG(32)
+	msg := csprngEntropy(32)
 	b.ResetTimer()
 
 	for i := 0; i < b.N; i++ {
@@ -216,7 +227,7 @@ func BenchmarkSign(b *testing.B) {
 }
 
 func BenchmarkRecover(b *testing.B) {
-	msg := randentropy.GetEntropyCSPRNG(32)
+	msg := csprngEntropy(32)
 	_, seckey := generateKeyPair()
 	sig, _ := Sign(msg, seckey)
 	b.ResetTimer()