Skip to content
This repository has been archived by the owner on Feb 24, 2021. It is now read-only.

Commit

Permalink
test: check if we dialed to the right peer
Browse files Browse the repository at this point in the history
  • Loading branch information
daviddias committed Jan 7, 2018
1 parent ee1f64c commit 74f6fd8
Show file tree
Hide file tree
Showing 12 changed files with 138 additions and 95 deletions.
7 changes: 4 additions & 3 deletions .aegir.js
Original file line number Diff line number Diff line change
Expand Up @@ -15,17 +15,18 @@ module.exports = {
hooks: {
browser: {
pre: (done) => {
PeerId.createFromJSON(peerNodeJSON, (err, id) => {
PeerId.createFromJSON(peerNodeJSON, (err, peerId) => {
if (err) { throw err }

const ws = new WS()

listener = ws.createListener((conn) => {
const encrypted = secio.encrypt(id, id._privKey, conn, (err) => {
const encryptedConn = secio.encrypt(peerId, conn, undefined, (err) => {
if (err) { throw err }
})

pull(encrypted, encrypted)
// echo
pull(encryptedConn, encryptedConn)
})

listener.listen(ma, done)
Expand Down
12 changes: 5 additions & 7 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -43,12 +43,12 @@ const secio = require('libp2p-secio')

The current `secio` tag, usable in `multistream`.

### `const encryptedConnection = secio.encrypt(id, key, plainTextConnection [, callback])`
### `const encryptedConnection = secio.encrypt(localPeerId, plainTextConnection [, remotePeerId] [, callback])`

- `id: PeerId` - The id of the node we are doing the SECIO handshake with.
- `key: RSAPrivateKey` - The private key of our node node.
- `insecure: PullStream` - The insecure connection.
- `callback: Function` - Called if an error happens during the initialization.
- `localPeerId: PeerId` - A PeerId object containing the Private, Public and Id of our node.
- `plainTextConnection: Connection` - The insecure connection to be secured.
- `remotePeerId: PeerId` - A PeerId object containing the Public and/or Id of the node we are doing the SECIO handshake with.
- `callback: Function` - Optional, Called if an error happens during the initialization.

Returns an encrypted [Connection object](https://github.com/libp2p/interface-connection) that is the upgraded `plainTextConnection` with now having every byte encripted.

Expand Down Expand Up @@ -78,8 +78,6 @@ const nodeStreamInstance = pullToStream(pullStreamInstance)

To learn more about this utility, visit https://pull-stream.github.io/#pull-stream-to-stream.



## Contribute

Feel free to join in. All welcome. Open an [issue](https://github.com/libp2p/js-libp2p-secio/issues)!
Expand Down
8 changes: 4 additions & 4 deletions benchmarks/send.js
Original file line number Diff line number Diff line change
Expand Up @@ -53,8 +53,8 @@ suite.add('establish an encrypted channel', (deferred) => {
const peerA = peers[0]
const peerB = peers[1]

const aToB = secio.encrypt(peerB, peerA.privKey, p[0], (err) => { throw err })
const bToA = secio.encrypt(peerA, peerB.privKey, p[1], (err) => { throw err })
const aToB = secio.encrypt(peerA, p[0], peerB, (err) => { throw err })
const bToA = secio.encrypt(peerB, p[1], peerA, (err) => { throw err })

sendData(aToB, bToA, {}, deferred)
}, { defer: true })
Expand Down Expand Up @@ -83,8 +83,8 @@ cases.forEach((el) => {
const peerA = peers[0]
const peerB = peers[1]

const aToB = secio.encrypt(peerB, peerA.privKey, p[0], (err) => { throw err })
const bToA = secio.encrypt(peerA, peerB.privKey, p[1], (err) => { throw err })
const aToB = secio.encrypt(peerA, p[0], peerB, (err) => { throw err })
const bToA = secio.encrypt(peerB, p[1], peerA, (err) => { throw err })

sendData(aToB, bToA, { times: times, size: size }, deferred)
}, { defer: true })
Expand Down
1 change: 1 addition & 0 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -31,6 +31,7 @@
"libp2p-crypto": "~0.11.0",
"multihashing-async": "~0.4.7",
"peer-id": "~0.10.4",
"peer-info": "^0.11.4",
"protons": "^1.0.1",
"pull-defer": "^0.2.2",
"pull-handshake": "^1.1.4",
Expand Down
10 changes: 9 additions & 1 deletion src/handshake/crypto.js
Original file line number Diff line number Diff line change
Expand Up @@ -68,12 +68,20 @@ exports.identify = (state, msg, callback) => {
const pubkey = state.proposal.in.pubkey

state.key.remote = crypto.keys.unmarshalPublicKey(pubkey)

PeerId.createFromPubKey(pubkey.toString('base64'), (err, remoteId) => {
if (err) {
return callback(err)
}

state.id.remote = remoteId
// If we know who we are dialing to, double check
if (state.id.remote) {
if (state.id.remote.toB58String() !== remoteId.toB58String()) {
return callback(new Error('dialed to the wrong peer, Ids do not match'))
}
} else {
state.id.remote = remoteId
}

log('1.1 identify - %s - identified remote peer as %s', state.id.local.toB58String(), state.id.remote.toB58String())
callback()
Expand Down
4 changes: 1 addition & 3 deletions src/handshake/exchange.js
Original file line number Diff line number Diff line change
Expand Up @@ -27,9 +27,7 @@ module.exports = function exchange (state, cb) {
},
(cb) => crypto.generateKeys(state, cb)
], (err) => {
if (err) {
return cb(err)
}
if (err) { return cb(err) }

log('2. exchange - finish')
cb()
Expand Down
9 changes: 6 additions & 3 deletions src/handshake/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -6,9 +6,9 @@ const propose = require('./propose')
const exchange = require('./exchange')
const finish = require('./finish')

// Performs initial communication over insecure channel to share
// keys, IDs, and initiate communication, assigning all necessary params.
module.exports = function handshake (state) {
// Performs initial communication over insecure channel to share keys, IDs,
// and initiate communication, assigning all necessary params.
module.exports = function handshake (state, callback) {
series([
(cb) => propose(state, cb),
(cb) => exchange(state, cb),
Expand All @@ -22,6 +22,9 @@ module.exports = function handshake (state) {
}
state.shake.abort(err)
}

// signal when the handshake is finished so that plumbing can happen
callback()
})

return state.stream
Expand Down
54 changes: 35 additions & 19 deletions src/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -2,41 +2,57 @@

const pull = require('pull-stream')
const Connection = require('interface-connection').Connection
const assert = require('assert')
const PeerInfo = require('peer-info')
const debug = require('debug')
const once = require('once')
const log = debug('libp2p:secio')
log.error = debug('libp2p:secio:error')

const handshake = require('./handshake')
const State = require('./state')

module.exports = {
tag: '/secio/1.0.0',
encrypt (local, key, insecure, callback) {
if (!local) {
throw new Error('no local id provided')
}
encrypt (localId, conn, remoteId, callback) {
assert(localId, 'no local private key provided')
assert(conn, 'no connection for the handshake provided')

if (!key) {
throw new Error('no local private key provided')
if (typeof remoteId === 'function') {
callback = remoteId
remoteId = undefined
}

if (!insecure) {
throw new Error('no insecure stream provided')
}
callback = once(callback || function (err) {
if (err) { log.error(err) }
})

const timeout = 60 * 1000 * 5

const state = new State(localId, remoteId, timeout, callback)

if (!callback) {
callback = (err) => {
if (err) {
console.error(err)
function finish (err) {
if (err) { return callback(err) }

conn.getPeerInfo((err, peerInfo) => {
encryptedConnection.setInnerConn(state.secure)

if (err) { // no peerInfo yet, means I'm the receiver
encryptedConnection.setPeerInfo(new PeerInfo(state.id.remote))
}
}

This comment has been minimized.

Copy link
@fiatjaf

fiatjaf Jan 9, 2018

Why isn't the state.id.remote or state.key.remote used to set the info for the encryptedConnection here? The encrypted connections that go out of this function do not have an attached peerInfo with a public key, but it seems to me that the information is here and should be made available on the connection object. What am I missing?

callback()
})
}

const state = new State(local, key, 60 * 1000 * 5, callback)
const encryptedConnection = new Connection(undefined, conn)

pull(
insecure,
handshake(state),
insecure
conn,
handshake(state, finish),
conn
)

return new Connection(state.secure, insecure)
return encryptedConnection
}
}
57 changes: 16 additions & 41 deletions src/state.js
Original file line number Diff line number Diff line change
Expand Up @@ -4,68 +4,43 @@ const handshake = require('pull-handshake')
const deferred = require('pull-defer')

class State {
constructor (id, key, timeout, cb) {
constructor (localId, remoteId, timeout, callback) {
if (typeof timeout === 'function') {
cb = timeout
callback = timeout
timeout = undefined
}

this.setup()
this.id.local = id
this.key.local = key

this.id.local = localId
// TODO use remoteId to verify PeersIdentity
this.id.remote = remoteId
this.key.local = localId.privKey
this.timeout = timeout || 60 * 1000
cb = cb || (() => {})
callback = callback || (() => {})

this.secure = deferred.duplex()
this.stream = handshake({timeout: this.timeout}, cb)
this.stream = handshake({ timeout: this.timeout }, callback)
this.shake = this.stream.handshake
delete this.stream.handshake
}

setup () {
this.id = {
local: null,
remote: null
}

this.key = {
local: null,
remote: null
}

this.id = { local: null, remote: null }
this.key = { local: null, remote: null }
this.shake = null

this.cleanSecrets()
}

// remove all data from the handshake that is not needed anymore
cleanSecrets () {
this.shared = {}

this.ephemeralKey = {
local: null,
remote: null
}

this.proposal = {
in: null,
out: null
}

this.proposalEncoded = {
in: null,
out: null
}

this.protocols = {
local: null,
remote: null
}

this.exchange = {
in: null,
out: null
}
this.ephemeralKey = { local: null, remote: null }
this.proposal = { in: null, out: null }
this.proposalEncoded = { in: null, out: null }
this.protocols = { local: null, remote: null }
this.exchange = { in: null, out: null }
}
}

Expand Down
4 changes: 1 addition & 3 deletions src/support.js
Original file line number Diff line number Diff line change
Expand Up @@ -116,9 +116,7 @@ exports.digest = (buf, cb) => {
exports.write = function write (state, msg, cb) {
cb = cb || (() => {})
pull(
pull.values([
msg
]),
pull.values([msg]),
lp.encode({fixed: true, bytes: 4}),
pull.collect((err, res) => {
if (err) {
Expand Down
17 changes: 12 additions & 5 deletions test/browser.js
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,9 @@ const WS = require('libp2p-websockets')
const PeerId = require('peer-id')
const parallel = require('async/parallel')

const peerNodeJSON = require('./fixtures/peer-node.json')
const peerBrowserJSON = require('./fixtures/peer-browser.json')

const secio = require('../src')

describe('secio between browser <-> nodejs through websockets', () => {
Expand All @@ -22,17 +24,22 @@ describe('secio between browser <-> nodejs through websockets', () => {

before((done) => {
parallel([
(cb) => PeerId.createFromJSON(peerNodeJSON, cb),
(cb) => PeerId.createFromJSON(peerBrowserJSON, cb),

(cb) => {
const ws = new WS()
conn = ws.dial(ma, cb)
}
], (err, res) => {
if (err) {
return done(err)
}
expect(err).to.not.exist()

encryptedConn = secio.encrypt(res[0], res[0]._privKey, conn)
const peerIdNode = res[0]
const peerIdBrowser = res[1]

encryptedConn = secio.encrypt(peerIdBrowser, conn, peerIdNode, (err) => {
expect(err).to.not.exist()
})
done()
})
})
Expand All @@ -44,7 +51,7 @@ describe('secio between browser <-> nodejs through websockets', () => {
source: pull.values([message]),
sink: pull.collect((err, results) => {
expect(err).to.not.exist()
expect(results).to.be.eql([message])
expect(results).to.eql([message])
done()
})
}, 'GoodBye')
Expand Down
Loading

0 comments on commit 74f6fd8

Please sign in to comment.