aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--p2p/crypto.go44
-rw-r--r--p2p/crypto_test.go14
-rw-r--r--p2p/peer.go2
3 files changed, 31 insertions, 29 deletions
diff --git a/p2p/crypto.go b/p2p/crypto.go
index f5307cd5a..361012743 100644
--- a/p2p/crypto.go
+++ b/p2p/crypto.go
@@ -7,20 +7,20 @@ import (
"io"
"github.com/ethereum/go-ethereum/crypto"
+ "github.com/ethereum/go-ethereum/crypto/secp256k1"
ethlogger "github.com/ethereum/go-ethereum/logger"
"github.com/obscuren/ecies"
- "github.com/obscuren/secp256k1-go"
)
var clogger = ethlogger.NewLogger("CRYPTOID")
-var (
+const (
sskLen int = 16 // ecies.MaxSharedKeyLength(pubKey) / 2
sigLen int = 65 // elliptic S256
pubLen int = 64 // 512 bit pubkey in uncompressed representation without format byte
- keyLen int = 32 // ECDSA
- msgLen int = 194 // sigLen + keyLen + pubLen + keyLen + 1 = 194
- resLen int = 97 // pubLen + keyLen + 1
+ shaLen int = 32 // hash length (for nonce etc)
+ msgLen int = 194 // sigLen + shaLen + pubLen + shaLen + 1 = 194
+ resLen int = 97 // pubLen + shaLen + 1
iHSLen int = 307 // size of the final ECIES payload sent as initiator's handshake
rHSLen int = 210 // size of the final ECIES payload sent as receiver's handshake
)
@@ -157,7 +157,7 @@ func (self *cryptoId) Run(conn io.ReadWriter, remotePubKeyS []byte, sessionToken
}
clogger.Debugf("receiver handshake (sent to %v):\n%v", hexkey(remotePubKeyS), hexkey(response))
}
- return self.newSession(initNonce, recNonce, auth, randomPrivKey, remoteRandomPubKey)
+ return self.newSession(initiator, initNonce, recNonce, auth, randomPrivKey, remoteRandomPubKey)
}
/*
@@ -198,7 +198,7 @@ func (self *cryptoId) startHandshake(remotePubKeyS, sessionToken []byte) (auth [
return
}
- var tokenFlag byte
+ var tokenFlag byte // = 0x00
if sessionToken == nil {
// no session token found means we need to generate shared secret.
// ecies shared secret is used as initial session token for new peers
@@ -216,7 +216,7 @@ func (self *cryptoId) startHandshake(remotePubKeyS, sessionToken []byte) (auth [
// E(remote-pubk, S(ecdhe-random, token^nonce) || H(ecdhe-random-pubk) || pubk || nonce || 0x1)
// allocate msgLen long message,
var msg []byte = make([]byte, msgLen)
- initNonce = msg[msgLen-keyLen-1 : msgLen-1]
+ initNonce = msg[msgLen-shaLen-1 : msgLen-1]
if _, err = rand.Read(initNonce); err != nil {
return
}
@@ -245,9 +245,9 @@ func (self *cryptoId) startHandshake(remotePubKeyS, sessionToken []byte) (auth [
if randomPubKey64, err = ExportPublicKey(&randomPrvKey.PublicKey); err != nil {
return
}
- copy(msg[sigLen:sigLen+keyLen], crypto.Sha3(randomPubKey64))
+ copy(msg[sigLen:sigLen+shaLen], crypto.Sha3(randomPubKey64))
// pubkey copied to the correct segment.
- copy(msg[sigLen+keyLen:sigLen+keyLen+pubLen], self.pubKeyS)
+ copy(msg[sigLen+shaLen:sigLen+shaLen+pubLen], self.pubKeyS)
// nonce is already in the slice
// stick tokenFlag byte to the end
msg[msgLen-1] = tokenFlag
@@ -295,7 +295,7 @@ func (self *cryptoId) respondToHandshake(auth, remotePubKeyS, sessionToken []byt
}
// the initiator nonce is read off the end of the message
- initNonce = msg[msgLen-keyLen-1 : msgLen-1]
+ initNonce = msg[msgLen-shaLen-1 : msgLen-1]
// I prove that i own prv key (to derive shared secret, and read nonce off encrypted msg) and that I own shared secret
// they prove they own the private key belonging to ecdhe-random-pubk
// we can now reconstruct the signed message and recover the peers pubkey
@@ -311,8 +311,8 @@ func (self *cryptoId) respondToHandshake(auth, remotePubKeyS, sessionToken []byt
// now we find ourselves a long task too, fill it random
var resp = make([]byte, resLen)
- // generate keyLen long nonce
- respNonce = resp[pubLen : pubLen+keyLen]
+ // generate shaLen long nonce
+ respNonce = resp[pubLen : pubLen+shaLen]
if _, err = rand.Read(respNonce); err != nil {
return
}
@@ -350,7 +350,7 @@ func (self *cryptoId) completeHandshake(auth []byte) (respNonce []byte, remoteRa
return
}
- respNonce = msg[pubLen : pubLen+keyLen]
+ respNonce = msg[pubLen : pubLen+shaLen]
var remoteRandomPubKeyS = msg[:pubLen]
if remoteRandomPubKey, err = ImportPublicKey(remoteRandomPubKeyS); err != nil {
return
@@ -364,7 +364,7 @@ func (self *cryptoId) completeHandshake(auth []byte) (respNonce []byte, remoteRa
/*
newSession is called after the handshake is completed. The arguments are values negotiated in the handshake and the return value is a new session : a new session Token to be remembered for the next time we connect with this peer. And a MsgReadWriter that implements an encrypted and authenticated connection with key material obtained from the crypto handshake key exchange
*/
-func (self *cryptoId) newSession(initNonce, respNonce, auth []byte, privKey *ecdsa.PrivateKey, remoteRandomPubKey *ecdsa.PublicKey) (sessionToken []byte, rw *secretRW, err error) {
+func (self *cryptoId) newSession(initiator bool, initNonce, respNonce, auth []byte, privKey *ecdsa.PrivateKey, remoteRandomPubKey *ecdsa.PublicKey) (sessionToken []byte, rw *secretRW, err error) {
// 3) Now we can trust ecdhe-random-pubk to derive new keys
//ecdhe-shared-secret = ecdh.agree(ecdhe-random, remote-ecdhe-random-pubk)
var dhSharedSecret []byte
@@ -382,12 +382,14 @@ func (self *cryptoId) newSession(initNonce, respNonce, auth []byte, privKey *ecd
// mac-secret = crypto.Sha3(ecdhe-shared-secret || aes-secret)
var macSecret = crypto.Sha3(append(dhSharedSecret, aesSecret...))
// # destroy ecdhe-shared-secret
- // egress-mac = crypto.Sha3(mac-secret^nonce || auth)
- var egressMac = crypto.Sha3(append(Xor(macSecret, respNonce), auth...))
- // # destroy nonce
- // ingress-mac = crypto.Sha3(mac-secret^initiator-nonce || auth),
- var ingressMac = crypto.Sha3(append(Xor(macSecret, initNonce), auth...))
- // # destroy remote-nonce
+ var egressMac, ingressMac []byte
+ if initiator {
+ egressMac = Xor(macSecret, respNonce)
+ ingressMac = Xor(macSecret, initNonce)
+ } else {
+ egressMac = Xor(macSecret, initNonce)
+ ingressMac = Xor(macSecret, respNonce)
+ }
rw = &secretRW{
aesSecret: aesSecret,
macSecret: macSecret,
diff --git a/p2p/crypto_test.go b/p2p/crypto_test.go
index 47b16040a..919d38df6 100644
--- a/p2p/crypto_test.go
+++ b/p2p/crypto_test.go
@@ -106,12 +106,12 @@ func TestCryptoHandshake(t *testing.T) {
}
// now both parties should have the same session parameters
- initSessionToken, initSecretRW, err := initiator.newSession(initNonce, recNonce, auth, randomPrivKey, remoteRandomPubKey)
+ initSessionToken, initSecretRW, err := initiator.newSession(true, initNonce, recNonce, auth, randomPrivKey, remoteRandomPubKey)
if err != nil {
t.Errorf("%v", err)
}
- recSessionToken, recSecretRW, err := receiver.newSession(remoteInitNonce, remoteRecNonce, auth, remoteRandomPrivKey, remoteInitRandomPubKey)
+ recSessionToken, recSecretRW, err := receiver.newSession(false, remoteInitNonce, remoteRecNonce, auth, remoteRandomPrivKey, remoteInitRandomPubKey)
if err != nil {
t.Errorf("%v", err)
}
@@ -136,11 +136,11 @@ func TestCryptoHandshake(t *testing.T) {
if !bytes.Equal(initSecretRW.macSecret, recSecretRW.macSecret) {
t.Errorf("macSecrets do not match")
}
- if !bytes.Equal(initSecretRW.egressMac, recSecretRW.egressMac) {
- t.Errorf("egressMacs do not match")
+ if !bytes.Equal(initSecretRW.egressMac, recSecretRW.ingressMac) {
+ t.Errorf("initiator's egressMac do not match receiver's ingressMac")
}
- if !bytes.Equal(initSecretRW.ingressMac, recSecretRW.ingressMac) {
- t.Errorf("ingressMacs do not match")
+ if !bytes.Equal(initSecretRW.ingressMac, recSecretRW.egressMac) {
+ t.Errorf("initiator's inressMac do not match receiver's egressMac")
}
}
@@ -191,7 +191,7 @@ func TestPeersHandshake(t *testing.T) {
<-receiver.cryptoReady
close(ready)
}()
- timeout := time.After(1 * time.Second)
+ timeout := time.After(10 * time.Second)
select {
case <-ready:
case <-timeout:
diff --git a/p2p/peer.go b/p2p/peer.go
index 99f1a61d3..62df58f8d 100644
--- a/p2p/peer.go
+++ b/p2p/peer.go
@@ -343,7 +343,7 @@ func (p *Peer) handleCryptoHandshake() (loop readLoop, err error) {
// it is survived by an encrypted readwriter
var initiator bool
var sessionToken []byte
- sessionToken = make([]byte, keyLen)
+ sessionToken = make([]byte, shaLen)
if _, err = rand.Read(sessionToken); err != nil {
return
}