diff --git a/src/crypto.ts b/src/crypto.ts index 5d583d2..34f8c06 100644 --- a/src/crypto.ts +++ b/src/crypto.ts @@ -1,17 +1,27 @@ -import { Handshake } from "./handshake"; import { Buffer } from "buffer"; +import { Handshake } from "./handshake"; interface ReturnEncryptionWrapper { (source: Iterable): AsyncIterableIterator; } +const maxPlaintextLength = 65519; + // Returns generator that encrypts payload from the user export function encryptStream(handshake: Handshake): ReturnEncryptionWrapper { return async function * (source) { for await (const chunk of source) { - const chunkBuffer = Buffer.from(chunk); - const data = await handshake.encrypt(chunkBuffer, handshake.session); - yield data; + const chunkBuffer = Buffer.from(chunk.buffer, chunk.byteOffset, chunk.length); + + for (let i = 0; i < chunkBuffer.length; i += maxPlaintextLength) { + let end = i + maxPlaintextLength; + if (end > chunkBuffer.length) { + end = chunkBuffer.length; + } + + const data = handshake.encrypt(chunkBuffer.slice(i, end), handshake.session); + yield data; + } } } } @@ -21,9 +31,18 @@ export function encryptStream(handshake: Handshake): ReturnEncryptionWrapper { export function decryptStream(handshake: Handshake): ReturnEncryptionWrapper { return async function * (source) { for await (const chunk of source) { - const chunkBuffer = Buffer.from(chunk); - const decrypted = await handshake.decrypt(chunkBuffer, handshake.session); - yield decrypted + const chunkBuffer = Buffer.from(chunk.buffer, chunk.byteOffset, chunk.length); + + for (let i = 0; i < chunkBuffer.length; i += maxPlaintextLength) { + let end = i + maxPlaintextLength; + if (end > chunkBuffer.length) { + end = chunkBuffer.length; + } + + const chunk = chunkBuffer.slice(i, end); + const decrypted = await handshake.decrypt(chunk, handshake.session); + yield decrypted; + } } } } diff --git a/src/encoder.ts b/src/encoder.ts index ea946ef..6c4cf75 100644 --- a/src/encoder.ts +++ b/src/encoder.ts @@ -4,13 +4,13 @@ import {MessageBuffer} from "./xx"; export const int16BEEncode = (value, target, offset) => { target = target || Buffer.allocUnsafe(2); - return target.writeInt16BE(value, offset); + return target.writeUInt16BE(value, offset); }; int16BEEncode.bytes = 2; export const int16BEDecode = data => { if (data.length < 2) throw RangeError('Could not decode int16BE'); - return data.readInt16BE(0); + return data.readUInt16BE(0); }; int16BEDecode.bytes = 2; diff --git a/test/noise.test.ts b/test/noise.test.ts index 6d42cd5..d6a8dd2 100644 --- a/test/noise.test.ts +++ b/test/noise.test.ts @@ -4,6 +4,7 @@ import DuplexPair from 'it-pair/duplex'; import { Noise } from "../src"; import {createPeerIdsFromFixtures} from "./fixtures/peer"; import Wrap from "it-pb-rpc"; +import { random } from "bcrypto"; import {Handshake} from "../src/handshake"; import { createHandshakePayload, @@ -96,4 +97,31 @@ describe("Noise", () => { assert(false, e.message); } }) + + + it("should test large payloads", async() => { + try { + const { privateKey: libp2pInitPrivKey } = getKeyPairFromPeerId(localPeer); + const { privateKey: libp2pRespPrivKey } = getKeyPairFromPeerId(remotePeer); + const noiseInit = new Noise(libp2pInitPrivKey); + const noiseResp = new Noise(libp2pRespPrivKey); + + const [inboundConnection, outboundConnection] = DuplexPair(); + const [outbound, inbound] = await Promise.all([ + noiseInit.secureOutbound(localPeer, outboundConnection, remotePeer), + noiseResp.secureInbound(remotePeer, inboundConnection, localPeer), + ]); + const wrappedInbound = Wrap(inbound.conn); + const wrappedOutbound = Wrap(outbound.conn); + + const largePlaintext = random.randomBytes(100000); + wrappedOutbound.writeLP(largePlaintext); + const response = await wrappedInbound.readLP(); + + expect(response.length).equals(largePlaintext.length); + } catch (e) { + console.error(e); + assert(false, e.message); + } + }); }); diff --git a/test/utils.ts b/test/utils.ts index 2ac5b7b..5e8b430 100644 --- a/test/utils.ts +++ b/test/utils.ts @@ -1,5 +1,6 @@ import * as crypto from 'libp2p-crypto'; import {KeyPair, PeerId} from "../src/@types/libp2p"; +import {bytes} from "../src/@types/basic"; export async function generateEd25519Keys() { return await crypto.keys.generateKeyPair('ed25519');