Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
16 changes: 1 addition & 15 deletions .aegir.js
Original file line number Diff line number Diff line change
@@ -1,27 +1,13 @@
const path = require('path')

/** @type {import('aegir').Options["build"]["config"]} */
const esbuild = {
inject: [path.join(__dirname, 'test/fixtures/node-globals.js')]
}


/** @type {import('aegir').PartialOptions} */
const config = {
tsRepo: true,
docs: {
entryPoint: "src/index.ts"
},
test: {
browser :{
config: {
buildConfig: esbuild
}
}
},
build: {
bundlesizeMax: '231KB',
config: esbuild
bundlesizeMax: '231KB'
}
}

Expand Down
16 changes: 9 additions & 7 deletions .github/workflows/ci.yml
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,7 @@ jobs:
name: Lint and Typecheck
runs-on: ubuntu-latest
steps:
- uses: actions/setup-node@v1
- uses: actions/setup-node@v2
with:
node-version: 16
- uses: actions/checkout@v2
Expand Down Expand Up @@ -44,7 +44,7 @@ jobs:
os: ["ubuntu-latest", "macos-latest", "windows-latest"]
runs-on: ${{ matrix.os }}
steps:
- uses: actions/setup-node@v1
- uses: actions/setup-node@v2
with:
node-version: ${{ matrix.node }}
- uses: actions/checkout@v2
Expand All @@ -67,7 +67,7 @@ jobs:
needs: check
runs-on: ubuntu-latest
steps:
- uses: actions/setup-node@v1
- uses: actions/setup-node@v2
with:
node-version: 16
- uses: actions/checkout@v2
Expand All @@ -89,7 +89,7 @@ jobs:
needs: check
runs-on: ubuntu-latest
steps:
- uses: actions/setup-node@v1
- uses: actions/setup-node@v2
with:
node-version: 16
- uses: actions/checkout@v2
Expand All @@ -111,7 +111,7 @@ jobs:
needs: check
runs-on: ubuntu-latest
steps:
- uses: actions/setup-node@v1
- uses: actions/setup-node@v2
with:
node-version: 16
- uses: actions/checkout@v2
Expand All @@ -134,7 +134,7 @@ jobs:
needs: check
runs-on: ubuntu-latest
steps:
- uses: actions/setup-node@v1
- uses: actions/setup-node@v2
with:
node-version: 16
- uses: actions/checkout@v2
Expand All @@ -156,7 +156,7 @@ jobs:
needs: check
runs-on: ubuntu-latest
steps:
- uses: actions/setup-node@v1
- uses: actions/setup-node@v2
with:
node-version: 16
- uses: actions/checkout@v2
Expand All @@ -172,3 +172,5 @@ jobs:
${{ runner.os }}-yarn-
- run: yarn --prefer-offline --frozen-lockfile
- run: npx xvfb-maybe aegir test -t electron-renderer --bail
env:
ESBUILD_WORKER_THREADS: 0
12 changes: 8 additions & 4 deletions package.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
{
"name": "@chainsafe/libp2p-noise",
"version": "4.1.1",
"version": "5.0.0",
"main": "dist/src/index.js",
"types": "dist/src/index.d.ts",
"files": [
Expand Down Expand Up @@ -33,30 +33,33 @@
"proto:gen": "pbjs -t static-module -r libp2p-noise -o ./src/proto/payload.js ./src/proto/payload.proto && pbts -o ./src/proto/payload.d.ts ./src/proto/payload.js && yarn run lint --fix"
},
"browser": {
"./dist/src/alloc-unsafe.js": "./dist/src/alloc-unsafe-browser.js",
"util": false
},
"devDependencies": {
"@types/bl": "^5.0.2",
"aegir": "^33.1.0",
"aegir": "^36.1.1",
"benchmark": "^2.1.4",
"buffer": "^6.0.3",
"chai": "^4.3.4",
"events": "^3.3.0",
"libp2p-crypto": "^0.21.0",
"microtime": "^3.0.0",
"mocha": "^9.0.2",
"sinon": "^11.1.1"
"sinon": "^12.0.1",
"util": "^0.12.4"
},
"dependencies": {
"@stablelib/chacha20poly1305": "^1.0.1",
"@stablelib/hkdf": "^1.0.1",
"@stablelib/sha256": "^1.0.1",
"@stablelib/x25519": "^1.0.1",
"bl": "^5.0.0",
"debug": "^4.3.1",
"it-buffer": "^0.1.3",
"it-length-prefixed": "^5.0.3",
"it-pair": "^1.0.0",
"it-pb-rpc": "^0.1.11",
"it-pb-rpc": "^0.2.0",
"it-pipe": "^1.1.0",
"peer-id": "^0.16.0",
"protobufjs": "^6.11.2",
Expand All @@ -74,6 +77,7 @@
},
"ignorePatterns": [
"src/proto/payload.js",
"src/proto/payload.d.ts",
"test/fixtures/node-globals.js"
]
}
Expand Down
8 changes: 3 additions & 5 deletions src/@types/basic.d.ts
Original file line number Diff line number Diff line change
@@ -1,8 +1,6 @@
import { Buffer } from 'buffer'

