mirror of
https://github.com/ethereum/go-ethereum.git
synced 2026-07-27 15:16:43 +00:00
crypto: add btcec fallback for sign/recover without cgo
This commit adds a non-cgo fallback implementation of secp256k1 operations.
This commit is contained in:
parent
a2715b6cfb
commit
34a257546c
17 changed files with 231 additions and 174 deletions
|
|
@ -32,7 +32,6 @@ import (
|
||||||
"github.com/ethereum/go-ethereum/accounts"
|
"github.com/ethereum/go-ethereum/accounts"
|
||||||
"github.com/ethereum/go-ethereum/common"
|
"github.com/ethereum/go-ethereum/common"
|
||||||
"github.com/ethereum/go-ethereum/crypto"
|
"github.com/ethereum/go-ethereum/crypto"
|
||||||
"github.com/ethereum/go-ethereum/crypto/secp256k1"
|
|
||||||
"github.com/pborman/uuid"
|
"github.com/pborman/uuid"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
|
@ -157,7 +156,7 @@ func NewKeyForDirectICAP(rand io.Reader) *Key {
|
||||||
panic("key generation: could not read from random source: " + err.Error())
|
panic("key generation: could not read from random source: " + err.Error())
|
||||||
}
|
}
|
||||||
reader := bytes.NewReader(randBytes)
|
reader := bytes.NewReader(randBytes)
|
||||||
privateKeyECDSA, err := ecdsa.GenerateKey(secp256k1.S256(), reader)
|
privateKeyECDSA, err := ecdsa.GenerateKey(crypto.S256(), reader)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
panic("key generation: ecdsa.GenerateKey failed: " + err.Error())
|
panic("key generation: ecdsa.GenerateKey failed: " + err.Error())
|
||||||
}
|
}
|
||||||
|
|
@ -169,7 +168,7 @@ func NewKeyForDirectICAP(rand io.Reader) *Key {
|
||||||
}
|
}
|
||||||
|
|
||||||
func newKey(rand io.Reader) (*Key, error) {
|
func newKey(rand io.Reader) (*Key, error) {
|
||||||
privateKeyECDSA, err := ecdsa.GenerateKey(secp256k1.S256(), rand)
|
privateKeyECDSA, err := ecdsa.GenerateKey(crypto.S256(), rand)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -21,23 +21,24 @@ import (
|
||||||
"crypto/elliptic"
|
"crypto/elliptic"
|
||||||
"crypto/rand"
|
"crypto/rand"
|
||||||
"crypto/sha256"
|
"crypto/sha256"
|
||||||
"fmt"
|
"encoding/hex"
|
||||||
|
"errors"
|
||||||
"io"
|
"io"
|
||||||
"io/ioutil"
|
"io/ioutil"
|
||||||
"math/big"
|
"math/big"
|
||||||
"os"
|
"os"
|
||||||
|
|
||||||
"encoding/hex"
|
|
||||||
"errors"
|
|
||||||
|
|
||||||
"github.com/ethereum/go-ethereum/common"
|
"github.com/ethereum/go-ethereum/common"
|
||||||
"github.com/ethereum/go-ethereum/crypto/ecies"
|
|
||||||
"github.com/ethereum/go-ethereum/crypto/secp256k1"
|
|
||||||
"github.com/ethereum/go-ethereum/crypto/sha3"
|
"github.com/ethereum/go-ethereum/crypto/sha3"
|
||||||
"github.com/ethereum/go-ethereum/rlp"
|
"github.com/ethereum/go-ethereum/rlp"
|
||||||
"golang.org/x/crypto/ripemd160"
|
"golang.org/x/crypto/ripemd160"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
var (
|
||||||
|
secp256k1_N, _ = new(big.Int).SetString("fffffffffffffffffffffffffffffffebaaedce6af48a03bbfd25e8cd0364141", 16)
|
||||||
|
secp256k1_halfN = new(big.Int).Div(secp256k1_N, big.NewInt(2))
|
||||||
|
)
|
||||||
|
|
||||||
func Keccak256(data ...[]byte) []byte {
|
func Keccak256(data ...[]byte) []byte {
|
||||||
d := sha3.NewKeccak256()
|
d := sha3.NewKeccak256()
|
||||||
for _, b := range data {
|
for _, b := range data {
|
||||||
|
|
@ -78,26 +79,16 @@ func Ripemd160(data []byte) []byte {
|
||||||
return ripemd.Sum(nil)
|
return ripemd.Sum(nil)
|
||||||
}
|
}
|
||||||
|
|
||||||
// Ecrecover returns the public key for the private key that was used to
|
// ToECDSA creates a private key with the given D value.
|
||||||
// calculate the signature.
|
|
||||||
//
|
|
||||||
// Note: secp256k1 expects the recover id to be either 0, 1. Ethereum
|
|
||||||
// signatures have a recover id with an offset of 27. Callers must take
|
|
||||||
// this into account and if "recovering" from an Ethereum signature adjust.
|
|
||||||
func Ecrecover(hash, sig []byte) ([]byte, error) {
|
|
||||||
return secp256k1.RecoverPubkey(hash, sig)
|
|
||||||
}
|
|
||||||
|
|
||||||
// New methods using proper ecdsa keys from the stdlib
|
|
||||||
func ToECDSA(prv []byte) *ecdsa.PrivateKey {
|
func ToECDSA(prv []byte) *ecdsa.PrivateKey {
|
||||||
if len(prv) == 0 {
|
if len(prv) == 0 {
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
priv := new(ecdsa.PrivateKey)
|
priv := new(ecdsa.PrivateKey)
|
||||||
priv.PublicKey.Curve = secp256k1.S256()
|
priv.PublicKey.Curve = S256()
|
||||||
priv.D = common.BigD(prv)
|
priv.D = common.BigD(prv)
|
||||||
priv.PublicKey.X, priv.PublicKey.Y = secp256k1.S256().ScalarBaseMult(prv)
|
priv.PublicKey.X, priv.PublicKey.Y = priv.PublicKey.Curve.ScalarBaseMult(prv)
|
||||||
return priv
|
return priv
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -112,15 +103,15 @@ func ToECDSAPub(pub []byte) *ecdsa.PublicKey {
|
||||||
if len(pub) == 0 {
|
if len(pub) == 0 {
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
x, y := elliptic.Unmarshal(secp256k1.S256(), pub)
|
x, y := elliptic.Unmarshal(S256(), pub)
|
||||||
return &ecdsa.PublicKey{Curve: secp256k1.S256(), X: x, Y: y}
|
return &ecdsa.PublicKey{Curve: S256(), X: x, Y: y}
|
||||||
}
|
}
|
||||||
|
|
||||||
func FromECDSAPub(pub *ecdsa.PublicKey) []byte {
|
func FromECDSAPub(pub *ecdsa.PublicKey) []byte {
|
||||||
if pub == nil || pub.X == nil || pub.Y == nil {
|
if pub == nil || pub.X == nil || pub.Y == nil {
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
return elliptic.Marshal(secp256k1.S256(), pub.X, pub.Y)
|
return elliptic.Marshal(S256(), pub.X, pub.Y)
|
||||||
}
|
}
|
||||||
|
|
||||||
// HexToECDSA parses a secp256k1 private key.
|
// HexToECDSA parses a secp256k1 private key.
|
||||||
|
|
@ -164,7 +155,7 @@ func SaveECDSA(file string, key *ecdsa.PrivateKey) error {
|
||||||
}
|
}
|
||||||
|
|
||||||
func GenerateKey() (*ecdsa.PrivateKey, error) {
|
func GenerateKey() (*ecdsa.PrivateKey, error) {
|
||||||
return ecdsa.GenerateKey(secp256k1.S256(), rand.Reader)
|
return ecdsa.GenerateKey(S256(), rand.Reader)
|
||||||
}
|
}
|
||||||
|
|
||||||
// ValidateSignatureValues verifies whether the signature values are valid with
|
// ValidateSignatureValues verifies whether the signature values are valid with
|
||||||
|
|
@ -175,49 +166,11 @@ func ValidateSignatureValues(v byte, r, s *big.Int, homestead bool) bool {
|
||||||
}
|
}
|
||||||
// reject upper range of s values (ECDSA malleability)
|
// reject upper range of s values (ECDSA malleability)
|
||||||
// see discussion in secp256k1/libsecp256k1/include/secp256k1.h
|
// see discussion in secp256k1/libsecp256k1/include/secp256k1.h
|
||||||
if homestead && s.Cmp(secp256k1.HalfN) > 0 {
|
if homestead && s.Cmp(secp256k1_halfN) > 0 {
|
||||||
return false
|
return false
|
||||||
}
|
}
|
||||||
// Frontier: allow s to be in full N range
|
// Frontier: allow s to be in full N range
|
||||||
return r.Cmp(secp256k1.N) < 0 && s.Cmp(secp256k1.N) < 0 && (v == 0 || v == 1)
|
return r.Cmp(secp256k1_N) < 0 && s.Cmp(secp256k1_N) < 0 && (v == 0 || v == 1)
|
||||||
}
|
|
||||||
|
|
||||||
func SigToPub(hash, sig []byte) (*ecdsa.PublicKey, error) {
|
|
||||||
s, err := Ecrecover(hash, sig)
|
|
||||||
if err != nil {
|
|
||||||
return nil, err
|
|
||||||
}
|
|
||||||
|
|
||||||
x, y := elliptic.Unmarshal(secp256k1.S256(), s)
|
|
||||||
return &ecdsa.PublicKey{Curve: secp256k1.S256(), X: x, Y: y}, nil
|
|
||||||
}
|
|
||||||
|
|
||||||
// Sign calculates an ECDSA signature.
|
|
||||||
//
|
|
||||||
// This function is susceptible to chosen plaintext attacks that can leak
|
|
||||||
// information about the private key that is used for signing. Callers must
|
|
||||||
// be aware that the given hash cannot be chosen by an adversery. Common
|
|
||||||
// solution is to hash any input before calculating the signature.
|
|
||||||
//
|
|
||||||
// The produced signature is in the [R || S || V] format where V is 0 or 1.
|
|
||||||
func Sign(data []byte, prv *ecdsa.PrivateKey) (sig []byte, err error) {
|
|
||||||
if len(data) != 32 {
|
|
||||||
return nil, fmt.Errorf("hash is required to be exactly 32 bytes (%d)", len(data))
|
|
||||||
}
|
|
||||||
|
|
||||||
seckey := common.LeftPadBytes(prv.D.Bytes(), prv.Params().BitSize/8)
|
|
||||||
defer zeroBytes(seckey)
|
|
||||||
sig, err = secp256k1.Sign(data, seckey)
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
func Encrypt(pub *ecdsa.PublicKey, message []byte) ([]byte, error) {
|
|
||||||
return ecies.Encrypt(rand.Reader, ecies.ImportECDSAPublic(pub), message, nil, nil)
|
|
||||||
}
|
|
||||||
|
|
||||||
func Decrypt(prv *ecdsa.PrivateKey, ct []byte) ([]byte, error) {
|
|
||||||
key := ecies.ImportECDSA(prv)
|
|
||||||
return key.Decrypt(rand.Reader, ct, nil, nil)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
func PubkeyToAddress(p ecdsa.PublicKey) common.Address {
|
func PubkeyToAddress(p ecdsa.PublicKey) common.Address {
|
||||||
|
|
|
||||||
|
|
@ -170,7 +170,7 @@ func TestValidateSignatureValues(t *testing.T) {
|
||||||
minusOne := big.NewInt(-1)
|
minusOne := big.NewInt(-1)
|
||||||
one := common.Big1
|
one := common.Big1
|
||||||
zero := common.Big0
|
zero := common.Big0
|
||||||
secp256k1nMinus1 := new(big.Int).Sub(secp256k1.N, common.Big1)
|
secp256k1nMinus1 := new(big.Int).Sub(secp256k1_N, common.Big1)
|
||||||
|
|
||||||
// correct v,r,s
|
// correct v,r,s
|
||||||
check(true, 0, one, one)
|
check(true, 0, one, one)
|
||||||
|
|
@ -197,9 +197,9 @@ func TestValidateSignatureValues(t *testing.T) {
|
||||||
// correct sig with max r,s
|
// correct sig with max r,s
|
||||||
check(true, 0, secp256k1nMinus1, secp256k1nMinus1)
|
check(true, 0, secp256k1nMinus1, secp256k1nMinus1)
|
||||||
// correct v, combinations of incorrect r,s at upper limit
|
// correct v, combinations of incorrect r,s at upper limit
|
||||||
check(false, 0, secp256k1.N, secp256k1nMinus1)
|
check(false, 0, secp256k1_N, secp256k1nMinus1)
|
||||||
check(false, 0, secp256k1nMinus1, secp256k1.N)
|
check(false, 0, secp256k1nMinus1, secp256k1_N)
|
||||||
check(false, 0, secp256k1.N, secp256k1.N)
|
check(false, 0, secp256k1_N, secp256k1_N)
|
||||||
|
|
||||||
// current callers ensures r,s cannot be negative, but let's test for that too
|
// current callers ensures r,s cannot be negative, but let's test for that too
|
||||||
// as crypto package could be used stand-alone
|
// as crypto package could be used stand-alone
|
||||||
|
|
|
||||||
|
|
@ -42,7 +42,7 @@ import (
|
||||||
"hash"
|
"hash"
|
||||||
"math/big"
|
"math/big"
|
||||||
|
|
||||||
"github.com/ethereum/go-ethereum/crypto/secp256k1"
|
ethcrypto "github.com/ethereum/go-ethereum/crypto"
|
||||||
)
|
)
|
||||||
|
|
||||||
var (
|
var (
|
||||||
|
|
@ -120,7 +120,7 @@ func (curve secgNamedCurve) Equal(curve2 secgNamedCurve) bool {
|
||||||
func namedCurveFromOID(curve secgNamedCurve) elliptic.Curve {
|
func namedCurveFromOID(curve secgNamedCurve) elliptic.Curve {
|
||||||
switch {
|
switch {
|
||||||
case curve.Equal(secgNamedCurveS256):
|
case curve.Equal(secgNamedCurveS256):
|
||||||
return secp256k1.S256()
|
return ethcrypto.S256()
|
||||||
case curve.Equal(secgNamedCurveP256):
|
case curve.Equal(secgNamedCurveP256):
|
||||||
return elliptic.P256()
|
return elliptic.P256()
|
||||||
case curve.Equal(secgNamedCurveP384):
|
case curve.Equal(secgNamedCurveP384):
|
||||||
|
|
@ -139,7 +139,7 @@ func oidFromNamedCurve(curve elliptic.Curve) (secgNamedCurve, bool) {
|
||||||
return secgNamedCurveP384, true
|
return secgNamedCurveP384, true
|
||||||
case elliptic.P521():
|
case elliptic.P521():
|
||||||
return secgNamedCurveP521, true
|
return secgNamedCurveP521, true
|
||||||
case secp256k1.S256():
|
case ethcrypto.S256():
|
||||||
return secgNamedCurveS256, true
|
return secgNamedCurveS256, true
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -31,7 +31,6 @@ package ecies
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"bytes"
|
"bytes"
|
||||||
"crypto/ecdsa"
|
|
||||||
"crypto/elliptic"
|
"crypto/elliptic"
|
||||||
"crypto/rand"
|
"crypto/rand"
|
||||||
"crypto/sha256"
|
"crypto/sha256"
|
||||||
|
|
@ -42,7 +41,7 @@ import (
|
||||||
"math/big"
|
"math/big"
|
||||||
"testing"
|
"testing"
|
||||||
|
|
||||||
"github.com/ethereum/go-ethereum/crypto/secp256k1"
|
"github.com/ethereum/go-ethereum/crypto"
|
||||||
)
|
)
|
||||||
|
|
||||||
var dumpEnc bool
|
var dumpEnc bool
|
||||||
|
|
@ -150,7 +149,7 @@ func TestSharedKey(t *testing.T) {
|
||||||
func TestSharedKeyPadding(t *testing.T) {
|
func TestSharedKeyPadding(t *testing.T) {
|
||||||
// sanity checks
|
// sanity checks
|
||||||
prv0 := hexKey("1adf5c18167d96a1f9a0b1ef63be8aa27eaf6032c233b2b38f7850cf5b859fd9")
|
prv0 := hexKey("1adf5c18167d96a1f9a0b1ef63be8aa27eaf6032c233b2b38f7850cf5b859fd9")
|
||||||
prv1 := hexKey("97a076fc7fcd9208240668e31c9abee952cbb6e375d1b8febc7499d6e16f1a")
|
prv1 := hexKey("0097a076fc7fcd9208240668e31c9abee952cbb6e375d1b8febc7499d6e16f1a")
|
||||||
x0, _ := new(big.Int).SetString("1a8ed022ff7aec59dc1b440446bdda5ff6bcb3509a8b109077282b361efffbd8", 16)
|
x0, _ := new(big.Int).SetString("1a8ed022ff7aec59dc1b440446bdda5ff6bcb3509a8b109077282b361efffbd8", 16)
|
||||||
x1, _ := new(big.Int).SetString("6ab3ac374251f638d0abb3ef596d1dc67955b507c104e5f2009724812dc027b8", 16)
|
x1, _ := new(big.Int).SetString("6ab3ac374251f638d0abb3ef596d1dc67955b507c104e5f2009724812dc027b8", 16)
|
||||||
y0, _ := new(big.Int).SetString("e040bd480b1deccc3bc40bd5b1fdcb7bfd352500b477cb9471366dbd4493f923", 16)
|
y0, _ := new(big.Int).SetString("e040bd480b1deccc3bc40bd5b1fdcb7bfd352500b477cb9471366dbd4493f923", 16)
|
||||||
|
|
@ -354,7 +353,7 @@ func BenchmarkGenSharedKeyP256(b *testing.B) {
|
||||||
|
|
||||||
// Benchmark the generation of S256 shared keys.
|
// Benchmark the generation of S256 shared keys.
|
||||||
func BenchmarkGenSharedKeyS256(b *testing.B) {
|
func BenchmarkGenSharedKeyS256(b *testing.B) {
|
||||||
prv, err := GenerateKey(rand.Reader, secp256k1.S256(), nil)
|
prv, err := GenerateKey(rand.Reader, crypto.S256(), nil)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
fmt.Println(err.Error())
|
fmt.Println(err.Error())
|
||||||
b.FailNow()
|
b.FailNow()
|
||||||
|
|
@ -597,6 +596,29 @@ func TestBasicKeyValidation(t *testing.T) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func TestBox(t *testing.T) {
|
||||||
|
prv1 := hexKey("4b50fa71f5c3eeb8fdc452224b2395af2fcc3d125e06c32c82e048c0559db03f")
|
||||||
|
prv2 := hexKey("d0b043b4c5d657670778242d82d68a29d25d7d711127d17b8e299f156dad361a")
|
||||||
|
pub2 := &prv2.PublicKey
|
||||||
|
|
||||||
|
message := []byte("Hello, world.")
|
||||||
|
ct, err := Encrypt(rand.Reader, pub2, message, nil, nil)
|
||||||
|
if err != nil {
|
||||||
|
t.Fatal(err)
|
||||||
|
}
|
||||||
|
|
||||||
|
pt, err := prv2.Decrypt(rand.Reader, ct, nil, nil)
|
||||||
|
if err != nil {
|
||||||
|
t.Fatal(err)
|
||||||
|
}
|
||||||
|
if !bytes.Equal(pt, message) {
|
||||||
|
t.Fatal("ecies: plaintext doesn't match message")
|
||||||
|
}
|
||||||
|
if _, err = prv1.Decrypt(rand.Reader, ct, nil, nil); err == nil {
|
||||||
|
t.Fatal("ecies: encryption should not have succeeded")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// Verify GenerateShared against static values - useful when
|
// Verify GenerateShared against static values - useful when
|
||||||
// debugging changes in underlying libs
|
// debugging changes in underlying libs
|
||||||
func TestSharedKeyStatic(t *testing.T) {
|
func TestSharedKeyStatic(t *testing.T) {
|
||||||
|
|
@ -628,11 +650,10 @@ func TestSharedKeyStatic(t *testing.T) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// TODO: remove after refactoring packages crypto and crypto/ecies
|
|
||||||
func hexKey(prv string) *PrivateKey {
|
func hexKey(prv string) *PrivateKey {
|
||||||
priv := new(ecdsa.PrivateKey)
|
key, err := crypto.HexToECDSA(prv)
|
||||||
priv.PublicKey.Curve = secp256k1.S256()
|
if err != nil {
|
||||||
priv.D, _ = new(big.Int).SetString(prv, 16)
|
panic(err)
|
||||||
priv.PublicKey.X, priv.PublicKey.Y = secp256k1.S256().ScalarBaseMult(priv.D.Bytes())
|
}
|
||||||
return ImportECDSA(priv)
|
return ImportECDSA(key)
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -42,11 +42,11 @@ import (
|
||||||
"fmt"
|
"fmt"
|
||||||
"hash"
|
"hash"
|
||||||
|
|
||||||
"github.com/ethereum/go-ethereum/crypto/secp256k1"
|
ethcrypto "github.com/ethereum/go-ethereum/crypto"
|
||||||
)
|
)
|
||||||
|
|
||||||
var (
|
var (
|
||||||
DefaultCurve = secp256k1.S256()
|
DefaultCurve = ethcrypto.S256()
|
||||||
ErrUnsupportedECDHAlgorithm = fmt.Errorf("ecies: unsupported ECDH algorithm")
|
ErrUnsupportedECDHAlgorithm = fmt.Errorf("ecies: unsupported ECDH algorithm")
|
||||||
ErrUnsupportedECIESParameters = fmt.Errorf("ecies: unsupported ECIES parameters")
|
ErrUnsupportedECIESParameters = fmt.Errorf("ecies: unsupported ECIES parameters")
|
||||||
)
|
)
|
||||||
|
|
@ -100,7 +100,7 @@ var (
|
||||||
)
|
)
|
||||||
|
|
||||||
var paramsFromCurve = map[elliptic.Curve]*ECIESParams{
|
var paramsFromCurve = map[elliptic.Curve]*ECIESParams{
|
||||||
secp256k1.S256(): ECIES_AES128_SHA256,
|
ethcrypto.S256(): ECIES_AES128_SHA256,
|
||||||
elliptic.P256(): ECIES_AES128_SHA256,
|
elliptic.P256(): ECIES_AES128_SHA256,
|
||||||
elliptic.P384(): ECIES_AES256_SHA384,
|
elliptic.P384(): ECIES_AES256_SHA384,
|
||||||
elliptic.P521(): ECIES_AES256_SHA512,
|
elliptic.P521(): ECIES_AES256_SHA512,
|
||||||
|
|
|
||||||
|
|
@ -1,56 +0,0 @@
|
||||||
// Copyright 2014 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 crypto
|
|
||||||
|
|
||||||
import (
|
|
||||||
"bytes"
|
|
||||||
"fmt"
|
|
||||||
"testing"
|
|
||||||
|
|
||||||
"github.com/ethereum/go-ethereum/common"
|
|
||||||
)
|
|
||||||
|
|
||||||
func TestBox(t *testing.T) {
|
|
||||||
prv1 := ToECDSA(common.Hex2Bytes("4b50fa71f5c3eeb8fdc452224b2395af2fcc3d125e06c32c82e048c0559db03f"))
|
|
||||||
prv2 := ToECDSA(common.Hex2Bytes("d0b043b4c5d657670778242d82d68a29d25d7d711127d17b8e299f156dad361a"))
|
|
||||||
pub2 := ToECDSAPub(common.Hex2Bytes("04bd27a63c91fe3233c5777e6d3d7b39204d398c8f92655947eb5a373d46e1688f022a1632d264725cbc7dc43ee1cfebde42fa0a86d08b55d2acfbb5e9b3b48dc5"))
|
|
||||||
|
|
||||||
message := []byte("Hello, world.")
|
|
||||||
ct, err := Encrypt(pub2, message)
|
|
||||||
if err != nil {
|
|
||||||
fmt.Println(err.Error())
|
|
||||||
t.FailNow()
|
|
||||||
}
|
|
||||||
|
|
||||||
pt, err := Decrypt(prv2, ct)
|
|
||||||
if err != nil {
|
|
||||||
fmt.Println(err.Error())
|
|
||||||
t.FailNow()
|
|
||||||
}
|
|
||||||
|
|
||||||
if !bytes.Equal(pt, message) {
|
|
||||||
fmt.Println("ecies: plaintext doesn't match message")
|
|
||||||
t.FailNow()
|
|
||||||
}
|
|
||||||
|
|
||||||
_, err = Decrypt(prv1, pt)
|
|
||||||
if err == nil {
|
|
||||||
fmt.Println("ecies: encryption should not have succeeded")
|
|
||||||
t.FailNow()
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
@ -42,17 +42,9 @@ import (
|
||||||
"unsafe"
|
"unsafe"
|
||||||
)
|
)
|
||||||
|
|
||||||
var (
|
var context *C.secp256k1_context
|
||||||
context *C.secp256k1_context
|
|
||||||
N *big.Int
|
|
||||||
HalfN *big.Int
|
|
||||||
)
|
|
||||||
|
|
||||||
func init() {
|
func init() {
|
||||||
N, _ = new(big.Int).SetString("fffffffffffffffffffffffffffffffebaaedce6af48a03bbfd25e8cd0364141", 16)
|
|
||||||
// N / 2 == 57896044618658097711785492504343953926418782139537452191302581570759080747168
|
|
||||||
HalfN, _ = new(big.Int).SetString("7fffffffffffffffffffffffffffffff5d576e7357a4501ddfe92f46681b20a0", 16)
|
|
||||||
|
|
||||||
// around 20 ms on a modern CPU.
|
// around 20 ms on a modern CPU.
|
||||||
context = C.secp256k1_context_create_sign_verify()
|
context = C.secp256k1_context_create_sign_verify()
|
||||||
C.secp256k1_context_set_illegal_callback(context, C.callbackFunc(C.secp256k1GoPanicIllegal), nil)
|
C.secp256k1_context_set_illegal_callback(context, C.callbackFunc(C.secp256k1GoPanicIllegal), nil)
|
||||||
|
|
|
||||||
64
crypto/signature_cgo.go
Normal file
64
crypto/signature_cgo.go
Normal file
|
|
@ -0,0 +1,64 @@
|
||||||
|
// Copyright 2016 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/>.
|
||||||
|
|
||||||
|
// +build !nacl,!js,!nocgo
|
||||||
|
|
||||||
|
package crypto
|
||||||
|
|
||||||
|
import (
|
||||||
|
"crypto/ecdsa"
|
||||||
|
"crypto/elliptic"
|
||||||
|
"fmt"
|
||||||
|
|
||||||
|
"github.com/ethereum/go-ethereum/common"
|
||||||
|
"github.com/ethereum/go-ethereum/crypto/secp256k1"
|
||||||
|
)
|
||||||
|
|
||||||
|
func Ecrecover(hash, sig []byte) ([]byte, error) {
|
||||||
|
return secp256k1.RecoverPubkey(hash, sig)
|
||||||
|
}
|
||||||
|
|
||||||
|
func SigToPub(hash, sig []byte) (*ecdsa.PublicKey, error) {
|
||||||
|
s, err := Ecrecover(hash, sig)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
|
||||||
|
x, y := elliptic.Unmarshal(S256(), s)
|
||||||
|
return &ecdsa.PublicKey{Curve: S256(), X: x, Y: y}, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// Sign calculates an ECDSA signature.
|
||||||
|
//
|
||||||
|
// This function is susceptible to chosen plaintext attacks that can leak
|
||||||
|
// information about the private key that is used for signing. Callers must
|
||||||
|
// be aware that the given hash cannot be chosen by an adversery. Common
|
||||||
|
// solution is to hash any input before calculating the signature.
|
||||||
|
//
|
||||||
|
// The produced signature is in the [R || S || V] format where V is 0 or 1.
|
||||||
|
func Sign(hash []byte, prv *ecdsa.PrivateKey) (sig []byte, err error) {
|
||||||
|
if len(hash) != 32 {
|
||||||
|
return nil, fmt.Errorf("hash is required to be exactly 32 bytes (%d)", len(hash))
|
||||||
|
}
|
||||||
|
seckey := common.LeftPadBytes(prv.D.Bytes(), prv.Params().BitSize/8)
|
||||||
|
defer zeroBytes(seckey)
|
||||||
|
return secp256k1.Sign(hash, seckey)
|
||||||
|
}
|
||||||
|
|
||||||
|
// S256 returns an instance of the secp256k1 curve.
|
||||||
|
func S256() elliptic.Curve {
|
||||||
|
return secp256k1.S256()
|
||||||
|
}
|
||||||
77
crypto/signature_nocgo.go
Normal file
77
crypto/signature_nocgo.go
Normal file
|
|
@ -0,0 +1,77 @@
|
||||||
|
// Copyright 2016 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/>.
|
||||||
|
|
||||||
|
// +build nacl js nocgo
|
||||||
|
|
||||||
|
package crypto
|
||||||
|
|
||||||
|
import (
|
||||||
|
"crypto/ecdsa"
|
||||||
|
"crypto/elliptic"
|
||||||
|
"fmt"
|
||||||
|
|
||||||
|
"github.com/btcsuite/btcd/btcec"
|
||||||
|
)
|
||||||
|
|
||||||
|
func Ecrecover(hash, sig []byte) ([]byte, error) {
|
||||||
|
pub, err := SigToPub(hash, sig)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
bytes := (*btcec.PublicKey)(pub).SerializeUncompressed()
|
||||||
|
return bytes, err
|
||||||
|
}
|
||||||
|
|
||||||
|
func SigToPub(hash, sig []byte) (*ecdsa.PublicKey, error) {
|
||||||
|
// Convert to btcec input format with 'recovery id' v at the beginning.
|
||||||
|
btcsig := make([]byte, 65)
|
||||||
|
btcsig[0] = sig[64] + 27
|
||||||
|
copy(btcsig[1:], sig)
|
||||||
|
|
||||||
|
pub, _, err := btcec.RecoverCompact(btcec.S256(), btcsig, hash)
|
||||||
|
return (*ecdsa.PublicKey)(pub), err
|
||||||
|
}
|
||||||
|
|
||||||
|
// Sign calculates an ECDSA signature.
|
||||||
|
//
|
||||||
|
// This function is susceptible to chosen plaintext attacks that can leak
|
||||||
|
// information about the private key that is used for signing. Callers must
|
||||||
|
// be aware that the given hash cannot be chosen by an adversery. Common
|
||||||
|
// solution is to hash any input before calculating the signature.
|
||||||
|
//
|
||||||
|
// The produced signature is in the [R || S || V] format where V is 0 or 1.
|
||||||
|
func Sign(hash []byte, prv *ecdsa.PrivateKey) ([]byte, error) {
|
||||||
|
if len(hash) != 32 {
|
||||||
|
return nil, fmt.Errorf("hash is required to be exactly 32 bytes (%d)", len(hash))
|
||||||
|
}
|
||||||
|
if prv.Curve != btcec.S256() {
|
||||||
|
return nil, fmt.Errorf("private key curve is not secp256k1")
|
||||||
|
}
|
||||||
|
sig, err := btcec.SignCompact(btcec.S256(), (*btcec.PrivateKey)(prv), hash, false)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
// Convert to Ethereum signature format with 'recovery id' v at the end.
|
||||||
|
v := sig[0] - 27
|
||||||
|
copy(sig, sig[1:])
|
||||||
|
sig[64] = v
|
||||||
|
return sig, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// S256 returns an instance of the secp256k1 curve.
|
||||||
|
func S256() elliptic.Curve {
|
||||||
|
return btcec.S256()
|
||||||
|
}
|
||||||
|
|
@ -14,18 +14,23 @@
|
||||||
// You should have received a copy of the GNU Lesser General Public License
|
// 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/>.
|
// along with the go-ethereum library. If not, see <http://www.gnu.org/licenses/>.
|
||||||
|
|
||||||
package discv5
|
package crypto
|
||||||
|
|
||||||
import (
|
import (
|
||||||
//"github.com/btcsuite/btcd/btcec"
|
"bytes"
|
||||||
"github.com/ethereum/go-ethereum/crypto/secp256k1"
|
"encoding/hex"
|
||||||
|
"testing"
|
||||||
)
|
)
|
||||||
|
|
||||||
func S256() *secp256k1.BitCurve {
|
func TestRecoverSanity(t *testing.T) {
|
||||||
return secp256k1.S256()
|
msg, _ := hex.DecodeString("ce0677bb30baa8cf067c88db9811f4333d131bf8bcf12fe7065d211dce971008")
|
||||||
|
sig, _ := hex.DecodeString("90f27b8b488db00b00606796d2987f6a5f59ae62ea05effe84fef5b8b0e549984a691139ad57a3f0b906637673aa2f63d1f55cb1a69199d4009eea23ceaddc9301")
|
||||||
|
pubkey1, _ := hex.DecodeString("04e32df42865e97135acfb65f3bae71bdc86f4d49150ad6a440b6f15878109880a0a2b2667f7e725ceea70c673093bf67663e0312623c8e091b13cf2c0f11ef652")
|
||||||
|
pubkey2, err := Ecrecover(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)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// This version should be used for NaCl compilation
|
|
||||||
/*func S256() *btcec.KoblitzCurve {
|
|
||||||
return S256()
|
|
||||||
}*/
|
|
||||||
|
|
@ -259,7 +259,7 @@ func PubkeyID(pub *ecdsa.PublicKey) NodeID {
|
||||||
// Pubkey returns the public key represented by the node ID.
|
// Pubkey returns the public key represented by the node ID.
|
||||||
// It returns an error if the ID is not a point on the curve.
|
// It returns an error if the ID is not a point on the curve.
|
||||||
func (id NodeID) Pubkey() (*ecdsa.PublicKey, error) {
|
func (id NodeID) Pubkey() (*ecdsa.PublicKey, error) {
|
||||||
p := &ecdsa.PublicKey{Curve: secp256k1.S256(), X: new(big.Int), Y: new(big.Int)}
|
p := &ecdsa.PublicKey{Curve: crypto.S256(), X: new(big.Int), Y: new(big.Int)}
|
||||||
half := len(id) / 2
|
half := len(id) / 2
|
||||||
p.X.SetBytes(id[:half])
|
p.X.SetBytes(id[:half])
|
||||||
p.Y.SetBytes(id[half:])
|
p.Y.SetBytes(id[half:])
|
||||||
|
|
|
||||||
|
|
@ -297,7 +297,7 @@ func PubkeyID(pub *ecdsa.PublicKey) NodeID {
|
||||||
// Pubkey returns the public key represented by the node ID.
|
// Pubkey returns the public key represented by the node ID.
|
||||||
// It returns an error if the ID is not a point on the curve.
|
// It returns an error if the ID is not a point on the curve.
|
||||||
func (id NodeID) Pubkey() (*ecdsa.PublicKey, error) {
|
func (id NodeID) Pubkey() (*ecdsa.PublicKey, error) {
|
||||||
p := &ecdsa.PublicKey{Curve: S256(), X: new(big.Int), Y: new(big.Int)}
|
p := &ecdsa.PublicKey{Curve: crypto.S256(), X: new(big.Int), Y: new(big.Int)}
|
||||||
half := len(id) / 2
|
half := len(id) / 2
|
||||||
p.X.SetBytes(id[:half])
|
p.X.SetBytes(id[:half])
|
||||||
p.Y.SetBytes(id[half:])
|
p.Y.SetBytes(id[half:])
|
||||||
|
|
|
||||||
|
|
@ -303,7 +303,7 @@ func (h *encHandshake) makeAuthMsg(prv *ecdsa.PrivateKey, token []byte) (*authMs
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
// Generate random keypair to for ECDH.
|
// Generate random keypair to for ECDH.
|
||||||
h.randomPrivKey, err = ecies.GenerateKey(rand.Reader, secp256k1.S256(), nil)
|
h.randomPrivKey, err = ecies.GenerateKey(rand.Reader, crypto.S256(), nil)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
|
|
@ -381,7 +381,7 @@ func (h *encHandshake) handleAuthMsg(msg *authMsgV4, prv *ecdsa.PrivateKey) erro
|
||||||
// Generate random keypair for ECDH.
|
// Generate random keypair for ECDH.
|
||||||
// If a private key is already set, use it instead of generating one (for testing).
|
// If a private key is already set, use it instead of generating one (for testing).
|
||||||
if h.randomPrivKey == nil {
|
if h.randomPrivKey == nil {
|
||||||
h.randomPrivKey, err = ecies.GenerateKey(rand.Reader, secp256k1.S256(), nil)
|
h.randomPrivKey, err = ecies.GenerateKey(rand.Reader, crypto.S256(), nil)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -21,11 +21,13 @@ package whisperv2
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"crypto/ecdsa"
|
"crypto/ecdsa"
|
||||||
|
crand "crypto/rand"
|
||||||
"math/rand"
|
"math/rand"
|
||||||
"time"
|
"time"
|
||||||
|
|
||||||
"github.com/ethereum/go-ethereum/common"
|
"github.com/ethereum/go-ethereum/common"
|
||||||
"github.com/ethereum/go-ethereum/crypto"
|
"github.com/ethereum/go-ethereum/crypto"
|
||||||
|
"github.com/ethereum/go-ethereum/crypto/ecies"
|
||||||
"github.com/ethereum/go-ethereum/logger"
|
"github.com/ethereum/go-ethereum/logger"
|
||||||
"github.com/ethereum/go-ethereum/logger/glog"
|
"github.com/ethereum/go-ethereum/logger/glog"
|
||||||
)
|
)
|
||||||
|
|
@ -131,13 +133,13 @@ func (self *Message) Recover() *ecdsa.PublicKey {
|
||||||
|
|
||||||
// encrypt encrypts a message payload with a public key.
|
// encrypt encrypts a message payload with a public key.
|
||||||
func (self *Message) encrypt(key *ecdsa.PublicKey) (err error) {
|
func (self *Message) encrypt(key *ecdsa.PublicKey) (err error) {
|
||||||
self.Payload, err = crypto.Encrypt(key, self.Payload)
|
self.Payload, err = ecies.Encrypt(crand.Reader, ecies.ImportECDSAPublic(key), self.Payload, nil, nil)
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
// decrypt decrypts an encrypted payload with a private key.
|
// decrypt decrypts an encrypted payload with a private key.
|
||||||
func (self *Message) decrypt(key *ecdsa.PrivateKey) error {
|
func (self *Message) decrypt(key *ecdsa.PrivateKey) error {
|
||||||
cleartext, err := crypto.Decrypt(key, self.Payload)
|
cleartext, err := ecies.ImportECDSA(key).Decrypt(crand.Reader, self.Payload, nil, nil)
|
||||||
if err == nil {
|
if err == nil {
|
||||||
self.Payload = cleartext
|
self.Payload = cleartext
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -23,7 +23,6 @@ import (
|
||||||
"time"
|
"time"
|
||||||
|
|
||||||
"github.com/ethereum/go-ethereum/crypto"
|
"github.com/ethereum/go-ethereum/crypto"
|
||||||
"github.com/ethereum/go-ethereum/crypto/secp256k1"
|
|
||||||
)
|
)
|
||||||
|
|
||||||
// Tests whether a message can be wrapped without any identity or encryption.
|
// Tests whether a message can be wrapped without any identity or encryption.
|
||||||
|
|
@ -73,8 +72,8 @@ func TestMessageCleartextSignRecover(t *testing.T) {
|
||||||
if pubKey == nil {
|
if pubKey == nil {
|
||||||
t.Fatalf("failed to recover public key")
|
t.Fatalf("failed to recover public key")
|
||||||
}
|
}
|
||||||
p1 := elliptic.Marshal(secp256k1.S256(), key.PublicKey.X, key.PublicKey.Y)
|
p1 := elliptic.Marshal(crypto.S256(), key.PublicKey.X, key.PublicKey.Y)
|
||||||
p2 := elliptic.Marshal(secp256k1.S256(), pubKey.X, pubKey.Y)
|
p2 := elliptic.Marshal(crypto.S256(), pubKey.X, pubKey.Y)
|
||||||
if !bytes.Equal(p1, p2) {
|
if !bytes.Equal(p1, p2) {
|
||||||
t.Fatalf("public key mismatch: have 0x%x, want 0x%x", p2, p1)
|
t.Fatalf("public key mismatch: have 0x%x, want 0x%x", p2, p1)
|
||||||
}
|
}
|
||||||
|
|
@ -151,8 +150,8 @@ func TestMessageFullCrypto(t *testing.T) {
|
||||||
if pubKey == nil {
|
if pubKey == nil {
|
||||||
t.Fatalf("failed to recover public key")
|
t.Fatalf("failed to recover public key")
|
||||||
}
|
}
|
||||||
p1 := elliptic.Marshal(secp256k1.S256(), fromKey.PublicKey.X, fromKey.PublicKey.Y)
|
p1 := elliptic.Marshal(crypto.S256(), fromKey.PublicKey.X, fromKey.PublicKey.Y)
|
||||||
p2 := elliptic.Marshal(secp256k1.S256(), pubKey.X, pubKey.Y)
|
p2 := elliptic.Marshal(crypto.S256(), pubKey.X, pubKey.Y)
|
||||||
if !bytes.Equal(p1, p2) {
|
if !bytes.Equal(p1, p2) {
|
||||||
t.Fatalf("public key mismatch: have 0x%x, want 0x%x", p2, p1)
|
t.Fatalf("public key mismatch: have 0x%x, want 0x%x", p2, p1)
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -30,6 +30,7 @@ import (
|
||||||
|
|
||||||
"github.com/ethereum/go-ethereum/common"
|
"github.com/ethereum/go-ethereum/common"
|
||||||
"github.com/ethereum/go-ethereum/crypto"
|
"github.com/ethereum/go-ethereum/crypto"
|
||||||
|
"github.com/ethereum/go-ethereum/crypto/ecies"
|
||||||
"github.com/ethereum/go-ethereum/logger"
|
"github.com/ethereum/go-ethereum/logger"
|
||||||
"github.com/ethereum/go-ethereum/logger/glog"
|
"github.com/ethereum/go-ethereum/logger/glog"
|
||||||
"golang.org/x/crypto/pbkdf2"
|
"golang.org/x/crypto/pbkdf2"
|
||||||
|
|
@ -163,7 +164,7 @@ func (msg *SentMessage) encryptAsymmetric(key *ecdsa.PublicKey) error {
|
||||||
if !ValidatePublicKey(key) {
|
if !ValidatePublicKey(key) {
|
||||||
return fmt.Errorf("Invalid public key provided for asymmetric encryption")
|
return fmt.Errorf("Invalid public key provided for asymmetric encryption")
|
||||||
}
|
}
|
||||||
encrypted, err := crypto.Encrypt(key, msg.Raw)
|
encrypted, err := ecies.Encrypt(crand.Reader, ecies.ImportECDSAPublic(key), msg.Raw, nil, nil)
|
||||||
if err == nil {
|
if err == nil {
|
||||||
msg.Raw = encrypted
|
msg.Raw = encrypted
|
||||||
}
|
}
|
||||||
|
|
@ -293,7 +294,7 @@ func (msg *ReceivedMessage) decryptSymmetric(key []byte, salt []byte, nonce []by
|
||||||
|
|
||||||
// decryptAsymmetric decrypts an encrypted payload with a private key.
|
// decryptAsymmetric decrypts an encrypted payload with a private key.
|
||||||
func (msg *ReceivedMessage) decryptAsymmetric(key *ecdsa.PrivateKey) error {
|
func (msg *ReceivedMessage) decryptAsymmetric(key *ecdsa.PrivateKey) error {
|
||||||
decrypted, err := crypto.Decrypt(key, msg.Raw)
|
decrypted, err := ecies.ImportECDSA(key).Decrypt(crand.Reader, msg.Raw, nil, nil)
|
||||||
if err == nil {
|
if err == nil {
|
||||||
msg.Raw = decrypted
|
msg.Raw = decrypted
|
||||||
}
|
}
|
||||||
|
|
|
||||||
Loading…
Reference in a new issue