Skip to content

Commit

Permalink
Merge branch 'release-v2.0' into feat/errors-with-name-property
Browse files Browse the repository at this point in the history
  • Loading branch information
achingbrain authored Aug 14, 2024
2 parents 0cb280a + dc8c1ec commit cadfd7e
Show file tree
Hide file tree
Showing 13 changed files with 77 additions and 50 deletions.
11 changes: 7 additions & 4 deletions packages/connection-encrypter-plaintext/src/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -31,6 +31,7 @@ import type { Uint8ArrayList } from 'uint8arraylist'
const PROTOCOL = '/plaintext/2.0.0'

export interface PlaintextComponents {
peerId: PeerId
logger: ComponentLogger
}

Expand All @@ -44,10 +45,12 @@ export interface PlaintextInit {

class Plaintext implements ConnectionEncrypter {
public protocol: string = PROTOCOL
private readonly peerId: PeerId
private readonly log: Logger
private readonly timeout: number

constructor (components: PlaintextComponents, init: PlaintextInit = {}) {
this.peerId = components.peerId
this.log = components.logger.forComponent('libp2p:plaintext')
this.timeout = init.timeout ?? 1000
}
Expand All @@ -58,12 +61,12 @@ class Plaintext implements ConnectionEncrypter {
'@libp2p/connection-encryption'
]

async secureInbound <Stream extends Duplex<AsyncGenerator<Uint8Array | Uint8ArrayList>> = MultiaddrConnection> (localId: PeerId, conn: Stream, remoteId?: PeerId): Promise<SecuredConnection<Stream>> {
return this._encrypt(localId, conn, remoteId)
async secureInbound <Stream extends Duplex<AsyncGenerator<Uint8Array | Uint8ArrayList>> = MultiaddrConnection> (conn: Stream, remoteId?: PeerId): Promise<SecuredConnection<Stream>> {
return this._encrypt(this.peerId, conn, remoteId)
}

async secureOutbound <Stream extends Duplex<AsyncGenerator<Uint8Array | Uint8ArrayList>> = MultiaddrConnection> (localId: PeerId, conn: Stream, remoteId?: PeerId): Promise<SecuredConnection<Stream>> {
return this._encrypt(localId, conn, remoteId)
async secureOutbound <Stream extends Duplex<AsyncGenerator<Uint8Array | Uint8ArrayList>> = MultiaddrConnection> (conn: Stream, remoteId?: PeerId): Promise<SecuredConnection<Stream>> {
return this._encrypt(this.peerId, conn, remoteId)
}

/**
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2,12 +2,14 @@

import suite from '@libp2p/interface-compliance-tests/connection-encryption'
import { defaultLogger } from '@libp2p/logger'
import { createEd25519PeerId } from '@libp2p/peer-id-factory'
import { plaintext } from '../src/index.js'

describe('plaintext compliance', () => {
suite({
async setup () {
async setup (opts) {
return plaintext()({
peerId: opts?.peerId ?? await createEd25519PeerId(),
logger: defaultLogger()
})
},
Expand Down
19 changes: 15 additions & 4 deletions packages/connection-encrypter-plaintext/test/index.spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@ describe('plaintext', () => {
let remotePeer: PeerId
let wrongPeer: PeerId
let encrypter: ConnectionEncrypter
let encrypterRemote: ConnectionEncrypter

beforeEach(async () => {
[localPeer, remotePeer, wrongPeer] = await Promise.all([
Expand All @@ -24,6 +25,11 @@ describe('plaintext', () => {
])

encrypter = plaintext()({
peerId: localPeer,
logger: defaultLogger()
})
encrypterRemote = plaintext()({
peerId: remotePeer,
logger: defaultLogger()
})
})
Expand All @@ -42,8 +48,8 @@ describe('plaintext', () => {
})

await Promise.all([
encrypter.secureInbound(remotePeer, inbound),
encrypter.secureOutbound(localPeer, outbound, wrongPeer)
encrypterRemote.secureInbound(inbound),
encrypter.secureOutbound(outbound, wrongPeer)
]).then(() => expect.fail('should have failed'), (err) => {
expect(err).to.exist()
expect(err).to.have.property('name', 'UnexpectedPeerError')
Expand All @@ -54,6 +60,11 @@ describe('plaintext', () => {
const peer = await createRSAPeerId()
remotePeer = peerIdFromBytes(peer.toBytes())

encrypter = plaintext()({
peerId: remotePeer,
logger: defaultLogger()
})

const { inbound, outbound } = mockMultiaddrConnPair({
remotePeer,
addrs: [
Expand All @@ -63,8 +74,8 @@ describe('plaintext', () => {
})

await expect(Promise.all([
encrypter.secureInbound(localPeer, inbound),
encrypter.secureOutbound(remotePeer, outbound, localPeer)
encrypter.secureInbound(inbound),
encrypterRemote.secureOutbound(outbound, localPeer)
]))
.to.eventually.be.rejected.with.property('name', 'InvalidCryptoExchangeError')
})
Expand Down
3 changes: 2 additions & 1 deletion packages/connection-encrypter-tls/src/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -19,11 +19,12 @@
*/

import { TLS } from './tls.js'
import type { ComponentLogger, ConnectionEncrypter } from '@libp2p/interface'
import type { ComponentLogger, ConnectionEncrypter, PeerId } from '@libp2p/interface'

export const PROTOCOL = '/tls/1.0.0'

export interface TLSComponents {
peerId: PeerId
logger: ComponentLogger
}

Expand Down
14 changes: 8 additions & 6 deletions packages/connection-encrypter-tls/src/tls.ts
Original file line number Diff line number Diff line change
Expand Up @@ -31,10 +31,12 @@ import type { Uint8ArrayList } from 'uint8arraylist'
export class TLS implements ConnectionEncrypter {
public protocol: string = PROTOCOL
private readonly log: Logger
private readonly peerId: PeerId
private readonly timeout: number

constructor (components: TLSComponents, init: TLSInit = {}) {
this.log = components.logger.forComponent('libp2p:tls')
this.peerId = components.peerId
this.timeout = init.timeout ?? 1000
}

Expand All @@ -44,20 +46,20 @@ export class TLS implements ConnectionEncrypter {
'@libp2p/connection-encryption'
]

async secureInbound <Stream extends Duplex<AsyncGenerator<Uint8Array | Uint8ArrayList>> = MultiaddrConnection> (localId: PeerId, conn: Stream, remoteId?: PeerId): Promise<SecuredConnection<Stream>> {
return this._encrypt(localId, conn, true, remoteId)
async secureInbound <Stream extends Duplex<AsyncGenerator<Uint8Array | Uint8ArrayList>> = MultiaddrConnection> (conn: Stream, remoteId?: PeerId): Promise<SecuredConnection<Stream>> {
return this._encrypt(conn, true, remoteId)
}

async secureOutbound <Stream extends Duplex<AsyncGenerator<Uint8Array | Uint8ArrayList>> = MultiaddrConnection> (localId: PeerId, conn: Stream, remoteId?: PeerId): Promise<SecuredConnection<Stream>> {
return this._encrypt(localId, conn, false, remoteId)
async secureOutbound <Stream extends Duplex<AsyncGenerator<Uint8Array | Uint8ArrayList>> = MultiaddrConnection> (conn: Stream, remoteId?: PeerId): Promise<SecuredConnection<Stream>> {
return this._encrypt(conn, false, remoteId)
}

/**
* Encrypt connection
*/
async _encrypt <Stream extends Duplex<AsyncGenerator<Uint8Array | Uint8ArrayList>> = MultiaddrConnection> (localId: PeerId, conn: Stream, isServer: boolean, remoteId?: PeerId): Promise<SecuredConnection<Stream>> {
async _encrypt <Stream extends Duplex<AsyncGenerator<Uint8Array | Uint8ArrayList>> = MultiaddrConnection> (conn: Stream, isServer: boolean, remoteId?: PeerId): Promise<SecuredConnection<Stream>> {
const opts: TLSSocketOptions = {
...await generateCertificate(localId),
...await generateCertificate(this.peerId),
isServer,
// require TLS 1.3 or later
minVersion: 'TLSv1.3',
Expand Down
4 changes: 3 additions & 1 deletion packages/connection-encrypter-tls/test/compliance.spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,12 +2,14 @@

import suite from '@libp2p/interface-compliance-tests/connection-encryption'
import { defaultLogger } from '@libp2p/logger'
import { createEd25519PeerId } from '@libp2p/peer-id-factory'
import { tls } from '../src/index.js'

describe('tls compliance', () => {
suite({
async setup () {
async setup (opts) {
return tls()({
peerId: opts?.peerId ?? await createEd25519PeerId(),
logger: defaultLogger()
})
},
Expand Down
14 changes: 10 additions & 4 deletions packages/connection-encrypter-tls/test/index.spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,7 @@ describe('tls', () => {
])

encrypter = tls()({
peerId: await createEd25519PeerId(),
logger: defaultLogger()
})
})
Expand All @@ -42,8 +43,8 @@ describe('tls', () => {
})

await Promise.all([
encrypter.secureInbound(remotePeer, inbound),
encrypter.secureOutbound(localPeer, outbound, wrongPeer)
encrypter.secureInbound(inbound, remotePeer),
encrypter.secureOutbound(outbound, wrongPeer)
]).then(() => expect.fail('should have failed'), (err) => {
expect(err).to.exist()
expect(err).to.have.property('name', 'UnexpectedPeerError')
Expand All @@ -54,6 +55,11 @@ describe('tls', () => {
const peer = await createRSAPeerId()
remotePeer = peerIdFromBytes(peer.toBytes())

encrypter = tls()({
peerId: remotePeer,
logger: defaultLogger()
})

const { inbound, outbound } = mockMultiaddrConnPair({
remotePeer,
addrs: [
Expand All @@ -63,8 +69,8 @@ describe('tls', () => {
})

await expect(Promise.all([
encrypter.secureInbound(localPeer, inbound),
encrypter.secureOutbound(remotePeer, outbound, localPeer)
encrypter.secureInbound(inbound),
encrypter.secureOutbound(outbound, localPeer)
]))
.to.eventually.be.rejected.with.property('name', 'InvalidParametersError')
})
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -9,21 +9,28 @@ import { createMaConnPair } from './utils/index.js'
import type { TestSetup } from '../index.js'
import type { ConnectionEncrypter, PeerId } from '@libp2p/interface'

export default (common: TestSetup<ConnectionEncrypter>): void => {
export interface ConnectionEncrypterSetupArgs {
peerId: PeerId
}

export default (common: TestSetup<ConnectionEncrypter, ConnectionEncrypterSetupArgs>): void => {
describe('interface-connection-encrypter compliance tests', () => {
let crypto: ConnectionEncrypter
let cryptoRemote: ConnectionEncrypter
let localPeer: PeerId
let remotePeer: PeerId
let mitmPeer: PeerId

before(async () => {
[
crypto,
cryptoRemote,
localPeer,
remotePeer,
mitmPeer
] = await Promise.all([
common.setup(),
common.setup({ peerId: await PeerIdFactory.createFromJSON(peers[0]) }),
common.setup({ peerId: await PeerIdFactory.createFromJSON(peers[1]) }),
PeerIdFactory.createFromJSON(peers[0]),
PeerIdFactory.createFromJSON(peers[1]),
PeerIdFactory.createFromJSON(peers[2])
Expand All @@ -46,8 +53,8 @@ export default (common: TestSetup<ConnectionEncrypter>): void => {
inboundResult,
outboundResult
] = await Promise.all([
crypto.secureInbound(remotePeer, localConn),
crypto.secureOutbound(localPeer, remoteConn, remotePeer)
cryptoRemote.secureInbound(localConn),
crypto.secureOutbound(remoteConn, remotePeer)
])

// Echo server
Expand Down Expand Up @@ -76,8 +83,8 @@ export default (common: TestSetup<ConnectionEncrypter>): void => {
inboundResult,
outboundResult
] = await Promise.all([
crypto.secureInbound(remotePeer, localConn),
crypto.secureOutbound(localPeer, remoteConn, remotePeer)
cryptoRemote.secureInbound(localConn),
crypto.secureOutbound(remoteConn, remotePeer)
])

// Inbound should return the initiator (local) peer
Expand All @@ -90,8 +97,8 @@ export default (common: TestSetup<ConnectionEncrypter>): void => {
const [localConn, remoteConn] = createMaConnPair()

await Promise.all([
crypto.secureInbound(remotePeer, localConn, mitmPeer),
crypto.secureOutbound(localPeer, remoteConn, remotePeer)
cryptoRemote.secureInbound(localConn, mitmPeer),
crypto.secureOutbound(remoteConn, remotePeer)
]).then(() => expect.fail(), (err) => {
expect(err).to.exist()
expect(err).to.have.property('name', 'UnexpectedPeerError')
Expand Down
4 changes: 2 additions & 2 deletions packages/interface/src/connection-encrypter/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -15,14 +15,14 @@ export interface ConnectionEncrypter<Extension = unknown> {
* pass it for extra verification, otherwise it will be determined during
* the handshake.
*/
secureOutbound <Stream extends Duplex<AsyncGenerator<Uint8Array | Uint8ArrayList>> = MultiaddrConnection> (localPeer: PeerId, connection: Stream, remotePeer?: PeerId): Promise<SecuredConnection<Stream, Extension>>
secureOutbound <Stream extends Duplex<AsyncGenerator<Uint8Array | Uint8ArrayList>> = MultiaddrConnection> (connection: Stream, remotePeer?: PeerId): Promise<SecuredConnection<Stream, Extension>>

/**
* Decrypt incoming data. If the remote PeerId is known,
* pass it for extra verification, otherwise it will be determined during
* the handshake
*/
secureInbound <Stream extends Duplex<AsyncGenerator<Uint8Array | Uint8ArrayList>> = MultiaddrConnection> (localPeer: PeerId, connection: Stream, remotePeer?: PeerId): Promise<SecuredConnection<Stream, Extension>>
secureInbound <Stream extends Duplex<AsyncGenerator<Uint8Array | Uint8ArrayList>> = MultiaddrConnection> (connection: Stream, remotePeer?: PeerId): Promise<SecuredConnection<Stream, Extension>>
}

export interface SecuredConnection<Stream = any, Extension = unknown> {
Expand Down
4 changes: 2 additions & 2 deletions packages/libp2p/src/upgrader.ts
Original file line number Diff line number Diff line change
Expand Up @@ -640,7 +640,7 @@ export class DefaultUpgrader implements Upgrader {
connection.log('encrypting inbound connection using', protocol)

return {
...await encrypter.secureInbound(this.components.peerId, stream),
...await encrypter.secureInbound(stream),
protocol
}
} catch (err: any) {
Expand Down Expand Up @@ -677,7 +677,7 @@ export class DefaultUpgrader implements Upgrader {
connection.log('encrypting outbound connection to %p using %s', remotePeerId, encrypter)

return {
...await encrypter.secureOutbound(this.components.peerId, stream, remotePeerId),
...await encrypter.secureOutbound(stream, remotePeerId),
protocol
}
} catch (err: any) {
Expand Down
12 changes: 6 additions & 6 deletions packages/libp2p/test/upgrading/upgrader.spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -173,7 +173,7 @@ describe('Upgrader', () => {
})
remoteUpgrader = new DefaultUpgrader(remoteComponents, {
connectionEncryption: [
plaintext()(localComponents)
plaintext()(remoteComponents)
],
muxers: [],
inboundUpgradeTimeout: 1000
Expand Down Expand Up @@ -360,19 +360,19 @@ describe('Upgrader', () => {
})
remoteUpgrader = new DefaultUpgrader(remoteComponents, {
connectionEncryption: [
plaintext()(localComponents)
plaintext()(remoteComponents)
],
muxers: [
yamux()(localComponents),
mplex()(localComponents)
yamux()(remoteComponents),
mplex()(remoteComponents)
],
inboundUpgradeTimeout: 1000
})

// Wait for the results of each side of the connection
const results = await Promise.allSettled([
localUpgrader.upgradeOutbound(outbound),
remoteUpgrader.upgradeInbound(inbound)
localUpgrader.upgradeOutbound(inbound),
remoteUpgrader.upgradeInbound(outbound)
])

// Ensure both sides fail
Expand Down
4 changes: 1 addition & 3 deletions packages/transport-webrtc/src/private-to-public/transport.ts
Original file line number Diff line number Diff line change
Expand Up @@ -190,8 +190,6 @@ export class WebRTCDirectTransport implements Transport {
// wait for peerconnection.onopen to fire, or for the datachannel to open
const handshakeDataChannel = await dataChannelOpenPromise

const myPeerId = this.components.peerId

// Do noise handshake.
// Set the Noise Prologue to libp2p-webrtc-noise:<FINGERPRINTS> before starting the actual Noise handshake.
// <FINGERPRINTS> is the concatenation of the of the two TLS fingerprints of A and B in their multihash byte representation, sorted in ascending order.
Expand Down Expand Up @@ -260,7 +258,7 @@ export class WebRTCDirectTransport implements Transport {

// For outbound connections, the remote is expected to start the noise handshake.
// Therefore, we need to secure an inbound noise connection from the remote.
await connectionEncrypter.secureInbound(myPeerId, wrappedDuplex, theirPeerId)
await connectionEncrypter.secureInbound(wrappedDuplex, theirPeerId)

return await options.upgrader.upgradeOutbound(maConn, { skipProtection: true, skipEncryption: true, muxerFactory })
} catch (err) {
Expand Down
Loading

0 comments on commit cadfd7e

Please sign in to comment.