export type bytes = Buffer
export type bytes32 = Buffer
export type bytes16 = Buffer
export type bytes = Uint8Array
export type bytes32 = Uint8Array
export type bytes16 = Uint8Array

export type uint32 = number
export type uint64 = number
2 changes: 1 addition & 1 deletion src/@types/handshake-interface.d.ts
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@ import PeerId from 'peer-id'
export interface IHandshake {
session: NoiseSession
remotePeer: PeerId
remoteEarlyData: Buffer
remoteEarlyData: bytes
encrypt: (plaintext: bytes, session: NoiseSession) => bytes
decrypt: (ciphertext: bytes, session: NoiseSession) => {plaintext: bytes, valid: boolean}
}
11 changes: 5 additions & 6 deletions src/@types/it-length-prefixed/index.d.ts
Original file line number Diff line number Diff line change
@@ -1,20 +1,19 @@
declare module 'it-length-prefixed' {
import BufferList from 'bl'
import { Buffer } from 'buffer'
import BufferList from 'bl/BufferList'

interface LengthDecoderFunction {
(data: Buffer | BufferList): number
(data: Uint8Array | BufferList): number
bytes: number
}

interface LengthEncoderFunction {
(value: number, target: Buffer, offset: number): number|Buffer
(value: number, target: Uint8Array, offset: number): number|Uint8Array
bytes: number
}

interface Encoder {
(options?: Partial<{lengthEncoder: LengthEncoderFunction}>): AsyncGenerator<BufferList, Buffer>
single: (chunk: Buffer, options?: Partial<{lengthEncoder: LengthEncoderFunction}>) => BufferList
(options?: Partial<{lengthEncoder: LengthEncoderFunction}>): AsyncGenerator<BufferList, Uint8Array>
single: (chunk: Uint8Array, options?: Partial<{lengthEncoder: LengthEncoderFunction}>) => BufferList
MIN_POOL_SIZE: number
DEFAULT_POOL_SIZE: number
}
Expand Down
2 changes: 1 addition & 1 deletion src/@types/libp2p.d.ts
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,6 @@ export interface INoiseConnection {

export interface SecureOutbound {
conn: any
remoteEarlyData: Buffer
remoteEarlyData: Uint8Array
remotePeer: PeerId
}
22 changes: 8 additions & 14 deletions src/crypto.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,3 @@
import { Buffer } from 'buffer'
import { IHandshake } from './@types/handshake-interface'
import { NOISE_MSG_MAX_LENGTH_BYTES, NOISE_MSG_MAX_LENGTH_BYTES_WITHOUT_TAG } from './constants'

Expand All @@ -10,15 +9,13 @@ interface IReturnEncryptionWrapper {
export function encryptStream (handshake: IHandshake): IReturnEncryptionWrapper {
return async function * (source) {
for await (const chunk of source) {
const chunkBuffer = Buffer.from(chunk.buffer, chunk.byteOffset, chunk.length)

for (let i = 0; i < chunkBuffer.length; i += NOISE_MSG_MAX_LENGTH_BYTES_WITHOUT_TAG) {
for (let i = 0; i < chunk.length; i += NOISE_MSG_MAX_LENGTH_BYTES_WITHOUT_TAG) {
let end = i + NOISE_MSG_MAX_LENGTH_BYTES_WITHOUT_TAG
if (end > chunkBuffer.length) {
end = chunkBuffer.length
if (end > chunk.length) {
end = chunk.length
}

const data = handshake.encrypt(chunkBuffer.slice(i, end), handshake.session)
const data = handshake.encrypt(chunk.slice(i, end), handshake.session)
yield data
}
}
Expand All @@ -29,16 +26,13 @@ export function encryptStream (handshake: IHandshake): IReturnEncryptionWrapper
export function decryptStream (handshake: IHandshake): IReturnEncryptionWrapper {
return async function * (source) {
for await (const chunk of source) {
const chunkBuffer = Buffer.from(chunk.buffer, chunk.byteOffset, chunk.length)

for (let i = 0; i < chunkBuffer.length; i += NOISE_MSG_MAX_LENGTH_BYTES) {
for (let i = 0; i < chunk.length; i += NOISE_MSG_MAX_LENGTH_BYTES) {
let end = i + NOISE_MSG_MAX_LENGTH_BYTES
if (end > chunkBuffer.length) {
end = chunkBuffer.length
if (end > chunk.length) {
end = chunk.length
}

const chunk = chunkBuffer.slice(i, end)
const { plaintext: decrypted, valid } = await handshake.decrypt(chunk, handshake.session)
const { plaintext: decrypted, valid } = await handshake.decrypt(chunk.slice(i, end), handshake.session)
if (!valid) {
throw new Error('Failed to validate decrypted chunk')
}
Expand Down
37 changes: 25 additions & 12 deletions src/encoder.ts
Original file line number Diff line number Diff line change
@@ -1,33 +1,46 @@
import { Buffer } from 'buffer'
import { bytes } from './@types/basic'
import { MessageBuffer } from './@types/handshake'
import BufferList from 'bl'
import BufferList from 'bl/BufferList'
import { concat as uint8ArrayConcat } from 'uint8arrays/concat'

export const uint16BEEncode = (value: number, target: Buffer, offset: number): Buffer => {
target = target || Buffer.allocUnsafe(2)
target.writeUInt16BE(value, offset)
const allocUnsafe = (len: number): Uint8Array => {
if (globalThis.Buffer) {
return globalThis.Buffer.allocUnsafe(len)
}

return new Uint8Array(len)
}

export const uint16BEEncode = (value: number, target: Uint8Array, offset: number): Uint8Array => {
target = target || allocUnsafe(2)
new DataView(target.buffer, target.byteOffset, target.byteLength).setUint16(offset, value, false)
return target
}
uint16BEEncode.bytes = 2

export const uint16BEDecode = (data: Buffer | BufferList): number => {
export const uint16BEDecode = (data: Uint8Array | BufferList): number => {
if (data.length < 2) throw RangeError('Could not decode int16BE')
return data.readUInt16BE(0)

if (data instanceof BufferList) {
return data.readUInt16BE(0)
}

return new DataView(data.buffer, data.byteOffset, data.byteLength).getUint16(0, false)
}
uint16BEDecode.bytes = 2

// Note: IK and XX encoder usage is opposite (XX uses in stages encode0 where IK uses encode1)

export function encode0 (message: MessageBuffer): bytes {
return Buffer.concat([message.ne, message.ciphertext])
return uint8ArrayConcat([message.ne, message.ciphertext], message.ne.length + message.ciphertext.length)
}

export function encode1 (message: MessageBuffer): bytes {
return Buffer.concat([message.ne, message.ns, message.ciphertext])
return uint8ArrayConcat([message.ne, message.ns, message.ciphertext], message.ne.length + message.ns.length + message.ciphertext.length)
}

export function encode2 (message: MessageBuffer): bytes {
return Buffer.concat([message.ns, message.ciphertext])
return uint8ArrayConcat([message.ns, message.ciphertext], message.ns.length + message.ciphertext.length)
}

export function decode0 (input: bytes): MessageBuffer {
Expand All @@ -38,7 +51,7 @@ export function decode0 (input: bytes): MessageBuffer {
return {
ne: input.slice(0, 32),
ciphertext: input.slice(32, input.length),
ns: Buffer.alloc(0)
ns: new Uint8Array(0)
}
}

Expand All @@ -60,7 +73,7 @@ export function decode2 (input: bytes): MessageBuffer {
}

return {
ne: Buffer.alloc(0),
ne: new Uint8Array(0),
ns: input.slice(0, 48),
ciphertext: input.slice(48, input.length)
}
Expand Down
4 changes: 2 additions & 2 deletions src/errors.ts
Original file line number Diff line number Diff line change
@@ -1,9 +1,9 @@
import BufferList from 'bl'

export class FailedIKError extends Error {
public initialMsg: string|BufferList|Buffer
public initialMsg: string|BufferList|Uint8Array

constructor (initialMsg: string|BufferList|Buffer, message?: string) {
constructor (initialMsg: string|BufferList|Uint8Array, message?: string) {
super(message)

this.initialMsg = initialMsg
Expand Down
Loading