Skip to content
This repository was archived by the owner on Dec 7, 2019. It is now read-only.

Commit 0f79fbe

Browse files
authored
Merge pull request #35 from c3systems/forPR
Added ECDSA; Added RSA tests; Fixed linting errors; Handling all un-handled errors
2 parents 137c71c + 5d08597 commit 0f79fbe

12 files changed

+513
-56
lines changed

.gitignore

+7
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,7 @@
1+
.DS_Store
2+
3+
# vim
4+
.swp
5+
*~
6+
*.swp
7+
*.swo

ecdsa.go

+186
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,186 @@
1+
package crypto
2+
3+
import (
4+
"crypto/ecdsa"
5+
"crypto/elliptic"
6+
"crypto/rand"
7+
"crypto/x509"
8+
"encoding/asn1"
9+
"errors"
10+
"io"
11+
"math/big"
12+
13+
pb "github.com/libp2p/go-libp2p-crypto/pb"
14+
15+
sha256 "github.com/minio/sha256-simd"
16+
)
17+
18+
// ECDSAPrivateKey is an implementation of an ECDSA private key
19+
type ECDSAPrivateKey struct {
20+
priv *ecdsa.PrivateKey
21+
}
22+
23+
// ECDSAPublicKey is an implementation of an ECDSA public key
24+
type ECDSAPublicKey struct {
25+
pub *ecdsa.PublicKey
26+
}
27+
28+
// ECDSASig holds the r and s values of an ECDSA signature
29+
type ECDSASig struct {
30+
R, S *big.Int
31+
}
32+
33+
var (
34+
// ErrNotECDSAPubKey is returned when the public key passed is not an ecdsa public key
35+
ErrNotECDSAPubKey = errors.New("not an ecdsa public key")
36+
// ErrNilSig is returned when the signature is nil
37+
ErrNilSig = errors.New("sig is nil")
38+
// ErrNilPrivateKey is returned when a nil private key is provided
39+
ErrNilPrivateKey = errors.New("private key is nil")
40+
// ECDSACurve is the default ecdsa curve used
41+
ECDSACurve = elliptic.P256()
42+
)
43+
44+
// GenerateECDSAKeyPair generates a new ecdsa private and public key
45+
func GenerateECDSAKeyPair(src io.Reader) (PrivKey, PubKey, error) {
46+
return GenerateECDSAKeyPairWithCurve(ECDSACurve, src)
47+
}
48+
49+
// GenerateECDSAKeyPairWithCurve generates a new ecdsa private and public key with a speicified curve
50+
func GenerateECDSAKeyPairWithCurve(curve elliptic.Curve, src io.Reader) (PrivKey, PubKey, error) {
51+
priv, err := ecdsa.GenerateKey(curve, src)
52+
if err != nil {
53+
return nil, nil, err
54+
}
55+
56+
return &ECDSAPrivateKey{priv}, &ECDSAPublicKey{&priv.PublicKey}, nil
57+
}
58+
59+
// ECDSAKeyPairFromKey generates a new ecdsa private and public key from an input private key
60+
func ECDSAKeyPairFromKey(priv *ecdsa.PrivateKey) (PrivKey, PubKey, error) {
61+
if priv == nil {
62+
return nil, nil, ErrNilPrivateKey
63+
}
64+
65+
return &ECDSAPrivateKey{priv}, &ECDSAPublicKey{&priv.PublicKey}, nil
66+
}
67+
68+
// MarshalECDSAPrivateKey returns x509 bytes from a private key
69+
func MarshalECDSAPrivateKey(ePriv ECDSAPrivateKey) ([]byte, error) {
70+
return x509.MarshalECPrivateKey(ePriv.priv)
71+
}
72+
73+
// MarshalECDSAPublicKey returns x509 bytes from a public key
74+
func MarshalECDSAPublicKey(ePub ECDSAPublicKey) ([]byte, error) {
75+
return x509.MarshalPKIXPublicKey(ePub.pub)
76+
}
77+
78+
// UnmarshalECDSAPrivateKey returns a private key from x509 bytes
79+
func UnmarshalECDSAPrivateKey(data []byte) (PrivKey, error) {
80+
priv, err := x509.ParseECPrivateKey(data)
81+
if err != nil {
82+
return nil, err
83+
}
84+
85+
return &ECDSAPrivateKey{priv}, nil
86+
}
87+
88+
// UnmarshalECDSAPublicKey returns the public key from x509 bytes
89+
func UnmarshalECDSAPublicKey(data []byte) (PubKey, error) {
90+
pubIfc, err := x509.ParsePKIXPublicKey(data)
91+
if err != nil {
92+
return nil, err
93+
}
94+
95+
pub, ok := pubIfc.(*ecdsa.PublicKey)
96+
if !ok {
97+
return nil, ErrNotECDSAPubKey
98+
}
99+
100+
return &ECDSAPublicKey{pub}, nil
101+
}
102+
103+
// Bytes returns the private key as protobuf bytes
104+
func (ePriv *ECDSAPrivateKey) Bytes() ([]byte, error) {
105+
return MarshalPrivateKey(ePriv)
106+
}
107+
108+
// Type returns the key type
109+
func (ePriv *ECDSAPrivateKey) Type() pb.KeyType {
110+
return pb.KeyType_ECDSA
111+
}
112+
113+
// Raw returns x509 bytes from a private key
114+
func (ePriv *ECDSAPrivateKey) Raw() ([]byte, error) {
115+
return x509.MarshalECPrivateKey(ePriv.priv)
116+
}
117+
118+
// Equals compares to private keys
119+
func (ePriv *ECDSAPrivateKey) Equals(o Key) bool {
120+
oPriv, ok := o.(*ECDSAPrivateKey)
121+
if !ok {
122+
return false
123+
}
124+
125+
return ePriv.priv.D.Cmp(oPriv.priv.D) == 0
126+
}
127+
128+
// Sign returns the signature of the input data
129+
func (ePriv *ECDSAPrivateKey) Sign(data []byte) ([]byte, error) {
130+
hash := sha256.Sum256(data)
131+
r, s, err := ecdsa.Sign(rand.Reader, ePriv.priv, hash[:])
132+
if err != nil {
133+
return nil, err
134+
}
135+
136+
return asn1.Marshal(ECDSASig{
137+
R: r,
138+
S: s,
139+
})
140+
}
141+
142+
// GetPublic returns a public key
143+
func (ePriv *ECDSAPrivateKey) GetPublic() PubKey {
144+
return &ECDSAPublicKey{&ePriv.priv.PublicKey}
145+
}
146+
147+
// Bytes returns the public key as protobuf bytes
148+
func (ePub *ECDSAPublicKey) Bytes() ([]byte, error) {
149+
return MarshalPublicKey(ePub)
150+
}
151+
152+
// Type returns the key type
153+
func (ePub *ECDSAPublicKey) Type() pb.KeyType {
154+
return pb.KeyType_ECDSA
155+
}
156+
157+
// Raw returns x509 bytes from a public key
158+
func (ePub ECDSAPublicKey) Raw() ([]byte, error) {
159+
return x509.MarshalPKIXPublicKey(ePub.pub)
160+
}
161+
162+
// Equals compares to public keys
163+
func (ePub *ECDSAPublicKey) Equals(o Key) bool {
164+
oPub, ok := o.(*ECDSAPublicKey)
165+
if !ok {
166+
return false
167+
}
168+
169+
return ePub.pub.X != nil && ePub.pub.Y != nil && oPub.pub.X != nil && oPub.pub.Y != nil &&
170+
0 == ePub.pub.X.Cmp(oPub.pub.X) && 0 == ePub.pub.Y.Cmp(oPub.pub.Y)
171+
}
172+
173+
// Verify compares data to a signature
174+
func (ePub *ECDSAPublicKey) Verify(data, sigBytes []byte) (bool, error) {
175+
sig := new(ECDSASig)
176+
if _, err := asn1.Unmarshal(sigBytes, sig); err != nil {
177+
return false, err
178+
}
179+
if sig == nil {
180+
return false, ErrNilSig
181+
}
182+
183+
hash := sha256.Sum256(data)
184+
185+
return ecdsa.Verify(ePub.pub, hash[:], sig.R, sig.S), nil
186+
}

