Skip to content
This repository was archived by the owner on Jun 26, 2023. It is now read-only.

Commit 11f964c

Browse files
committed
feat: add basic crypto interface test suite
1 parent 0551fac commit 11f964c

File tree

7 files changed

+186
-2
lines changed

7 files changed

+186
-2
lines changed

package.json

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -51,6 +51,7 @@
5151
},
5252
"devDependencies": {
5353
"aegir": "^20.4.1",
54+
"it-handshake": "^1.0.0",
5455
"it-pair": "^1.0.0",
5556
"it-pipe": "^1.0.1",
5657
"peer-info": "^0.17.0"

src/crypto/README.md

Lines changed: 16 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -9,7 +9,22 @@ interface-crypto
99

1010
## Using the Test Suite
1111

12-
TODO:
12+
You can also check out the [internal test suite](../../test/crypto/compliance.spec.js) to see the setup in action.
13+
14+
```js
15+
const tests = require('libp2p-interfaces/src/crypto/tests')
16+
const yourCrypto = require('./your-crypto')
17+
18+
tests({
19+
setup () {
20+
// Set up your crypto if needed, then return it
21+
return yourCrypto
22+
},
23+
teardown () {
24+
// Clean up your crypto if needed
25+
}
26+
})
27+
```
1328

1429
## API
1530

src/crypto/tests/index.js

Lines changed: 86 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,86 @@
1+
/* eslint-env mocha */
2+
'use strict'
3+
4+
const duplexPair = require('it-pair/duplex')
5+
const pipe = require('it-pipe')
6+
const peers = require('../../utils/peers')
7+
const PeerId = require('peer-id')
8+
const { collect } = require('streaming-iterables')
9+
const chai = require('chai')
10+
const expect = chai.expect
11+
chai.use(require('dirty-chai'))
12+
13+
module.exports = (common) => {
14+
describe('interface-crypto', () => {
15+
let crypto
16+
let localPeer
17+
let remotePeer
18+
19+
before(async () => {
20+
[
21+
crypto,
22+
localPeer,
23+
remotePeer
24+
] = await Promise.all([
25+
common.setup(),
26+
PeerId.createFromJSON(peers[0]),
27+
PeerId.createFromJSON(peers[1])
28+
])
29+
})
30+
31+
after(() => common.teardown && common.teardown())
32+
33+
it('has a protocol string', () => {
34+
expect(crypto.protocol).to.exist()
35+
expect(crypto.protocol).to.be.a('string')
36+
})
37+
38+
it('it wraps the provided duplex connection', async () => {
39+
const [localConn, remoteConn] = duplexPair()
40+
41+
const [
42+
inboundResult,
43+
outboundResult
44+
] = await Promise.all([
45+
crypto.secureInbound(remotePeer, localConn),
46+
crypto.secureOutbound(localPeer, remoteConn, remotePeer)
47+
])
48+
49+
// Echo server
50+
pipe(inboundResult.conn, inboundResult.conn)
51+
52+
// Send some data and collect the result
53+
const input = Buffer.from('data to encrypt')
54+
const result = await pipe(
55+
[input],
56+
outboundResult.conn,
57+
// Convert BufferList to Buffer via slice
58+
(source) => (async function * toBuffer () {
59+
for await (const chunk of source) {
60+
yield chunk.slice()
61+
}
62+
})(),
63+
collect
64+
)
65+
66+
expect(result).to.eql([input])
67+
})
68+
69+
it('should return the remote peer id', async () => {
70+
const [localConn, remoteConn] = duplexPair()
71+
72+
const [
73+
inboundResult,
74+
outboundResult
75+
] = await Promise.all([
76+
crypto.secureInbound(remotePeer, localConn),
77+
crypto.secureOutbound(localPeer, remoteConn, remotePeer)
78+
])
79+
80+
// Inbound should return the initiator (local) peer
81+
expect(inboundResult.remotePeer.id).to.eql(localPeer.id)
82+
// Outbound should return the receiver (remote) peer
83+
expect(outboundResult.remotePeer.id).to.eql(remotePeer.id)
84+
})
85+
})
86+
}
File renamed without changes.

test/connection/compliance.spec.js

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,7 @@
33

44
const tests = require('../../src/connection/tests')
55
const { Connection } = require('../../src/connection')
6-
const peers = require('../utils/peers')
6+
const peers = require('../../src/utils/peers')
77
const PeerId = require('peer-id')
88
const multiaddr = require('multiaddr')
99
const pair = require('it-pair')

test/crypto/compliance.spec.js

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,13 @@
1+
/* eslint-env mocha */
2+
'use strict'
3+
4+
const tests = require('../../src/crypto/tests')
5+
const mockCrypto = require('./mock-crypto')
6+
7+
describe('compliance tests', () => {
8+
tests({
9+
setup () {
10+
return mockCrypto
11+
}
12+
})
13+
})

test/crypto/mock-crypto.js

Lines changed: 69 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,69 @@
1+
'use strict'
2+
3+
const PeerId = require('peer-id')
4+
const handshake = require('it-handshake')
5+
const duplexPair = require('it-pair/duplex')
6+
const pipe = require('it-pipe')
7+
8+
// A basic transform that does nothing to the data
9+
const transform = () => {
10+
return (source) => (async function * () {
11+
for await (const chunk of source) {
12+
yield chunk
13+
}
14+
})()
15+
}
16+
17+
module.exports = {
18+
protocol: 'insecure',
19+
secureInbound: async (localPeer, duplex) => {
20+
// 1. Perform a basic handshake.
21+
const shake = handshake(duplex)
22+
shake.write(localPeer.id)
23+
const remoteId = await shake.read()
24+
shake.rest()
25+
26+
// 2. Create your encryption box/unbox wrapper
27+
const wrapper = duplexPair()
28+
const encrypt = transform() // Use transform iterables to modify data
29+
const decrypt = transform()
30+
31+
pipe(
32+
wrapper[0], // We write to wrapper
33+
encrypt, // The data is encrypted
34+
shake.stream, // It goes to the remote peer
35+
decrypt, // Decrypt the incoming data
36+
wrapper[0] // Pipe to the wrapper
37+
)
38+
39+
return {
40+
conn: wrapper[1],
41+
remotePeer: new PeerId(remoteId.slice())
42+
}
43+
},
44+
secureOutbound: async (localPeer, duplex, remotePeer) => {
45+
// 1. Perform a basic handshake.
46+
const shake = handshake(duplex)
47+
shake.write(localPeer.id)
48+
const remoteId = await shake.read()
49+
shake.rest()
50+
51+
// 2. Create your encryption box/unbox wrapper
52+
const wrapper = duplexPair()
53+
const encrypt = transform()
54+
const decrypt = transform()
55+
56+
pipe(
57+
wrapper[0], // We write to wrapper
58+
encrypt, // The data is encrypted
59+
shake.stream, // It goes to the remote peer
60+
decrypt, // Decrypt the incoming data
61+
wrapper[0] // Pipe to the wrapper
62+
)
63+
64+
return {
65+
conn: wrapper[1],
66+
remotePeer: new PeerId(remoteId.slice())
67+
}
68+
}
69+
}

0 commit comments

Comments
 (0)