split large plaintexts into chunks
@@ -20,6 +20,11 @@ import (
const payload_string = "noise-libp2p-static-key:"
+// Each encrypted transport message must be <= 65,535 bytes, including 16
+// bytes of authentication data. To write larger plaintexts, we split them
+// into fragments of maxPlaintextLength before encrypting.
+const maxPlaintextLength = 65519
+
var log = logging.Logger("noise")
type secureSession struct {
@@ -234,6 +239,7 @@ func (s *secureSession) Read(buf []byte) (int, error) {
return l, nil
}
+ readChunk := func(buf []byte) (int, error) {
// read length of encrypted message
l, err := s.readLength()
if err != nil {
@@ -259,10 +265,26 @@ func (s *secureSession) Read(buf []byte) (int, error) {
s.msgBuffer = append(s.msgBuffer, plaintext...)
c := copy(buf, s.msgBuffer)
s.msgBuffer = s.msgBuffer[c:]
-
return c, nil
}
+ total := 0
+ for i := 0; i < len(buf); i += maxPlaintextLength {
+ end := i + maxPlaintextLength
+ if end > len(buf) {
+ end = len(buf)
+ }
+
+ c, err := readChunk(buf[i:end])
+ total += c
+ if err != nil {
+ return total, err
+ }
+ }
+
+ return total, nil
+}
+
func (s *secureSession) RemoteAddr() net.Addr {
return s.insecure.RemoteAddr()
}
@@ -291,6 +313,7 @@ func (s *secureSession) Write(in []byte) (int, error) {
s.rwLock.Lock()
defer s.rwLock.Unlock()
+ writeChunk := func(in []byte) (int, error) {
ciphertext, err := s.Encrypt(in)
if err != nil {
log.Error("encrypt error", err)
@@ -307,6 +330,22 @@ func (s *secureSession) Write(in []byte) (int, error) {
return len(in), err
}
+ written := 0
+ for i := 0; i < len(in); i += maxPlaintextLength {
+ end := i + maxPlaintextLength
+ if end > len(in) {
+ end = len(in)
+ }
+
+ l, err := writeChunk(in[i:end])
+ written += l
+ if err != nil {
+ return written, err
+ }
+ }
+ return written, nil
+}
+
func (s *secureSession) Close() error {
return s.insecure.Close()
}
