]> Cypherpunks.ru repositories - nncp.git/commitdiff
Encrypt actual packet size, hide it
authorSergey Matveev <stargrave@stargrave.org>
Thu, 12 Jan 2017 21:09:49 +0000 (00:09 +0300)
committerSergey Matveev <stargrave@stargrave.org>
Thu, 12 Jan 2017 21:09:49 +0000 (00:09 +0300)
src/cypherpunks.ru/nncp/cmd/nncp-pkt/main.go
src/cypherpunks.ru/nncp/pkt.go
src/cypherpunks.ru/nncp/pkt_test.go

index f11b1b8a3d4bbcd6b516c7de52dd2f1efe0c0c1f..222750df7337bb4d7844f839cf8559b7801280ee 100644 (file)
@@ -62,7 +62,7 @@ func main() {
        }
 
        var err error
-       beginning := make([]byte, nncp.PktOverhead-blake2b.Size256)
+       beginning := make([]byte, nncp.PktOverhead - 8 - 2*blake2b.Size256)
        if _, err = io.ReadFull(os.Stdin, beginning); err != nil {
                log.Fatalln("Not enough data to read")
        }
@@ -130,8 +130,8 @@ func main() {
                        return
                }
                fmt.Printf(
-                       "Packet type: encrypted\nNiceness: %d\nSender: %s\nPayload size: %s (%d bytes)\n",
-                       pktEnc.Nice, pktEnc.Sender, humanize.IBytes(pktEnc.Size), pktEnc.Size,
+                       "Packet type: encrypted\nNiceness: %d\nSender: %s\n",
+                       pktEnc.Nice, pktEnc.Sender,
                )
                return
        }