ecdsa_test.go

+96
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,96 @@
1+
package crypto
2+
3+
import (
4+
"crypto/rand"
5+
"testing"
6+
)
7+
8+
func TestECDSABasicSignAndVerify(t *testing.T) {
9+
priv, pub, err := GenerateECDSAKeyPair(rand.Reader)
10+
if err != nil {
11+
t.Fatal(err)
12+
}
13+
14+
data := []byte("hello! and welcome to some awesome crypto primitives")
15+
16+
sig, err := priv.Sign(data)
17+
if err != nil {
18+
t.Fatal(err)
19+
}
20+
21+
ok, err := pub.Verify(data, sig)
22+
if err != nil {
23+
t.Fatal(err)
24+
}
25+
26+
if !ok {
27+
t.Fatal("signature didnt match")
28+
}
29+
30+
// change data
31+
data[0] = ^data[0]
32+
ok, err = pub.Verify(data, sig)
33+
if err != nil {
34+
t.Fatal(err)
35+
}
36+
37+
if ok {
38+
t.Fatal("signature matched and shouldn't")
39+
}
40+
}
41+
42+
func TestECDSASignZero(t *testing.T) {
43+
priv, pub, err := GenerateECDSAKeyPair(rand.Reader)
44+
if err != nil {
45+
t.Fatal(err)
46+
}
47+
48+
data := make([]byte, 0)
49+
sig, err := priv.Sign(data)
50+
if err != nil {
51+
t.Fatal(err)
52+
}
53+
54+
ok, err := pub.Verify(data, sig)
55+
if err != nil {
56+
t.Fatal(err)
57+
}
58+
if !ok {
59+
t.Fatal("signature didn't match")
60+
}
61+
}
62+
63+
func TestECDSAMarshalLoop(t *testing.T) {
64+
priv, pub, err := GenerateECDSAKeyPair(rand.Reader)
65+
if err != nil {
66+
t.Fatal(err)
67+
}
68+
69+
privB, err := priv.Bytes()
70+
if err != nil {
71+
t.Fatal(err)
72+
}
73+
74+
privNew, err := UnmarshalPrivateKey(privB)
75+
if err != nil {
76+
t.Fatal(err)
77+
}
78+
79+
if !priv.Equals(privNew) || !privNew.Equals(priv) {
80+
t.Fatal("keys are not equal")
81+
}
82+
83+
pubB, err := pub.Bytes()
84+
if err != nil {
85+
t.Fatal(err)
86+
}
87+
pubNew, err := UnmarshalPublicKey(pubB)
88+
if err != nil {
89+
t.Fatal(err)
90+
}
91+
92+
if !pub.Equals(pubNew) || !pubNew.Equals(pub) {
93+
t.Fatal("keys are not equal")
94+
}
95+
96+
}

