Skip to content

Commit

Permalink
fix: send raw plaintext public key during handshake (#2599)
Browse files Browse the repository at this point in the history
In js, all "public keys" are marshaled using protobuf PublicKey message.

However, according to [specs](https://github.com/libp2p/specs/blob/master/plaintext/README.md) and other implementations, the `Data` field should contains the raw key, instead of the protobuf marshaled key, and then put in to the exchange.

Otherwise, js-libp2p will not connect to golang or rust libp2p, raising the "Public key did not match id" error.

---------

Co-authored-by: Alex Potsides <[email protected]>
  • Loading branch information
oott123 and achingbrain authored Aug 16, 2024
1 parent 52ac523 commit 359265a
Show file tree
Hide file tree
Showing 4 changed files with 27 additions and 9 deletions.
3 changes: 2 additions & 1 deletion packages/connection-encrypter-plaintext/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -52,7 +52,9 @@
"doc-check": "aegir doc-check"
},
"dependencies": {
"@libp2p/crypto": "^4.1.9",
"@libp2p/interface": "^1.7.0",
"@libp2p/peer-id-factory": "^4.2.4",
"@libp2p/peer-id": "^4.2.4",
"it-protobuf-stream": "^1.1.3",
"it-stream-types": "^2.0.1",
Expand All @@ -62,7 +64,6 @@
"devDependencies": {
"@libp2p/interface-compliance-tests": "^5.4.12",
"@libp2p/logger": "^4.0.20",
"@libp2p/peer-id-factory": "^4.2.4",
"@multiformats/multiaddr": "^12.2.3",
"aegir": "^44.0.1",
"protons": "^7.5.0",
Expand Down
24 changes: 19 additions & 5 deletions packages/connection-encrypter-plaintext/src/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -20,11 +20,13 @@
* ```
*/

import { supportedKeys } from '@libp2p/crypto/keys'
import { UnexpectedPeerError, InvalidCryptoExchangeError, serviceCapabilities } from '@libp2p/interface'
import { peerIdFromBytes, peerIdFromKeys } from '@libp2p/peer-id'
import { peerIdFromBytes } from '@libp2p/peer-id'
import { createFromPubKey } from '@libp2p/peer-id-factory'
import { pbStream } from 'it-protobuf-stream'
import { Exchange, KeyType } from './pb/proto.js'
import type { ComponentLogger, Logger, MultiaddrConnection, ConnectionEncrypter, SecuredConnection, PeerId } from '@libp2p/interface'
import { Exchange, KeyType, PublicKey } from './pb/proto.js'
import type { ComponentLogger, Logger, MultiaddrConnection, ConnectionEncrypter, SecuredConnection, PeerId, PublicKey as PubKey } from '@libp2p/interface'
import type { Duplex } from 'it-stream-types'
import type { Uint8ArrayList } from 'uint8arraylist'

Expand Down Expand Up @@ -91,7 +93,7 @@ class Plaintext implements ConnectionEncrypter {
id: localId.toBytes(),
pubkey: {
Type: type,
Data: localId.publicKey ?? new Uint8Array(0)
Data: localId.publicKey == null ? new Uint8Array(0) : (PublicKey.decode(localId.publicKey).Data ?? new Uint8Array(0))
}
}, {
signal
Expand All @@ -116,7 +118,19 @@ class Plaintext implements ConnectionEncrypter {
throw new Error('Remote id missing')
}

peerId = await peerIdFromKeys(response.pubkey.Data)
let pubKey: PubKey

if (response.pubkey.Type === KeyType.RSA) {
pubKey = supportedKeys.rsa.unmarshalRsaPublicKey(response.pubkey.Data)
} else if (response.pubkey.Type === KeyType.Ed25519) {
pubKey = supportedKeys.ed25519.unmarshalEd25519PublicKey(response.pubkey.Data)
} else if (response.pubkey.Type === KeyType.Secp256k1) {
pubKey = supportedKeys.secp256k1.unmarshalSecp256k1PublicKey(response.pubkey.Data)
} else {
throw new Error('Unknown public key type')
}

peerId = await createFromPubKey(pubKey)

if (!peerId.equals(peerIdFromBytes(response.id))) {
throw new Error('Public key did not match id')
Expand Down
6 changes: 3 additions & 3 deletions packages/integration-tests/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -49,15 +49,15 @@
"@libp2p/interface": "^1.3.1",
"@libp2p/interface-compliance-tests": "^5.4.4",
"@libp2p/interface-internal": "^1.2.1",
"@libp2p/interop": "^12.1.0",
"@libp2p/interop": "^12.2.0",
"@libp2p/kad-dht": "^12.0.16",
"@libp2p/logger": "^4.0.12",
"@libp2p/mdns": "^10.0.23",
"@libp2p/mplex": "^10.0.23",
"@libp2p/peer-id": "^4.1.1",
"@libp2p/peer-id-factory": "^4.1.1",
"@libp2p/ping": "^1.0.18",
"@libp2p/plaintext": "^1.0.23",
"@libp2p/plaintext": "^1.1.5",
"@libp2p/tcp": "^9.0.25",
"@libp2p/tls": "^1.0.10",
"@libp2p/webrtc": "^4.0.32",
Expand All @@ -70,7 +70,7 @@
"delay": "^6.0.0",
"detect-browser": "^5.3.0",
"execa": "^9.1.0",
"go-libp2p": "^1.2.0",
"go-libp2p": "^1.5.0",
"it-all": "^3.0.6",
"it-pipe": "^3.0.1",
"libp2p": "^1.5.2",
Expand Down
3 changes: 3 additions & 0 deletions packages/integration-tests/test/interop.ts
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@ import { kadDHT, passthroughMapper } from '@libp2p/kad-dht'
import { logger } from '@libp2p/logger'
import { mplex } from '@libp2p/mplex'
import { peerIdFromKeys } from '@libp2p/peer-id'
import { plaintext } from '@libp2p/plaintext'
import { tcp } from '@libp2p/tcp'
import { tls } from '@libp2p/tls'
import { multiaddr } from '@multiformats/multiaddr'
Expand Down Expand Up @@ -160,6 +161,8 @@ async function createJsPeer (options: SpawnOptions): Promise<Daemon> {
opts.connectionEncryption?.push(noise())
} else if (options.encryption === 'tls') {
opts.connectionEncryption?.push(tls())
} else if (options.encryption === 'plaintext') {
opts.connectionEncryption?.push(plaintext())
}

if (options.muxer === 'mplex') {
Expand Down

0 comments on commit 359265a

Please sign in to comment.