Merge pull request #9 from NodeFactoryIo/fix/larger-payload

Fix sending payloads larger than 65,519 bytes
This commit is contained in:
Marin Petrunić 2019-12-27 13:26:14 +01:00 committed by GitHub
commit 094cffc9cc
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
4 changed files with 57 additions and 9 deletions

View File

@ -1,29 +1,48 @@
import { Handshake } from "./handshake";
import { Buffer } from "buffer";
import { Handshake } from "./handshake";
interface ReturnEncryptionWrapper {
(source: Iterable<Uint8Array>): AsyncIterableIterator<Uint8Array>;
}
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);
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;
}
}
}
}
// Decrypt received payload to the user
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;
}
}
}
}

View File

@ -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;

View File

@ -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);
}
});
});

View File

@ -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');