Skip to content

Commit c10f7dc

Browse files
committed
chore: add connection encryption examples
1 parent 02d95cc commit c10f7dc

File tree

11 files changed

+266
-0
lines changed

11 files changed

+266
-0
lines changed

README.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -49,6 +49,7 @@ Feel free to jump directly into the examples, however going through the followin
4949
#### Understanding how libp2p works
5050

5151
- [Circuit Relay](./examples/js-libp2p-example-circuit-relay) - configuring Circuit Relay connections
52+
- [Connection Encryption](./examples/js-libp2p-example-connection-encryption) - how to encrypt connection between libp2p nodes
5253

5354
#### Other examples
5455

Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,17 @@
1+
# ⚠️ IMPORTANT ⚠️
2+
3+
# Please do not create a Pull Request for this repository
4+
5+
The contents of this repository are automatically synced from the parent [js-libp2p Examples Project](https://github.com/libp2p/js-libp2p-examples) so any changes made to the standalone repository will be lost after the next sync.
6+
7+
Please open a PR against [js-libp2p Examples](https://github.com/libp2p/js-libp2p-examples) instead.
8+
9+
## Contributing
10+
11+
Contributions are what make the open source community such an amazing place to be learn, inspire, and create. Any contributions you make are **greatly appreciated**.
12+
13+
1. Fork the [js-libp2p Examples Project](https://github.com/libp2p/js-libp2p-examples)
14+
2. Create your Feature Branch (`git checkout -b feature/amazing-example`)
15+
3. Commit your Changes (`git commit -a -m 'feat: add some amazing example'`)
16+
4. Push to the Branch (`git push origin feature/amazing-example`)
17+
5. Open a Pull Request
Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,19 @@
1+
name: pull
2+
3+
on:
4+
workflow_dispatch
5+
6+
jobs:
7+
sync:
8+
runs-on: ubuntu-latest
9+
steps:
10+
- uses: actions/checkout@v2
11+
- name: Pull from another repository
12+
uses: ipfs-examples/actions-pull-directory-from-repo@main
13+
with:
14+
source-repo: libp2p/js-libp2p-examples
15+
source-folder-path: examples/${{ github.event.repository.name }}
16+
source-branch: main
17+
target-branch: main
18+
git-username: github-actions
19+
git-email: [email protected]
Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,4 @@
1+
This project is dual licensed under MIT and Apache-2.0.
2+
3+
MIT: https://www.opensource.org/licenses/mit
4+
Apache-2.0: https://www.apache.org/licenses/license-2.0
Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. You may obtain a copy of the License at
2+
3+
http://www.apache.org/licenses/LICENSE-2.0
4+
5+
Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language governing permissions and limitations under the License.
Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,19 @@
1+
The MIT License (MIT)
2+
3+
Permission is hereby granted, free of charge, to any person obtaining a copy
4+
of this software and associated documentation files (the "Software"), to deal
5+
in the Software without restriction, including without limitation the rights
6+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
7+
copies of the Software, and to permit persons to whom the Software is
8+
furnished to do so, subject to the following conditions:
9+
10+
The above copyright notice and this permission notice shall be included in
11+
all copies or substantial portions of the Software.
12+
13+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
14+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
15+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
16+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
17+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
18+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
19+
THE SOFTWARE.
Lines changed: 67 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,67 @@
1+
# @libp2p/example-connection-encryption <!-- omit in toc -->
2+
3+
[![libp2p.io](https://img.shields.io/badge/project-libp2p-yellow.svg?style=flat-square)](http://libp2p.io/)
4+
[![Discuss](https://img.shields.io/discourse/https/discuss.libp2p.io/posts.svg?style=flat-square)](https://discuss.libp2p.io)
5+
[![codecov](https://img.shields.io/codecov/c/github/libp2p/js-libp2p-examples.svg?style=flat-square)](https://codecov.io/gh/libp2p/js-libp2p-examples)
6+
[![CI](https://img.shields.io/github/actions/workflow/status/libp2p/js-libp2p-examples/ci.yml?branch=main\&style=flat-square)](https://github.com/libp2p/js-libp2p-examples/actions/workflows/ci.yml?query=branch%3Amain)
7+
8+
> An example of how to configure connection encrypters
9+
10+
## Table of contents <!-- omit in toc -->
11+
12+
- [Set up encrypted communications](#set-up-encrypted-communications)
13+
- [License](#license)
14+
- [Contribution](#contribution)
15+
16+
All traffic sent over connections between two libp2p nodes is encrypted. This gives us peace of mind that the node we are talking to is the node we think we are talking to, and that no-one is able to eavesdrop or interfere with the data we are exchanging.
17+
18+
You may have noticed that every time we dial the [multiaddr](https://multiformats.io/multiaddr) of a peer in libp2p space, we include the [PeerId](https://docs.libp2p.io/concepts/fundamentals/peers/#peer-id) at the end:
19+
20+
```
21+
/ip4/127.0.0.1/tcp/89765/p2p/12D3Foo
22+
```
23+
24+
For some types of `PeerID`, it is the public key of the remote node (Ed25519 and secp256k1) or, when the public key is too large to embed in a string, it can be the a hash of the public key (RSA).
25+
26+
Including the `PeerID` in the multiaddr allows us to authenticate the remote peer by creating a crypto challenge that allows them to prove they hold the the private key that matches the public key we know.
27+
28+
Once authenticated in this fashion we can proceed to encrypt/decrypt all traffic sent over the connection.
29+
30+
There are several strategies for performing encryption, the most common uses the [Noise Protocol Framework](http://www.noiseprotocol.org/).
31+
32+
js-libp2p also supports a plaintext "encryption" implementation that should not be used in production but is sometimes useful for testing.
33+
34+
## Set up encrypted communications
35+
36+
To add them to your libp2p configuration, all you have to do is:
37+
38+
```JavaScript
39+
import { noise } from '@chainsafe/libp2p-noise'
40+
import { yamux } from '@chainsafe/libp2p-yamux'
41+
import { tcp } from '@libp2p/tcp'
42+
import { createLibp2p } from 'libp2p'
43+
44+
const createNode = async () => {
45+
return await createLibp2p({
46+
transports: [ tcp() ],
47+
streamMuxers: [ yamux() ],
48+
// Attach noise as the crypto channel to use
49+
conectionEncrypters: [ noise() ]
50+
})
51+
}
52+
```
53+
54+
And that's it, from now on, all your libp2p communications are encrypted. Try running the example [noise.js](./noise.js) to see it working.
55+
56+
To experiment with the plaintext implementation, run [plaintext.js](./plaintext.js).
57+
58+
## License
59+
60+
Licensed under either of
61+
62+
- Apache 2.0, ([LICENSE-APACHE](LICENSE-APACHE) / <http://www.apache.org/licenses/LICENSE-2.0>)
63+
- MIT ([LICENSE-MIT](LICENSE-MIT) / <http://opensource.org/licenses/MIT>)
64+
65+
## Contribution
66+
67+
Unless you explicitly state otherwise, any contribution intentionally submitted for inclusion in the work by you, as defined in the Apache-2.0 license, shall be dual licensed as above, without any additional terms or conditions.
Lines changed: 43 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,43 @@
1+
/* eslint-disable no-console */
2+
3+
import { noise } from '@chainsafe/libp2p-noise'
4+
import { yamux } from '@chainsafe/libp2p-yamux'
5+
import { tcp } from '@libp2p/tcp'
6+
import { pipe } from 'it-pipe'
7+
import { createLibp2p } from 'libp2p'
8+
import { fromString as uint8ArrayFromString } from 'uint8arrays/from-string'
9+
import { toString as uint8ArrayToString } from 'uint8arrays/to-string'
10+
11+
const createNode = async () => {
12+
const node = await createLibp2p({
13+
addresses: {
14+
listen: ['/ip4/0.0.0.0/tcp/0']
15+
},
16+
transports: [tcp()],
17+
streamMuxers: [yamux()],
18+
connectionEncryption: [noise()]
19+
})
20+
21+
return node
22+
}
23+
24+
const node1 = await createNode()
25+
const node2 = await createNode()
26+
27+
node2.handle('/a-protocol', ({ stream }) => {
28+
pipe(
29+
stream,
30+
async function (source) {
31+
for await (const msg of source) {
32+
console.log(uint8ArrayToString(msg.subarray()))
33+
}
34+
}
35+
)
36+
})
37+
38+
const stream = await node1.dialProtocol(node2.getMultiaddrs(), '/a-protocol')
39+
40+
await pipe(
41+
[uint8ArrayFromString('This information is sent out encrypted to the other peer')],
42+
stream
43+
)
Lines changed: 31 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,31 @@
1+
{
2+
"name": "@libp2p/example-connection-encryption",
3+
"version": "0.0.0",
4+
"description": "An example of how to configure connection encryption",
5+
"license": "Apache-2.0 OR MIT",
6+
"homepage": "https://github.com/libp2p/js-libp2p-examples/tree/master/examples/js-libp2p-example-connection-encryption#readme",
7+
"repository": {
8+
"type": "git",
9+
"url": "git+https://github.com/libp2p/js-libp2p-examples.git"
10+
},
11+
"bugs": {
12+
"url": "https://github.com/libp2p/js-libp2p-examples/issues"
13+
},
14+
"type": "module",
15+
"scripts": {
16+
"test": "test-node-example test/*"
17+
},
18+
"dependencies": {
19+
"@chainsafe/libp2p-noise": "^13.0.0",
20+
"@chainsafe/libp2p-yamux": "^5.0.0",
21+
"@libp2p/mplex": "^9.0.0",
22+
"@libp2p/tcp": "^8.0.0",
23+
"it-pipe": "^3.0.1",
24+
"libp2p": "^0.46.0",
25+
"uint8arrays": "^4.0.6"
26+
},
27+
"devDependencies": {
28+
"test-ipfs-example": "^1.0.0"
29+
},
30+
"private": true
31+
}
Lines changed: 43 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,43 @@
1+
/* eslint-disable no-console */
2+
3+
import { yamux } from '@chainsafe/libp2p-yamux'
4+
import { tcp } from '@libp2p/tcp'
5+
import { pipe } from 'it-pipe'
6+
import { createLibp2p } from 'libp2p'
7+
import { plaintext } from 'libp2p/insecure'
8+
import { fromString as uint8ArrayFromString } from 'uint8arrays/from-string'
9+
import { toString as uint8ArrayToString } from 'uint8arrays/to-string'
10+
11+
const createNode = async () => {
12+
const node = await createLibp2p({
13+
addresses: {
14+
listen: ['/ip4/0.0.0.0/tcp/0']
15+
},
16+
transports: [tcp()],
17+
streamMuxers: [yamux()],
18+
connectionEncryption: [plaintext()]
19+
})
20+
21+
return node
22+
}
23+
24+
const node1 = await createNode()
25+
const node2 = await createNode()
26+
27+
node2.handle('/a-protocol', ({ stream }) => {
28+
pipe(
29+
stream,
30+
async function (source) {
31+
for await (const msg of source) {
32+
console.log(uint8ArrayToString(msg.subarray()))
33+
}
34+
}
35+
)
36+
})
37+
38+
const stream = await node1.dialProtocol(node2.getMultiaddrs(), '/a-protocol')
39+
40+
await pipe(
41+
[uint8ArrayFromString('This information is sent out encrypted to the other peer')],
42+
stream
43+
)

0 commit comments

Comments
 (0)