mirror of
https://github.com/fluencelabs/js-libp2p-noise
synced 2025-07-31 04:22:20 +00:00
Merge pull request #3 from NodeFactoryIo/morrigan/interface
New interface with XX handshake
This commit is contained in:
@@ -16,6 +16,7 @@
|
||||
"devDependencies": {
|
||||
"@babel/cli": "^7.6.4",
|
||||
"@babel/core": "^7.6.4",
|
||||
"@babel/plugin-proposal-async-generator-functions": "^7.7.0",
|
||||
"@babel/plugin-proposal-object-rest-spread": "^7.6.2",
|
||||
"@babel/preset-env": "^7.6.3",
|
||||
"@babel/preset-typescript": "^7.6.0",
|
||||
@@ -45,13 +46,16 @@
|
||||
"@babel/preset-typescript"
|
||||
],
|
||||
"plugins": [
|
||||
"@babel/plugin-proposal-object-rest-spread"
|
||||
"@babel/plugin-proposal-object-rest-spread",
|
||||
"@babel/plugin-proposal-async-generator-functions"
|
||||
]
|
||||
},
|
||||
"dependencies": {
|
||||
"bcrypto": "^4.2.3",
|
||||
"bn.js": "^5.0.0",
|
||||
"buffer": "^5.4.3",
|
||||
"it-pair": "^1.0.0",
|
||||
"it-pb-rpc": "^0.1.3",
|
||||
"protobufjs": "~6.8.8"
|
||||
}
|
||||
}
|
||||
|
6
src/@types/it-pair/index.d.ts
vendored
Normal file
6
src/@types/it-pair/index.d.ts
vendored
Normal file
@@ -0,0 +1,6 @@
|
||||
export type Duplex = [Stream, Stream];
|
||||
|
||||
type Stream = {
|
||||
sink(source: Iterable<any>);
|
||||
source: Record<string, any>;
|
||||
}
|
15
src/@types/it-pb-rpc/index.d.ts
vendored
Normal file
15
src/@types/it-pb-rpc/index.d.ts
vendored
Normal file
@@ -0,0 +1,15 @@
|
||||
declare module "it-pb-rpc" {
|
||||
import { Buffer } from "buffer";
|
||||
import { Duplex } from "it-pair";
|
||||
type WrappedDuplex = {
|
||||
read(bytes: number): Buffer;
|
||||
readLP(): Buffer;
|
||||
write(input: Buffer): void;
|
||||
writeLP(input: Buffer): void;
|
||||
unwrap(): Duplex;
|
||||
}
|
||||
|
||||
function Wrap (duplex: any): WrappedDuplex;
|
||||
|
||||
export = Wrap;
|
||||
}
|
25
src/@types/libp2p.ts
Normal file
25
src/@types/libp2p.ts
Normal file
@@ -0,0 +1,25 @@
|
||||
import { bytes, bytes32 } from "./basic";
|
||||
import { Duplex } from "it-pair";
|
||||
|
||||
export interface KeyPair {
|
||||
publicKey: bytes32;
|
||||
privateKey: bytes32;
|
||||
}
|
||||
|
||||
export type PeerId = {
|
||||
id: string;
|
||||
privKey: string;
|
||||
pubKey: string;
|
||||
};
|
||||
|
||||
export interface NoiseConnection {
|
||||
remoteEarlyData?(): bytes;
|
||||
secureOutbound(localPeer: PeerId, insecure: any, remotePeer: PeerId): Promise<SecureOutbound>;
|
||||
secureInbound(localPeer: PeerId, insecure: any, remotePeer: PeerId): Promise<SecureOutbound>;
|
||||
}
|
||||
|
||||
export type SecureOutbound = {
|
||||
conn: Duplex;
|
||||
remotePeer: PeerId;
|
||||
}
|
||||
|
15
src/crypto.ts
Normal file
15
src/crypto.ts
Normal file
@@ -0,0 +1,15 @@
|
||||
import { Duplex } from "it-pair";
|
||||
import { NoiseSession } from "./xx";
|
||||
|
||||
// Send encrypted payload from the user to stream
|
||||
export async function encryptStreams(streams: Duplex, session: NoiseSession): Promise<Duplex> {
|
||||
// TODO: implement
|
||||
return streams;
|
||||
}
|
||||
|
||||
|
||||
// Decrypt received payload from the stream and pipe to user
|
||||
export async function decryptStreams(streams: Duplex, session: NoiseSession): Promise<Duplex> {
|
||||
// TODO: implement
|
||||
return streams;
|
||||
}
|
@@ -1,3 +0,0 @@
|
||||
export function encrypt() {
|
||||
return "Encrypt world";
|
||||
}
|
89
src/handshake.ts
Normal file
89
src/handshake.ts
Normal file
@@ -0,0 +1,89 @@
|
||||
import { bytes, bytes32 } from "./@types/basic";
|
||||
import { NoiseSession, XXHandshake } from "./xx";
|
||||
import { KeyPair } from "./@types/libp2p";
|
||||
import { Buffer } from "buffer";
|
||||
import {
|
||||
createHandshakePayload,
|
||||
decodeMessageBuffer,
|
||||
encodeMessageBuffer,
|
||||
getHandshakePayload,
|
||||
signPayload
|
||||
} from "./utils";
|
||||
import { WrappedConnection } from "./noise";
|
||||
|
||||
type handshakeType = "XX";
|
||||
|
||||
export class Handshake {
|
||||
private type: handshakeType;
|
||||
private remotePublicKey: bytes;
|
||||
private prologue: bytes32;
|
||||
private staticKeys: KeyPair;
|
||||
private connection: WrappedConnection;
|
||||
private xx: XXHandshake;
|
||||
|
||||
constructor(
|
||||
type: handshakeType,
|
||||
remotePublicKey: bytes,
|
||||
prologue: bytes32,
|
||||
staticKeys: KeyPair,
|
||||
connection: WrappedConnection,
|
||||
) {
|
||||
this.type = type;
|
||||
this.remotePublicKey = remotePublicKey;
|
||||
this.prologue = prologue;
|
||||
this.staticKeys = staticKeys;
|
||||
this.connection = connection;
|
||||
|
||||
this.xx = new XXHandshake();
|
||||
}
|
||||
|
||||
// stage 0
|
||||
async propose(isInitiator: boolean, earlyData?: bytes): Promise<NoiseSession> {
|
||||
const ns = await this.xx.initSession(isInitiator, this.prologue, this.staticKeys, this.remotePublicKey);
|
||||
|
||||
if (isInitiator) {
|
||||
const signedPayload = signPayload(this.staticKeys.privateKey, getHandshakePayload(this.staticKeys.publicKey));
|
||||
const handshakePayload = await createHandshakePayload(
|
||||
this.staticKeys.publicKey,
|
||||
signedPayload,
|
||||
earlyData,
|
||||
this.staticKeys.privateKey
|
||||
);
|
||||
const message = Buffer.concat([Buffer.alloc(0), handshakePayload]);
|
||||
const messageBuffer = await this.xx.sendMessage(ns, message);
|
||||
this.connection.writeLP(encodeMessageBuffer(messageBuffer));
|
||||
} else {
|
||||
const receivedMessageBuffer = (await this.connection.readLP()).slice();
|
||||
const plaintext = await this.xx.recvMessage(ns, decodeMessageBuffer(receivedMessageBuffer));
|
||||
}
|
||||
|
||||
return ns;
|
||||
}
|
||||
|
||||
// stage 1
|
||||
async exchange(isInitiator: boolean, session: NoiseSession): Promise<void> {
|
||||
if (isInitiator) {
|
||||
const receivedMessageBuffer = (await this.connection.readLP()).slice();
|
||||
const plaintext = await this.xx.recvMessage(session, decodeMessageBuffer(receivedMessageBuffer));
|
||||
} else {
|
||||
// create payload as responder
|
||||
const signedPayload = signPayload(this.staticKeys.privateKey, getHandshakePayload(this.staticKeys.publicKey));
|
||||
const handshakePayload = await createHandshakePayload(this.remotePublicKey, signedPayload);
|
||||
|
||||
const message = Buffer.concat([Buffer.alloc(0), handshakePayload]);
|
||||
const messageBuffer = await this.xx.sendMessage(session, message);
|
||||
this.connection.writeLP(encodeMessageBuffer(messageBuffer));
|
||||
}
|
||||
}
|
||||
|
||||
// stage 2
|
||||
async finish(isInitiator: boolean, session: NoiseSession): Promise<void> {
|
||||
if (isInitiator) {
|
||||
const messageBuffer = await this.xx.sendMessage(session, Buffer.alloc(0));
|
||||
this.connection.writeLP(encodeMessageBuffer(messageBuffer));
|
||||
} else {
|
||||
const receivedMessageBuffer = (await this.connection.readLP()).slice();
|
||||
const plaintext = await this.xx.recvMessage(session, decodeMessageBuffer(receivedMessageBuffer));
|
||||
}
|
||||
}
|
||||
}
|
@@ -1,8 +1 @@
|
||||
import { encrypt } from './encrypt';
|
||||
|
||||
const tag = '/noise';
|
||||
|
||||
export {
|
||||
tag,
|
||||
encrypt,
|
||||
}
|
||||
export * from "./noise";
|
||||
|
85
src/noise.ts
Normal file
85
src/noise.ts
Normal file
@@ -0,0 +1,85 @@
|
||||
import { x25519 } from 'bcrypto';
|
||||
import { Buffer } from "buffer";
|
||||
import Wrap from 'it-pb-rpc';
|
||||
|
||||
import { Handshake } from "./handshake";
|
||||
import { generateKeypair } from "./utils";
|
||||
import { decryptStreams, encryptStreams } from "./crypto";
|
||||
import { bytes } from "./@types/basic";
|
||||
import { NoiseConnection, PeerId, KeyPair, SecureOutbound } from "./@types/libp2p";
|
||||
import { Duplex } from "./@types/it-pair";
|
||||
|
||||
export type WrappedConnection = ReturnType<typeof Wrap>;
|
||||
|
||||
export class Noise implements NoiseConnection {
|
||||
public protocol = "/noise";
|
||||
|
||||
private readonly privateKey: bytes;
|
||||
private readonly staticKeys: KeyPair;
|
||||
private readonly earlyData?: bytes;
|
||||
|
||||
constructor(privateKey: bytes, staticNoiseKey?: bytes, earlyData?: bytes) {
|
||||
this.privateKey = privateKey;
|
||||
this.earlyData = earlyData;
|
||||
|
||||
if (staticNoiseKey) {
|
||||
const publicKey = x25519.publicKeyCreate(staticNoiseKey);
|
||||
this.staticKeys = {
|
||||
privateKey: staticNoiseKey,
|
||||
publicKey,
|
||||
}
|
||||
} else {
|
||||
this.staticKeys = generateKeypair();
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Encrypt outgoing data to the remote party (handshake as initiator)
|
||||
* @param {PeerId} localPeer - PeerId of the receiving peer
|
||||
* @param connection - streaming iterable duplex that will be encrypted
|
||||
* @param {PeerId} remotePeer - PeerId of the remote peer. Used to validate the integrity of the remote peer.
|
||||
* @returns {Promise<SecureOutbound>}
|
||||
*/
|
||||
public async secureOutbound(localPeer: PeerId, connection: any, remotePeer: PeerId): Promise<SecureOutbound> {
|
||||
const wrappedConnection = Wrap(connection);
|
||||
const remotePublicKey = Buffer.from(remotePeer.pubKey);
|
||||
const session = await this.createSecureConnection(wrappedConnection, remotePublicKey, true);
|
||||
|
||||
return {
|
||||
conn: session,
|
||||
remotePeer,
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Decrypt incoming data (handshake as responder).
|
||||
* @param {PeerId} localPeer - PeerId of the receiving peer.
|
||||
* @param connection - streaming iterable duplex that will be encryption.
|
||||
* @param {PeerId} remotePeer - optional PeerId of the initiating peer, if known. This may only exist during transport upgrades.
|
||||
* @returns {Promise<SecureOutbound>}
|
||||
*/
|
||||
// tslint:disable-next-line
|
||||
public async secureInbound(localPeer: PeerId, connection: any, remotePeer: PeerId): Promise<SecureOutbound> {
|
||||
return {
|
||||
conn: undefined,
|
||||
remotePeer
|
||||
}
|
||||
}
|
||||
|
||||
private async createSecureConnection(
|
||||
connection: WrappedConnection,
|
||||
remotePublicKey: bytes,
|
||||
isInitiator: boolean,
|
||||
): Promise<Duplex> {
|
||||
const prologue = Buffer.from(this.protocol);
|
||||
const handshake = new Handshake('XX', remotePublicKey, prologue, this.staticKeys, connection);
|
||||
|
||||
const session = await handshake.propose(isInitiator, this.earlyData);
|
||||
await handshake.exchange(isInitiator, session);
|
||||
await handshake.finish(isInitiator, session);
|
||||
|
||||
return await encryptStreams(connection, session);
|
||||
}
|
||||
|
||||
|
||||
}
|
73
src/utils.ts
Normal file
73
src/utils.ts
Normal file
@@ -0,0 +1,73 @@
|
||||
import { x25519, ed25519 } from 'bcrypto';
|
||||
import protobuf from "protobufjs";
|
||||
import { Buffer } from "buffer";
|
||||
|
||||
import { KeyPair } from "./@types/libp2p";
|
||||
import { bytes } from "./@types/basic";
|
||||
import { MessageBuffer } from "./xx";
|
||||
|
||||
export async function loadPayloadProto () {
|
||||
const payloadProtoBuf = await protobuf.load("protos/payload.proto");
|
||||
return payloadProtoBuf.lookupType("pb.NoiseHandshakePayload");
|
||||
}
|
||||
|
||||
export function generateKeypair(): KeyPair {
|
||||
const privateKey = x25519.privateKeyGenerate();
|
||||
const publicKey = x25519.publicKeyCreate(privateKey);
|
||||
|
||||
return {
|
||||
publicKey,
|
||||
privateKey,
|
||||
}
|
||||
}
|
||||
|
||||
export async function createHandshakePayload(
|
||||
libp2pPublicKey: bytes,
|
||||
signedPayload: bytes,
|
||||
earlyData?: bytes,
|
||||
libp2pPrivateKey?: bytes,
|
||||
): Promise<bytes> {
|
||||
const NoiseHandshakePayload = await loadPayloadProto();
|
||||
const payloadInit = NoiseHandshakePayload.create({
|
||||
libp2pKey: libp2pPublicKey,
|
||||
noiseStaticKeySignature: signedPayload,
|
||||
...resolveEarlyDataPayload(libp2pPrivateKey, earlyData),
|
||||
});
|
||||
|
||||
return Buffer.from(NoiseHandshakePayload.encode(payloadInit).finish());
|
||||
}
|
||||
|
||||
|
||||
export function signPayload(privateKey: bytes, payload: bytes) {
|
||||
return ed25519.sign(payload, privateKey);
|
||||
}
|
||||
|
||||
export const getHandshakePayload = (publicKey: bytes ) => Buffer.concat([Buffer.from("noise-libp2p-static-key:"), publicKey]);
|
||||
|
||||
export const getEarlyDataPayload = (earlyData: bytes) => Buffer.concat([Buffer.from("noise-libp2p-early-data:"), earlyData]);
|
||||
|
||||
function resolveEarlyDataPayload(privateKey?: bytes, earlyData?: bytes): Record<string, any> {
|
||||
if (!earlyData || !privateKey) {
|
||||
return {};
|
||||
}
|
||||
|
||||
const payload = getEarlyDataPayload(earlyData);
|
||||
const signedPayload = signPayload(privateKey, payload);
|
||||
return {
|
||||
libp2pData: payload,
|
||||
libp2pDataSignature: signedPayload,
|
||||
}
|
||||
}
|
||||
|
||||
export function encodeMessageBuffer(message: MessageBuffer): bytes {
|
||||
return Buffer.concat([message.ne, message.ns, message.ciphertext]);
|
||||
}
|
||||
|
||||
export function decodeMessageBuffer(message: bytes): MessageBuffer {
|
||||
return {
|
||||
ne: message.slice(0, 32),
|
||||
ns: message.slice(32, 80),
|
||||
ciphertext: message.slice(80, message.length),
|
||||
}
|
||||
}
|
||||
|
30
src/xx.ts
30
src/xx.ts
@@ -1,14 +1,12 @@
|
||||
import {bytes32, bytes16, uint32, uint64, bytes} from './types/basic'
|
||||
import { Buffer } from 'buffer';
|
||||
import { AEAD, x25519, HKDF, SHA256 } from 'bcrypto';
|
||||
import { BN } from 'bn.js';
|
||||
|
||||
export interface KeyPair {
|
||||
publicKey: bytes32;
|
||||
privateKey: bytes32;
|
||||
}
|
||||
import { bytes32, uint32, uint64, bytes } from './@types/basic'
|
||||
import { KeyPair } from './@types/libp2p'
|
||||
import { generateKeypair } from './utils';
|
||||
|
||||
interface MessageBuffer {
|
||||
export interface MessageBuffer {
|
||||
ne: bytes32;
|
||||
ns: bytes;
|
||||
ciphertext: bytes;
|
||||
@@ -34,7 +32,7 @@ type HandshakeState = {
|
||||
psk: bytes32;
|
||||
}
|
||||
|
||||
type NoiseSession = {
|
||||
export type NoiseSession = {
|
||||
hs: HandshakeState;
|
||||
h?: bytes32;
|
||||
cs1?: CipherState;
|
||||
@@ -157,7 +155,7 @@ export class XXHandshake {
|
||||
return { cs, ck, h };
|
||||
}
|
||||
|
||||
private mixKey(ss: SymmetricState, ikm: bytes32) {
|
||||
private mixKey(ss: SymmetricState, ikm: bytes32): void {
|
||||
const [ ck, tempK ] = this.getHkdf(ss.ck, ikm);
|
||||
ss.cs = this.initializeKey(tempK) as CipherState;
|
||||
ss.ck = ck;
|
||||
@@ -185,7 +183,7 @@ export class XXHandshake {
|
||||
return [ k1, k2, k3 ];
|
||||
}
|
||||
|
||||
private mixHash(ss: SymmetricState, data: bytes) {
|
||||
private mixHash(ss: SymmetricState, data: bytes): void {
|
||||
ss.h = this.getHash(ss.h, data);
|
||||
}
|
||||
|
||||
@@ -227,7 +225,7 @@ export class XXHandshake {
|
||||
|
||||
private async writeMessageA(hs: HandshakeState, payload: bytes): Promise<MessageBuffer> {
|
||||
const ns = Buffer.alloc(0);
|
||||
hs.e = await this.generateKeypair();
|
||||
hs.e = generateKeypair();
|
||||
const ne = hs.e.publicKey;
|
||||
|
||||
this.mixHash(hs.ss, ne);
|
||||
@@ -237,7 +235,7 @@ export class XXHandshake {
|
||||
}
|
||||
|
||||
private async writeMessageB(hs: HandshakeState, payload: bytes): Promise<MessageBuffer> {
|
||||
hs.e = await this.generateKeypair();
|
||||
hs.e = generateKeypair();
|
||||
const ne = hs.e.publicKey;
|
||||
this.mixHash(hs.ss, ne);
|
||||
|
||||
@@ -318,16 +316,6 @@ export class XXHandshake {
|
||||
return this.decryptWithAd(cs, Buffer.alloc(0), message.ciphertext);
|
||||
}
|
||||
|
||||
public async generateKeypair(): Promise<KeyPair> {
|
||||
const privateKey = x25519.privateKeyGenerate();
|
||||
const publicKey = x25519.publicKeyCreate(privateKey);
|
||||
|
||||
return {
|
||||
publicKey,
|
||||
privateKey,
|
||||
}
|
||||
}
|
||||
|
||||
public async initSession(initiator: boolean, prologue: bytes32, s: KeyPair, rs: bytes32): Promise<NoiseSession> {
|
||||
const psk = this.createEmptyKey();
|
||||
let hs;
|
||||
|
38
test/handshake.test.ts
Normal file
38
test/handshake.test.ts
Normal file
@@ -0,0 +1,38 @@
|
||||
import {assert} from "chai";
|
||||
import Duplex from 'it-pair/duplex';
|
||||
import {Buffer} from "buffer";
|
||||
import Wrap from "it-pb-rpc";
|
||||
|
||||
import {Handshake} from "../src/handshake";
|
||||
import {generateKeypair} from "../src/utils";
|
||||
|
||||
describe("Handshake", () => {
|
||||
it("should propose, exchange and finish handshake", async() => {
|
||||
const duplex = Duplex();
|
||||
const connectionFrom = Wrap(duplex[0]);
|
||||
const connectionTo = Wrap(duplex[1]);
|
||||
|
||||
const prologue = Buffer.from('/noise');
|
||||
const staticKeysInitiator = generateKeypair();
|
||||
const staticKeysResponder = generateKeypair();
|
||||
|
||||
const handshakeInitator = new Handshake('XX', staticKeysResponder.publicKey, prologue, staticKeysInitiator, connectionFrom);
|
||||
const handshakeResponder = new Handshake('XX', staticKeysInitiator.publicKey, prologue, staticKeysResponder, connectionTo);
|
||||
|
||||
const sessionInitator = await handshakeInitator.propose(true);
|
||||
const sessionResponder = await handshakeResponder.propose(false);
|
||||
|
||||
await handshakeResponder.exchange(false, sessionResponder);
|
||||
await handshakeInitator.exchange(true, sessionInitator);
|
||||
|
||||
await handshakeInitator.finish(true, sessionInitator);
|
||||
await handshakeResponder.finish(false, sessionResponder);
|
||||
|
||||
if (sessionInitator.cs1 && sessionResponder.cs1 && sessionInitator.cs2 && sessionResponder.cs2) {
|
||||
assert(sessionInitator.cs1.k.equals(sessionResponder.cs1.k));
|
||||
assert(sessionInitator.cs2.k.equals(sessionResponder.cs2.k));
|
||||
} else {
|
||||
assert(false);
|
||||
}
|
||||
});
|
||||
});
|
@@ -1,9 +1,11 @@
|
||||
import { expect } from "chai";
|
||||
import { tag, encrypt} from "../src";
|
||||
import { Noise } from "../src";
|
||||
|
||||
describe("Index", () => {
|
||||
it("should expose right tag and encrypt function", () => {
|
||||
expect(tag).to.equal('/noise');
|
||||
expect(typeof(encrypt)).to.equal('function');
|
||||
it("should expose class with tag and required functions", () => {
|
||||
const noise = new Noise(Buffer.from("privatekey"));
|
||||
expect(noise.protocol).to.equal('/noise');
|
||||
expect(typeof(noise.secureInbound)).to.equal('function');
|
||||
expect(typeof(noise.secureOutbound)).to.equal('function');
|
||||
})
|
||||
});
|
||||
|
14
test/noise.test.ts
Normal file
14
test/noise.test.ts
Normal file
@@ -0,0 +1,14 @@
|
||||
import { expect } from "chai";
|
||||
import DuplexPair from 'it-pair/duplex';
|
||||
|
||||
import { Noise } from "../src";
|
||||
import {generateEd25519Keys} from "./utils";
|
||||
|
||||
describe("Noise", () => {
|
||||
it("should encrypt outgoing data using secureOutbound", async() => {
|
||||
// const libp2pKeys = await generateEd25519Keys();
|
||||
//
|
||||
// const noise = new Noise(libp2pKeys._key);
|
||||
// await noise.secureOutbound();
|
||||
})
|
||||
});
|
@@ -1,11 +1,5 @@
|
||||
import protobuf from "protobufjs";
|
||||
import * as crypto from 'libp2p-crypto';
|
||||
|
||||
export async function loadPayloadProto () {
|
||||
const payloadProtoBuf = await protobuf.load("protos/payload.proto");
|
||||
return payloadProtoBuf.lookupType("pb.NoiseHandshakePayload");
|
||||
}
|
||||
|
||||
export async function generateEd25519Keys() {
|
||||
return await crypto.keys.generateKeyPair('ed25519');
|
||||
}
|
||||
|
@@ -1,8 +1,10 @@
|
||||
import { expect, assert } from "chai";
|
||||
import { Buffer } from 'buffer';
|
||||
|
||||
import { XXHandshake, KeyPair } from "../src/xx";
|
||||
import { loadPayloadProto, generateEd25519Keys } from "./utils";
|
||||
import { XXHandshake } from "../src/xx";
|
||||
import { KeyPair } from "../src/@types/libp2p";
|
||||
import { generateEd25519Keys } from "./utils";
|
||||
import {createHandshakePayload, generateKeypair, getHandshakePayload} from "../src/utils";
|
||||
|
||||
describe("Index", () => {
|
||||
const prologue = Buffer.from("/noise", "utf-8");
|
||||
@@ -10,12 +12,12 @@ describe("Index", () => {
|
||||
it("Test creating new XX session", async () => {
|
||||
const xx = new XXHandshake();
|
||||
|
||||
const kpInitiator: KeyPair = await xx.generateKeypair();
|
||||
const kpResponder: KeyPair = await xx.generateKeypair();
|
||||
const kpInitiator: KeyPair = await generateKeypair();
|
||||
const kpResponder: KeyPair = await generateKeypair();
|
||||
|
||||
|
||||
const session = await xx.initSession(true, prologue, kpInitiator, kpResponder.publicKey);
|
||||
})
|
||||
});
|
||||
|
||||
it("Test get HKDF", async () => {
|
||||
const xx = new XXHandshake();
|
||||
@@ -28,20 +30,19 @@ describe("Index", () => {
|
||||
expect(k1.toString('hex')).to.equal('cc5659adff12714982f806e2477a8d5ddd071def4c29bb38777b7e37046f6914');
|
||||
expect(k2.toString('hex')).to.equal('a16ada915e551ab623f38be674bb4ef15d428ae9d80688899c9ef9b62ef208fa');
|
||||
expect(k3.toString('hex')).to.equal('ff67bf9727e31b06efc203907e6786667d2c7a74ac412b4d31a80ba3fd766f68');
|
||||
})
|
||||
});
|
||||
|
||||
async function doHandshake(xx) {
|
||||
const kpInit = await xx.generateKeypair();
|
||||
const kpResp = await xx.generateKeypair();
|
||||
const payloadString = Buffer.from("noise-libp2p-static-key:");
|
||||
const kpInit = await generateKeypair();
|
||||
const kpResp = await generateKeypair();
|
||||
|
||||
// initiator setup
|
||||
const libp2pInitKeys = await generateEd25519Keys();
|
||||
const initSignedPayload = await libp2pInitKeys.sign(Buffer.concat([payloadString, kpInit.publicKey]));
|
||||
const initSignedPayload = await libp2pInitKeys.sign(getHandshakePayload(kpInit.publicKey));
|
||||
|
||||
// responder setup
|
||||
const libp2pRespKeys = await generateEd25519Keys();
|
||||
const respSignedPayload = await libp2pRespKeys.sign(Buffer.concat([payloadString, kpResp.publicKey]));
|
||||
const respSignedPayload = await libp2pRespKeys.sign(getHandshakePayload(kpResp.publicKey));
|
||||
|
||||
// initiator: new XX noise session
|
||||
const nsInit = await xx.initSession(true, prologue, kpInit, kpResp.publicKey);
|
||||
@@ -51,12 +52,7 @@ describe("Index", () => {
|
||||
/* STAGE 0 */
|
||||
|
||||
// initiator creates payload
|
||||
const NoiseHandshakePayload = await loadPayloadProto();
|
||||
const payloadInit = NoiseHandshakePayload.create({
|
||||
libp2pKey: libp2pInitKeys.bytes,
|
||||
noiseStaticKeySignature: initSignedPayload,
|
||||
});
|
||||
const payloadInitEnc = NoiseHandshakePayload.encode(payloadInit).finish();
|
||||
const payloadInitEnc = await createHandshakePayload(libp2pInitKeys.bytes, initSignedPayload)
|
||||
|
||||
// initiator sends message
|
||||
const message = Buffer.concat([Buffer.alloc(0), payloadInitEnc]);
|
||||
@@ -71,11 +67,7 @@ describe("Index", () => {
|
||||
/* STAGE 1 */
|
||||
|
||||
// responder creates payload
|
||||
const payloadResp = NoiseHandshakePayload.create({
|
||||
libp2pKey: libp2pRespKeys.bytes,
|
||||
noiseStaticKeySignature: respSignedPayload,
|
||||
});
|
||||
const payloadRespEnc = NoiseHandshakePayload.encode(payloadResp).finish();
|
||||
const payloadRespEnc = await createHandshakePayload(libp2pRespKeys.bytes, respSignedPayload);
|
||||
|
||||
const message1 = Buffer.concat([message, payloadRespEnc]);
|
||||
const messageBuffer2 = await xx.sendMessage(nsResp, message1);
|
||||
|
@@ -7,7 +7,8 @@
|
||||
"noImplicitAny": false,
|
||||
"typeRoots": [
|
||||
"./node_modules/@types",
|
||||
"./node_modules/bn.js-typings/index.d.ts"
|
||||
"./node_modules/bn.js-typings/index.d.ts",
|
||||
"./src/@types"
|
||||
]
|
||||
},
|
||||
"include": [
|
||||
|
177
yarn.lock
177
yarn.lock
@@ -56,6 +56,16 @@
|
||||
lodash "^4.17.13"
|
||||
source-map "^0.5.0"
|
||||
|
||||
"@babel/generator@^7.7.2":
|
||||
version "7.7.2"
|
||||
resolved "https://registry.yarnpkg.com/@babel/generator/-/generator-7.7.2.tgz#2f4852d04131a5e17ea4f6645488b5da66ebf3af"
|
||||
integrity sha512-WthSArvAjYLz4TcbKOi88me+KmDJdKSlfwwN8CnUYn9jBkzhq0ZEPuBfkAWIvjJ3AdEV1Cf/+eSQTnp3IDJKlQ==
|
||||
dependencies:
|
||||
"@babel/types" "^7.7.2"
|
||||
jsesc "^2.5.1"
|
||||
lodash "^4.17.13"
|
||||
source-map "^0.5.0"
|
||||
|
||||
"@babel/helper-annotate-as-pure@^7.0.0":
|
||||
version "7.0.0"
|
||||
resolved "https://registry.yarnpkg.com/@babel/helper-annotate-as-pure/-/helper-annotate-as-pure-7.0.0.tgz#323d39dd0b50e10c7c06ca7d7638e6864d8c5c32"
|
||||
@@ -63,6 +73,13 @@
|
||||
dependencies:
|
||||
"@babel/types" "^7.0.0"
|
||||
|
||||
"@babel/helper-annotate-as-pure@^7.7.0":
|
||||
version "7.7.0"
|
||||
resolved "https://registry.yarnpkg.com/@babel/helper-annotate-as-pure/-/helper-annotate-as-pure-7.7.0.tgz#efc54032d43891fe267679e63f6860aa7dbf4a5e"
|
||||
integrity sha512-k50CQxMlYTYo+GGyUGFwpxKVtxVJi9yh61sXZji3zYHccK9RYliZGSTOgci85T+r+0VFN2nWbGM04PIqwfrpMg==
|
||||
dependencies:
|
||||
"@babel/types" "^7.7.0"
|
||||
|
||||
"@babel/helper-builder-binary-assignment-operator-visitor@^7.1.0":
|
||||
version "7.1.0"
|
||||
resolved "https://registry.yarnpkg.com/@babel/helper-builder-binary-assignment-operator-visitor/-/helper-builder-binary-assignment-operator-visitor-7.1.0.tgz#6b69628dfe4087798e0c4ed98e3d4a6b2fbd2f5f"
|
||||
@@ -118,6 +135,15 @@
|
||||
"@babel/template" "^7.1.0"
|
||||
"@babel/types" "^7.0.0"
|
||||
|
||||
"@babel/helper-function-name@^7.7.0":
|
||||
version "7.7.0"
|
||||
resolved "https://registry.yarnpkg.com/@babel/helper-function-name/-/helper-function-name-7.7.0.tgz#44a5ad151cfff8ed2599c91682dda2ec2c8430a3"
|
||||
integrity sha512-tDsJgMUAP00Ugv8O2aGEua5I2apkaQO7lBGUq1ocwN3G23JE5Dcq0uh3GvFTChPa4b40AWiAsLvCZOA2rdnQ7Q==
|
||||
dependencies:
|
||||
"@babel/helper-get-function-arity" "^7.7.0"
|
||||
"@babel/template" "^7.7.0"
|
||||
"@babel/types" "^7.7.0"
|
||||
|
||||
"@babel/helper-get-function-arity@^7.0.0":
|
||||
version "7.0.0"
|
||||
resolved "https://registry.yarnpkg.com/@babel/helper-get-function-arity/-/helper-get-function-arity-7.0.0.tgz#83572d4320e2a4657263734113c42868b64e49c3"
|
||||
@@ -125,6 +151,13 @@
|
||||
dependencies:
|
||||
"@babel/types" "^7.0.0"
|
||||
|
||||
"@babel/helper-get-function-arity@^7.7.0":
|
||||
version "7.7.0"
|
||||
resolved "https://registry.yarnpkg.com/@babel/helper-get-function-arity/-/helper-get-function-arity-7.7.0.tgz#c604886bc97287a1d1398092bc666bc3d7d7aa2d"
|
||||
integrity sha512-tLdojOTz4vWcEnHWHCuPN5P85JLZWbm5Fx5ZsMEMPhF3Uoe3O7awrbM2nQ04bDOUToH/2tH/ezKEOR8zEYzqyw==
|
||||
dependencies:
|
||||
"@babel/types" "^7.7.0"
|
||||
|
||||
"@babel/helper-hoist-variables@^7.4.4":
|
||||
version "7.4.4"
|
||||
resolved "https://registry.yarnpkg.com/@babel/helper-hoist-variables/-/helper-hoist-variables-7.4.4.tgz#0298b5f25c8c09c53102d52ac4a98f773eb2850a"
|
||||
@@ -188,6 +221,17 @@
|
||||
"@babel/traverse" "^7.1.0"
|
||||
"@babel/types" "^7.0.0"
|
||||
|
||||
"@babel/helper-remap-async-to-generator@^7.7.0":
|
||||
version "7.7.0"
|
||||
resolved "https://registry.yarnpkg.com/@babel/helper-remap-async-to-generator/-/helper-remap-async-to-generator-7.7.0.tgz#4d69ec653e8bff5bce62f5d33fc1508f223c75a7"
|
||||
integrity sha512-pHx7RN8X0UNHPB/fnuDnRXVZ316ZigkO8y8D835JlZ2SSdFKb6yH9MIYRU4fy/KPe5sPHDFOPvf8QLdbAGGiyw==
|
||||
dependencies:
|
||||
"@babel/helper-annotate-as-pure" "^7.7.0"
|
||||
"@babel/helper-wrap-function" "^7.7.0"
|
||||
"@babel/template" "^7.7.0"
|
||||
"@babel/traverse" "^7.7.0"
|
||||
"@babel/types" "^7.7.0"
|
||||
|
||||
"@babel/helper-replace-supers@^7.5.5":
|
||||
version "7.5.5"
|
||||
resolved "https://registry.yarnpkg.com/@babel/helper-replace-supers/-/helper-replace-supers-7.5.5.tgz#f84ce43df031222d2bad068d2626cb5799c34bc2"
|
||||
@@ -213,6 +257,13 @@
|
||||
dependencies:
|
||||
"@babel/types" "^7.4.4"
|
||||
|
||||
"@babel/helper-split-export-declaration@^7.7.0":
|
||||
version "7.7.0"
|
||||
resolved "https://registry.yarnpkg.com/@babel/helper-split-export-declaration/-/helper-split-export-declaration-7.7.0.tgz#1365e74ea6c614deeb56ebffabd71006a0eb2300"
|
||||
integrity sha512-HgYSI8rH08neWlAH3CcdkFg9qX9YsZysZI5GD8LjhQib/mM0jGOZOVkoUiiV2Hu978fRtjtsGsW6w0pKHUWtqA==
|
||||
dependencies:
|
||||
"@babel/types" "^7.7.0"
|
||||
|
||||
"@babel/helper-wrap-function@^7.1.0":
|
||||
version "7.2.0"
|
||||
resolved "https://registry.yarnpkg.com/@babel/helper-wrap-function/-/helper-wrap-function-7.2.0.tgz#c4e0012445769e2815b55296ead43a958549f6fa"
|
||||
@@ -223,6 +274,16 @@
|
||||
"@babel/traverse" "^7.1.0"
|
||||
"@babel/types" "^7.2.0"
|
||||
|
||||
"@babel/helper-wrap-function@^7.7.0":
|
||||
version "7.7.0"
|
||||
resolved "https://registry.yarnpkg.com/@babel/helper-wrap-function/-/helper-wrap-function-7.7.0.tgz#15af3d3e98f8417a60554acbb6c14e75e0b33b74"
|
||||
integrity sha512-sd4QjeMgQqzshSjecZjOp8uKfUtnpmCyQhKQrVJBBgeHAB/0FPi33h3AbVlVp07qQtMD4QgYSzaMI7VwncNK/w==
|
||||
dependencies:
|
||||
"@babel/helper-function-name" "^7.7.0"
|
||||
"@babel/template" "^7.7.0"
|
||||
"@babel/traverse" "^7.7.0"
|
||||
"@babel/types" "^7.7.0"
|
||||
|
||||
"@babel/helpers@^7.6.2":
|
||||
version "7.6.2"
|
||||
resolved "https://registry.yarnpkg.com/@babel/helpers/-/helpers-7.6.2.tgz#681ffe489ea4dcc55f23ce469e58e59c1c045153"
|
||||
@@ -246,6 +307,11 @@
|
||||
resolved "https://registry.yarnpkg.com/@babel/parser/-/parser-7.6.4.tgz#cb9b36a7482110282d5cb6dd424ec9262b473d81"
|
||||
integrity sha512-D8RHPW5qd0Vbyo3qb+YjO5nvUVRTXFLQ/FsDxJU2Nqz4uB5EnUN0ZQSEYpvTIbRuttig1XbHWU5oMeQwQSAA+A==
|
||||
|
||||
"@babel/parser@^7.7.0", "@babel/parser@^7.7.2":
|
||||
version "7.7.3"
|
||||
resolved "https://registry.yarnpkg.com/@babel/parser/-/parser-7.7.3.tgz#5fad457c2529de476a248f75b0f090b3060af043"
|
||||
integrity sha512-bqv+iCo9i+uLVbI0ILzKkvMorqxouI+GbV13ivcARXn9NNEabi2IEz912IgNpT/60BNXac5dgcfjb94NjsF33A==
|
||||
|
||||
"@babel/plugin-proposal-async-generator-functions@^7.2.0":
|
||||
version "7.2.0"
|
||||
resolved "https://registry.yarnpkg.com/@babel/plugin-proposal-async-generator-functions/-/plugin-proposal-async-generator-functions-7.2.0.tgz#b289b306669dce4ad20b0252889a15768c9d417e"
|
||||
@@ -255,6 +321,15 @@
|
||||
"@babel/helper-remap-async-to-generator" "^7.1.0"
|
||||
"@babel/plugin-syntax-async-generators" "^7.2.0"
|
||||
|
||||
"@babel/plugin-proposal-async-generator-functions@^7.7.0":
|
||||
version "7.7.0"
|
||||
resolved "https://registry.yarnpkg.com/@babel/plugin-proposal-async-generator-functions/-/plugin-proposal-async-generator-functions-7.7.0.tgz#83ef2d6044496b4c15d8b4904e2219e6dccc6971"
|
||||
integrity sha512-ot/EZVvf3mXtZq0Pd0+tSOfGWMizqmOohXmNZg6LNFjHOV+wOPv7BvVYh8oPR8LhpIP3ye8nNooKL50YRWxpYA==
|
||||
dependencies:
|
||||
"@babel/helper-plugin-utils" "^7.0.0"
|
||||
"@babel/helper-remap-async-to-generator" "^7.7.0"
|
||||
"@babel/plugin-syntax-async-generators" "^7.2.0"
|
||||
|
||||
"@babel/plugin-proposal-dynamic-import@^7.5.0":
|
||||
version "7.5.0"
|
||||
resolved "https://registry.yarnpkg.com/@babel/plugin-proposal-dynamic-import/-/plugin-proposal-dynamic-import-7.5.0.tgz#e532202db4838723691b10a67b8ce509e397c506"
|
||||
@@ -684,6 +759,15 @@
|
||||
"@babel/parser" "^7.6.0"
|
||||
"@babel/types" "^7.6.0"
|
||||
|
||||
"@babel/template@^7.7.0":
|
||||
version "7.7.0"
|
||||
resolved "https://registry.yarnpkg.com/@babel/template/-/template-7.7.0.tgz#4fadc1b8e734d97f56de39c77de76f2562e597d0"
|
||||
integrity sha512-OKcwSYOW1mhWbnTBgQY5lvg1Fxg+VyfQGjcBduZFljfc044J5iDlnDSfhQ867O17XHiSCxYHUxHg2b7ryitbUQ==
|
||||
dependencies:
|
||||
"@babel/code-frame" "^7.0.0"
|
||||
"@babel/parser" "^7.7.0"
|
||||
"@babel/types" "^7.7.0"
|
||||
|
||||
"@babel/traverse@^7.1.0", "@babel/traverse@^7.4.4", "@babel/traverse@^7.5.5", "@babel/traverse@^7.6.2", "@babel/traverse@^7.6.3":
|
||||
version "7.6.3"
|
||||
resolved "https://registry.yarnpkg.com/@babel/traverse/-/traverse-7.6.3.tgz#66d7dba146b086703c0fb10dd588b7364cec47f9"
|
||||
@@ -699,6 +783,21 @@
|
||||
globals "^11.1.0"
|
||||
lodash "^4.17.13"
|
||||
|
||||
"@babel/traverse@^7.7.0":
|
||||
version "7.7.2"
|
||||
resolved "https://registry.yarnpkg.com/@babel/traverse/-/traverse-7.7.2.tgz#ef0a65e07a2f3c550967366b3d9b62a2dcbeae09"
|
||||
integrity sha512-TM01cXib2+rgIZrGJOLaHV/iZUAxf4A0dt5auY6KNZ+cm6aschuJGqKJM3ROTt3raPUdIDk9siAufIFEleRwtw==
|
||||
dependencies:
|
||||
"@babel/code-frame" "^7.5.5"
|
||||
"@babel/generator" "^7.7.2"
|
||||
"@babel/helper-function-name" "^7.7.0"
|
||||
"@babel/helper-split-export-declaration" "^7.7.0"
|
||||
"@babel/parser" "^7.7.2"
|
||||
"@babel/types" "^7.7.2"
|
||||
debug "^4.1.0"
|
||||
globals "^11.1.0"
|
||||
lodash "^4.17.13"
|
||||
|
||||
"@babel/types@^7.0.0", "@babel/types@^7.2.0", "@babel/types@^7.4.4", "@babel/types@^7.5.5", "@babel/types@^7.6.0", "@babel/types@^7.6.3":
|
||||
version "7.6.3"
|
||||
resolved "https://registry.yarnpkg.com/@babel/types/-/types-7.6.3.tgz#3f07d96f854f98e2fbd45c64b0cb942d11e8ba09"
|
||||
@@ -708,6 +807,15 @@
|
||||
lodash "^4.17.13"
|
||||
to-fast-properties "^2.0.0"
|
||||
|
||||
"@babel/types@^7.7.0", "@babel/types@^7.7.2":
|
||||
version "7.7.2"
|
||||
resolved "https://registry.yarnpkg.com/@babel/types/-/types-7.7.2.tgz#550b82e5571dcd174af576e23f0adba7ffc683f7"
|
||||
integrity sha512-YTf6PXoh3+eZgRCBzzP25Bugd2ngmpQVrk7kXX0i5N9BO7TFBtIgZYs7WtxtOGs8e6A4ZI7ECkbBCEHeXocvOA==
|
||||
dependencies:
|
||||
esutils "^2.0.2"
|
||||
lodash "^4.17.13"
|
||||
to-fast-properties "^2.0.0"
|
||||
|
||||
"@protobufjs/aspromise@^1.1.1", "@protobufjs/aspromise@^1.1.2":
|
||||
version "1.1.2"
|
||||
resolved "https://registry.yarnpkg.com/@protobufjs/aspromise/-/aspromise-1.1.2.tgz#9b8b0cc663d669a7d8f6f5d0893a14d348f30fbf"
|
||||
@@ -1049,6 +1157,13 @@ bip66@^1.1.5:
|
||||
dependencies:
|
||||
safe-buffer "^5.0.1"
|
||||
|
||||
bl@^4.0.0:
|
||||
version "4.0.0"
|
||||
resolved "https://registry.yarnpkg.com/bl/-/bl-4.0.0.tgz#fc7351c473992110749d3552087e1fe942021e65"
|
||||
integrity sha512-QwQvAZZA1Bw1FWnhNj2X5lu+sPxxB2ITH3mqEqYyahN6JZR13ONjk+XiTnBaGEzMPUrAgOkaD68pBH1rvPRPsw==
|
||||
dependencies:
|
||||
readable-stream "^3.4.0"
|
||||
|
||||
blakejs@^1.1.0:
|
||||
version "1.1.0"
|
||||
resolved "https://registry.yarnpkg.com/blakejs/-/blakejs-1.1.0.tgz#69df92ef953aa88ca51a32df6ab1c54a155fc7a5"
|
||||
@@ -1735,6 +1850,11 @@ fast-deep-equal@^2.0.1:
|
||||
resolved "https://registry.yarnpkg.com/fast-deep-equal/-/fast-deep-equal-2.0.1.tgz#7b05218ddf9667bf7f370bf7fdb2cb15fdd0aa49"
|
||||
integrity sha1-ewUhjd+WZ79/Nwv3/bLLFf3Qqkk=
|
||||
|
||||
fast-fifo@^1.0.0:
|
||||
version "1.0.0"
|
||||
resolved "https://registry.yarnpkg.com/fast-fifo/-/fast-fifo-1.0.0.tgz#9bc72e6860347bb045a876d1c5c0af11e9b984e7"
|
||||
integrity sha512-4VEXmjxLj7sbs8J//cn2qhRap50dGzF5n8fjay8mau+Jn4hxSeR3xPFwxMaQq/pDaq7+KQk0PAbC2+nWDkJrmQ==
|
||||
|
||||
fast-json-stable-stringify@^2.0.0:
|
||||
version "2.0.0"
|
||||
resolved "https://registry.yarnpkg.com/fast-json-stable-stringify/-/fast-json-stable-stringify-2.0.0.tgz#d5142c0caee6b1189f87d3a76111064f86c8bbf2"
|
||||
@@ -1882,6 +2002,11 @@ get-func-name@^2.0.0:
|
||||
resolved "https://registry.yarnpkg.com/get-func-name/-/get-func-name-2.0.0.tgz#ead774abee72e20409433a066366023dd6887a41"
|
||||
integrity sha1-6td0q+5y4gQJQzoGY2YCPdaIekE=
|
||||
|
||||
get-iterator@^1.0.2:
|
||||
version "1.0.2"
|
||||
resolved "https://registry.yarnpkg.com/get-iterator/-/get-iterator-1.0.2.tgz#cd747c02b4c084461fac14f48f6b45a80ed25c82"
|
||||
integrity sha512-v+dm9bNVfOYsY1OrhaCrmyOcYoSeVvbt+hHZ0Au+T+p1y+0Uyj9aMaGIeUTT6xdpRbWzDeYKvfOslPhggQMcsg==
|
||||
|
||||
get-value@^2.0.3, get-value@^2.0.6:
|
||||
version "2.0.6"
|
||||
resolved "https://registry.yarnpkg.com/get-value/-/get-value-2.0.6.tgz#dc15ca1c672387ca76bd37ac0a395ba2042a2c28"
|
||||
@@ -2304,6 +2429,53 @@ isobject@^3.0.0, isobject@^3.0.1:
|
||||
resolved "https://registry.yarnpkg.com/isobject/-/isobject-3.0.1.tgz#4e431e92b11a9731636aa1f9c8d1ccbcfdab78df"
|
||||
integrity sha1-TkMekrEalzFjaqH5yNHMvP2reN8=
|
||||
|
||||
it-handshake@^1.0.1:
|
||||
version "1.0.1"
|
||||
resolved "https://registry.yarnpkg.com/it-handshake/-/it-handshake-1.0.1.tgz#ed37a5622fcb82cfcb1e7eaebcf4872361cabe11"
|
||||
integrity sha512-ZDN6HfaS9ZMOohEUr5j0TYI8nCtiSJsucXHwoeiH9IHal3sLDYcSpYWQe+CsUHHK5rMnPHwDiiPptP/Yioc0kg==
|
||||
dependencies:
|
||||
it-pushable "^1.4.0"
|
||||
it-reader "^2.0.0"
|
||||
p-defer "^3.0.0"
|
||||
|
||||
it-length-prefixed@^3.0.0:
|
||||
version "3.0.0"
|
||||
resolved "https://registry.yarnpkg.com/it-length-prefixed/-/it-length-prefixed-3.0.0.tgz#cdedb3a785796ba8263c97d9bd4816c9fe33a6d2"
|
||||
integrity sha512-OQPbWaGDcSK1Wzzi8XtyXscBV1sMhFz6q5zHGchBc5oV4hM6ifIl6PTS8stk8MqkBELSyWO6CbEluS1rg4UUTw==
|
||||
dependencies:
|
||||
bl "^4.0.0"
|
||||
buffer "^5.4.3"
|
||||
varint "^5.0.0"
|
||||
|
||||
it-pair@^1.0.0:
|
||||
version "1.0.0"
|
||||
resolved "https://registry.yarnpkg.com/it-pair/-/it-pair-1.0.0.tgz#b1add81f49af16a10b2939dbef7b1974fae87d6a"
|
||||
integrity sha512-9raOiDu5OAuDOahtMtapKQDrQTxBfzlzrNcB6o7JARHkt+7Bb1dMkW/TpYdAjBJE77KH3e2zGzwpGUP9tXbLww==
|
||||
dependencies:
|
||||
get-iterator "^1.0.2"
|
||||
|
||||
it-pb-rpc@^0.1.3:
|
||||
version "0.1.3"
|
||||
resolved "https://registry.yarnpkg.com/it-pb-rpc/-/it-pb-rpc-0.1.3.tgz#3d8e98454cd3fda31a4767b86267b45a7a141aa6"
|
||||
integrity sha512-Zzq7ODzzFSZLsYzQVRqqaOnQENslRt0kY6QQ8ApaciCaX4xXJhtIFK9UrPbWAgXkyTDFJuLH5GgDAph/JN7JQg==
|
||||
dependencies:
|
||||
it-handshake "^1.0.1"
|
||||
it-length-prefixed "^3.0.0"
|
||||
|
||||
it-pushable@^1.4.0:
|
||||
version "1.4.0"
|
||||
resolved "https://registry.yarnpkg.com/it-pushable/-/it-pushable-1.4.0.tgz#772d81b40ccab93c963a20420ab1ef2ecfc9b97d"
|
||||
integrity sha512-W7251Tj88YBqUIEDWCwd3F8JettSbze+bBp5B3ASzz5tYWaLUI1VDNGbjllH1T6RJ71a5jUSTSt5vHjvuzwoFw==
|
||||
dependencies:
|
||||
fast-fifo "^1.0.0"
|
||||
|
||||
it-reader@^2.0.0:
|
||||
version "2.0.0"
|
||||
resolved "https://registry.yarnpkg.com/it-reader/-/it-reader-2.0.0.tgz#2ddc15a976b39906e805c88c5fb315c3805071ae"
|
||||
integrity sha512-y+GeTA3wq4z5yol7s/aXr0fIi4jMkPeo2DcX5AJo6IPgonjiQA7q1Y/yCMWro7PxGXj9mDUj9m/gAsSUrVRw7A==
|
||||
dependencies:
|
||||
bl "^4.0.0"
|
||||
|
||||
js-levenshtein@^1.1.3:
|
||||
version "1.1.6"
|
||||
resolved "https://registry.yarnpkg.com/js-levenshtein/-/js-levenshtein-1.1.6.tgz#c6cee58eb3550372df8deb85fad5ce66ce01d59d"
|
||||
@@ -2921,6 +3093,11 @@ output-file-sync@^2.0.0:
|
||||
is-plain-obj "^1.1.0"
|
||||
mkdirp "^0.5.1"
|
||||
|
||||
p-defer@^3.0.0:
|
||||
version "3.0.0"
|
||||
resolved "https://registry.yarnpkg.com/p-defer/-/p-defer-3.0.0.tgz#d1dceb4ee9b2b604b1d94ffec83760175d4e6f83"
|
||||
integrity sha512-ugZxsxmtTln604yeYd29EGrNhazN2lywetzpKhfmQjW/VJmhpDmWbiX+h0zL8V91R0UXkhb3KtPmyq9PZw3aYw==
|
||||
|
||||
p-limit@^2.0.0:
|
||||
version "2.2.1"
|
||||
resolved "https://registry.yarnpkg.com/p-limit/-/p-limit-2.2.1.tgz#aa07a788cc3151c939b5131f63570f0dd2009537"
|
||||
|
Reference in New Issue
Block a user