mirror of
https://github.com/libp2p/go-libp2p-core.git
synced 2025-04-09 15:00:11 +08:00
absorb go-libp2p-crypto.
This commit is contained in:
parent
ec2a527976
commit
3a54eb68d1
84
crypto/bench_test.go
Normal file
84
crypto/bench_test.go
Normal file
@ -0,0 +1,84 @@
|
||||
package crypto
|
||||
|
||||
import "testing"
|
||||
|
||||
func BenchmarkSignRSA1B(b *testing.B) { RunBenchmarkSignRSA(b, 1) }
|
||||
func BenchmarkSignRSA10B(b *testing.B) { RunBenchmarkSignRSA(b, 10) }
|
||||
func BenchmarkSignRSA100B(b *testing.B) { RunBenchmarkSignRSA(b, 100) }
|
||||
func BenchmarkSignRSA1000B(b *testing.B) { RunBenchmarkSignRSA(b, 1000) }
|
||||
func BenchmarkSignRSA10000B(b *testing.B) { RunBenchmarkSignRSA(b, 10000) }
|
||||
func BenchmarkSignRSA100000B(b *testing.B) { RunBenchmarkSignRSA(b, 100000) }
|
||||
|
||||
func BenchmarkVerifyRSA1B(b *testing.B) { RunBenchmarkVerifyRSA(b, 1) }
|
||||
func BenchmarkVerifyRSA10B(b *testing.B) { RunBenchmarkVerifyRSA(b, 10) }
|
||||
func BenchmarkVerifyRSA100B(b *testing.B) { RunBenchmarkVerifyRSA(b, 100) }
|
||||
func BenchmarkVerifyRSA1000B(b *testing.B) { RunBenchmarkVerifyRSA(b, 1000) }
|
||||
func BenchmarkVerifyRSA10000B(b *testing.B) { RunBenchmarkVerifyRSA(b, 10000) }
|
||||
func BenchmarkVerifyRSA100000B(b *testing.B) { RunBenchmarkVerifyRSA(b, 100000) }
|
||||
|
||||
func BenchmarkSignEd255191B(b *testing.B) { RunBenchmarkSignEd25519(b, 1) }
|
||||
func BenchmarkSignEd2551910B(b *testing.B) { RunBenchmarkSignEd25519(b, 10) }
|
||||
func BenchmarkSignEd25519100B(b *testing.B) { RunBenchmarkSignEd25519(b, 100) }
|
||||
func BenchmarkSignEd255191000B(b *testing.B) { RunBenchmarkSignEd25519(b, 1000) }
|
||||
func BenchmarkSignEd2551910000B(b *testing.B) { RunBenchmarkSignEd25519(b, 10000) }
|
||||
func BenchmarkSignEd25519100000B(b *testing.B) { RunBenchmarkSignEd25519(b, 100000) }
|
||||
|
||||
func BenchmarkVerifyEd255191B(b *testing.B) { RunBenchmarkVerifyEd25519(b, 1) }
|
||||
func BenchmarkVerifyEd2551910B(b *testing.B) { RunBenchmarkVerifyEd25519(b, 10) }
|
||||
func BenchmarkVerifyEd25519100B(b *testing.B) { RunBenchmarkVerifyEd25519(b, 100) }
|
||||
func BenchmarkVerifyEd255191000B(b *testing.B) { RunBenchmarkVerifyEd25519(b, 1000) }
|
||||
func BenchmarkVerifyEd2551910000B(b *testing.B) { RunBenchmarkVerifyEd25519(b, 10000) }
|
||||
func BenchmarkVerifyEd25519100000B(b *testing.B) { RunBenchmarkVerifyEd25519(b, 100000) }
|
||||
|
||||
func RunBenchmarkSignRSA(b *testing.B, numBytes int) {
|
||||
runBenchmarkSign(b, numBytes, RSA)
|
||||
}
|
||||
|
||||
func RunBenchmarkSignEd25519(b *testing.B, numBytes int) {
|
||||
runBenchmarkSign(b, numBytes, Ed25519)
|
||||
}
|
||||
|
||||
func runBenchmarkSign(b *testing.B, numBytes int, t int) {
|
||||
secret, _, err := GenerateKeyPair(t, 1024)
|
||||
if err != nil {
|
||||
b.Fatal(err)
|
||||
}
|
||||
someData := make([]byte, numBytes)
|
||||
b.ResetTimer()
|
||||
for i := 0; i < b.N; i++ {
|
||||
_, err := secret.Sign(someData)
|
||||
if err != nil {
|
||||
b.Fatal(err)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func RunBenchmarkVerifyRSA(b *testing.B, numBytes int) {
|
||||
runBenchmarkSign(b, numBytes, RSA)
|
||||
}
|
||||
|
||||
func RunBenchmarkVerifyEd25519(b *testing.B, numBytes int) {
|
||||
runBenchmarkSign(b, numBytes, Ed25519)
|
||||
}
|
||||
|
||||
func runBenchmarkVerify(b *testing.B, numBytes int, t int) {
|
||||
secret, public, err := GenerateKeyPair(t, 1024)
|
||||
if err != nil {
|
||||
b.Fatal(err)
|
||||
}
|
||||
someData := make([]byte, numBytes)
|
||||
signature, err := secret.Sign(someData)
|
||||
if err != nil {
|
||||
b.Fatal(err)
|
||||
}
|
||||
b.ResetTimer()
|
||||
for i := 0; i < b.N; i++ {
|
||||
valid, err := public.Verify(someData, signature)
|
||||
if err != nil {
|
||||
b.Fatal(err)
|
||||
}
|
||||
if !valid {
|
||||
b.Fatal("signature should be valid")
|
||||
}
|
||||
}
|
||||
}
|
186
crypto/ecdsa.go
Normal file
186
crypto/ecdsa.go
Normal file
@ -0,0 +1,186 @@
|
||||
package crypto
|
||||
|
||||
import (
|
||||
"crypto/ecdsa"
|
||||
"crypto/elliptic"
|
||||
"crypto/rand"
|
||||
"crypto/x509"
|
||||
"encoding/asn1"
|
||||
"errors"
|
||||
"io"
|
||||
"math/big"
|
||||
|
||||
pb "github.com/libp2p/go-libp2p-core/crypto/pb"
|
||||
|
||||
sha256 "github.com/minio/sha256-simd"
|
||||
)
|
||||
|
||||
// ECDSAPrivateKey is an implementation of an ECDSA private key
|
||||
type ECDSAPrivateKey struct {
|
||||
priv *ecdsa.PrivateKey
|
||||
}
|
||||
|
||||
// ECDSAPublicKey is an implementation of an ECDSA public key
|
||||
type ECDSAPublicKey struct {
|
||||
pub *ecdsa.PublicKey
|
||||
}
|
||||
|
||||
// ECDSASig holds the r and s values of an ECDSA signature
|
||||
type ECDSASig struct {
|
||||
R, S *big.Int
|
||||
}
|
||||
|
||||
var (
|
||||
// ErrNotECDSAPubKey is returned when the public key passed is not an ecdsa public key
|
||||
ErrNotECDSAPubKey = errors.New("not an ecdsa public key")
|
||||
// ErrNilSig is returned when the signature is nil
|
||||
ErrNilSig = errors.New("sig is nil")
|
||||
// ErrNilPrivateKey is returned when a nil private key is provided
|
||||
ErrNilPrivateKey = errors.New("private key is nil")
|
||||
// ECDSACurve is the default ecdsa curve used
|
||||
ECDSACurve = elliptic.P256()
|
||||
)
|
||||
|
||||
// GenerateECDSAKeyPair generates a new ecdsa private and public key
|
||||
func GenerateECDSAKeyPair(src io.Reader) (PrivKey, PubKey, error) {
|
||||
return GenerateECDSAKeyPairWithCurve(ECDSACurve, src)
|
||||
}
|
||||
|
||||
// GenerateECDSAKeyPairWithCurve generates a new ecdsa private and public key with a speicified curve
|
||||
func GenerateECDSAKeyPairWithCurve(curve elliptic.Curve, src io.Reader) (PrivKey, PubKey, error) {
|
||||
priv, err := ecdsa.GenerateKey(curve, src)
|
||||
if err != nil {
|
||||
return nil, nil, err
|
||||
}
|
||||
|
||||
return &ECDSAPrivateKey{priv}, &ECDSAPublicKey{&priv.PublicKey}, nil
|
||||
}
|
||||
|
||||
// ECDSAKeyPairFromKey generates a new ecdsa private and public key from an input private key
|
||||
func ECDSAKeyPairFromKey(priv *ecdsa.PrivateKey) (PrivKey, PubKey, error) {
|
||||
if priv == nil {
|
||||
return nil, nil, ErrNilPrivateKey
|
||||
}
|
||||
|
||||
return &ECDSAPrivateKey{priv}, &ECDSAPublicKey{&priv.PublicKey}, nil
|
||||
}
|
||||
|
||||
// MarshalECDSAPrivateKey returns x509 bytes from a private key
|
||||
func MarshalECDSAPrivateKey(ePriv ECDSAPrivateKey) ([]byte, error) {
|
||||
return x509.MarshalECPrivateKey(ePriv.priv)
|
||||
}
|
||||
|
||||
// MarshalECDSAPublicKey returns x509 bytes from a public key
|
||||
func MarshalECDSAPublicKey(ePub ECDSAPublicKey) ([]byte, error) {
|
||||
return x509.MarshalPKIXPublicKey(ePub.pub)
|
||||
}
|
||||
|
||||
// UnmarshalECDSAPrivateKey returns a private key from x509 bytes
|
||||
func UnmarshalECDSAPrivateKey(data []byte) (PrivKey, error) {
|
||||
priv, err := x509.ParseECPrivateKey(data)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
return &ECDSAPrivateKey{priv}, nil
|
||||
}
|
||||
|
||||
// UnmarshalECDSAPublicKey returns the public key from x509 bytes
|
||||
func UnmarshalECDSAPublicKey(data []byte) (PubKey, error) {
|
||||
pubIfc, err := x509.ParsePKIXPublicKey(data)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
pub, ok := pubIfc.(*ecdsa.PublicKey)
|
||||
if !ok {
|
||||
return nil, ErrNotECDSAPubKey
|
||||
}
|
||||
|
||||
return &ECDSAPublicKey{pub}, nil
|
||||
}
|
||||
|
||||
// Bytes returns the private key as protobuf bytes
|
||||
func (ePriv *ECDSAPrivateKey) Bytes() ([]byte, error) {
|
||||
return MarshalPrivateKey(ePriv)
|
||||
}
|
||||
|
||||
// Type returns the key type
|
||||
func (ePriv *ECDSAPrivateKey) Type() pb.KeyType {
|
||||
return pb.KeyType_ECDSA
|
||||
}
|
||||
|
||||
// Raw returns x509 bytes from a private key
|
||||
func (ePriv *ECDSAPrivateKey) Raw() ([]byte, error) {
|
||||
return x509.MarshalECPrivateKey(ePriv.priv)
|
||||
}
|
||||
|
||||
// Equals compares to private keys
|
||||
func (ePriv *ECDSAPrivateKey) Equals(o Key) bool {
|
||||
oPriv, ok := o.(*ECDSAPrivateKey)
|
||||
if !ok {
|
||||
return false
|
||||
}
|
||||
|
||||
return ePriv.priv.D.Cmp(oPriv.priv.D) == 0
|
||||
}
|
||||
|
||||
// Sign returns the signature of the input data
|
||||
func (ePriv *ECDSAPrivateKey) Sign(data []byte) ([]byte, error) {
|
||||
hash := sha256.Sum256(data)
|
||||
r, s, err := ecdsa.Sign(rand.Reader, ePriv.priv, hash[:])
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
return asn1.Marshal(ECDSASig{
|
||||
R: r,
|
||||
S: s,
|
||||
})
|
||||
}
|
||||
|
||||
// GetPublic returns a public key
|
||||
func (ePriv *ECDSAPrivateKey) GetPublic() PubKey {
|
||||
return &ECDSAPublicKey{&ePriv.priv.PublicKey}
|
||||
}
|
||||
|
||||
// Bytes returns the public key as protobuf bytes
|
||||
func (ePub *ECDSAPublicKey) Bytes() ([]byte, error) {
|
||||
return MarshalPublicKey(ePub)
|
||||
}
|
||||
|
||||
// Type returns the key type
|
||||
func (ePub *ECDSAPublicKey) Type() pb.KeyType {
|
||||
return pb.KeyType_ECDSA
|
||||
}
|
||||
|
||||
// Raw returns x509 bytes from a public key
|
||||
func (ePub ECDSAPublicKey) Raw() ([]byte, error) {
|
||||
return x509.MarshalPKIXPublicKey(ePub.pub)
|
||||
}
|
||||
|
||||
// Equals compares to public keys
|
||||
func (ePub *ECDSAPublicKey) Equals(o Key) bool {
|
||||
oPub, ok := o.(*ECDSAPublicKey)
|
||||
if !ok {
|
||||
return false
|
||||
}
|
||||
|
||||
return ePub.pub.X != nil && ePub.pub.Y != nil && oPub.pub.X != nil && oPub.pub.Y != nil &&
|
||||
0 == ePub.pub.X.Cmp(oPub.pub.X) && 0 == ePub.pub.Y.Cmp(oPub.pub.Y)
|
||||
}
|
||||
|
||||
// Verify compares data to a signature
|
||||
func (ePub *ECDSAPublicKey) Verify(data, sigBytes []byte) (bool, error) {
|
||||
sig := new(ECDSASig)
|
||||
if _, err := asn1.Unmarshal(sigBytes, sig); err != nil {
|
||||
return false, err
|
||||
}
|
||||
if sig == nil {
|
||||
return false, ErrNilSig
|
||||
}
|
||||
|
||||
hash := sha256.Sum256(data)
|
||||
|
||||
return ecdsa.Verify(ePub.pub, hash[:], sig.R, sig.S), nil
|
||||
}
|
96
crypto/ecdsa_test.go
Normal file
96
crypto/ecdsa_test.go
Normal file
@ -0,0 +1,96 @@
|
||||
package crypto
|
||||
|
||||
import (
|
||||
"crypto/rand"
|
||||
"testing"
|
||||
)
|
||||
|
||||
func TestECDSABasicSignAndVerify(t *testing.T) {
|
||||
priv, pub, err := GenerateECDSAKeyPair(rand.Reader)
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
|
||||
data := []byte("hello! and welcome to some awesome crypto primitives")
|
||||
|
||||
sig, err := priv.Sign(data)
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
|
||||
ok, err := pub.Verify(data, sig)
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
|
||||
if !ok {
|
||||
t.Fatal("signature didnt match")
|
||||
}
|
||||
|
||||
// change data
|
||||
data[0] = ^data[0]
|
||||
ok, err = pub.Verify(data, sig)
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
|
||||
if ok {
|
||||
t.Fatal("signature matched and shouldn't")
|
||||
}
|
||||
}
|
||||
|
||||
func TestECDSASignZero(t *testing.T) {
|
||||
priv, pub, err := GenerateECDSAKeyPair(rand.Reader)
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
|
||||
data := make([]byte, 0)
|
||||
sig, err := priv.Sign(data)
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
|
||||
ok, err := pub.Verify(data, sig)
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
if !ok {
|
||||
t.Fatal("signature didn't match")
|
||||
}
|
||||
}
|
||||
|
||||
func TestECDSAMarshalLoop(t *testing.T) {
|
||||
priv, pub, err := GenerateECDSAKeyPair(rand.Reader)
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
|
||||
privB, err := priv.Bytes()
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
|
||||
privNew, err := UnmarshalPrivateKey(privB)
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
|
||||
if !priv.Equals(privNew) || !privNew.Equals(priv) {
|
||||
t.Fatal("keys are not equal")
|
||||
}
|
||||
|
||||
pubB, err := pub.Bytes()
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
pubNew, err := UnmarshalPublicKey(pubB)
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
|
||||
if !pub.Equals(pubNew) || !pubNew.Equals(pub) {
|
||||
t.Fatal("keys are not equal")
|
||||
}
|
||||
|
||||
}
|
155
crypto/ed25519.go
Normal file
155
crypto/ed25519.go
Normal file
@ -0,0 +1,155 @@
|
||||
package crypto
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
"errors"
|
||||
"fmt"
|
||||
"io"
|
||||
|
||||
pb "github.com/libp2p/go-libp2p-core/crypto/pb"
|
||||
|
||||
"golang.org/x/crypto/ed25519"
|
||||
)
|
||||
|
||||
// Ed25519PrivateKey is an ed25519 private key.
|
||||
type Ed25519PrivateKey struct {
|
||||
k ed25519.PrivateKey
|
||||
}
|
||||
|
||||
// Ed25519PublicKey is an ed25519 public key.
|
||||
type Ed25519PublicKey struct {
|
||||
k ed25519.PublicKey
|
||||
}
|
||||
|
||||
// GenerateEd25519Key generate a new ed25519 private and public key pair.
|
||||
func GenerateEd25519Key(src io.Reader) (PrivKey, PubKey, error) {
|
||||
pub, priv, err := ed25519.GenerateKey(src)
|
||||
if err != nil {
|
||||
return nil, nil, err
|
||||
}
|
||||
|
||||
return &Ed25519PrivateKey{
|
||||
k: priv,
|
||||
},
|
||||
&Ed25519PublicKey{
|
||||
k: pub,
|
||||
},
|
||||
nil
|
||||
}
|
||||
|
||||
// Type of the private key (Ed25519).
|
||||
func (k *Ed25519PrivateKey) Type() pb.KeyType {
|
||||
return pb.KeyType_Ed25519
|
||||
}
|
||||
|
||||
// Bytes marshals an ed25519 private key to protobuf bytes.
|
||||
func (k *Ed25519PrivateKey) Bytes() ([]byte, error) {
|
||||
return MarshalPrivateKey(k)
|
||||
}
|
||||
|
||||
// Raw private key bytes.
|
||||
func (k *Ed25519PrivateKey) Raw() ([]byte, error) {
|
||||
// The Ed25519 private key contains two 32-bytes curve points, the private
|
||||
// key and the public key.
|
||||
// It makes it more efficient to get the public key without re-computing an
|
||||
// elliptic curve multiplication.
|
||||
buf := make([]byte, len(k.k))
|
||||
copy(buf, k.k)
|
||||
|
||||
return buf, nil
|
||||
}
|
||||
|
||||
func (k *Ed25519PrivateKey) pubKeyBytes() []byte {
|
||||
return k.k[ed25519.PrivateKeySize-ed25519.PublicKeySize:]
|
||||
}
|
||||
|
||||
// Equals compares two ed25519 private keys.
|
||||
func (k *Ed25519PrivateKey) Equals(o Key) bool {
|
||||
edk, ok := o.(*Ed25519PrivateKey)
|
||||
if !ok {
|
||||
return false
|
||||
}
|
||||
|
||||
return bytes.Equal(k.k, edk.k)
|
||||
}
|
||||
|
||||
// GetPublic returns an ed25519 public key from a private key.
|
||||
func (k *Ed25519PrivateKey) GetPublic() PubKey {
|
||||
return &Ed25519PublicKey{k: k.pubKeyBytes()}
|
||||
}
|
||||
|
||||
// Sign returns a signature from an input message.
|
||||
func (k *Ed25519PrivateKey) Sign(msg []byte) ([]byte, error) {
|
||||
return ed25519.Sign(k.k, msg), nil
|
||||
}
|
||||
|
||||
// Type of the public key (Ed25519).
|
||||
func (k *Ed25519PublicKey) Type() pb.KeyType {
|
||||
return pb.KeyType_Ed25519
|
||||
}
|
||||
|
||||
// Bytes returns a ed25519 public key as protobuf bytes.
|
||||
func (k *Ed25519PublicKey) Bytes() ([]byte, error) {
|
||||
return MarshalPublicKey(k)
|
||||
}
|
||||
|
||||
// Raw public key bytes.
|
||||
func (k *Ed25519PublicKey) Raw() ([]byte, error) {
|
||||
return k.k, nil
|
||||
}
|
||||
|
||||
// Equals compares two ed25519 public keys.
|
||||
func (k *Ed25519PublicKey) Equals(o Key) bool {
|
||||
edk, ok := o.(*Ed25519PublicKey)
|
||||
if !ok {
|
||||
return false
|
||||
}
|
||||
|
||||
return bytes.Equal(k.k, edk.k)
|
||||
}
|
||||
|
||||
// Verify checks a signature agains the input data.
|
||||
func (k *Ed25519PublicKey) Verify(data []byte, sig []byte) (bool, error) {
|
||||
return ed25519.Verify(k.k, data, sig), nil
|
||||
}
|
||||
|
||||
// UnmarshalEd25519PublicKey returns a public key from input bytes.
|
||||
func UnmarshalEd25519PublicKey(data []byte) (PubKey, error) {
|
||||
if len(data) != 32 {
|
||||
return nil, errors.New("expect ed25519 public key data size to be 32")
|
||||
}
|
||||
|
||||
return &Ed25519PublicKey{
|
||||
k: ed25519.PublicKey(data),
|
||||
}, nil
|
||||
}
|
||||
|
||||
// UnmarshalEd25519PrivateKey returns a private key from input bytes.
|
||||
func UnmarshalEd25519PrivateKey(data []byte) (PrivKey, error) {
|
||||
switch len(data) {
|
||||
case ed25519.PrivateKeySize + ed25519.PublicKeySize:
|
||||
// Remove the redundant public key. See issue #36.
|
||||
redundantPk := data[ed25519.PrivateKeySize:]
|
||||
pk := data[ed25519.PrivateKeySize-ed25519.PublicKeySize : ed25519.PrivateKeySize]
|
||||
if !bytes.Equal(pk, redundantPk) {
|
||||
return nil, errors.New("expected redundant ed25519 public key to be redundant")
|
||||
}
|
||||
|
||||
// No point in storing the extra data.
|
||||
newKey := make([]byte, ed25519.PrivateKeySize)
|
||||
copy(newKey, data[:ed25519.PrivateKeySize])
|
||||
data = newKey
|
||||
case ed25519.PrivateKeySize:
|
||||
default:
|
||||
return nil, fmt.Errorf(
|
||||
"expected ed25519 data size to be %d or %d, got %d",
|
||||
ed25519.PrivateKeySize,
|
||||
ed25519.PrivateKeySize+ed25519.PublicKeySize,
|
||||
len(data),
|
||||
)
|
||||
}
|
||||
|
||||
return &Ed25519PrivateKey{
|
||||
k: ed25519.PrivateKey(data),
|
||||
}, nil
|
||||
}
|
220
crypto/ed25519_test.go
Normal file
220
crypto/ed25519_test.go
Normal file
@ -0,0 +1,220 @@
|
||||
package crypto
|
||||
|
||||
import (
|
||||
"crypto/rand"
|
||||
"testing"
|
||||
|
||||
pb "github.com/libp2p/go-libp2p-core/crypto/pb"
|
||||
|
||||
"golang.org/x/crypto/ed25519"
|
||||
)
|
||||
|
||||
func TestBasicSignAndVerify(t *testing.T) {
|
||||
priv, pub, err := GenerateEd25519Key(rand.Reader)
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
|
||||
data := []byte("hello! and welcome to some awesome crypto primitives")
|
||||
|
||||
sig, err := priv.Sign(data)
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
|
||||
ok, err := pub.Verify(data, sig)
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
|
||||
if !ok {
|
||||
t.Fatal("signature didn't match")
|
||||
}
|
||||
|
||||
// change data
|
||||
data[0] = ^data[0]
|
||||
ok, err = pub.Verify(data, sig)
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
|
||||
if ok {
|
||||
t.Fatal("signature matched and shouldn't")
|
||||
}
|
||||
}
|
||||
|
||||
func TestSignZero(t *testing.T) {
|
||||
priv, pub, err := GenerateEd25519Key(rand.Reader)
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
|
||||
data := make([]byte, 0)
|
||||
sig, err := priv.Sign(data)
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
|
||||
ok, err := pub.Verify(data, sig)
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
if !ok {
|
||||
t.Fatal("signature didn't match")
|
||||
}
|
||||
}
|
||||
|
||||
func TestMarshalLoop(t *testing.T) {
|
||||
priv, pub, err := GenerateEd25519Key(rand.Reader)
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
|
||||
t.Run("PrivateKey", func(t *testing.T) {
|
||||
for name, f := range map[string]func() ([]byte, error){
|
||||
"Bytes": priv.Bytes,
|
||||
"Marshal": func() ([]byte, error) {
|
||||
return MarshalPrivateKey(priv)
|
||||
},
|
||||
"Redundant": func() ([]byte, error) {
|
||||
// See issue #36.
|
||||
// Ed25519 private keys used to contain the public key twice.
|
||||
// For backwards-compatibility, we need to continue supporting
|
||||
// that scenario.
|
||||
pbmes := new(pb.PrivateKey)
|
||||
pbmes.Type = priv.Type()
|
||||
data, err := priv.Raw()
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
|
||||
pbmes.Data = append(data, data[len(data)-ed25519.PublicKeySize:]...)
|
||||
return pbmes.Marshal()
|
||||
},
|
||||
} {
|
||||
t.Run(name, func(t *testing.T) {
|
||||
bts, err := f()
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
|
||||
privNew, err := UnmarshalPrivateKey(bts)
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
|
||||
if !priv.Equals(privNew) || !privNew.Equals(priv) {
|
||||
t.Fatal("keys are not equal")
|
||||
}
|
||||
|
||||
msg := []byte("My child, my sister,\nThink of the rapture\nOf living together there!")
|
||||
signed, err := privNew.Sign(msg)
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
|
||||
ok, err := privNew.GetPublic().Verify(msg, signed)
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
|
||||
if !ok {
|
||||
t.Fatal("signature didn't match")
|
||||
}
|
||||
})
|
||||
}
|
||||
})
|
||||
|
||||
t.Run("PublicKey", func(t *testing.T) {
|
||||
for name, f := range map[string]func() ([]byte, error){
|
||||
"Bytes": pub.Bytes,
|
||||
"Marshal": func() ([]byte, error) {
|
||||
return MarshalPublicKey(pub)
|
||||
},
|
||||
} {
|
||||
t.Run(name, func(t *testing.T) {
|
||||
bts, err := f()
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
pubNew, err := UnmarshalPublicKey(bts)
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
|
||||
if !pub.Equals(pubNew) || !pubNew.Equals(pub) {
|
||||
t.Fatal("keys are not equal")
|
||||
}
|
||||
})
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
func TestUnmarshalErrors(t *testing.T) {
|
||||
t.Run("PublicKey", func(t *testing.T) {
|
||||
t.Run("Invalid data length", func(t *testing.T) {
|
||||
pbmes := &pb.PublicKey{
|
||||
Type: pb.KeyType_Ed25519,
|
||||
Data: []byte{42},
|
||||
}
|
||||
|
||||
data, err := pbmes.Marshal()
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
|
||||
_, err = UnmarshalPublicKey(data)
|
||||
if err == nil {
|
||||
t.Fatal("expected an error")
|
||||
}
|
||||
})
|
||||
})
|
||||
|
||||
t.Run("PrivateKey", func(t *testing.T) {
|
||||
t.Run("Redundant public key mismatch", func(t *testing.T) {
|
||||
priv, _, err := GenerateEd25519Key(rand.Reader)
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
|
||||
pbmes := new(pb.PrivateKey)
|
||||
pbmes.Type = priv.Type()
|
||||
data, err := priv.Raw()
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
|
||||
// Append the private key instead of the public key.
|
||||
pbmes.Data = append(data, data[:ed25519.PublicKeySize]...)
|
||||
b, err := pbmes.Marshal()
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
|
||||
_, err = UnmarshalPrivateKey(b)
|
||||
if err == nil {
|
||||
t.Fatal("expected an error")
|
||||
}
|
||||
if err.Error() != "expected redundant ed25519 public key to be redundant" {
|
||||
t.Fatalf("invalid error received: %s", err.Error())
|
||||
}
|
||||
})
|
||||
|
||||
t.Run("Invalid data length", func(t *testing.T) {
|
||||
pbmes := &pb.PrivateKey{
|
||||
Type: pb.KeyType_Ed25519,
|
||||
Data: []byte{42},
|
||||
}
|
||||
|
||||
data, err := pbmes.Marshal()
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
|
||||
_, err = UnmarshalPrivateKey(data)
|
||||
if err == nil {
|
||||
t.Fatal("expected an error")
|
||||
}
|
||||
})
|
||||
})
|
||||
}
|
352
crypto/key.go
Normal file
352
crypto/key.go
Normal file
@ -0,0 +1,352 @@
|
||||
// Package crypto implements various cryptographic utilities used by ipfs.
|
||||
// This includes a Public and Private key interface and an RSA key implementation
|
||||
// that satisfies it.
|
||||
package crypto
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
"crypto/elliptic"
|
||||
"crypto/hmac"
|
||||
"crypto/rand"
|
||||
"crypto/sha1"
|
||||
"crypto/sha512"
|
||||
"encoding/base64"
|
||||
"errors"
|
||||
"fmt"
|
||||
"hash"
|
||||
"io"
|
||||
|
||||
pb "github.com/libp2p/go-libp2p-core/crypto/pb"
|
||||
|
||||
"github.com/gogo/protobuf/proto"
|
||||
sha256 "github.com/minio/sha256-simd"
|
||||
)
|
||||
|
||||
const (
|
||||
// RSA is an enum for the supported RSA key type
|
||||
RSA = iota
|
||||
// Ed25519 is an enum for the supported Ed25519 key type
|
||||
Ed25519
|
||||
// Secp256k1 is an enum for the supported Secp256k1 key type
|
||||
Secp256k1
|
||||
// ECDSA is an enum for the supported ECDSA key type
|
||||
ECDSA
|
||||
)
|
||||
|
||||
var (
|
||||
// ErrBadKeyType is returned when a key is not supported
|
||||
ErrBadKeyType = errors.New("invalid or unsupported key type")
|
||||
// KeyTypes is a list of supported keys
|
||||
KeyTypes = []int{
|
||||
RSA,
|
||||
Ed25519,
|
||||
Secp256k1,
|
||||
ECDSA,
|
||||
}
|
||||
)
|
||||
|
||||
// PubKeyUnmarshaller is a func that creates a PubKey from a given slice of bytes
|
||||
type PubKeyUnmarshaller func(data []byte) (PubKey, error)
|
||||
|
||||
// PrivKeyUnmarshaller is a func that creates a PrivKey from a given slice of bytes
|
||||
type PrivKeyUnmarshaller func(data []byte) (PrivKey, error)
|
||||
|
||||
// PubKeyUnmarshallers is a map of unmarshallers by key type
|
||||
var PubKeyUnmarshallers = map[pb.KeyType]PubKeyUnmarshaller{
|
||||
pb.KeyType_RSA: UnmarshalRsaPublicKey,
|
||||
pb.KeyType_Ed25519: UnmarshalEd25519PublicKey,
|
||||
pb.KeyType_Secp256k1: UnmarshalSecp256k1PublicKey,
|
||||
pb.KeyType_ECDSA: UnmarshalECDSAPublicKey,
|
||||
}
|
||||
|
||||
// PrivKeyUnmarshallers is a map of unmarshallers by key type
|
||||
var PrivKeyUnmarshallers = map[pb.KeyType]PrivKeyUnmarshaller{
|
||||
pb.KeyType_RSA: UnmarshalRsaPrivateKey,
|
||||
pb.KeyType_Ed25519: UnmarshalEd25519PrivateKey,
|
||||
pb.KeyType_Secp256k1: UnmarshalSecp256k1PrivateKey,
|
||||
pb.KeyType_ECDSA: UnmarshalECDSAPrivateKey,
|
||||
}
|
||||
|
||||
// Key represents a crypto key that can be compared to another key
|
||||
type Key interface {
|
||||
// Bytes returns a serialized, storeable representation of this key
|
||||
// DEPRECATED in favor of Marshal / Unmarshal
|
||||
Bytes() ([]byte, error)
|
||||
|
||||
// Equals checks whether two PubKeys are the same
|
||||
Equals(Key) bool
|
||||
|
||||
// Raw returns the raw bytes of the key (not wrapped in the
|
||||
// libp2p-crypto protobuf).
|
||||
//
|
||||
// This function is the inverse of {Priv,Pub}KeyUnmarshaler.
|
||||
Raw() ([]byte, error)
|
||||
|
||||
// Type returns the protobof key type.
|
||||
Type() pb.KeyType
|
||||
}
|
||||
|
||||
// PrivKey represents a private key that can be used to generate a public key,
|
||||
// sign data, and decrypt data that was encrypted with a public key
|
||||
type PrivKey interface {
|
||||
Key
|
||||
|
||||
// Cryptographically sign the given bytes
|
||||
Sign([]byte) ([]byte, error)
|
||||
|
||||
// Return a public key paired with this private key
|
||||
GetPublic() PubKey
|
||||
}
|
||||
|
||||
// PubKey is a public key
|
||||
type PubKey interface {
|
||||
Key
|
||||
|
||||
// Verify that 'sig' is the signed hash of 'data'
|
||||
Verify(data []byte, sig []byte) (bool, error)
|
||||
}
|
||||
|
||||
// GenSharedKey generates the shared key from a given private key
|
||||
type GenSharedKey func([]byte) ([]byte, error)
|
||||
|
||||
// GenerateKeyPair generates a private and public key
|
||||
func GenerateKeyPair(typ, bits int) (PrivKey, PubKey, error) {
|
||||
return GenerateKeyPairWithReader(typ, bits, rand.Reader)
|
||||
}
|
||||
|
||||
// GenerateKeyPairWithReader returns a keypair of the given type and bitsize
|
||||
func GenerateKeyPairWithReader(typ, bits int, src io.Reader) (PrivKey, PubKey, error) {
|
||||
switch typ {
|
||||
case RSA:
|
||||
return GenerateRSAKeyPair(bits, src)
|
||||
case Ed25519:
|
||||
return GenerateEd25519Key(src)
|
||||
case Secp256k1:
|
||||
return GenerateSecp256k1Key(src)
|
||||
case ECDSA:
|
||||
return GenerateECDSAKeyPair(src)
|
||||
default:
|
||||
return nil, nil, ErrBadKeyType
|
||||
}
|
||||
}
|
||||
|
||||
// GenerateEKeyPair returns an ephemeral public key and returns a function that will compute
|
||||
// the shared secret key. Used in the identify module.
|
||||
//
|
||||
// Focuses only on ECDH now, but can be made more general in the future.
|
||||
func GenerateEKeyPair(curveName string) ([]byte, GenSharedKey, error) {
|
||||
var curve elliptic.Curve
|
||||
|
||||
switch curveName {
|
||||
case "P-256":
|
||||
curve = elliptic.P256()
|
||||
case "P-384":
|
||||
curve = elliptic.P384()
|
||||
case "P-521":
|
||||
curve = elliptic.P521()
|
||||
}
|
||||
|
||||
priv, x, y, err := elliptic.GenerateKey(curve, rand.Reader)
|
||||
if err != nil {
|
||||
return nil, nil, err
|
||||
}
|
||||
|
||||
pubKey := elliptic.Marshal(curve, x, y)
|
||||
|
||||
done := func(theirPub []byte) ([]byte, error) {
|
||||
// Verify and unpack node's public key.
|
||||
x, y := elliptic.Unmarshal(curve, theirPub)
|
||||
if x == nil {
|
||||
return nil, fmt.Errorf("malformed public key: %d %v", len(theirPub), theirPub)
|
||||
}
|
||||
|
||||
if !curve.IsOnCurve(x, y) {
|
||||
return nil, errors.New("invalid public key")
|
||||
}
|
||||
|
||||
// Generate shared secret.
|
||||
secret, _ := curve.ScalarMult(x, y, priv)
|
||||
|
||||
return secret.Bytes(), nil
|
||||
}
|
||||
|
||||
return pubKey, done, nil
|
||||
}
|
||||
|
||||
// StretchedKeys ...
|
||||
type StretchedKeys struct {
|
||||
IV []byte
|
||||
MacKey []byte
|
||||
CipherKey []byte
|
||||
}
|
||||
|
||||
// KeyStretcher returns a set of keys for each party by stretching the shared key.
|
||||
// (myIV, theirIV, myCipherKey, theirCipherKey, myMACKey, theirMACKey)
|
||||
func KeyStretcher(cipherType string, hashType string, secret []byte) (StretchedKeys, StretchedKeys) {
|
||||
var cipherKeySize int
|
||||
var ivSize int
|
||||
switch cipherType {
|
||||
case "AES-128":
|
||||
ivSize = 16
|
||||
cipherKeySize = 16
|
||||
case "AES-256":
|
||||
ivSize = 16
|
||||
cipherKeySize = 32
|
||||
case "Blowfish":
|
||||
ivSize = 8
|
||||
// Note: 24 arbitrarily selected, needs more thought
|
||||
cipherKeySize = 32
|
||||
}
|
||||
|
||||
hmacKeySize := 20
|
||||
|
||||
seed := []byte("key expansion")
|
||||
|
||||
result := make([]byte, 2*(ivSize+cipherKeySize+hmacKeySize))
|
||||
|
||||
var h func() hash.Hash
|
||||
|
||||
switch hashType {
|
||||
case "SHA1":
|
||||
h = sha1.New
|
||||
case "SHA256":
|
||||
h = sha256.New
|
||||
case "SHA512":
|
||||
h = sha512.New
|
||||
default:
|
||||
panic("Unrecognized hash function, programmer error?")
|
||||
}
|
||||
|
||||
m := hmac.New(h, secret)
|
||||
// note: guaranteed to never return an error
|
||||
m.Write(seed)
|
||||
|
||||
a := m.Sum(nil)
|
||||
|
||||
j := 0
|
||||
for j < len(result) {
|
||||
m.Reset()
|
||||
|
||||
// note: guaranteed to never return an error.
|
||||
m.Write(a)
|
||||
m.Write(seed)
|
||||
|
||||
b := m.Sum(nil)
|
||||
|
||||
todo := len(b)
|
||||
|
||||
if j+todo > len(result) {
|
||||
todo = len(result) - j
|
||||
}
|
||||
|
||||
copy(result[j:j+todo], b)
|
||||
|
||||
j += todo
|
||||
|
||||
m.Reset()
|
||||
|
||||
// note: guaranteed to never return an error.
|
||||
m.Write(a)
|
||||
|
||||
a = m.Sum(nil)
|
||||
}
|
||||
|
||||
half := len(result) / 2
|
||||
r1 := result[:half]
|
||||
r2 := result[half:]
|
||||
|
||||
var k1 StretchedKeys
|
||||
var k2 StretchedKeys
|
||||
|
||||
k1.IV = r1[0:ivSize]
|
||||
k1.CipherKey = r1[ivSize : ivSize+cipherKeySize]
|
||||
k1.MacKey = r1[ivSize+cipherKeySize:]
|
||||
|
||||
k2.IV = r2[0:ivSize]
|
||||
k2.CipherKey = r2[ivSize : ivSize+cipherKeySize]
|
||||
k2.MacKey = r2[ivSize+cipherKeySize:]
|
||||
|
||||
return k1, k2
|
||||
}
|
||||
|
||||
// UnmarshalPublicKey converts a protobuf serialized public key into its
|
||||
// representative object
|
||||
func UnmarshalPublicKey(data []byte) (PubKey, error) {
|
||||
pmes := new(pb.PublicKey)
|
||||
err := proto.Unmarshal(data, pmes)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
um, ok := PubKeyUnmarshallers[pmes.GetType()]
|
||||
if !ok {
|
||||
return nil, ErrBadKeyType
|
||||
}
|
||||
|
||||
return um(pmes.GetData())
|
||||
}
|
||||
|
||||
// MarshalPublicKey converts a public key object into a protobuf serialized
|
||||
// public key
|
||||
func MarshalPublicKey(k PubKey) ([]byte, error) {
|
||||
pbmes := new(pb.PublicKey)
|
||||
pbmes.Type = k.Type()
|
||||
data, err := k.Raw()
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
pbmes.Data = data
|
||||
|
||||
return proto.Marshal(pbmes)
|
||||
}
|
||||
|
||||
// UnmarshalPrivateKey converts a protobuf serialized private key into its
|
||||
// representative object
|
||||
func UnmarshalPrivateKey(data []byte) (PrivKey, error) {
|
||||
pmes := new(pb.PrivateKey)
|
||||
err := proto.Unmarshal(data, pmes)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
um, ok := PrivKeyUnmarshallers[pmes.GetType()]
|
||||
if !ok {
|
||||
return nil, ErrBadKeyType
|
||||
}
|
||||
|
||||
return um(pmes.GetData())
|
||||
}
|
||||
|
||||
// MarshalPrivateKey converts a key object into its protobuf serialized form.
|
||||
func MarshalPrivateKey(k PrivKey) ([]byte, error) {
|
||||
pbmes := new(pb.PrivateKey)
|
||||
pbmes.Type = k.Type()
|
||||
data, err := k.Raw()
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
pbmes.Data = data
|
||||
return proto.Marshal(pbmes)
|
||||
}
|
||||
|
||||
// ConfigDecodeKey decodes from b64 (for config file), and unmarshals.
|
||||
func ConfigDecodeKey(b string) ([]byte, error) {
|
||||
return base64.StdEncoding.DecodeString(b)
|
||||
}
|
||||
|
||||
// ConfigEncodeKey encodes to b64 (for config file), and marshals.
|
||||
func ConfigEncodeKey(b []byte) string {
|
||||
return base64.StdEncoding.EncodeToString(b)
|
||||
}
|
||||
|
||||
// KeyEqual checks whether two
|
||||
func KeyEqual(k1, k2 Key) bool {
|
||||
if k1 == k2 {
|
||||
return true
|
||||
}
|
||||
|
||||
b1, err1 := k1.Bytes()
|
||||
b2, err2 := k2.Bytes()
|
||||
return bytes.Equal(b1, b2) && err1 == err2
|
||||
}
|
147
crypto/key_test.go
Normal file
147
crypto/key_test.go
Normal file
@ -0,0 +1,147 @@
|
||||
package crypto_test
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
"crypto/rand"
|
||||
"testing"
|
||||
|
||||
. "github.com/libp2p/go-libp2p-core/crypto"
|
||||
pb "github.com/libp2p/go-libp2p-core/crypto/pb"
|
||||
tu "github.com/libp2p/go-libp2p-core/crypto/test"
|
||||
)
|
||||
|
||||
func TestKeys(t *testing.T) {
|
||||
for _, typ := range KeyTypes {
|
||||
testKeyType(typ, t)
|
||||
}
|
||||
}
|
||||
|
||||
func testKeyType(typ int, t *testing.T) {
|
||||
sk, pk, err := tu.RandTestKeyPair(typ, 512)
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
|
||||
testKeySignature(t, sk)
|
||||
testKeyEncoding(t, sk)
|
||||
testKeyEquals(t, sk)
|
||||
testKeyEquals(t, pk)
|
||||
}
|
||||
|
||||
func testKeySignature(t *testing.T, sk PrivKey) {
|
||||
pk := sk.GetPublic()
|
||||
|
||||
text := make([]byte, 16)
|
||||
if _, err := rand.Read(text); err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
|
||||
sig, err := sk.Sign(text)
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
|
||||
valid, err := pk.Verify(text, sig)
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
|
||||
if !valid {
|
||||
t.Fatal("Invalid signature.")
|
||||
}
|
||||
}
|
||||
|
||||
func testKeyEncoding(t *testing.T, sk PrivKey) {
|
||||
skbm, err := MarshalPrivateKey(sk)
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
|
||||
sk2, err := UnmarshalPrivateKey(skbm)
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
|
||||
if !sk.Equals(sk2) {
|
||||
t.Error("Unmarshaled private key didn't match original.\n")
|
||||
}
|
||||
|
||||
skbm2, err := MarshalPrivateKey(sk2)
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
|
||||
if !bytes.Equal(skbm, skbm2) {
|
||||
t.Error("skb -> marshal -> unmarshal -> skb failed.\n", skbm, "\n", skbm2)
|
||||
}
|
||||
|
||||
pk := sk.GetPublic()
|
||||
pkbm, err := MarshalPublicKey(pk)
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
|
||||
pk2, err := UnmarshalPublicKey(pkbm)
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
|
||||
if !pk.Equals(pk2) {
|
||||
t.Error("Unmarshaled public key didn't match original.\n")
|
||||
}
|
||||
|
||||
pkbm2, err := MarshalPublicKey(pk)
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
|
||||
if !bytes.Equal(pkbm, pkbm2) {
|
||||
t.Error("skb -> marshal -> unmarshal -> skb failed.\n", pkbm, "\n", pkbm2)
|
||||
}
|
||||
}
|
||||
|
||||
func testKeyEquals(t *testing.T, k Key) {
|
||||
kb, err := k.Bytes()
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
|
||||
if !KeyEqual(k, k) {
|
||||
t.Fatal("Key not equal to itself.")
|
||||
}
|
||||
|
||||
if !KeyEqual(k, testkey(kb)) {
|
||||
t.Fatal("Key not equal to key with same bytes.")
|
||||
}
|
||||
|
||||
sk, pk, err := tu.RandTestKeyPair(RSA, 512)
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
|
||||
if KeyEqual(k, sk) {
|
||||
t.Fatal("Keys should not equal.")
|
||||
}
|
||||
|
||||
if KeyEqual(k, pk) {
|
||||
t.Fatal("Keys should not equal.")
|
||||
}
|
||||
}
|
||||
|
||||
type testkey []byte
|
||||
|
||||
func (pk testkey) Bytes() ([]byte, error) {
|
||||
return pk, nil
|
||||
}
|
||||
|
||||
func (pk testkey) Type() pb.KeyType {
|
||||
return pb.KeyType_RSA
|
||||
}
|
||||
|
||||
func (pk testkey) Raw() ([]byte, error) {
|
||||
return pk, nil
|
||||
}
|
||||
|
||||
func (pk testkey) Equals(k Key) bool {
|
||||
return KeyEqual(pk, k)
|
||||
}
|
11
crypto/pb/Makefile
Normal file
11
crypto/pb/Makefile
Normal file
@ -0,0 +1,11 @@
|
||||
PB = $(wildcard *.proto)
|
||||
GO = $(PB:.proto=.pb.go)
|
||||
|
||||
all: $(GO)
|
||||
|
||||
%.pb.go: %.proto
|
||||
protoc --proto_path=$(GOPATH)/src:. --gogofaster_out=. $<
|
||||
|
||||
clean:
|
||||
rm -f *.pb.go
|
||||
rm -f *.go
|
643
crypto/pb/crypto.pb.go
Normal file
643
crypto/pb/crypto.pb.go
Normal file
@ -0,0 +1,643 @@
|
||||
// Code generated by protoc-gen-gogo. DO NOT EDIT.
|
||||
// source: crypto.proto
|
||||
|
||||
package crypto_pb
|
||||
|
||||
import (
|
||||
fmt "fmt"
|
||||
github_com_gogo_protobuf_proto "github.com/gogo/protobuf/proto"
|
||||
proto "github.com/gogo/protobuf/proto"
|
||||
io "io"
|
||||
math "math"
|
||||
)
|
||||
|
||||
// Reference imports to suppress errors if they are not otherwise used.
|
||||
var _ = proto.Marshal
|
||||
var _ = fmt.Errorf
|
||||
var _ = math.Inf
|
||||
|
||||
// This is a compile-time assertion to ensure that this generated file
|
||||
// is compatible with the proto package it is being compiled against.
|
||||
// A compilation error at this line likely means your copy of the
|
||||
// proto package needs to be updated.
|
||||
const _ = proto.GoGoProtoPackageIsVersion2 // please upgrade the proto package
|
||||
|
||||
type KeyType int32
|
||||
|
||||
const (
|
||||
KeyType_RSA KeyType = 0
|
||||
KeyType_Ed25519 KeyType = 1
|
||||
KeyType_Secp256k1 KeyType = 2
|
||||
KeyType_ECDSA KeyType = 3
|
||||
)
|
||||
|
||||
var KeyType_name = map[int32]string{
|
||||
0: "RSA",
|
||||
1: "Ed25519",
|
||||
2: "Secp256k1",
|
||||
3: "ECDSA",
|
||||
}
|
||||
|
||||
var KeyType_value = map[string]int32{
|
||||
"RSA": 0,
|
||||
"Ed25519": 1,
|
||||
"Secp256k1": 2,
|
||||
"ECDSA": 3,
|
||||
}
|
||||
|
||||
func (x KeyType) Enum() *KeyType {
|
||||
p := new(KeyType)
|
||||
*p = x
|
||||
return p
|
||||
}
|
||||
|
||||
func (x KeyType) String() string {
|
||||
return proto.EnumName(KeyType_name, int32(x))
|
||||
}
|
||||
|
||||
func (x *KeyType) UnmarshalJSON(data []byte) error {
|
||||
value, err := proto.UnmarshalJSONEnum(KeyType_value, data, "KeyType")
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
*x = KeyType(value)
|
||||
return nil
|
||||
}
|
||||
|
||||
func (KeyType) EnumDescriptor() ([]byte, []int) {
|
||||
return fileDescriptor_527278fb02d03321, []int{0}
|
||||
}
|
||||
|
||||
type PublicKey struct {
|
||||
Type KeyType `protobuf:"varint,1,req,name=Type,enum=crypto.pb.KeyType" json:"Type"`
|
||||
Data []byte `protobuf:"bytes,2,req,name=Data" json:"Data"`
|
||||
}
|
||||
|
||||
func (m *PublicKey) Reset() { *m = PublicKey{} }
|
||||
func (m *PublicKey) String() string { return proto.CompactTextString(m) }
|
||||
func (*PublicKey) ProtoMessage() {}
|
||||
func (*PublicKey) Descriptor() ([]byte, []int) {
|
||||
return fileDescriptor_527278fb02d03321, []int{0}
|
||||
}
|
||||
func (m *PublicKey) XXX_Unmarshal(b []byte) error {
|
||||
return m.Unmarshal(b)
|
||||
}
|
||||
func (m *PublicKey) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) {
|
||||
if deterministic {
|
||||
return xxx_messageInfo_PublicKey.Marshal(b, m, deterministic)
|
||||
} else {
|
||||
b = b[:cap(b)]
|
||||
n, err := m.MarshalTo(b)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return b[:n], nil
|
||||
}
|
||||
}
|
||||
func (m *PublicKey) XXX_Merge(src proto.Message) {
|
||||
xxx_messageInfo_PublicKey.Merge(m, src)
|
||||
}
|
||||
func (m *PublicKey) XXX_Size() int {
|
||||
return m.Size()
|
||||
}
|
||||
func (m *PublicKey) XXX_DiscardUnknown() {
|
||||
xxx_messageInfo_PublicKey.DiscardUnknown(m)
|
||||
}
|
||||
|
||||
var xxx_messageInfo_PublicKey proto.InternalMessageInfo
|
||||
|
||||
func (m *PublicKey) GetType() KeyType {
|
||||
if m != nil {
|
||||
return m.Type
|
||||
}
|
||||
return KeyType_RSA
|
||||
}
|
||||
|
||||
func (m *PublicKey) GetData() []byte {
|
||||
if m != nil {
|
||||
return m.Data
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
type PrivateKey struct {
|
||||
Type KeyType `protobuf:"varint,1,req,name=Type,enum=crypto.pb.KeyType" json:"Type"`
|
||||
Data []byte `protobuf:"bytes,2,req,name=Data" json:"Data"`
|
||||
}
|
||||
|
||||
func (m *PrivateKey) Reset() { *m = PrivateKey{} }
|
||||
func (m *PrivateKey) String() string { return proto.CompactTextString(m) }
|
||||
func (*PrivateKey) ProtoMessage() {}
|
||||
func (*PrivateKey) Descriptor() ([]byte, []int) {
|
||||
return fileDescriptor_527278fb02d03321, []int{1}
|
||||
}
|
||||
func (m *PrivateKey) XXX_Unmarshal(b []byte) error {
|
||||
return m.Unmarshal(b)
|
||||
}
|
||||
func (m *PrivateKey) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) {
|
||||
if deterministic {
|
||||
return xxx_messageInfo_PrivateKey.Marshal(b, m, deterministic)
|
||||
} else {
|
||||
b = b[:cap(b)]
|
||||
n, err := m.MarshalTo(b)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return b[:n], nil
|
||||
}
|
||||
}
|
||||
func (m *PrivateKey) XXX_Merge(src proto.Message) {
|
||||
xxx_messageInfo_PrivateKey.Merge(m, src)
|
||||
}
|
||||
func (m *PrivateKey) XXX_Size() int {
|
||||
return m.Size()
|
||||
}
|
||||
func (m *PrivateKey) XXX_DiscardUnknown() {
|
||||
xxx_messageInfo_PrivateKey.DiscardUnknown(m)
|
||||
}
|
||||
|
||||
var xxx_messageInfo_PrivateKey proto.InternalMessageInfo
|
||||
|
||||
func (m *PrivateKey) GetType() KeyType {
|
||||
if m != nil {
|
||||
return m.Type
|
||||
}
|
||||
return KeyType_RSA
|
||||
}
|
||||
|
||||
func (m *PrivateKey) GetData() []byte {
|
||||
if m != nil {
|
||||
return m.Data
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func init() {
|
||||
proto.RegisterEnum("crypto.pb.KeyType", KeyType_name, KeyType_value)
|
||||
proto.RegisterType((*PublicKey)(nil), "crypto.pb.PublicKey")
|
||||
proto.RegisterType((*PrivateKey)(nil), "crypto.pb.PrivateKey")
|
||||
}
|
||||
|
||||
func init() { proto.RegisterFile("crypto.proto", fileDescriptor_527278fb02d03321) }
|
||||
|
||||
var fileDescriptor_527278fb02d03321 = []byte{
|
||||
// 203 bytes of a gzipped FileDescriptorProto
|
||||
0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0xe2, 0xe2, 0x49, 0x2e, 0xaa, 0x2c,
|
||||
0x28, 0xc9, 0xd7, 0x2b, 0x28, 0xca, 0x2f, 0xc9, 0x17, 0xe2, 0x84, 0xf1, 0x92, 0x94, 0x82, 0xb9,
|
||||
0x38, 0x03, 0x4a, 0x93, 0x72, 0x32, 0x93, 0xbd, 0x53, 0x2b, 0x85, 0x74, 0xb8, 0x58, 0x42, 0x2a,
|
||||
0x0b, 0x52, 0x25, 0x18, 0x15, 0x98, 0x34, 0xf8, 0x8c, 0x84, 0xf4, 0xe0, 0xca, 0xf4, 0xbc, 0x53,
|
||||
0x2b, 0x41, 0x32, 0x4e, 0x2c, 0x27, 0xee, 0xc9, 0x33, 0x04, 0x81, 0x55, 0x09, 0x49, 0x70, 0xb1,
|
||||
0xb8, 0x24, 0x96, 0x24, 0x4a, 0x30, 0x29, 0x30, 0x69, 0xf0, 0xc0, 0x64, 0x40, 0x22, 0x4a, 0x21,
|
||||
0x5c, 0x5c, 0x01, 0x45, 0x99, 0x65, 0x89, 0x25, 0xa9, 0x54, 0x34, 0x55, 0xcb, 0x92, 0x8b, 0x1d,
|
||||
0xaa, 0x41, 0x88, 0x9d, 0x8b, 0x39, 0x28, 0xd8, 0x51, 0x80, 0x41, 0x88, 0x9b, 0x8b, 0xdd, 0x35,
|
||||
0xc5, 0xc8, 0xd4, 0xd4, 0xd0, 0x52, 0x80, 0x51, 0x88, 0x97, 0x8b, 0x33, 0x38, 0x35, 0xb9, 0xc0,
|
||||
0xc8, 0xd4, 0x2c, 0xdb, 0x50, 0x80, 0x49, 0x88, 0x93, 0x8b, 0xd5, 0xd5, 0xd9, 0x25, 0xd8, 0x51,
|
||||
0x80, 0xd9, 0x49, 0xe2, 0xc4, 0x23, 0x39, 0xc6, 0x0b, 0x8f, 0xe4, 0x18, 0x1f, 0x3c, 0x92, 0x63,
|
||||
0x9c, 0xf0, 0x58, 0x8e, 0xe1, 0xc2, 0x63, 0x39, 0x86, 0x1b, 0x8f, 0xe5, 0x18, 0x00, 0x01, 0x00,
|
||||
0x00, 0xff, 0xff, 0x13, 0xbe, 0xd4, 0xff, 0x19, 0x01, 0x00, 0x00,
|
||||
}
|
||||
|
||||
func (m *PublicKey) Marshal() (dAtA []byte, err error) {
|
||||
size := m.Size()
|
||||
dAtA = make([]byte, size)
|
||||
n, err := m.MarshalTo(dAtA)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return dAtA[:n], nil
|
||||
}
|
||||
|
||||
func (m *PublicKey) MarshalTo(dAtA []byte) (int, error) {
|
||||
var i int
|
||||
_ = i
|
||||
var l int
|
||||
_ = l
|
||||
dAtA[i] = 0x8
|
||||
i++
|
||||
i = encodeVarintCrypto(dAtA, i, uint64(m.Type))
|
||||
if m.Data != nil {
|
||||
dAtA[i] = 0x12
|
||||
i++
|
||||
i = encodeVarintCrypto(dAtA, i, uint64(len(m.Data)))
|
||||
i += copy(dAtA[i:], m.Data)
|
||||
}
|
||||
return i, nil
|
||||
}
|
||||
|
||||
func (m *PrivateKey) Marshal() (dAtA []byte, err error) {
|
||||
size := m.Size()
|
||||
dAtA = make([]byte, size)
|
||||
n, err := m.MarshalTo(dAtA)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return dAtA[:n], nil
|
||||
}
|
||||
|
||||
func (m *PrivateKey) MarshalTo(dAtA []byte) (int, error) {
|
||||
var i int
|
||||
_ = i
|
||||
var l int
|
||||
_ = l
|
||||
dAtA[i] = 0x8
|
||||
i++
|
||||
i = encodeVarintCrypto(dAtA, i, uint64(m.Type))
|
||||
if m.Data != nil {
|
||||
dAtA[i] = 0x12
|
||||
i++
|
||||
i = encodeVarintCrypto(dAtA, i, uint64(len(m.Data)))
|
||||
i += copy(dAtA[i:], m.Data)
|
||||
}
|
||||
return i, nil
|
||||
}
|
||||
|
||||
func encodeVarintCrypto(dAtA []byte, offset int, v uint64) int {
|
||||
for v >= 1<<7 {
|
||||
dAtA[offset] = uint8(v&0x7f | 0x80)
|
||||
v >>= 7
|
||||
offset++
|
||||
}
|
||||
dAtA[offset] = uint8(v)
|
||||
return offset + 1
|
||||
}
|
||||
func (m *PublicKey) Size() (n int) {
|
||||
if m == nil {
|
||||
return 0
|
||||
}
|
||||
var l int
|
||||
_ = l
|
||||
n += 1 + sovCrypto(uint64(m.Type))
|
||||
if m.Data != nil {
|
||||
l = len(m.Data)
|
||||
n += 1 + l + sovCrypto(uint64(l))
|
||||
}
|
||||
return n
|
||||
}
|
||||
|
||||
func (m *PrivateKey) Size() (n int) {
|
||||
if m == nil {
|
||||
return 0
|
||||
}
|
||||
var l int
|
||||
_ = l
|
||||
n += 1 + sovCrypto(uint64(m.Type))
|
||||
if m.Data != nil {
|
||||
l = len(m.Data)
|
||||
n += 1 + l + sovCrypto(uint64(l))
|
||||
}
|
||||
return n
|
||||
}
|
||||
|
||||
func sovCrypto(x uint64) (n int) {
|
||||
for {
|
||||
n++
|
||||
x >>= 7
|
||||
if x == 0 {
|
||||
break
|
||||
}
|
||||
}
|
||||
return n
|
||||
}
|
||||
func sozCrypto(x uint64) (n int) {
|
||||
return sovCrypto(uint64((x << 1) ^ uint64((int64(x) >> 63))))
|
||||
}
|
||||
func (m *PublicKey) Unmarshal(dAtA []byte) error {
|
||||
var hasFields [1]uint64
|
||||
l := len(dAtA)
|
||||
iNdEx := 0
|
||||
for iNdEx < l {
|
||||
preIndex := iNdEx
|
||||
var wire uint64
|
||||
for shift := uint(0); ; shift += 7 {
|
||||
if shift >= 64 {
|
||||
return ErrIntOverflowCrypto
|
||||
}
|
||||
if iNdEx >= l {
|
||||
return io.ErrUnexpectedEOF
|
||||
}
|
||||
b := dAtA[iNdEx]
|
||||
iNdEx++
|
||||
wire |= uint64(b&0x7F) << shift
|
||||
if b < 0x80 {
|
||||
break
|
||||
}
|
||||
}
|
||||
fieldNum := int32(wire >> 3)
|
||||
wireType := int(wire & 0x7)
|
||||
if wireType == 4 {
|
||||
return fmt.Errorf("proto: PublicKey: wiretype end group for non-group")
|
||||
}
|
||||
if fieldNum <= 0 {
|
||||
return fmt.Errorf("proto: PublicKey: illegal tag %d (wire type %d)", fieldNum, wire)
|
||||
}
|
||||
switch fieldNum {
|
||||
case 1:
|
||||
if wireType != 0 {
|
||||
return fmt.Errorf("proto: wrong wireType = %d for field Type", wireType)
|
||||
}
|
||||
m.Type = 0
|
||||
for shift := uint(0); ; shift += 7 {
|
||||
if shift >= 64 {
|
||||
return ErrIntOverflowCrypto
|
||||
}
|
||||
if iNdEx >= l {
|
||||
return io.ErrUnexpectedEOF
|
||||
}
|
||||
b := dAtA[iNdEx]
|
||||
iNdEx++
|
||||
m.Type |= KeyType(b&0x7F) << shift
|
||||
if b < 0x80 {
|
||||
break
|
||||
}
|
||||
}
|
||||
hasFields[0] |= uint64(0x00000001)
|
||||
case 2:
|
||||
if wireType != 2 {
|
||||
return fmt.Errorf("proto: wrong wireType = %d for field Data", wireType)
|
||||
}
|
||||
var byteLen int
|
||||
for shift := uint(0); ; shift += 7 {
|
||||
if shift >= 64 {
|
||||
return ErrIntOverflowCrypto
|
||||
}
|
||||
if iNdEx >= l {
|
||||
return io.ErrUnexpectedEOF
|
||||
}
|
||||
b := dAtA[iNdEx]
|
||||
iNdEx++
|
||||
byteLen |= int(b&0x7F) << shift
|
||||
if b < 0x80 {
|
||||
break
|
||||
}
|
||||
}
|
||||
if byteLen < 0 {
|
||||
return ErrInvalidLengthCrypto
|
||||
}
|
||||
postIndex := iNdEx + byteLen
|
||||
if postIndex < 0 {
|
||||
return ErrInvalidLengthCrypto
|
||||
}
|
||||
if postIndex > l {
|
||||
return io.ErrUnexpectedEOF
|
||||
}
|
||||
m.Data = append(m.Data[:0], dAtA[iNdEx:postIndex]...)
|
||||
if m.Data == nil {
|
||||
m.Data = []byte{}
|
||||
}
|
||||
iNdEx = postIndex
|
||||
hasFields[0] |= uint64(0x00000002)
|
||||
default:
|
||||
iNdEx = preIndex
|
||||
skippy, err := skipCrypto(dAtA[iNdEx:])
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
if skippy < 0 {
|
||||
return ErrInvalidLengthCrypto
|
||||
}
|
||||
if (iNdEx + skippy) < 0 {
|
||||
return ErrInvalidLengthCrypto
|
||||
}
|
||||
if (iNdEx + skippy) > l {
|
||||
return io.ErrUnexpectedEOF
|
||||
}
|
||||
iNdEx += skippy
|
||||
}
|
||||
}
|
||||
if hasFields[0]&uint64(0x00000001) == 0 {
|
||||
return github_com_gogo_protobuf_proto.NewRequiredNotSetError("Type")
|
||||
}
|
||||
if hasFields[0]&uint64(0x00000002) == 0 {
|
||||
return github_com_gogo_protobuf_proto.NewRequiredNotSetError("Data")
|
||||
}
|
||||
|
||||
if iNdEx > l {
|
||||
return io.ErrUnexpectedEOF
|
||||
}
|
||||
return nil
|
||||
}
|
||||
func (m *PrivateKey) Unmarshal(dAtA []byte) error {
|
||||
var hasFields [1]uint64
|
||||
l := len(dAtA)
|
||||
iNdEx := 0
|
||||
for iNdEx < l {
|
||||
preIndex := iNdEx
|
||||
var wire uint64
|
||||
for shift := uint(0); ; shift += 7 {
|
||||
if shift >= 64 {
|
||||
return ErrIntOverflowCrypto
|
||||
}
|
||||
if iNdEx >= l {
|
||||
return io.ErrUnexpectedEOF
|
||||
}
|
||||
b := dAtA[iNdEx]
|
||||
iNdEx++
|
||||
wire |= uint64(b&0x7F) << shift
|
||||
if b < 0x80 {
|
||||
break
|
||||
}
|
||||
}
|
||||
fieldNum := int32(wire >> 3)
|
||||
wireType := int(wire & 0x7)
|
||||
if wireType == 4 {
|
||||
return fmt.Errorf("proto: PrivateKey: wiretype end group for non-group")
|
||||
}
|
||||
if fieldNum <= 0 {
|
||||
return fmt.Errorf("proto: PrivateKey: illegal tag %d (wire type %d)", fieldNum, wire)
|
||||
}
|
||||
switch fieldNum {
|
||||
case 1:
|
||||
if wireType != 0 {
|
||||
return fmt.Errorf("proto: wrong wireType = %d for field Type", wireType)
|
||||
}
|
||||
m.Type = 0
|
||||
for shift := uint(0); ; shift += 7 {
|
||||
if shift >= 64 {
|
||||
return ErrIntOverflowCrypto
|
||||
}
|
||||
if iNdEx >= l {
|
||||
return io.ErrUnexpectedEOF
|
||||
}
|
||||
b := dAtA[iNdEx]
|
||||
iNdEx++
|
||||
m.Type |= KeyType(b&0x7F) << shift
|
||||
if b < 0x80 {
|
||||
break
|
||||
}
|
||||
}
|
||||
hasFields[0] |= uint64(0x00000001)
|
||||
case 2:
|
||||
if wireType != 2 {
|
||||
return fmt.Errorf("proto: wrong wireType = %d for field Data", wireType)
|
||||
}
|
||||
var byteLen int
|
||||
for shift := uint(0); ; shift += 7 {
|
||||
if shift >= 64 {
|
||||
return ErrIntOverflowCrypto
|
||||
}
|
||||
if iNdEx >= l {
|
||||
return io.ErrUnexpectedEOF
|
||||
}
|
||||
b := dAtA[iNdEx]
|
||||
iNdEx++
|
||||
byteLen |= int(b&0x7F) << shift
|
||||
if b < 0x80 {
|
||||
break
|
||||
}
|
||||
}
|
||||
if byteLen < 0 {
|
||||
return ErrInvalidLengthCrypto
|
||||
}
|
||||
postIndex := iNdEx + byteLen
|
||||
if postIndex < 0 {
|
||||
return ErrInvalidLengthCrypto
|
||||
}
|
||||
if postIndex > l {
|
||||
return io.ErrUnexpectedEOF
|
||||
}
|
||||
m.Data = append(m.Data[:0], dAtA[iNdEx:postIndex]...)
|
||||
if m.Data == nil {
|
||||
m.Data = []byte{}
|
||||
}
|
||||
iNdEx = postIndex
|
||||
hasFields[0] |= uint64(0x00000002)
|
||||
default:
|
||||
iNdEx = preIndex
|
||||
skippy, err := skipCrypto(dAtA[iNdEx:])
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
if skippy < 0 {
|
||||
return ErrInvalidLengthCrypto
|
||||
}
|
||||
if (iNdEx + skippy) < 0 {
|
||||
return ErrInvalidLengthCrypto
|
||||
}
|
||||
if (iNdEx + skippy) > l {
|
||||
return io.ErrUnexpectedEOF
|
||||
}
|
||||
iNdEx += skippy
|
||||
}
|
||||
}
|
||||
if hasFields[0]&uint64(0x00000001) == 0 {
|
||||
return github_com_gogo_protobuf_proto.NewRequiredNotSetError("Type")
|
||||
}
|
||||
if hasFields[0]&uint64(0x00000002) == 0 {
|
||||
return github_com_gogo_protobuf_proto.NewRequiredNotSetError("Data")
|
||||
}
|
||||
|
||||
if iNdEx > l {
|
||||
return io.ErrUnexpectedEOF
|
||||
}
|
||||
return nil
|
||||
}
|
||||
func skipCrypto(dAtA []byte) (n int, err error) {
|
||||
l := len(dAtA)
|
||||
iNdEx := 0
|
||||
for iNdEx < l {
|
||||
var wire uint64
|
||||
for shift := uint(0); ; shift += 7 {
|
||||
if shift >= 64 {
|
||||
return 0, ErrIntOverflowCrypto
|
||||
}
|
||||
if iNdEx >= l {
|
||||
return 0, io.ErrUnexpectedEOF
|
||||
}
|
||||
b := dAtA[iNdEx]
|
||||
iNdEx++
|
||||
wire |= (uint64(b) & 0x7F) << shift
|
||||
if b < 0x80 {
|
||||
break
|
||||
}
|
||||
}
|
||||
wireType := int(wire & 0x7)
|
||||
switch wireType {
|
||||
case 0:
|
||||
for shift := uint(0); ; shift += 7 {
|
||||
if shift >= 64 {
|
||||
return 0, ErrIntOverflowCrypto
|
||||
}
|
||||
if iNdEx >= l {
|
||||
return 0, io.ErrUnexpectedEOF
|
||||
}
|
||||
iNdEx++
|
||||
if dAtA[iNdEx-1] < 0x80 {
|
||||
break
|
||||
}
|
||||
}
|
||||
return iNdEx, nil
|
||||
case 1:
|
||||
iNdEx += 8
|
||||
return iNdEx, nil
|
||||
case 2:
|
||||
var length int
|
||||
for shift := uint(0); ; shift += 7 {
|
||||
if shift >= 64 {
|
||||
return 0, ErrIntOverflowCrypto
|
||||
}
|
||||
if iNdEx >= l {
|
||||
return 0, io.ErrUnexpectedEOF
|
||||
}
|
||||
b := dAtA[iNdEx]
|
||||
iNdEx++
|
||||
length |= (int(b) & 0x7F) << shift
|
||||
if b < 0x80 {
|
||||
break
|
||||
}
|
||||
}
|
||||
if length < 0 {
|
||||
return 0, ErrInvalidLengthCrypto
|
||||
}
|
||||
iNdEx += length
|
||||
if iNdEx < 0 {
|
||||
return 0, ErrInvalidLengthCrypto
|
||||
}
|
||||
return iNdEx, nil
|
||||
case 3:
|
||||
for {
|
||||
var innerWire uint64
|
||||
var start int = iNdEx
|
||||
for shift := uint(0); ; shift += 7 {
|
||||
if shift >= 64 {
|
||||
return 0, ErrIntOverflowCrypto
|
||||
}
|
||||
if iNdEx >= l {
|
||||
return 0, io.ErrUnexpectedEOF
|
||||
}
|
||||
b := dAtA[iNdEx]
|
||||
iNdEx++
|
||||
innerWire |= (uint64(b) & 0x7F) << shift
|
||||
if b < 0x80 {
|
||||
break
|
||||
}
|
||||
}
|
||||
innerWireType := int(innerWire & 0x7)
|
||||
if innerWireType == 4 {
|
||||
break
|
||||
}
|
||||
next, err := skipCrypto(dAtA[start:])
|
||||
if err != nil {
|
||||
return 0, err
|
||||
}
|
||||
iNdEx = start + next
|
||||
if iNdEx < 0 {
|
||||
return 0, ErrInvalidLengthCrypto
|
||||
}
|
||||
}
|
||||
return iNdEx, nil
|
||||
case 4:
|
||||
return iNdEx, nil
|
||||
case 5:
|
||||
iNdEx += 4
|
||||
return iNdEx, nil
|
||||
default:
|
||||
return 0, fmt.Errorf("proto: illegal wireType %d", wireType)
|
||||
}
|
||||
}
|
||||
panic("unreachable")
|
||||
}
|
||||
|
||||
var (
|
||||
ErrInvalidLengthCrypto = fmt.Errorf("proto: negative length found during unmarshaling")
|
||||
ErrIntOverflowCrypto = fmt.Errorf("proto: integer overflow")
|
||||
)
|
20
crypto/pb/crypto.proto
Normal file
20
crypto/pb/crypto.proto
Normal file
@ -0,0 +1,20 @@
|
||||
syntax = "proto2";
|
||||
|
||||
package crypto.pb;
|
||||
|
||||
enum KeyType {
|
||||
RSA = 0;
|
||||
Ed25519 = 1;
|
||||
Secp256k1 = 2;
|
||||
ECDSA = 3;
|
||||
}
|
||||
|
||||
message PublicKey {
|
||||
required KeyType Type = 1;
|
||||
required bytes Data = 2;
|
||||
}
|
||||
|
||||
message PrivateKey {
|
||||
required KeyType Type = 1;
|
||||
required bytes Data = 2;
|
||||
}
|
152
crypto/rsa.go
Normal file
152
crypto/rsa.go
Normal file
@ -0,0 +1,152 @@
|
||||
package crypto
|
||||
|
||||
import (
|
||||
"crypto"
|
||||
"crypto/rand"
|
||||
"crypto/rsa"
|
||||
"crypto/x509"
|
||||
"errors"
|
||||
"io"
|
||||
|
||||
pb "github.com/libp2p/go-libp2p-core/crypto/pb"
|
||||
|
||||
sha256 "github.com/minio/sha256-simd"
|
||||
)
|
||||
|
||||
// ErrRsaKeyTooSmall is returned when trying to generate or parse an RSA key
|
||||
// that's smaller than 512 bits. Keys need to be larger enough to sign a 256bit
|
||||
// hash so this is a reasonable absolute minimum.
|
||||
var ErrRsaKeyTooSmall = errors.New("rsa keys must be >= 512 bits to be useful")
|
||||
|
||||
// RsaPrivateKey is an rsa private key
|
||||
type RsaPrivateKey struct {
|
||||
sk *rsa.PrivateKey
|
||||
pk *rsa.PublicKey
|
||||
}
|
||||
|
||||
// RsaPublicKey is an rsa public key
|
||||
type RsaPublicKey struct {
|
||||
k *rsa.PublicKey
|
||||
}
|
||||
|
||||
// GenerateRSAKeyPair generates a new rsa private and public key
|
||||
func GenerateRSAKeyPair(bits int, src io.Reader) (PrivKey, PubKey, error) {
|
||||
if bits < 512 {
|
||||
return nil, nil, ErrRsaKeyTooSmall
|
||||
}
|
||||
priv, err := rsa.GenerateKey(src, bits)
|
||||
if err != nil {
|
||||
return nil, nil, err
|
||||
}
|
||||
pk := &priv.PublicKey
|
||||
return &RsaPrivateKey{sk: priv}, &RsaPublicKey{pk}, nil
|
||||
}
|
||||
|
||||
// Verify compares a signature against input data
|
||||
func (pk *RsaPublicKey) Verify(data, sig []byte) (bool, error) {
|
||||
hashed := sha256.Sum256(data)
|
||||
err := rsa.VerifyPKCS1v15(pk.k, crypto.SHA256, hashed[:], sig)
|
||||
if err != nil {
|
||||
return false, err
|
||||
}
|
||||
return true, nil
|
||||
}
|
||||
|
||||
func (pk *RsaPublicKey) Type() pb.KeyType {
|
||||
return pb.KeyType_RSA
|
||||
}
|
||||
|
||||
// Bytes returns protobuf bytes of a public key
|
||||
func (pk *RsaPublicKey) Bytes() ([]byte, error) {
|
||||
return MarshalPublicKey(pk)
|
||||
}
|
||||
|
||||
func (pk *RsaPublicKey) Raw() ([]byte, error) {
|
||||
return x509.MarshalPKIXPublicKey(pk.k)
|
||||
}
|
||||
|
||||
// Encrypt returns encrypted bytes from the inpu data
|
||||
func (pk *RsaPublicKey) Encrypt(b []byte) ([]byte, error) {
|
||||
return rsa.EncryptPKCS1v15(rand.Reader, pk.k, b)
|
||||
}
|
||||
|
||||
// Equals checks whether this key is equal to another
|
||||
func (pk *RsaPublicKey) Equals(k Key) bool {
|
||||
return KeyEqual(pk, k)
|
||||
}
|
||||
|
||||
// Sign returns a signature of the input data
|
||||
func (sk *RsaPrivateKey) Sign(message []byte) ([]byte, error) {
|
||||
hashed := sha256.Sum256(message)
|
||||
return rsa.SignPKCS1v15(rand.Reader, sk.sk, crypto.SHA256, hashed[:])
|
||||
}
|
||||
|
||||
// GetPublic returns a public key
|
||||
func (sk *RsaPrivateKey) GetPublic() PubKey {
|
||||
if sk.pk == nil {
|
||||
sk.pk = &sk.sk.PublicKey
|
||||
}
|
||||
return &RsaPublicKey{sk.pk}
|
||||
}
|
||||
|
||||
// Decrypt returns decrypted bytes of the input encrypted bytes
|
||||
func (sk *RsaPrivateKey) Decrypt(b []byte) ([]byte, error) {
|
||||
return rsa.DecryptPKCS1v15(rand.Reader, sk.sk, b)
|
||||
}
|
||||
|
||||
func (sk *RsaPrivateKey) Type() pb.KeyType {
|
||||
return pb.KeyType_RSA
|
||||
}
|
||||
|
||||
// Bytes returns protobuf bytes from a private key
|
||||
func (sk *RsaPrivateKey) Bytes() ([]byte, error) {
|
||||
return MarshalPrivateKey(sk)
|
||||
}
|
||||
|
||||
func (sk *RsaPrivateKey) Raw() ([]byte, error) {
|
||||
b := x509.MarshalPKCS1PrivateKey(sk.sk)
|
||||
return b, nil
|
||||
}
|
||||
|
||||
// Equals checks whether this key is equal to another
|
||||
func (sk *RsaPrivateKey) Equals(k Key) bool {
|
||||
return KeyEqual(sk, k)
|
||||
}
|
||||
|
||||
// UnmarshalRsaPrivateKey returns a private key from the input x509 bytes
|
||||
func UnmarshalRsaPrivateKey(b []byte) (PrivKey, error) {
|
||||
sk, err := x509.ParsePKCS1PrivateKey(b)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
if sk.N.BitLen() < 512 {
|
||||
return nil, ErrRsaKeyTooSmall
|
||||
}
|
||||
return &RsaPrivateKey{sk: sk}, nil
|
||||
}
|
||||
|
||||
// MarshalRsaPrivateKey returns the x509 bytes of the private key
|
||||
func MarshalRsaPrivateKey(k *RsaPrivateKey) []byte {
|
||||
return x509.MarshalPKCS1PrivateKey(k.sk)
|
||||
}
|
||||
|
||||
// UnmarshalRsaPublicKey returns a public key from the input x509 bytes
|
||||
func UnmarshalRsaPublicKey(b []byte) (PubKey, error) {
|
||||
pub, err := x509.ParsePKIXPublicKey(b)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
pk, ok := pub.(*rsa.PublicKey)
|
||||
if !ok {
|
||||
return nil, errors.New("not actually an rsa public key")
|
||||
}
|
||||
if pk.N.BitLen() < 512 {
|
||||
return nil, ErrRsaKeyTooSmall
|
||||
}
|
||||
return &RsaPublicKey{pk}, nil
|
||||
}
|
||||
|
||||
// MarshalRsaPublicKey returns the x509 bytes from the public key
|
||||
func MarshalRsaPublicKey(k *RsaPublicKey) ([]byte, error) {
|
||||
return x509.MarshalPKIXPublicKey(k.k)
|
||||
}
|
102
crypto/rsa_test.go
Normal file
102
crypto/rsa_test.go
Normal file
@ -0,0 +1,102 @@
|
||||
package crypto
|
||||
|
||||
import (
|
||||
"crypto/rand"
|
||||
"testing"
|
||||
)
|
||||
|
||||
func TestRSABasicSignAndVerify(t *testing.T) {
|
||||
priv, pub, err := GenerateRSAKeyPair(512, rand.Reader)
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
|
||||
data := []byte("hello! and welcome to some awesome crypto primitives")
|
||||
|
||||
sig, err := priv.Sign(data)
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
|
||||
ok, err := pub.Verify(data, sig)
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
|
||||
if !ok {
|
||||
t.Fatal("signature didnt match")
|
||||
}
|
||||
|
||||
// change data
|
||||
data[0] = ^data[0]
|
||||
ok, err = pub.Verify(data, sig)
|
||||
if err == nil {
|
||||
t.Fatal("should have produced a verification error")
|
||||
}
|
||||
|
||||
if ok {
|
||||
t.Fatal("signature matched and shouldn't")
|
||||
}
|
||||
}
|
||||
|
||||
func TestRSASmallKey(t *testing.T) {
|
||||
_, _, err := GenerateRSAKeyPair(384, rand.Reader)
|
||||
if err != ErrRsaKeyTooSmall {
|
||||
t.Fatal("should have refused to create small RSA key")
|
||||
}
|
||||
}
|
||||
|
||||
func TestRSASignZero(t *testing.T) {
|
||||
priv, pub, err := GenerateRSAKeyPair(512, rand.Reader)
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
|
||||
data := make([]byte, 0)
|
||||
sig, err := priv.Sign(data)
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
|
||||
ok, err := pub.Verify(data, sig)
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
if !ok {
|
||||
t.Fatal("signature didn't match")
|
||||
}
|
||||
}
|
||||
|
||||
func TestRSAMarshalLoop(t *testing.T) {
|
||||
priv, pub, err := GenerateRSAKeyPair(512, rand.Reader)
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
|
||||
privB, err := priv.Bytes()
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
|
||||
privNew, err := UnmarshalPrivateKey(privB)
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
|
||||
if !priv.Equals(privNew) || !privNew.Equals(priv) {
|
||||
t.Fatal("keys are not equal")
|
||||
}
|
||||
|
||||
pubB, err := pub.Bytes()
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
pubNew, err := UnmarshalPublicKey(pubB)
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
|
||||
if !pub.Equals(pubNew) || !pubNew.Equals(pub) {
|
||||
t.Fatal("keys are not equal")
|
||||
}
|
||||
}
|
125
crypto/secp256k1.go
Normal file
125
crypto/secp256k1.go
Normal file
@ -0,0 +1,125 @@
|
||||
package crypto
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"io"
|
||||
|
||||
pb "github.com/libp2p/go-libp2p-core/crypto/pb"
|
||||
|
||||
btcec "github.com/btcsuite/btcd/btcec"
|
||||
sha256 "github.com/minio/sha256-simd"
|
||||
)
|
||||
|
||||
// Secp256k1PrivateKey is an Secp256k1 private key
|
||||
type Secp256k1PrivateKey btcec.PrivateKey
|
||||
|
||||
// Secp256k1PublicKey is an Secp256k1 public key
|
||||
type Secp256k1PublicKey btcec.PublicKey
|
||||
|
||||
// GenerateSecp256k1Key generates a new Secp256k1 private and public key pair
|
||||
func GenerateSecp256k1Key(src io.Reader) (PrivKey, PubKey, error) {
|
||||
privk, err := btcec.NewPrivateKey(btcec.S256())
|
||||
if err != nil {
|
||||
return nil, nil, err
|
||||
}
|
||||
|
||||
k := (*Secp256k1PrivateKey)(privk)
|
||||
return k, k.GetPublic(), nil
|
||||
}
|
||||
|
||||
// UnmarshalSecp256k1PrivateKey returns a private key from bytes
|
||||
func UnmarshalSecp256k1PrivateKey(data []byte) (PrivKey, error) {
|
||||
if len(data) != btcec.PrivKeyBytesLen {
|
||||
return nil, fmt.Errorf("expected secp256k1 data size to be %d", btcec.PrivKeyBytesLen)
|
||||
}
|
||||
|
||||
privk, _ := btcec.PrivKeyFromBytes(btcec.S256(), data)
|
||||
return (*Secp256k1PrivateKey)(privk), nil
|
||||
}
|
||||
|
||||
// UnmarshalSecp256k1PublicKey returns a public key from bytes
|
||||
func UnmarshalSecp256k1PublicKey(data []byte) (PubKey, error) {
|
||||
k, err := btcec.ParsePubKey(data, btcec.S256())
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
return (*Secp256k1PublicKey)(k), nil
|
||||
}
|
||||
|
||||
// Bytes returns protobuf bytes from a private key
|
||||
func (k *Secp256k1PrivateKey) Bytes() ([]byte, error) {
|
||||
return MarshalPrivateKey(k)
|
||||
}
|
||||
|
||||
// Type returns the private key type
|
||||
func (k *Secp256k1PrivateKey) Type() pb.KeyType {
|
||||
return pb.KeyType_Secp256k1
|
||||
}
|
||||
|
||||
// Raw returns the bytes of the key
|
||||
func (k *Secp256k1PrivateKey) Raw() ([]byte, error) {
|
||||
return (*btcec.PrivateKey)(k).Serialize(), nil
|
||||
}
|
||||
|
||||
// Equals compares two private keys
|
||||
func (k *Secp256k1PrivateKey) Equals(o Key) bool {
|
||||
sk, ok := o.(*Secp256k1PrivateKey)
|
||||
if !ok {
|
||||
return false
|
||||
}
|
||||
|
||||
return k.D.Cmp(sk.D) == 0
|
||||
}
|
||||
|
||||
// Sign returns a signature from input data
|
||||
func (k *Secp256k1PrivateKey) Sign(data []byte) ([]byte, error) {
|
||||
hash := sha256.Sum256(data)
|
||||
sig, err := (*btcec.PrivateKey)(k).Sign(hash[:])
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
return sig.Serialize(), nil
|
||||
}
|
||||
|
||||
// GetPublic returns a public key
|
||||
func (k *Secp256k1PrivateKey) GetPublic() PubKey {
|
||||
return (*Secp256k1PublicKey)((*btcec.PrivateKey)(k).PubKey())
|
||||
}
|
||||
|
||||
// Bytes returns protobuf bytes from a public key
|
||||
func (k *Secp256k1PublicKey) Bytes() ([]byte, error) {
|
||||
return MarshalPublicKey(k)
|
||||
}
|
||||
|
||||
// Type returns the public key type
|
||||
func (k *Secp256k1PublicKey) Type() pb.KeyType {
|
||||
return pb.KeyType_Secp256k1
|
||||
}
|
||||
|
||||
// Raw returns the bytes of the key
|
||||
func (k *Secp256k1PublicKey) Raw() ([]byte, error) {
|
||||
return (*btcec.PublicKey)(k).SerializeCompressed(), nil
|
||||
}
|
||||
|
||||
// Equals compares two public keys
|
||||
func (k *Secp256k1PublicKey) Equals(o Key) bool {
|
||||
sk, ok := o.(*Secp256k1PublicKey)
|
||||
if !ok {
|
||||
return false
|
||||
}
|
||||
|
||||
return (*btcec.PublicKey)(k).IsEqual((*btcec.PublicKey)(sk))
|
||||
}
|
||||
|
||||
// Verify compares a signature against the input data
|
||||
func (k *Secp256k1PublicKey) Verify(data []byte, sigStr []byte) (bool, error) {
|
||||
sig, err := btcec.ParseDERSignature(sigStr, btcec.S256())
|
||||
if err != nil {
|
||||
return false, err
|
||||
}
|
||||
|
||||
hash := sha256.Sum256(data)
|
||||
return sig.Verify(hash[:], (*btcec.PublicKey)(k)), nil
|
||||
}
|
96
crypto/secp256k1_test.go
Normal file
96
crypto/secp256k1_test.go
Normal file
@ -0,0 +1,96 @@
|
||||
package crypto
|
||||
|
||||
import (
|
||||
"crypto/rand"
|
||||
"testing"
|
||||
)
|
||||
|
||||
func TestSecp256k1BasicSignAndVerify(t *testing.T) {
|
||||
priv, pub, err := GenerateSecp256k1Key(rand.Reader)
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
|
||||
data := []byte("hello! and welcome to some awesome crypto primitives")
|
||||
|
||||
sig, err := priv.Sign(data)
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
|
||||
ok, err := pub.Verify(data, sig)
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
|
||||
if !ok {
|
||||
t.Fatal("signature didnt match")
|
||||
}
|
||||
|
||||
// change data
|
||||
data[0] = ^data[0]
|
||||
ok, err = pub.Verify(data, sig)
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
|
||||
if ok {
|
||||
t.Fatal("signature matched and shouldn't")
|
||||
}
|
||||
}
|
||||
|
||||
func TestSecp256k1SignZero(t *testing.T) {
|
||||
priv, pub, err := GenerateSecp256k1Key(rand.Reader)
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
|
||||
data := make([]byte, 0)
|
||||
sig, err := priv.Sign(data)
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
|
||||
ok, err := pub.Verify(data, sig)
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
if !ok {
|
||||
t.Fatal("signature didn't match")
|
||||
}
|
||||
}
|
||||
|
||||
func TestSecp256k1MarshalLoop(t *testing.T) {
|
||||
priv, pub, err := GenerateSecp256k1Key(rand.Reader)
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
|
||||
privB, err := priv.Bytes()
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
|
||||
privNew, err := UnmarshalPrivateKey(privB)
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
|
||||
if !priv.Equals(privNew) || !privNew.Equals(priv) {
|
||||
t.Fatal("keys are not equal")
|
||||
}
|
||||
|
||||
pubB, err := pub.Bytes()
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
pubNew, err := UnmarshalPublicKey(pubB)
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
|
||||
if !pub.Equals(pubNew) || !pubNew.Equals(pub) {
|
||||
t.Fatal("keys are not equal")
|
||||
}
|
||||
|
||||
}
|
17
crypto/test/utils.go
Normal file
17
crypto/test/utils.go
Normal file
@ -0,0 +1,17 @@
|
||||
package test
|
||||
|
||||
import (
|
||||
"math/rand"
|
||||
"time"
|
||||
|
||||
ci "github.com/libp2p/go-libp2p-core/crypto"
|
||||
)
|
||||
|
||||
func RandTestKeyPair(typ, bits int) (ci.PrivKey, ci.PubKey, error) {
|
||||
return SeededTestKeyPair(typ, bits, time.Now().UnixNano())
|
||||
}
|
||||
|
||||
func SeededTestKeyPair(typ, bits int, seed int64) (ci.PrivKey, ci.PubKey, error) {
|
||||
r := rand.New(rand.NewSource(seed))
|
||||
return ci.GenerateKeyPairWithReader(typ, bits, r)
|
||||
}
|
5
go.mod
5
go.mod
@ -1,14 +1,17 @@
|
||||
module github.com/libp2p/go-libp2p-core
|
||||
|
||||
require (
|
||||
github.com/btcsuite/btcd v0.0.0-20190213025234-306aecffea32
|
||||
github.com/coreos/go-semver v0.3.0
|
||||
github.com/gogo/protobuf v1.2.1
|
||||
github.com/ipfs/go-cid v0.0.1
|
||||
github.com/jbenet/goprocess v0.0.0-20160826012719-b497e2f366b8
|
||||
github.com/kr/pretty v0.1.0 // indirect
|
||||
github.com/libp2p/go-libp2p-crypto v0.0.1
|
||||
github.com/minio/sha256-simd v0.0.0-20190131020904-2d45a736cd16
|
||||
github.com/mr-tron/base58 v1.1.1
|
||||
github.com/multiformats/go-multiaddr v0.0.2
|
||||
github.com/multiformats/go-multihash v0.0.1
|
||||
golang.org/x/crypto v0.0.0-20190225124518-7f87c0fbb88b
|
||||
golang.org/x/sys v0.0.0-20190222072716-a9d3bda3a223 // indirect
|
||||
gopkg.in/check.v1 v1.0.0-20180628173108-788fd7840127 // indirect
|
||||
)
|
||||
|
2
go.sum
2
go.sum
@ -35,8 +35,6 @@ github.com/kr/pretty v0.1.0/go.mod h1:dAy3ld7l9f0ibDNOQOHHMYYIIbhfbHSm3C4ZsoJORN
|
||||
github.com/kr/pty v1.1.1/go.mod h1:pFQYn66WHrOpPYNljwOMqo10TkYh1fy3cYio2l3bCsQ=
|
||||
github.com/kr/text v0.1.0 h1:45sCR5RtlFHMR4UwH9sdQ5TC8v0qDQCHnXt+kaKSTVE=
|
||||
github.com/kr/text v0.1.0/go.mod h1:4Jbv+DJW3UT/LiOwJeYQe1efqtUx/iVham/4vfdArNI=
|
||||
github.com/libp2p/go-libp2p-crypto v0.0.1 h1:JNQd8CmoGTohO/akqrH16ewsqZpci2CbgYH/LmYl8gw=
|
||||
github.com/libp2p/go-libp2p-crypto v0.0.1/go.mod h1:yJkNyDmO341d5wwXxDUGO0LykUVT72ImHNUqh5D/dBE=
|
||||
github.com/minio/blake2b-simd v0.0.0-20160723061019-3f5f724cb5b1 h1:lYpkrQH5ajf0OXOcUbGjvZxxijuBwbbmlSxLiuofa+g=
|
||||
github.com/minio/blake2b-simd v0.0.0-20160723061019-3f5f724cb5b1/go.mod h1:pD8RvIylQ358TN4wwqatJ8rNavkEINozVn9DtGI3dfQ=
|
||||
github.com/minio/sha256-simd v0.0.0-20190131020904-2d45a736cd16 h1:5W7KhL8HVF3XCFOweFD3BNESdnO8ewyYTFT2R+/b8FQ=
|
||||
|
@ -3,8 +3,8 @@ package network
|
||||
import (
|
||||
"io"
|
||||
|
||||
ic "github.com/libp2p/go-libp2p-core/crypto"
|
||||
"github.com/libp2p/go-libp2p-core/peer"
|
||||
ic "github.com/libp2p/go-libp2p-crypto"
|
||||
|
||||
ma "github.com/multiformats/go-multiaddr"
|
||||
)
|
||||
|
@ -6,7 +6,7 @@ import (
|
||||
"errors"
|
||||
"fmt"
|
||||
|
||||
ic "github.com/libp2p/go-libp2p-crypto"
|
||||
ic "github.com/libp2p/go-libp2p-core/crypto"
|
||||
b58 "github.com/mr-tron/base58/base58"
|
||||
mh "github.com/multiformats/go-multihash"
|
||||
)
|
||||
|
@ -7,7 +7,8 @@ import (
|
||||
"strings"
|
||||
"testing"
|
||||
|
||||
ic "github.com/libp2p/go-libp2p-crypto"
|
||||
ic "github.com/libp2p/go-libp2p-core/crypto"
|
||||
"github.com/libp2p/go-libp2p-core/peer"
|
||||
|
||||
tu "github.com/libp2p/go-libp2p-core/peer/test"
|
||||
mh "github.com/multiformats/go-multihash"
|
||||
@ -90,7 +91,7 @@ func (ks *keyset) load(hpkp, skBytesStr string) error {
|
||||
func TestIDMatchesPublicKey(t *testing.T) {
|
||||
|
||||
test := func(ks keyset) {
|
||||
p1, err := IDB58Decode(ks.hpkp)
|
||||
p1, err := peer.IDB58Decode(ks.hpkp)
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
@ -103,7 +104,7 @@ func TestIDMatchesPublicKey(t *testing.T) {
|
||||
t.Fatal("p1 does not match pk")
|
||||
}
|
||||
|
||||
p2, err := IDFromPublicKey(ks.pk)
|
||||
p2, err := peer.IDFromPublicKey(ks.pk)
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
@ -125,7 +126,7 @@ func TestIDMatchesPublicKey(t *testing.T) {
|
||||
func TestIDMatchesPrivateKey(t *testing.T) {
|
||||
|
||||
test := func(ks keyset) {
|
||||
p1, err := IDB58Decode(ks.hpkp)
|
||||
p1, err := peer.IDB58Decode(ks.hpkp)
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
@ -138,7 +139,7 @@ func TestIDMatchesPrivateKey(t *testing.T) {
|
||||
t.Fatal("p1 does not match sk")
|
||||
}
|
||||
|
||||
p2, err := IDFromPrivateKey(ks.sk)
|
||||
p2, err := peer.IDFromPrivateKey(ks.sk)
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
@ -161,7 +162,7 @@ func TestPublicKeyExtraction(t *testing.T) {
|
||||
t.Fatal(err)
|
||||
}
|
||||
|
||||
id, err := IDFromPublicKey(originalPub)
|
||||
id, err := peer.IDFromPublicKey(originalPub)
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
@ -178,7 +179,7 @@ func TestPublicKeyExtraction(t *testing.T) {
|
||||
}
|
||||
|
||||
// Test invalid multihash (invariant of the type of public key)
|
||||
pk, err := ID("").ExtractPublicKey()
|
||||
pk, err := peer.ID("").ExtractPublicKey()
|
||||
if err == nil {
|
||||
t.Fatal("expected an error")
|
||||
}
|
||||
@ -192,12 +193,12 @@ func TestPublicKeyExtraction(t *testing.T) {
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
rsaId, err := IDFromPublicKey(rsaPub)
|
||||
rsaId, err := peer.IDFromPublicKey(rsaPub)
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
extractedRsaPub, err := rsaId.ExtractPublicKey()
|
||||
if err != ErrNoPublicKey {
|
||||
if err != peer.ErrNoPublicKey {
|
||||
t.Fatal(err)
|
||||
}
|
||||
if extractedRsaPub != nil {
|
||||
@ -207,11 +208,11 @@ func TestPublicKeyExtraction(t *testing.T) {
|
||||
|
||||
func TestValidate(t *testing.T) {
|
||||
// Empty peer ID invalidates
|
||||
err := ID("").Validate()
|
||||
err := peer.ID("").Validate()
|
||||
if err == nil {
|
||||
t.Error("expected error")
|
||||
} else if err != ErrEmptyPeerID {
|
||||
t.Error("expected error message: " + ErrEmptyPeerID.Error())
|
||||
} else if err != peer.ErrEmptyPeerID {
|
||||
t.Error("expected error message: " + peer.ErrEmptyPeerID.Error())
|
||||
}
|
||||
|
||||
// Non-empty peer ID validates
|
||||
|
@ -8,7 +8,7 @@ import (
|
||||
|
||||
"github.com/libp2p/go-libp2p-core/peer"
|
||||
|
||||
ci "github.com/libp2p/go-libp2p-crypto"
|
||||
ci "github.com/libp2p/go-libp2p-core/crypto"
|
||||
mh "github.com/multiformats/go-multihash"
|
||||
)
|
||||
|
||||
|
@ -9,7 +9,7 @@ import (
|
||||
|
||||
"github.com/libp2p/go-libp2p-core/peer"
|
||||
|
||||
ic "github.com/libp2p/go-libp2p-crypto"
|
||||
ic "github.com/libp2p/go-libp2p-core/crypto"
|
||||
|
||||
ma "github.com/multiformats/go-multiaddr"
|
||||
)
|
||||
|
@ -5,8 +5,8 @@ import (
|
||||
"context"
|
||||
"errors"
|
||||
|
||||
ci "github.com/libp2p/go-libp2p-core/crypto"
|
||||
"github.com/libp2p/go-libp2p-core/peer"
|
||||
ci "github.com/libp2p/go-libp2p-crypto"
|
||||
|
||||
cid "github.com/ipfs/go-cid"
|
||||
)
|
||||
|
@ -7,7 +7,7 @@ import (
|
||||
"github.com/libp2p/go-libp2p-core/peer"
|
||||
"github.com/libp2p/go-libp2p-core/sec"
|
||||
|
||||
ci "github.com/libp2p/go-libp2p-crypto"
|
||||
ci "github.com/libp2p/go-libp2p-core/crypto"
|
||||
)
|
||||
|
||||
// ID is the multistream-select protocol ID that should be used when identifying
|
||||
|
Loading…
Reference in New Issue
Block a user