replace random nonces with message sequence numbers in tcp crypto
Since TCP is reliable, we do not need to transmit the nonce itself; the recipient can simply construct the nonce from its own message counter. Hence there is no message envelope and we can thus remove a whole layer of encoding.
This commit is contained in:
1 parent
87f47a60ae
commit
696bfe464c
3 files changed
+45
-79
No files matched your search
@@ -446,7 +446,7 @@ func (conn *LocalConnection) receiveTCP(decoder *gob.Decoder) {
|
||||
usingPassword := conn.SessionKey != nil
|
||||
var receiver TCPReceiver
|
||||
if usingPassword {
|
||||
receiver = NewEncryptedTCPReceiver(conn.SessionKey)
|
||||
receiver = NewEncryptedTCPReceiver(conn.SessionKey, conn.outbound)
|
||||
} else {
|
||||
receiver = NewSimpleTCPReceiver()
|
||||
}
|
||||
|
||||
+43
-77
@@ -1,7 +1,6 @@
|
||||
package router
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
"code.google.com/p/go-bit/bit"
|
||||
"code.google.com/p/go.crypto/nacl/box"
|
||||
"code.google.com/p/go.crypto/nacl/secretbox"
|
||||
@@ -39,22 +38,6 @@ func GenerateRandomNonce() ([24]byte, error) {
|
||||
return nonce, nil
|
||||
}
|
||||
|
||||
func EncryptPrefixNonce(plaintxt []byte, nonce *[24]byte, secret *[32]byte) []byte {
|
||||
buf := make([]byte, 24, 24+len(plaintxt)+secretbox.Overhead)
|
||||
copy(buf, nonce[:])
|
||||
// Seal *appends* to buf
|
||||
return secretbox.Seal(buf, plaintxt, nonce, secret)
|
||||
}
|
||||
|
||||
func DecryptPrefixNonce(ciphertxt []byte, secret *[32]byte) ([]byte, bool) {
|
||||
if len(ciphertxt) < secretbox.Overhead+24 {
|
||||
return nil, false
|
||||
}
|
||||
var nonce [24]byte
|
||||
copy(nonce[:], ciphertxt[:24])
|
||||
return secretbox.Open(nil, ciphertxt[24:], &nonce, secret)
|
||||
}
|
||||
|
||||
func SetNonceLow15Bits(nonce *[24]byte, offset uint16) {
|
||||
// ensure top bit of offset is 0
|
||||
offset = offset & ((1 << 15) - 1)
|
||||
@@ -419,7 +402,32 @@ func (di *NaClDecryptorInstance) advanceState(offsetNoFlags uint16) (*[24]byte,
|
||||
return di.nonce, di.usedOffsets, nil
|
||||
}
|
||||
|
||||
// TCP Senders
|
||||
// TCP Senders/Receivers
|
||||
|
||||
// The lowest 64 bits of the nonce contain the message sequence
|
||||
// number. The top most bit indicates the connection polarity at the
|
||||
// sender - '1' for outbound. The remaining 127 bits are zero. The
|
||||
// polarity is needed so that the two ends of a connection do not use
|
||||
// the same nonces. This is a requirement of the NaCl Security Model;
|
||||
// see http://nacl.cr.yp.to/box.html.
|
||||
type TCPCryptoState struct {
|
||||
sessionKey *[32]byte
|
||||
nonce [24]byte
|
||||
seqNo uint64
|
||||
}
|
||||
|
||||
func NewTCPCryptoState(sessionKey *[32]byte, outbound bool) *TCPCryptoState {
|
||||
s := &TCPCryptoState{sessionKey: sessionKey}
|
||||
if outbound {
|
||||
s.nonce[0] |= (1 << 7)
|
||||
}
|
||||
return s
|
||||
}
|
||||
|
||||
func (s *TCPCryptoState) advance() {
|
||||
s.seqNo++
|
||||
binary.BigEndian.PutUint64(s.nonce[16:24], s.seqNo)
|
||||
}
|
||||
|
||||
type TCPSender interface {
|
||||
Send([]byte) error
|
||||
@@ -430,17 +438,9 @@ type SimpleTCPSender struct {
|
||||
}
|
||||
|
||||
type EncryptedTCPSender struct {
|
||||
SimpleTCPSender
|
||||
sync.RWMutex
|
||||
outerEncoder *gob.Encoder
|
||||
innerEncoder *gob.Encoder
|
||||
buffer *bytes.Buffer
|
||||
sessionKey *[32]byte
|
||||
msgCount int
|
||||
}
|
||||
|
||||
type EncryptedTCPMessage struct {
|
||||
Number int
|
||||
Body []byte
|
||||
state *TCPCryptoState
|
||||
}
|
||||
|
||||
func NewSimpleTCPSender(encoder *gob.Encoder) *SimpleTCPSender {
|
||||
@@ -451,36 +451,20 @@ func (sender *SimpleTCPSender) Send(msg []byte) error {
|
||||
return sender.encoder.Encode(msg)
|
||||
}
|
||||
|
||||
func NewEncryptedTCPSender(encoder *gob.Encoder, sessionKey *[32]byte) *EncryptedTCPSender {
|
||||
buffer := new(bytes.Buffer)
|
||||
func NewEncryptedTCPSender(encoder *gob.Encoder, sessionKey *[32]byte, outbound bool) *EncryptedTCPSender {
|
||||
return &EncryptedTCPSender{
|
||||
outerEncoder: encoder,
|
||||
innerEncoder: gob.NewEncoder(buffer),
|
||||
buffer: buffer,
|
||||
sessionKey: sessionKey,
|
||||
msgCount: 0}
|
||||
SimpleTCPSender: *NewSimpleTCPSender(encoder),
|
||||
state: NewTCPCryptoState(sessionKey, outbound)}
|
||||
}
|
||||
|
||||
func (sender *EncryptedTCPSender) Send(msg []byte) error {
|
||||
nonce, err := GenerateRandomNonce()
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
sender.Lock()
|
||||
defer sender.Unlock()
|
||||
wrappedMsg := EncryptedTCPMessage{Number: sender.msgCount, Body: msg}
|
||||
buffer := sender.buffer
|
||||
buffer.Reset()
|
||||
err = sender.innerEncoder.Encode(wrappedMsg)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
sender.msgCount += 1
|
||||
return sender.outerEncoder.Encode(EncryptPrefixNonce(buffer.Bytes(), &nonce, sender.sessionKey))
|
||||
encodedMsg := secretbox.Seal(nil, msg, &sender.state.nonce, sender.state.sessionKey)
|
||||
sender.state.advance()
|
||||
return sender.SimpleTCPSender.Send(encodedMsg)
|
||||
}
|
||||
|
||||
// TCP Receivers
|
||||
|
||||
type TCPReceiver interface {
|
||||
Decode([]byte) ([]byte, error)
|
||||
}
|
||||
@@ -489,10 +473,8 @@ type SimpleTCPReceiver struct {
|
||||
}
|
||||
|
||||
type EncryptedTCPReceiver struct {
|
||||
sessionKey *[32]byte
|
||||
decoder *gob.Decoder
|
||||
buffer *bytes.Buffer
|
||||
msgCount int
|
||||
SimpleTCPReceiver
|
||||
state *TCPCryptoState
|
||||
}
|
||||
|
||||
func NewSimpleTCPReceiver() *SimpleTCPReceiver {
|
||||
@@ -503,33 +485,17 @@ func (receiver *SimpleTCPReceiver) Decode(msg []byte) ([]byte, error) {
|
||||
return msg, nil
|
||||
}
|
||||
|
||||
func NewEncryptedTCPReceiver(sessionKey *[32]byte) *EncryptedTCPReceiver {
|
||||
buffer := new(bytes.Buffer)
|
||||
func NewEncryptedTCPReceiver(sessionKey *[32]byte, outbound bool) *EncryptedTCPReceiver {
|
||||
return &EncryptedTCPReceiver{
|
||||
sessionKey: sessionKey,
|
||||
decoder: gob.NewDecoder(buffer),
|
||||
buffer: buffer,
|
||||
msgCount: 0}
|
||||
SimpleTCPReceiver: *NewSimpleTCPReceiver(),
|
||||
state: NewTCPCryptoState(sessionKey, !outbound)}
|
||||
}
|
||||
|
||||
func (receiver *EncryptedTCPReceiver) Decode(msg []byte) ([]byte, error) {
|
||||
plaintext, success := DecryptPrefixNonce(msg, receiver.sessionKey)
|
||||
decodedMsg, success := secretbox.Open(nil, msg, &receiver.state.nonce, receiver.state.sessionKey)
|
||||
if !success {
|
||||
return msg, fmt.Errorf("Unable to decrypt TCP msg")
|
||||
return nil, fmt.Errorf("Unable to decrypt TCP msg")
|
||||
}
|
||||
receiver.buffer.Reset()
|
||||
_, err := receiver.buffer.Write(plaintext)
|
||||
if err != nil {
|
||||
return msg, err
|
||||
}
|
||||
wrappedMsg := new(EncryptedTCPMessage)
|
||||
err = receiver.decoder.Decode(wrappedMsg)
|
||||
if err != nil {
|
||||
return msg, err
|
||||
}
|
||||
if wrappedMsg.Number != receiver.msgCount {
|
||||
return msg, fmt.Errorf("Received TCP message with wrong sequence number; possible replay attack")
|
||||
}
|
||||
receiver.msgCount += 1
|
||||
return wrappedMsg.Body, nil
|
||||
receiver.state.advance()
|
||||
return decodedMsg, nil
|
||||
}
|
||||
+1
-1
@@ -102,7 +102,7 @@ func (conn *LocalConnection) handshake(enc *gob.Encoder, dec *gob.Decoder, accep
|
||||
remotePublic[idx] = elem
|
||||
}
|
||||
conn.SessionKey = FormSessionKey(&remotePublic, private, conn.Router.Password)
|
||||
conn.tcpSender = NewEncryptedTCPSender(enc, conn.SessionKey)
|
||||
conn.tcpSender = NewEncryptedTCPSender(enc, conn.SessionKey, conn.outbound)
|
||||
conn.Decryptor = NewNaClDecryptor(conn.SessionKey)
|
||||
} else {
|
||||
if rpErr == nil {
|
||||
|
||||
Reference in new issue
Block a user