Merge branch 'master' into mpetrunic/fix-outbount-remote-peer

# Conflicts:
#	CHANGELOG.md
This commit is contained in:
Marin Petrunić 2020-03-11 09:11:39 +01:00
commit ec3c88e1b4
No known key found for this signature in database
GPG Key ID: 834D07135E110DA5
7 changed files with 45 additions and 25 deletions

View File

@ -10,6 +10,16 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
### Bugfixes ### Bugfixes
- return handshake remote peer from secureOutbound - return handshake remote peer from secureOutbound
## [1.0.0-rc.8] - 2019-03-05
### Breaking changes
- Disabled noise pipes
### Bugfixes
- fixed empty ephemeral bug in XX
- verification of AEAD decryption
## [1.0.0-rc.7] - 2019-02-20 ## [1.0.0-rc.7] - 2019-02-20
### Bugfixes ### Bugfixes

View File

@ -25,7 +25,7 @@ import {NOISE, Noise} from "libp2p-noise"
//custom noise configuration, pass it instead of NOISE instance //custom noise configuration, pass it instead of NOISE instance
const noise = new Noise(privateKey, Buffer.alloc(), false); const noise = new Noise(privateKey, Buffer.alloc(x));
const libp2p = new Libp2p({ const libp2p = new Libp2p({
modules: { modules: {
@ -35,7 +35,6 @@ const libp2p = new Libp2p({
``` ```
Where parameters for Noise constructor are: Where parameters for Noise constructor are:
- *private key* - required parameter (32 bytes libp2p peer private key)
- *static Noise key* - (optional) existing private Noise static key - *static Noise key* - (optional) existing private Noise static key
- *early data* - (optional) an early data payload to be sent in handshake messages - *early data* - (optional) an early data payload to be sent in handshake messages

View File

@ -1,6 +1,6 @@
{ {
"name": "libp2p-noise", "name": "libp2p-noise",
"version": "1.0.0-rc.7", "version": "1.0.0-rc.8",
"main": "dist/index.js", "main": "dist/index.js",
"types": "dist/index.d.ts", "types": "dist/index.d.ts",
"module": "lib/index.js", "module": "lib/index.js",

View File

@ -25,6 +25,10 @@ export function encode1(message: MessageBuffer): bytes {
return Buffer.concat([message.ne, message.ns, message.ciphertext]); return Buffer.concat([message.ne, message.ns, message.ciphertext]);
} }
export function encode2(message: MessageBuffer): bytes {
return Buffer.concat([message.ns, message.ciphertext]);
}
export function decode0(input: bytes): MessageBuffer { export function decode0(input: bytes): MessageBuffer {
if (input.length < 32) { if (input.length < 32) {
throw new Error("Cannot decode stage 0 MessageBuffer: length less than 32 bytes."); throw new Error("Cannot decode stage 0 MessageBuffer: length less than 32 bytes.");
@ -39,7 +43,7 @@ export function decode0(input: bytes): MessageBuffer {
export function decode1(input: bytes): MessageBuffer { export function decode1(input: bytes): MessageBuffer {
if (input.length < 80) { if (input.length < 80) {
throw new Error("Cannot decode stage 0 MessageBuffer: length less than 96 bytes."); throw new Error("Cannot decode stage 1 MessageBuffer: length less than 80 bytes.");
} }
return { return {
@ -48,3 +52,15 @@ export function decode1(input: bytes): MessageBuffer {
ciphertext: input.slice(80, input.length), ciphertext: input.slice(80, input.length),
} }
} }
export function decode2(input: bytes): MessageBuffer {
if (input.length < 48) {
throw new Error("Cannot decode stage 2 MessageBuffer: length less than 48 bytes.");
}
return {
ne: Buffer.alloc(0),
ns: input.slice(0, 48),
ciphertext: input.slice(48, input.length),
}
}

View File

@ -11,7 +11,7 @@ import {
verifySignedPayload, verifySignedPayload,
} from "./utils"; } from "./utils";
import { logger } from "./logger"; import { logger } from "./logger";
import { decode0, decode1, encode0, encode1 } from "./encoder"; import {decode0, decode1, decode2, encode0, encode1, encode2} from "./encoder";
import { WrappedConnection } from "./noise"; import { WrappedConnection } from "./noise";
import PeerId from "peer-id"; import PeerId from "peer-id";
@ -99,11 +99,11 @@ export class XXHandshake implements IHandshake {
if (this.isInitiator) { if (this.isInitiator) {
logger('Stage 2 - Initiator sending third handshake message.'); logger('Stage 2 - Initiator sending third handshake message.');
const messageBuffer = this.xx.sendMessage(this.session, this.payload); const messageBuffer = this.xx.sendMessage(this.session, this.payload);
this.connection.writeLP(encode1(messageBuffer)); this.connection.writeLP(encode2(messageBuffer));
logger('Stage 2 - Initiator sent message with signed payload.'); logger('Stage 2 - Initiator sent message with signed payload.');
} else { } else {
logger('Stage 2 - Responder waiting for third handshake message...'); logger('Stage 2 - Responder waiting for third handshake message...');
const receivedMessageBuffer = decode1((await this.connection.readLP()).slice()); const receivedMessageBuffer = decode2((await this.connection.readLP()).slice());
const {plaintext, valid} = this.xx.recvMessage(this.session, receivedMessageBuffer); const {plaintext, valid} = this.xx.recvMessage(this.session, receivedMessageBuffer);
if(!valid) { if(!valid) {
throw new Error("xx handshake stage 2 validation fail"); throw new Error("xx handshake stage 2 validation fail");

View File

@ -42,11 +42,11 @@ export class Noise implements INoiseConnection {
* *
* @param staticNoiseKey x25519 private key, reuse for faster handshakes * @param staticNoiseKey x25519 private key, reuse for faster handshakes
* @param earlyData * @param earlyData
* @param useNoisePipes enable IK handshake if initiator static key is known
*/ */
constructor(staticNoiseKey?: bytes, earlyData?: bytes, useNoisePipes = true) { constructor(staticNoiseKey?: bytes, earlyData?: bytes) {
this.earlyData = earlyData || Buffer.alloc(0); this.earlyData = earlyData || Buffer.alloc(0);
this.useNoisePipes = useNoisePipes; //disabled until properly specked
this.useNoisePipes = false;
if (staticNoiseKey) { if (staticNoiseKey) {
const publicKey = x25519.publicKeyCreate(staticNoiseKey); const publicKey = x25519.publicKeyCreate(staticNoiseKey);

View File

@ -1,18 +1,13 @@
import { expect, assert } from "chai"; import {assert, expect} from "chai";
import DuplexPair from 'it-pair/duplex'; import DuplexPair from 'it-pair/duplex';
import { Noise } from "../src"; import {Noise} from "../src";
import {createPeerIdsFromFixtures} from "./fixtures/peer"; import {createPeerIdsFromFixtures} from "./fixtures/peer";
import Wrap from "it-pb-rpc"; import Wrap from "it-pb-rpc";
import { random } from "bcrypto"; import {random} from "bcrypto";
import sinon from "sinon"; import sinon from "sinon";
import {XXHandshake} from "../src/handshake-xx"; import {XXHandshake} from "../src/handshake-xx";
import { import {createHandshakePayload, generateKeypair, getHandshakePayload, getPayload, signPayload} from "../src/utils";
createHandshakePayload, import {decode0, decode2, encode1, uint16BEDecode, uint16BEEncode} from "../src/encoder";
generateKeypair,
getHandshakePayload, getPayload,
signPayload
} from "../src/utils";
import {decode0, decode1, encode1, uint16BEDecode, uint16BEEncode} from "../src/encoder";
import {XX} from "../src/handshakes/xx"; import {XX} from "../src/handshakes/xx";
import {Buffer} from "buffer"; import {Buffer} from "buffer";
import {getKeyPairFromPeerId} from "./utils"; import {getKeyPairFromPeerId} from "./utils";
@ -89,7 +84,7 @@ describe("Noise", () => {
wrapped.writeLP(encode1(messageBuffer)); wrapped.writeLP(encode1(messageBuffer));
// Stage 2 - finish handshake // Stage 2 - finish handshake
receivedMessageBuffer = decode1((await wrapped.readLP()).slice()); receivedMessageBuffer = decode2((await wrapped.readLP()).slice());
xx.recvMessage(handshake.session, receivedMessageBuffer); xx.recvMessage(handshake.session, receivedMessageBuffer);
return {wrapped, handshake}; return {wrapped, handshake};
})(), })(),
@ -138,7 +133,7 @@ describe("Noise", () => {
} }
}); });
it("should communicate through encrypted streams with noise pipes", async() => { it.skip("should communicate through encrypted streams with noise pipes", async() => {
try { try {
const staticKeysInitiator = generateKeypair(); const staticKeysInitiator = generateKeypair();
const noiseInit = new Noise(staticKeysInitiator.privateKey); const noiseInit = new Noise(staticKeysInitiator.privateKey);
@ -172,7 +167,7 @@ describe("Noise", () => {
} }
}); });
it("IK -> XX fallback: initiator has invalid remote static key", async() => { it.skip("IK -> XX fallback: initiator has invalid remote static key", async() => {
try { try {
const staticKeysInitiator = generateKeypair(); const staticKeysInitiator = generateKeypair();
const noiseInit = new Noise(staticKeysInitiator.privateKey); const noiseInit = new Noise(staticKeysInitiator.privateKey);
@ -238,7 +233,7 @@ describe("Noise", () => {
} }
}); });
it("Initiator starts with XX (pipes disabled), responder has enabled noise pipes", async() => { it.skip("Initiator starts with XX (pipes disabled), responder has enabled noise pipes", async() => {
try { try {
const staticKeysInitiator = generateKeypair(); const staticKeysInitiator = generateKeypair();
const noiseInit = new Noise(staticKeysInitiator.privateKey, undefined, false); const noiseInit = new Noise(staticKeysInitiator.privateKey, undefined, false);
@ -273,7 +268,7 @@ describe("Noise", () => {
} }
}); });
it("IK: responder has no remote static key", async() => { it.skip("IK: responder has no remote static key", async() => {
try { try {
const staticKeysInitiator = generateKeypair(); const staticKeysInitiator = generateKeypair();
const noiseInit = new Noise(staticKeysInitiator.privateKey); const noiseInit = new Noise(staticKeysInitiator.privateKey);