index 2f240341c203810eccd3fe20e589a59bbb0f4b97..2802085330212d39693e7ea5e97523db1887aed8 100644 (file)
@@ -74,7 +74,6 @@ type PktTbs struct {
        Recipient *NodeId
        Sender    *NodeId
        ExchPub   *[32]byte
-       Size      uint64
 }
 
 type PktEnc struct {
@@ -83,7 +82,6 @@ type PktEnc struct {
        Sender  *NodeId
        ExchPub *[32]byte
        Sign    *[ed25519.SignatureSize]byte
-       Size    uint64
 }
 
 func init() {
@@ -96,7 +94,7 @@ func init() {
        if err != nil {
                panic(err)
        }
-       PktOverhead = int64(n) + blake2b.Size256
+       PktOverhead = 8 + blake2b.Size256 + int64(n) + blake2b.Size256
        buf.Reset()
 
        dummyId, err := NodeIdFromString("AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA")
@@ -109,7 +107,6 @@ func init() {
                Sender:  dummyId,
                ExchPub: new([32]byte),
                Sign:    new([ed25519.SignatureSize]byte),
-               Size:    123,
        }
        n, err = xdr.Marshal(&buf, pktEnc)
        if err != nil {
@@ -156,7 +153,6 @@ func PktEncWrite(our *NodeOur, their *Node, pkt *Pkt, nice uint8, size int64, da
                Recipient: their.Id,
                Sender:    our.Id,
                ExchPub:   pubEph,
-               Size:      uint64(size + PktOverhead),
        }
        var tbsBuf bytes.Buffer
        if _, err = xdr.Marshal(&tbsBuf, &tbs); err != nil {
@@ -170,7 +166,6 @@ func PktEncWrite(our *NodeOur, their *Node, pkt *Pkt, nice uint8, size int64, da
                Sender:  our.Id,
                ExchPub: pubEph,
                Sign:    signature,
-               Size:    tbs.Size,
        }
        if _, err = xdr.Marshal(out, &pktEnc); err != nil {
                return err
@@ -178,6 +173,16 @@ func PktEncWrite(our *NodeOur, their *Node, pkt *Pkt, nice uint8, size int64, da
        sharedKey := new([32]byte)
        curve25519.ScalarMult(sharedKey, prvEph, their.ExchPub)
        kdf := hkdf.New(blake256, sharedKey[:], nil, MagicNNCPEv1[:])
+
+       // Derive keys
+       keyEnc4Size := make([]byte, 32)
+       if _, err = io.ReadFull(kdf, keyEnc4Size); err != nil {
+               return err
+       }
+       keyAuth4Size := make([]byte, 64)
+       if _, err = io.ReadFull(kdf, keyAuth4Size); err != nil {
+               return err
+       }
        keyEnc := make([]byte, 32)
        if _, err = io.ReadFull(kdf, keyEnc); err != nil {
                return err
@@ -186,6 +191,17 @@ func PktEncWrite(our *NodeOur, their *Node, pkt *Pkt, nice uint8, size int64, da
        if _, err = io.ReadFull(kdf, keyAuth); err != nil {
                return err
        }
+
+       // Initialize ciphers and MACs
+       ciph4Size, err := twofish.NewCipher(keyEnc4Size)
+       if err != nil {
+               return err
+       }
+       ctr4Size := cipher.NewCTR(ciph4Size, make([]byte, twofish.BlockSize))
+       mac4Size, err := blake2b.New256(keyAuth4Size)
+       if err != nil {
+               return err
+       }
        ciph, err := twofish.NewCipher(keyEnc)
        if err != nil {
                return err
@@ -195,8 +211,17 @@ func PktEncWrite(our *NodeOur, their *Node, pkt *Pkt, nice uint8, size int64, da
        if err != nil {
                return err
        }
-       mw := io.MultiWriter(out, mac)
-       ae := &cipher.StreamWriter{S: ctr, W: mw}
+
+       mw := io.MultiWriter(out, mac4Size)
+       ae := &cipher.StreamWriter{S: ctr4Size, W: mw}
+       usize := uint64(size)
+       if _, err = xdr.Marshal(ae, &usize); err != nil {
+               return err
+       }
+       out.Write(mac4Size.Sum(nil))
+
+       mw = io.MultiWriter(out, mac)
+       ae = &cipher.StreamWriter{S: ctr, W: mw}
        ae.Write(pktBuf.Bytes())
        if _, err = io.CopyN(ae, data, int64(size)); err != nil {
                return err
@@ -213,7 +238,6 @@ func TbsVerify(our *NodeOur, their *Node, pktEnc *PktEnc) (bool, error) {
                Recipient: our.Id,
                Sender:    their.Id,
                ExchPub:   pktEnc.ExchPub,
-               Size:      pktEnc.Size,
        }
        var tbsBuf bytes.Buffer
        if _, err := xdr.Marshal(&tbsBuf, &tbs); err != nil {
@@ -245,6 +269,16 @@ func PktEncRead(our *NodeOur, nodes map[NodeId]*Node, data io.Reader, out io.Wri
        sharedKey := new([32]byte)
        curve25519.ScalarMult(sharedKey, our.ExchPrv, pktEnc.ExchPub)
        kdf := hkdf.New(blake256, sharedKey[:], nil, MagicNNCPEv1[:])
+
+       // Derive keys
+       keyEnc4Size := make([]byte, 32)
+       if _, err = io.ReadFull(kdf, keyEnc4Size); err != nil {
+               return their, err
+       }
+       keyAuth4Size := make([]byte, 64)
+       if _, err = io.ReadFull(kdf, keyAuth4Size); err != nil {
+               return their, err
+       }
        keyEnc := make([]byte, 32)
        if _, err = io.ReadFull(kdf, keyEnc); err != nil {
                return their, err
@@ -253,6 +287,17 @@ func PktEncRead(our *NodeOur, nodes map[NodeId]*Node, data io.Reader, out io.Wri
        if _, err = io.ReadFull(kdf, keyAuth); err != nil {
                return their, err
        }
+
+       // Initialize ciphers and MACs
+       ciph4Size, err := twofish.NewCipher(keyEnc4Size)
+       if err != nil {
+               return their, err
+       }
+       ctr4Size := cipher.NewCTR(ciph4Size, make([]byte, twofish.BlockSize))
+       mac4Size, err := blake2b.New256(keyAuth4Size)
+       if err != nil {
+               return their, err
+       }
        ciph, err := twofish.NewCipher(keyEnc)
        if err != nil {
                return their, err
@@ -262,15 +307,29 @@ func PktEncRead(our *NodeOur, nodes map[NodeId]*Node, data io.Reader, out io.Wri
        if err != nil {
                return their, err
        }
-       trA := io.TeeReader(data, mac)
-       ae := &cipher.StreamReader{S: ctr, R: trA}
-       if _, err = io.CopyN(out, ae, int64(pktEnc.Size)-blake2b.Size256); err != nil {
+
+       tr := io.TeeReader(data, mac4Size)
+       ae := &cipher.StreamReader{S: ctr4Size, R: tr}
+       var usize uint64
+       if _, err = xdr.Unmarshal(ae, &usize); err != nil {
                return their, err
        }
        tag := make([]byte, blake2b.Size256)
        if _, err = io.ReadFull(data, tag); err != nil {
                return their, err
        }
+       if subtle.ConstantTimeCompare(mac4Size.Sum(nil), tag) != 1 {
+               return their, errors.New("Unauthenticated payload")
+       }
+
+       tr = io.TeeReader(data, mac)
+       ae = &cipher.StreamReader{S: ctr, R: tr}
+       if _, err = io.CopyN(out, ae, PktOverhead+int64(usize)-8-blake2b.Size256-blake2b.Size256); err != nil {
+               return their, err
+       }
+       if _, err = io.ReadFull(data, tag); err != nil {
+               return their, err
+       }
        if subtle.ConstantTimeCompare(mac.Sum(nil), tag) != 1 {
                return their, errors.New("Unauthenticated payload")
        }
index 8ed0502aaeef07427386b290a9ff1e0b15f928c5..ec58785d298018edf2c3681a72a1e9c9ca08d039 100644 (file)
@@ -56,9 +56,6 @@ func TestPktEncWrite(t *testing.T) {
                if *pktEnc.Sender != *nodeOur.Id {
                        return false
                }
-               if pktEnc.Size != uint64(ct.Len()) {
-                       return false
-               }
                return true
        }
        if err := quick.Check(f, nil); err != nil {
@@ -75,7 +72,7 @@ func TestPktEncRead(t *testing.T) {
        if err != nil {
                panic(err)
        }
-       f := func(path string, pathSize uint8, data [1 << 16]byte, size uint16) bool {
+       f := func(path string, pathSize uint8, data [1 << 16]byte, size uint16, junk []byte) bool {
                dataR := bytes.NewReader(data[:])
                var ct bytes.Buffer
                if len(path) > int(pathSize) {
@@ -89,6 +86,7 @@ func TestPktEncRead(t *testing.T) {
                if err != nil {
                        return false
                }
+               ct.Write(junk)
                var pt bytes.Buffer
                nodes := make(map[NodeId]*Node)
                nodes[*node1.Id] = node1.Their()