ed25519.go

+12
Original file line numberDiff line numberDiff line change
@@ -6,17 +6,21 @@ import (
66
"io"
77

88
pb "github.com/libp2p/go-libp2p-crypto/pb"
9+
910
"golang.org/x/crypto/ed25519"
1011
)
1112

13+
// Ed25519PrivateKey is an ed25519 private key
1214
type Ed25519PrivateKey struct {
1315
k ed25519.PrivateKey
1416
}
1517

18+
// Ed25519PublicKey is an ed25519 public key
1619
type Ed25519PublicKey struct {
1720
k ed25519.PublicKey
1821
}
1922

23+
// GenerateEd25519Key generate a new ed25519 private and public key pair
2024
func GenerateEd25519Key(src io.Reader) (PrivKey, PubKey, error) {
2125
pub, priv, err := ed25519.GenerateKey(src)
2226
if err != nil {
@@ -36,6 +40,7 @@ func (k *Ed25519PrivateKey) Type() pb.KeyType {
3640
return pb.KeyType_Ed25519
3741
}
3842

43+
// Bytes marshals an ed25519 private key to protobuf bytes
3944
func (k *Ed25519PrivateKey) Bytes() ([]byte, error) {
4045
return MarshalPrivateKey(k)
4146
}
@@ -55,6 +60,7 @@ func (k *Ed25519PrivateKey) pubKeyBytes() []byte {
5560
return k.k[ed25519.PrivateKeySize-ed25519.PublicKeySize:]
5661
}
5762

63+
// Equals compares two ed25519 private keys
5864
func (k *Ed25519PrivateKey) Equals(o Key) bool {
5965
edk, ok := o.(*Ed25519PrivateKey)
6066
if !ok {
@@ -64,10 +70,12 @@ func (k *Ed25519PrivateKey) Equals(o Key) bool {
6470
return bytes.Equal(k.k, edk.k)
6571
}
6672

73+
// GetPublic returns an ed25519 public key from a private key
6774
func (k *Ed25519PrivateKey) GetPublic() PubKey {
6875
return &Ed25519PublicKey{k: k.pubKeyBytes()}
6976
}
7077

78+
// Sign returns a signature from an input message
7179
func (k *Ed25519PrivateKey) Sign(msg []byte) ([]byte, error) {
7280
return ed25519.Sign(k.k, msg), nil
7381
}
@@ -76,6 +84,7 @@ func (k *Ed25519PublicKey) Type() pb.KeyType {
7684
return pb.KeyType_Ed25519
7785
}
7886

87+
// Bytes returns a ed25519 public key as protobuf bytes
7988
func (k *Ed25519PublicKey) Bytes() ([]byte, error) {
8089
return MarshalPublicKey(k)
8190
}
@@ -84,6 +93,7 @@ func (k *Ed25519PublicKey) Raw() ([]byte, error) {
8493
return k.k, nil
8594
}
8695

96+
// Equals compares two ed25519 public keys
8797
func (k *Ed25519PublicKey) Equals(o Key) bool {
8898
edk, ok := o.(*Ed25519PublicKey)
8999
if !ok {
@@ -93,6 +103,7 @@ func (k *Ed25519PublicKey) Equals(o Key) bool {
93103
return bytes.Equal(k.k, edk.k)
94104
}
95105

106+
// Verify checks a signature agains the input data
96107
func (k *Ed25519PublicKey) Verify(data []byte, sig []byte) (bool, error) {
97108
return ed25519.Verify(k.k, data, sig), nil
98109
}
@@ -106,6 +117,7 @@ func UnmarshalEd25519PublicKey(data []byte) (PubKey, error) {
106117
}, nil
107118
}
108119

120+
// UnmarshalEd25519PrivateKey returns a private key from input bytes
109121
func UnmarshalEd25519PrivateKey(data []byte) (PrivKey, error) {
110122
switch len(data) {
111123
case ed25519.PrivateKeySize + ed25519.PublicKeySize:

0 commit comments

Comments
 (0)