1
0
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:
Raúl Kripalani 2019-04-22 13:54:17 +01:00
parent ec2a527976
commit 3a54eb68d1
24 changed files with 2429 additions and 21 deletions

84
crypto/bench_test.go Normal file
View 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
View 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
View 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
View 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
View 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
View 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
View 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
View 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
View 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
View 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
View 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
View 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
View 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
View 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
View 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
View File

@ -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
View File

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

View File

@ -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"
)

View File

@ -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"
)

View File

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

View File

@ -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"
)

View File

@ -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"
)

View File

@ -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"
)

View File

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