Skip to content

Commit

Permalink
fix!: update hashing libs to @noble (#323)
Browse files Browse the repository at this point in the history
* fix: update hashing libs

Signed-off-by: Marin Petrunic <[email protected]>

* chore: remove @noble/curve package

Signed-off-by: Marin Petrunic <[email protected]>

* fix!: rename stablelib crypto backend into pureJsCrypto

Signed-off-by: Marin Petrunic <[email protected]>

* fix lint

Signed-off-by: Marin Petrunic <[email protected]>

---------

Signed-off-by: Marin Petrunic <[email protected]>
  • Loading branch information
mpetrunic authored May 8, 2023
1 parent 8426920 commit 3732fda
Show file tree
Hide file tree
Showing 8 changed files with 45 additions and 48 deletions.
6 changes: 3 additions & 3 deletions benchmarks/benchmark.js
Original file line number Diff line number Diff line change
@@ -1,19 +1,19 @@
/* eslint-disable */

import { Noise } from '../dist/src/index.js'
import { noise } from '../dist/src/index.js'
import benchmark from 'benchmark'
import { duplexPair } from 'it-pair/duplex'
import { createFromJSON } from '@libp2p/peer-id-factory'

const bench = async function () {
console.log('Initializing handshake benchmark')
const initiator = new Noise()
const initiator = noise()()
const initiatorPeer = await createFromJSON({
id: '12D3KooWH45PiqBjfnEfDfCD6TqJrpqTBJvQDwGHvjGpaWwms46D',
privKey: 'CAESYBtKXrMwawAARmLScynQUuSwi/gGSkwqDPxi15N3dqDHa4T4iWupkMe5oYGwGH3Hyfvd/QcgSTqg71oYZJadJ6prhPiJa6mQx7mhgbAYfcfJ+939ByBJOqDvWhhklp0nqg==',
pubKey: 'CAESIGuE+IlrqZDHuaGBsBh9x8n73f0HIEk6oO9aGGSWnSeq'
})
const responder = new Noise()
const responder = noise()()
const responderPeer = await createFromJSON({
id: '12D3KooWP63uzL78BRMpkQ7augMdNi1h3VBrVWZucKjyhzGVaSi1',
privKey: 'CAESYPxO3SHyfc2578hDmfkGGBY255JjiLuVavJWy+9ivlpsxSyVKf36ipyRGL6szGzHuFs5ceEuuGVrPMg/rW2Ch1bFLJUp/fqKnJEYvqzMbMe4Wzlx4S64ZWs8yD+tbYKHVg==',
Expand Down
3 changes: 1 addition & 2 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -76,8 +76,7 @@
"@libp2p/logger": "^2.0.5",
"@libp2p/peer-id": "^2.0.0",
"@stablelib/chacha20poly1305": "^1.0.1",
"@stablelib/hkdf": "^1.0.1",
"@stablelib/sha256": "^1.0.1",
"@noble/hashes": "^1.3.0",
"@stablelib/x25519": "^1.0.3",
"it-length-prefixed": "^9.0.1",
"it-pair": "^2.0.2",
Expand Down
12 changes: 5 additions & 7 deletions src/crypto/stablelib.ts → src/crypto/js.ts
Original file line number Diff line number Diff line change
@@ -1,21 +1,19 @@
import { HKDF } from '@stablelib/hkdf'
import * as x25519 from '@stablelib/x25519'
import { SHA256, hash } from '@stablelib/sha256'
import { sha256 } from '@noble/hashes/sha256'
import { hkdf } from '@noble/hashes/hkdf'
import { ChaCha20Poly1305 } from '@stablelib/chacha20poly1305'
import type { bytes32, bytes } from '../@types/basic.js'
import type { Hkdf } from '../@types/handshake.js'
import type { KeyPair } from '../@types/libp2p.js'
import type { ICryptoInterface } from '../crypto.js'

export const stablelib: ICryptoInterface = {
export const pureJsCrypto: ICryptoInterface = {
hashSHA256 (data: Uint8Array): Uint8Array {
return hash(data)
return sha256(data)
},

getHKDF (ck: bytes32, ikm: Uint8Array): Hkdf {
const hkdf = new HKDF(SHA256, ikm, ck)
const okmU8Array = hkdf.expand(96)
const okm = okmU8Array
const okm = hkdf(sha256, ikm, ck, undefined, 96)

const k1 = okm.subarray(0, 32)
const k2 = okm.subarray(32, 64)
Expand Down
4 changes: 2 additions & 2 deletions src/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,8 +2,8 @@ import type { ConnectionEncrypter } from '@libp2p/interface-connection-encrypter
import { Noise } from './noise.js'
import type { NoiseInit } from './noise.js'
import type { NoiseExtensions } from './proto/payload.js'
export * from './crypto.js'
export * from './crypto/stablelib.js'
export type { ICryptoInterface } from './crypto.js'
export { pureJsCrypto } from './crypto/js.js'

export function noise (init: NoiseInit = {}): () => ConnectionEncrypter<NoiseExtensions> {
return () => new Noise(init)
Expand Down
4 changes: 2 additions & 2 deletions src/noise.ts
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@ import type { IHandshake } from './@types/handshake-interface.js'
import type { INoiseConnection, KeyPair } from './@types/libp2p.js'
import { NOISE_MSG_MAX_LENGTH_BYTES } from './constants.js'
import type { ICryptoInterface } from './crypto.js'
import { stablelib } from './crypto/stablelib.js'
import { pureJsCrypto } from './crypto/js.js'
import { decryptStream, encryptStream } from './crypto/streaming.js'
import { uint16BEDecode, uint16BEEncode } from './encoder.js'
import { XXHandshake } from './handshake-xx.js'
Expand Down Expand Up @@ -49,7 +49,7 @@ export class Noise implements INoiseConnection {
constructor (init: NoiseInit = {}) {
const { staticNoiseKey, extensions, crypto, prologueBytes, metrics } = init

this.crypto = crypto ?? stablelib
this.crypto = crypto ?? pureJsCrypto
this.extensions = extensions
this.metrics = metrics ? registerMetrics(metrics) : undefined

Expand Down
18 changes: 9 additions & 9 deletions test/handshakes/xx.spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@ import { toString as uint8ArrayToString } from 'uint8arrays/to-string'
import { equals as uint8ArrayEquals } from 'uint8arrays/equals'
import type { KeyPair } from '../../src/@types/libp2p.js'
import type { NoiseSession } from '../../src/@types/handshake.js'
import { stablelib } from '../../src/crypto/stablelib.js'
import { pureJsCrypto } from '../../src/crypto/js.js'
import { XX } from '../../src/handshakes/xx.js'
import { createHandshakePayload, getHandshakePayload } from '../../src/utils.js'
import { generateEd25519Keys } from '../utils.js'
Expand All @@ -14,9 +14,9 @@ describe('XX Handshake', () => {

it('Test creating new XX session', async () => {
try {
const xx = new XX(stablelib)
const xx = new XX(pureJsCrypto)

const kpInitiator: KeyPair = stablelib.generateX25519KeyPair()
const kpInitiator: KeyPair = pureJsCrypto.generateX25519KeyPair()

xx.initSession(true, prologue, kpInitiator)
} catch (e) {
Expand All @@ -31,15 +31,15 @@ describe('XX Handshake', () => {
const ck = Buffer.alloc(32)
ckBytes.copy(ck)

const [k1, k2, k3] = stablelib.getHKDF(ck, ikm)
const [k1, k2, k3] = pureJsCrypto.getHKDF(ck, ikm)
expect(uint8ArrayToString(k1, 'hex')).to.equal('cc5659adff12714982f806e2477a8d5ddd071def4c29bb38777b7e37046f6914')
expect(uint8ArrayToString(k2, 'hex')).to.equal('a16ada915e551ab623f38be674bb4ef15d428ae9d80688899c9ef9b62ef208fa')
expect(uint8ArrayToString(k3, 'hex')).to.equal('ff67bf9727e31b06efc203907e6786667d2c7a74ac412b4d31a80ba3fd766f68')
})

async function doHandshake (xx: XX): Promise<{ nsInit: NoiseSession, nsResp: NoiseSession }> {
const kpInit = stablelib.generateX25519KeyPair()
const kpResp = stablelib.generateX25519KeyPair()
const kpInit = pureJsCrypto.generateX25519KeyPair()
const kpResp = pureJsCrypto.generateX25519KeyPair()

// initiator setup
const libp2pInitKeys = await generateEd25519Keys()
Expand Down Expand Up @@ -107,7 +107,7 @@ describe('XX Handshake', () => {

it('Test handshake', async () => {
try {
const xx = new XX(stablelib)
const xx = new XX(pureJsCrypto)
await doHandshake(xx)
} catch (e) {
const err = e as Error
Expand All @@ -117,7 +117,7 @@ describe('XX Handshake', () => {

it('Test symmetric encrypt and decrypt', async () => {
try {
const xx = new XX(stablelib)
const xx = new XX(pureJsCrypto)
const { nsInit, nsResp } = await doHandshake(xx)
const ad = Buffer.from('authenticated')
const message = Buffer.from('HelloCrypto')
Expand All @@ -139,7 +139,7 @@ describe('XX Handshake', () => {
})

it('Test multiple messages encryption and decryption', async () => {
const xx = new XX(stablelib)
const xx = new XX(pureJsCrypto)
const { nsInit, nsResp } = await doHandshake(xx)
const ad = Buffer.from('authenticated')
const message = Buffer.from('ethereum1')
Expand Down
20 changes: 10 additions & 10 deletions test/noise.spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@ import { toString as uint8ArrayToString } from 'uint8arrays/to-string'
import { fromString as uint8ArrayFromString } from 'uint8arrays/from-string'
import sinon from 'sinon'
import { NOISE_MSG_MAX_LENGTH_BYTES } from '../src/constants.js'
import { stablelib } from '../src/crypto/stablelib.js'
import { pureJsCrypto } from '../src/crypto/js.js'
import { decode0, decode2, encode1, uint16BEDecode, uint16BEEncode } from '../src/encoder.js'
import { XX } from '../src/handshakes/xx.js'
import { XXHandshake } from '../src/handshake-xx.js'
Expand Down Expand Up @@ -68,11 +68,11 @@ describe('Noise', () => {
}
)
const prologue = Buffer.alloc(0)
const staticKeys = stablelib.generateX25519KeyPair()
const xx = new XX(stablelib)
const staticKeys = pureJsCrypto.generateX25519KeyPair()
const xx = new XX(pureJsCrypto)

const payload = await getPayload(remotePeer, staticKeys.publicKey)
const handshake = new XXHandshake(false, payload, prologue, stablelib, staticKeys, wrapped, localPeer, xx)
const handshake = new XXHandshake(false, payload, prologue, pureJsCrypto, staticKeys, wrapped, localPeer, xx)

let receivedMessageBuffer = decode0((await wrapped.readLP()).slice())
// The first handshake message contains the initiator's ephemeral public key
Expand Down Expand Up @@ -132,9 +132,9 @@ describe('Noise', () => {

it('should working without remote peer provided in incoming connection', async () => {
try {
const staticKeysInitiator = stablelib.generateX25519KeyPair()
const staticKeysInitiator = pureJsCrypto.generateX25519KeyPair()
const noiseInit = new Noise({ staticNoiseKey: staticKeysInitiator.privateKey })
const staticKeysResponder = stablelib.generateX25519KeyPair()
const staticKeysResponder = pureJsCrypto.generateX25519KeyPair()
const noiseResp = new Noise({ staticNoiseKey: staticKeysResponder.privateKey })

const [inboundConnection, outboundConnection] = duplexPair<Uint8Array>()
Expand Down Expand Up @@ -165,9 +165,9 @@ describe('Noise', () => {
it('should accept and return Noise extension from remote peer', async () => {
try {
const certhashInit = Buffer.from('certhash data from init')
const staticKeysInitiator = stablelib.generateX25519KeyPair()
const staticKeysInitiator = pureJsCrypto.generateX25519KeyPair()
const noiseInit = new Noise({ staticNoiseKey: staticKeysInitiator.privateKey, extensions: { webtransportCerthashes: [certhashInit] } })
const staticKeysResponder = stablelib.generateX25519KeyPair()
const staticKeysResponder = pureJsCrypto.generateX25519KeyPair()
const certhashResp = Buffer.from('certhash data from respon')
const noiseResp = new Noise({ staticNoiseKey: staticKeysResponder.privateKey, extensions: { webtransportCerthashes: [certhashResp] } })

Expand All @@ -187,8 +187,8 @@ describe('Noise', () => {

it('should accept a prologue', async () => {
try {
const noiseInit = new Noise({ staticNoiseKey: undefined, crypto: stablelib, prologueBytes: Buffer.from('Some prologue') })
const noiseResp = new Noise({ staticNoiseKey: undefined, crypto: stablelib, prologueBytes: Buffer.from('Some prologue') })
const noiseInit = new Noise({ staticNoiseKey: undefined, crypto: pureJsCrypto, prologueBytes: Buffer.from('Some prologue') })
const noiseResp = new Noise({ staticNoiseKey: undefined, crypto: pureJsCrypto, prologueBytes: Buffer.from('Some prologue') })

const [inboundConnection, outboundConnection] = duplexPair<Uint8Array>()
const [outbound, inbound] = await Promise.all([
Expand Down
26 changes: 13 additions & 13 deletions test/xx-handshake.spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@ import { assert, expect } from 'aegir/chai'
import { duplexPair } from 'it-pair/duplex'
import { pbStream } from 'it-pb-stream'
import { equals as uint8ArrayEquals } from 'uint8arrays/equals'
import { stablelib } from '../src/crypto/stablelib.js'
import { pureJsCrypto } from '../src/crypto/js.js'
import { XXHandshake } from '../src/handshake-xx.js'
import { getPayload } from '../src/utils.js'
import { createPeerIdsFromFixtures } from './fixtures/peer.js'
Expand All @@ -23,14 +23,14 @@ describe('XX Handshake', () => {
const connectionTo = pbStream(duplex[1])

const prologue = Buffer.alloc(0)
const staticKeysInitiator = stablelib.generateX25519KeyPair()
const staticKeysResponder = stablelib.generateX25519KeyPair()
const staticKeysInitiator = pureJsCrypto.generateX25519KeyPair()
const staticKeysResponder = pureJsCrypto.generateX25519KeyPair()

const initPayload = await getPayload(peerA, staticKeysInitiator.publicKey)
const handshakeInitator = new XXHandshake(true, initPayload, prologue, stablelib, staticKeysInitiator, connectionFrom, peerB)
const handshakeInitator = new XXHandshake(true, initPayload, prologue, pureJsCrypto, staticKeysInitiator, connectionFrom, peerB)

const respPayload = await getPayload(peerB, staticKeysResponder.publicKey)
const handshakeResponder = new XXHandshake(false, respPayload, prologue, stablelib, staticKeysResponder, connectionTo, peerA)
const handshakeResponder = new XXHandshake(false, respPayload, prologue, pureJsCrypto, staticKeysResponder, connectionTo, peerA)

await handshakeInitator.propose()
await handshakeResponder.propose()
Expand Down Expand Up @@ -70,14 +70,14 @@ describe('XX Handshake', () => {
const connectionTo = pbStream(duplex[1])

const prologue = Buffer.alloc(0)
const staticKeysInitiator = stablelib.generateX25519KeyPair()
const staticKeysResponder = stablelib.generateX25519KeyPair()
const staticKeysInitiator = pureJsCrypto.generateX25519KeyPair()
const staticKeysResponder = pureJsCrypto.generateX25519KeyPair()

const initPayload = await getPayload(peerA, staticKeysInitiator.publicKey)
const handshakeInitator = new XXHandshake(true, initPayload, prologue, stablelib, staticKeysInitiator, connectionFrom, fakePeer)
const handshakeInitator = new XXHandshake(true, initPayload, prologue, pureJsCrypto, staticKeysInitiator, connectionFrom, fakePeer)

const respPayload = await getPayload(peerB, staticKeysResponder.publicKey)
const handshakeResponder = new XXHandshake(false, respPayload, prologue, stablelib, staticKeysResponder, connectionTo, peerA)
const handshakeResponder = new XXHandshake(false, respPayload, prologue, pureJsCrypto, staticKeysResponder, connectionTo, peerA)

await handshakeInitator.propose()
await handshakeResponder.propose()
Expand All @@ -99,14 +99,14 @@ describe('XX Handshake', () => {
const connectionTo = pbStream(duplex[1])

const prologue = Buffer.alloc(0)
const staticKeysInitiator = stablelib.generateX25519KeyPair()
const staticKeysResponder = stablelib.generateX25519KeyPair()
const staticKeysInitiator = pureJsCrypto.generateX25519KeyPair()
const staticKeysResponder = pureJsCrypto.generateX25519KeyPair()

const initPayload = await getPayload(peerA, staticKeysInitiator.publicKey)
const handshakeInitator = new XXHandshake(true, initPayload, prologue, stablelib, staticKeysInitiator, connectionFrom, peerB)
const handshakeInitator = new XXHandshake(true, initPayload, prologue, pureJsCrypto, staticKeysInitiator, connectionFrom, peerB)

const respPayload = await getPayload(peerB, staticKeysResponder.publicKey)
const handshakeResponder = new XXHandshake(false, respPayload, prologue, stablelib, staticKeysResponder, connectionTo, fakePeer)
const handshakeResponder = new XXHandshake(false, respPayload, prologue, pureJsCrypto, staticKeysResponder, connectionTo, fakePeer)

await handshakeInitator.propose()
await handshakeResponder.propose()
Expand Down

0 comments on commit 3732fda

Please sign in to comment.