add correct authentication with HMAC

This commit is contained in:
zelig 2015-01-23 12:44:57 +00:00
parent a4b4f680a1
commit 2f00e5cad1
5 changed files with 28 additions and 28 deletions

View file

@ -150,7 +150,7 @@ func (self *cryptoId) NewSession(r io.Reader, w io.Writer, remotePubKeyS []byte,
} }
clogger.Debugf("receiver handshake (sent to %v):\n%v", hexkey(remotePubKeyS), hexkey(response)) clogger.Debugf("receiver handshake (sent to %v):\n%v", hexkey(remotePubKeyS), hexkey(response))
} }
return self.newSession(r, w, initNonce, recNonce, auth, randomPrivKey, remoteRandomPubKey) return self.newSession(r, w, initiator, initNonce, recNonce, auth, randomPrivKey, remoteRandomPubKey)
} }
/* /*
@ -357,7 +357,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 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(r io.Reader, w io.Writer, initNonce, respNonce, auth []byte, privKey *ecdsa.PrivateKey, remoteRandomPubKey *ecdsa.PublicKey) (sessionToken []byte, rw MsgReadWriter, err error) { func (self *cryptoId) newSession(r io.Reader, w io.Writer, initiator bool, initNonce, respNonce, auth []byte, privKey *ecdsa.PrivateKey, remoteRandomPubKey *ecdsa.PublicKey) (sessionToken []byte, rw MsgReadWriter, err error) {
// 3) Now we can trust ecdhe-random-pubk to derive new keys // 3) Now we can trust ecdhe-random-pubk to derive new keys
//ecdhe-shared-secret = ecdh.agree(ecdhe-random, remote-ecdhe-random-pubk) //ecdhe-shared-secret = ecdh.agree(ecdhe-random, remote-ecdhe-random-pubk)
var dhSharedSecret []byte var dhSharedSecret []byte
@ -375,13 +375,14 @@ func (self *cryptoId) newSession(r io.Reader, w io.Writer, initNonce, respNonce,
// mac-secret = crypto.Sha3(ecdhe-shared-secret || aes-secret) // mac-secret = crypto.Sha3(ecdhe-shared-secret || aes-secret)
var macSecret = crypto.Sha3(append(dhSharedSecret, aesSecret...)) var macSecret = crypto.Sha3(append(dhSharedSecret, aesSecret...))
// # destroy ecdhe-shared-secret // # destroy ecdhe-shared-secret
// egress-mac = crypto.Sha3(mac-secret^nonce || auth) var egressMac, ingressMac []byte
var egressMac = crypto.Sha3(append(Xor(macSecret, respNonce), auth...)) if initiator {
// # destroy nonce egressMac = Xor(macSecret, respNonce)
// ingress-mac = crypto.Sha3(mac-secret^initiator-nonce || auth), ingressMac = Xor(macSecret, initNonce)
var ingressMac = crypto.Sha3(append(Xor(macSecret, initNonce), auth...)) } else {
// # destroy remote-nonce egressMac = Xor(macSecret, initNonce)
ingressMac = Xor(macSecret, respNonce)
}
clogger.Debugf("aes-secret: %v", hexkey(aesSecret)) clogger.Debugf("aes-secret: %v", hexkey(aesSecret))
clogger.Debugf("mac-secret: %v", hexkey(macSecret)) clogger.Debugf("mac-secret: %v", hexkey(macSecret))
clogger.Debugf("egress-mac: %v", hexkey(egressMac)) clogger.Debugf("egress-mac: %v", hexkey(egressMac))

View file

@ -109,12 +109,12 @@ func TestCryptoHandshake(t *testing.T) {
conn0, conn1 := net.Pipe() conn0, conn1 := net.Pipe()
// now both parties should have the same session parameters // now both parties should have the same session parameters
initSessionToken, initRW, err := initiator.newSession(bufio.NewReader(conn0), conn0, initNonce, recNonce, auth, randomPrivKey, remoteRandomPubKey) initSessionToken, initRW, err := initiator.newSession(bufio.NewReader(conn0), conn0, true, initNonce, recNonce, auth, randomPrivKey, remoteRandomPubKey)
if err != nil { if err != nil {
t.Errorf("%v", err) t.Errorf("%v", err)
} }
recSessionToken, recRW, err := receiver.newSession(bufio.NewReader(conn1), conn1, remoteInitNonce, remoteRecNonce, auth, remoteRandomPrivKey, remoteInitRandomPubKey) recSessionToken, recRW, err := receiver.newSession(bufio.NewReader(conn1), conn1, false, remoteInitNonce, remoteRecNonce, auth, remoteRandomPrivKey, remoteInitRandomPubKey)
if err != nil { if err != nil {
t.Errorf("%v", err) t.Errorf("%v", err)
} }
@ -149,11 +149,11 @@ func TestCryptoHandshake(t *testing.T) {
if !bytes.Equal(initSecretRW.macSecret, recSecretRW.macSecret) { if !bytes.Equal(initSecretRW.macSecret, recSecretRW.macSecret) {
t.Errorf("macSecrets do not match") t.Errorf("macSecrets do not match")
} }
if !bytes.Equal(initSecretRW.egressMac, recSecretRW.egressMac) { if !bytes.Equal(initSecretRW.egressMac, recSecretRW.ingressMac) {
t.Errorf("egressMacs do not match") t.Errorf("initiator's egressMac do not match receiver's ingressMac")
} }
if !bytes.Equal(initSecretRW.ingressMac, recSecretRW.ingressMac) { if !bytes.Equal(initSecretRW.ingressMac, recSecretRW.egressMac) {
t.Errorf("ingressMacs do not match") t.Errorf("initiator's inressMac do not match receiver's egressMac")
} }
} }

View file

@ -7,11 +7,9 @@ import (
"crypto/hmac" "crypto/hmac"
"crypto/sha256" "crypto/sha256"
"encoding/binary" "encoding/binary"
"fmt"
"hash" "hash"
"io" "io"
// "github.com/ethereum/go-ethereum/crypto/sha256"
"github.com/ethereum/go-ethereum/ethutil" "github.com/ethereum/go-ethereum/ethutil"
"github.com/ethereum/go-ethereum/rlp" "github.com/ethereum/go-ethereum/rlp"
) )
@ -82,11 +80,11 @@ func (self *CryptoMsgRW) WriteMsg(msg Msg) (err error) {
copy(plaintext[listhdrLen:], code) copy(plaintext[listhdrLen:], code)
msg.Payload.Read(plaintext[listhdrLen+codeLen:]) msg.Payload.Read(plaintext[listhdrLen+codeLen:])
self.Encrypt(ciphertext, plaintext) self.Encrypt(ciphertext, plaintext)
fmt.Printf("ENCRYPT:\npt: %v\nct: %v\n", hexkey(plaintext), hexkey(ciphertext))
if _, err = self.w.Write(ciphertext); err != nil { if _, err = self.w.Write(ciphertext); err != nil {
return return
} }
if _, err = self.w.Write(self.egress.Sum(nil)); err != nil { mac := self.egress.Sum(nil)
if _, err = self.w.Write(mac); err != nil {
return return
} }
@ -130,18 +128,16 @@ func (self *CryptoMsgRW) readPayload(size uint32) (r rlp.ByteReader, err error)
ciphertext := make([]byte, size) ciphertext := make([]byte, size)
self.r.Read(ciphertext) self.r.Read(ciphertext)
self.Decrypt(plaintext, ciphertext) self.Decrypt(plaintext, ciphertext)
fmt.Printf("DECRYPT:\npt: %v\nct: %v\n", hexkey(plaintext), hexkey(ciphertext))
mac := make([]byte, 32) mac := make([]byte, 32)
if _, err = self.r.Read(mac); err != nil { if _, err = self.r.Read(mac); err != nil {
err = newPeerError(errRead, "%v", err) err = newPeerError(errRead, "%v", err)
return return
} }
// var expectedMac = self.ingress.Sum(nil) var expectedMac = self.ingress.Sum(nil)
// if !hmac.Equal(expectedMac, mac) { if !hmac.Equal(expectedMac, mac) {
// err = newPeerError(errAuthentication, "ingress incorrect") err = newPeerError(errAuthentication, "ingress incorrect:\nexp %v\ngot %v\n", hexkey(expectedMac), hexkey(mac))
// return return
// } }
r = bytes.NewReader(plaintext) r = bytes.NewReader(plaintext)
// r = io.LimitReader(bytes.NewReader(plaintext), int64(size))
return return
} }

View file

@ -4,7 +4,6 @@ import (
"bufio" "bufio"
"bytes" "bytes"
"crypto/rand" "crypto/rand"
// "fmt"
"io" "io"
"net" "net"
"testing" "testing"
@ -47,7 +46,8 @@ func TestEncryption(t *testing.T) {
} }
messenger0 := NewMessenger(rw0) messenger0 := NewMessenger(rw0)
rw1, err := NewCryptoMsgRW(bufio.NewReader(conn1), conn1, args[0], args[1], args[2], args[3]) // note that args 3/2 swapped! ingress <-> egress MAC should reverse
rw1, err := NewCryptoMsgRW(bufio.NewReader(conn1), conn1, args[0], args[1], args[3], args[2])
if err != nil { if err != nil {
return return
} }

View file

@ -321,6 +321,8 @@ func (p *Peer) handleCryptoHandshake() (err error) {
if crw, err = NewMsgRW(bufio.NewReader(p.conn), p.conn); err != nil { if crw, err = NewMsgRW(bufio.NewReader(p.conn), p.conn); err != nil {
return return
} }
p.Infof("insecure connection using no encryption/authentication")
case EthCrypto: case EthCrypto:
// cryptoId is just created for the lifecycle of the handshake // cryptoId is just created for the lifecycle of the handshake
// it is survived by an encrypted readwriter // it is survived by an encrypted readwriter
@ -350,6 +352,7 @@ func (p *Peer) handleCryptoHandshake() (err error) {
p.Errorf("%v", err) p.Errorf("%v", err)
} }
p.crw = NewMessenger(crw) p.crw = NewMessenger(crw)
p.Infof("secure connection using %v", p.CryptoType)
return return
} }