|
1 |
| -# @libp2p/crypto <!-- omit in toc --> |
2 |
| - |
3 | 1 | [](http://libp2p.io/)
|
4 | 2 | [](https://discuss.libp2p.io)
|
5 | 3 | [](https://codecov.io/gh/libp2p/js-libp2p)
|
6 | 4 | [](https://github.com/libp2p/js-libp2p/actions/workflows/main.yml?query=branch%3Amaster)
|
7 | 5 |
|
8 | 6 | > Crypto primitives for libp2p
|
9 | 7 |
|
10 |
| -## Table of contents <!-- omit in toc --> |
11 |
| - |
12 |
| -- [Install](#install) |
13 |
| - - [Browser `<script>` tag](#browser-script-tag) |
14 |
| -- [Lead Maintainer](#lead-maintainer) |
15 |
| -- [Usage](#usage) |
16 |
| - - [Web Crypto API](#web-crypto-api) |
17 |
| -- [API](#api) |
18 |
| - - [`crypto.aes`](#cryptoaes) |
19 |
| - - [`crypto.aes.create(key, iv)`](#cryptoaescreatekey-iv) |
20 |
| - - [`decrypt(data)`](#decryptdata) |
21 |
| - - [`encrypt(data)`](#encryptdata) |
22 |
| - - [`crypto.hmac`](#cryptohmac) |
23 |
| - - [`crypto.hmac.create(hash, secret)`](#cryptohmaccreatehash-secret) |
24 |
| - - [`digest(data)`](#digestdata) |
25 |
| - - [`crypto.keys`](#cryptokeys) |
26 |
| - - [`crypto.keys.generateKeyPair(type, bits)`](#cryptokeysgeneratekeypairtype-bits) |
27 |
| - - [`crypto.keys.generateEphemeralKeyPair(curve)`](#cryptokeysgenerateephemeralkeypaircurve) |
28 |
| - - [`crypto.keys.keyStretcher(cipherType, hashType, secret)`](#cryptokeyskeystretcherciphertype-hashtype-secret) |
29 |
| - - [`crypto.keys.marshalPublicKey(key, [type])`](#cryptokeysmarshalpublickeykey-type) |
30 |
| - - [`crypto.keys.unmarshalPublicKey(buf)`](#cryptokeysunmarshalpublickeybuf) |
31 |
| - - [`crypto.keys.marshalPrivateKey(key, [type])`](#cryptokeysmarshalprivatekeykey-type) |
32 |
| - - [`crypto.keys.unmarshalPrivateKey(buf)`](#cryptokeysunmarshalprivatekeybuf) |
33 |
| - - [`crypto.keys.import(encryptedKey, password)`](#cryptokeysimportencryptedkey-password) |
34 |
| - - [`privateKey.export(password, format)`](#privatekeyexportpassword-format) |
35 |
| - - [`crypto.randomBytes(number)`](#cryptorandombytesnumber) |
36 |
| - - [`crypto.pbkdf2(password, salt, iterations, keySize, hash)`](#cryptopbkdf2password-salt-iterations-keysize-hash) |
37 |
| -- [Contribute](#contribute) |
38 |
| -- [API Docs](#api-docs) |
39 |
| -- [License](#license) |
40 |
| -- [Contribution](#contribution) |
41 |
| - |
42 |
| -## Install |
| 8 | +# Install |
43 | 9 |
|
44 | 10 | ```console
|
45 | 11 | $ npm i @libp2p/crypto
|
46 | 12 | ```
|
47 | 13 |
|
48 |
| -### Browser `<script>` tag |
| 14 | +## Browser `<script>` tag |
49 | 15 |
|
50 | 16 | Loading this module through a script tag will make it's exports available as `Libp2pCrypto` in the global namespace.
|
51 | 17 |
|
52 | 18 | ```html
|
53 | 19 | <script src="https://unpkg.com/@libp2p/crypto/dist/index.min.js"></script>
|
54 | 20 | ```
|
55 | 21 |
|
56 |
| -This repo contains the JavaScript implementation of the crypto primitives needed for libp2p. This is based on this [go implementation](https://github.com/libp2p/go-libp2p-crypto). |
57 |
| - |
58 |
| -## Lead Maintainer |
59 |
| - |
60 |
| -[Jacob Heun](https://github.com/jacobheun/) |
61 |
| - |
62 |
| -## Usage |
63 |
| - |
64 |
| -```js |
65 |
| -const crypto = require('libp2p-crypto') |
66 |
| - |
67 |
| -// Now available to you: |
68 |
| -// |
69 |
| -// crypto.aes |
70 |
| -// crypto.hmac |
71 |
| -// crypto.keys |
72 |
| -// etc. |
73 |
| -// |
74 |
| -// See full API details below... |
75 |
| -``` |
76 |
| - |
77 |
| -### Web Crypto API |
78 |
| - |
79 |
| -The `libp2p-crypto` library depends on the [Web Crypto API](https://developer.mozilla.org/en-US/docs/Web/API/Web_Crypto_API) in the browser. Web Crypto is available in all modern browsers, however browsers restrict its usage to [Secure Contexts](https://developer.mozilla.org/en-US/docs/Web/Security/Secure_Contexts). |
80 |
| - |
81 |
| -**This means you will not be able to use some `libp2p-crypto` functions in the browser when the page is served over HTTP.** To enable the Web Crypto API and allow `libp2p-crypto` to work fully, please serve your page over HTTPS. |
82 |
| - |
83 |
| -## API |
84 |
| - |
85 |
| -### `crypto.aes` |
86 |
| - |
87 |
| -Exposes an interface to AES encryption (formerly Rijndael), as defined in U.S. Federal Information Processing Standards Publication 197. |
88 |
| - |
89 |
| -This uses `CTR` mode. |
90 |
| - |
91 |
| -#### `crypto.aes.create(key, iv)` |
92 |
| - |
93 |
| -- `key: Uint8Array` The key, if length `16` then `AES 128` is used. For length `32`, `AES 256` is used. |
94 |
| -- `iv: Uint8Array` Must have length `16`. |
95 |
| - |
96 |
| -Returns `Promise<{decrypt<Function>, encrypt<Function>}>` |
97 |
| - |
98 |
| -##### `decrypt(data)` |
99 |
| - |
100 |
| -- `data: Uint8Array` |
101 |
| - |
102 |
| -Returns `Promise<Uint8Array>` |
103 |
| - |
104 |
| -##### `encrypt(data)` |
105 |
| - |
106 |
| -- `data: Uint8Array` |
107 |
| - |
108 |
| -Returns `Promise<Uint8Array>` |
109 |
| - |
110 |
| -```js |
111 |
| -const crypto = require('libp2p-crypto') |
112 |
| - |
113 |
| -// Setting up Key and IV |
114 |
| - |
115 |
| -// A 16 bytes array, 128 Bits, AES-128 is chosen |
116 |
| -const key128 = Uint8Array.from([0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15]) |
117 |
| - |
118 |
| -// A 16 bytes array, 128 Bits, |
119 |
| -const IV = Uint8Array.from([0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15]) |
120 |
| - |
121 |
| -async function main () { |
122 |
| - const decryptedMessage = 'Hello, world!' |
123 |
| - |
124 |
| - // Encrypting |
125 |
| - const cipher = await crypto.aes.create(key128, IV) |
126 |
| - const encryptedBuffer = await cipher.encrypt(Uint8Array.from(decryptedMessage)) |
127 |
| - console.log(encryptedBuffer) |
128 |
| - // prints: <Uint8Array 42 f1 67 d9 2e 42 d0 32 9e b1 f8 3c> |
129 |
| - |
130 |
| - // Decrypting |
131 |
| - const decipher = await crypto.aes.create(key128, IV) |
132 |
| - const decryptedBuffer = await cipher.decrypt(encryptedBuffer) |
133 |
| - |
134 |
| - console.log(decryptedBuffer) |
135 |
| - // prints: <Uint8Array 42 f1 67 d9 2e 42 d0 32 9e b1 f8 3c> |
136 |
| - |
137 |
| - console.log(decryptedBuffer.toString('utf-8')) |
138 |
| - // prints: Hello, world! |
139 |
| -} |
140 |
| - |
141 |
| -main() |
142 |
| -``` |
143 |
| - |
144 |
| -### `crypto.hmac` |
145 |
| - |
146 |
| -Exposes an interface to the Keyed-Hash Message Authentication Code (HMAC) as defined in U.S. Federal Information Processing Standards Publication 198. An HMAC is a cryptographic hash that uses a key to sign a message. The receiver verifies the hash by recomputing it using the same key. |
147 |
| - |
148 |
| -#### `crypto.hmac.create(hash, secret)` |
149 |
| - |
150 |
| -- `hash: String` |
151 |
| -- `secret: Uint8Array` |
152 |
| - |
153 |
| -Returns `Promise<{digest<Function>}>` |
154 |
| - |
155 |
| -##### `digest(data)` |
156 |
| - |
157 |
| -- `data: Uint8Array` |
158 |
| - |
159 |
| -Returns `Promise<Uint8Array>` |
160 |
| - |
161 |
| -Example: |
162 |
| - |
163 |
| -```js |
164 |
| -const crypto = require('libp2p-crypto') |
165 |
| - |
166 |
| -async function main () { |
167 |
| - const hash = 'SHA1' // 'SHA256' || 'SHA512' |
168 |
| - const hmac = await crypto.hmac.create(hash, uint8ArrayFromString('secret')) |
169 |
| - const sig = await hmac.digest(uint8ArrayFromString('hello world')) |
170 |
| - console.log(sig) |
171 |
| -} |
172 |
| - |
173 |
| -main() |
174 |
| -``` |
175 |
| - |
176 |
| -### `crypto.keys` |
177 |
| - |
178 |
| -**Supported Key Types** |
179 |
| - |
180 |
| -The [`generateKeyPair`](#generatekeypairtype-bits), [`marshalPublicKey`](#marshalpublickeykey-type), and [`marshalPrivateKey`](#marshalprivatekeykey-type) functions accept a string `type` argument. |
181 |
| - |
182 |
| -Currently the `'RSA'`, `'ed25519'`, and `secp256k1` types are supported, although ed25519 and secp256k1 keys support only signing and verification of messages. For encryption / decryption support, RSA keys should be used. |
183 |
| - |
184 |
| -### `crypto.keys.generateKeyPair(type, bits)` |
185 |
| - |
186 |
| -- `type: String`, see [Supported Key Types](#supported-key-types) above. |
187 |
| -- `bits: Number` Minimum of 1024 |
188 |
| - |
189 |
| -Returns `Promise<{privateKey<Uint8Array>, publicKey<Uint8Array>}>` |
190 |
| - |
191 |
| -Generates a keypair of the given type and bitsize. |
192 |
| - |
193 |
| -### `crypto.keys.generateEphemeralKeyPair(curve)` |
194 |
| - |
195 |
| -- `curve: String`, one of `'P-256'`, `'P-384'`, `'P-521'` is currently supported |
196 |
| - |
197 |
| -Returns `Promise` |
198 |
| - |
199 |
| -Generates an ephemeral public key and returns a function that will compute the shared secret key. |
200 |
| - |
201 |
| -Focuses only on ECDH now, but can be made more general in the future. |
202 |
| - |
203 |
| -Resolves to an object of the form: |
204 |
| - |
205 |
| -```js |
206 |
| -{ |
207 |
| - key: Uint8Array, |
208 |
| - genSharedKey: Function |
209 |
| -} |
210 |
| -``` |
211 |
| - |
212 |
| -### `crypto.keys.keyStretcher(cipherType, hashType, secret)` |
213 |
| - |
214 |
| -- `cipherType: String`, one of `'AES-128'`, `'AES-256'`, `'Blowfish'` |
215 |
| -- `hashType: String`, one of `'SHA1'`, `SHA256`, `SHA512` |
216 |
| -- `secret: Uint8Array` |
217 |
| - |
218 |
| -Returns `Promise` |
219 |
| - |
220 |
| -Generates a set of keys for each party by stretching the shared key. |
221 |
| - |
222 |
| -Resolves to an object of the form: |
223 |
| - |
224 |
| -```js |
225 |
| -{ |
226 |
| - k1: { |
227 |
| - iv: Uint8Array, |
228 |
| - cipherKey: Uint8Array, |
229 |
| - macKey: Uint8Array |
230 |
| - }, |
231 |
| - k2: { |
232 |
| - iv: Uint8Array, |
233 |
| - cipherKey: Uint8Array, |
234 |
| - macKey: Uint8Array |
235 |
| - } |
236 |
| -} |
237 |
| -``` |
238 |
| - |
239 |
| -### `crypto.keys.marshalPublicKey(key, [type])` |
240 |
| - |
241 |
| -- `key: keys.rsa.RsaPublicKey | keys.ed25519.Ed25519PublicKey | keys.secp256k1.Secp256k1PublicKey` |
242 |
| -- `type: String`, see [Supported Key Types](#supported-key-types) above. Defaults to 'rsa'. |
243 |
| - |
244 |
| -Returns `Uint8Array` |
245 |
| - |
246 |
| -Converts a public key object into a protobuf serialized public key. |
247 |
| - |
248 |
| -### `crypto.keys.unmarshalPublicKey(buf)` |
249 |
| - |
250 |
| -- `buf: Uint8Array` |
251 |
| - |
252 |
| -Returns `RsaPublicKey|Ed25519PublicKey|Secp256k1PublicKey` |
253 |
| - |
254 |
| -Converts a protobuf serialized public key into its representative object. |
255 |
| - |
256 |
| -### `crypto.keys.marshalPrivateKey(key, [type])` |
257 |
| - |
258 |
| -- `key: keys.rsa.RsaPrivateKey | keys.ed25519.Ed25519PrivateKey | keys.secp256k1.Secp256k1PrivateKey` |
259 |
| -- `type: String`, see [Supported Key Types](#supported-key-types) above. |
260 |
| - |
261 |
| -Returns `Uint8Array` |
262 |
| - |
263 |
| -Converts a private key object into a protobuf serialized private key. |
264 |
| - |
265 |
| -### `crypto.keys.unmarshalPrivateKey(buf)` |
266 |
| - |
267 |
| -- `buf: Uint8Array` |
268 |
| - |
269 |
| -Returns `Promise<RsaPrivateKey|Ed25519PrivateKey|Secp256k1PrivateKey>` |
270 |
| - |
271 |
| -Converts a protobuf serialized private key into its representative object. |
272 |
| - |
273 |
| -### `crypto.keys.import(encryptedKey, password)` |
274 |
| - |
275 |
| -- `encryptedKey: string` |
276 |
| -- `password: string` |
277 |
| - |
278 |
| -Returns `Promise<PrivateKey>` |
279 |
| - |
280 |
| -Converts an exported private key into its representative object. Supported formats are 'pem' (RSA only) and 'libp2p-key'. |
281 |
| - |
282 |
| -### `privateKey.export(password, format)` |
283 |
| - |
284 |
| -- `password: string` |
285 |
| -- `format: string` the format to export to: 'pem' (rsa only), 'libp2p-key' |
286 |
| - |
287 |
| -Returns `string` |
288 |
| - |
289 |
| -Exports the password protected `PrivateKey`. RSA keys will be exported as password protected PEM by default. Ed25519 and Secp256k1 keys will be exported as password protected AES-GCM base64 encoded strings ('libp2p-key' format). |
290 |
| - |
291 |
| -### `crypto.randomBytes(number)` |
292 |
| - |
293 |
| -- `number: Number` |
294 |
| - |
295 |
| -Returns `Uint8Array` |
296 |
| - |
297 |
| -Generates a Uint8Array with length `number` populated by random bytes. |
298 |
| - |
299 |
| -### `crypto.pbkdf2(password, salt, iterations, keySize, hash)` |
300 |
| - |
301 |
| -- `password: String` |
302 |
| -- `salt: String` |
303 |
| -- `iterations: Number` |
304 |
| -- `keySize: Number` in bytes |
305 |
| -- `hash: String` the hashing algorithm ('sha1', 'sha2-512', ...) |
306 |
| - |
307 |
| -Computes the Password Based Key Derivation Function 2; returning a new password. |
308 |
| - |
309 |
| -## Contribute |
| 22 | +# Contribute |
310 | 23 |
|
311 | 24 | Feel free to join in. All welcome. Open an [issue](https://github.com/libp2p/js-libp2p-crypto/issues)!
|
312 | 25 |
|
313 | 26 | This repository falls under the IPFS [Code of Conduct](https://github.com/ipfs/community/blob/master/code-of-conduct.md).
|
314 | 27 |
|
315 | 28 | [](https://github.com/ipfs/community/blob/master/contributing.md)
|
316 | 29 |
|
317 |
| -## API Docs |
| 30 | +# API Docs |
318 | 31 |
|
319 | 32 | - <https://libp2p.github.io/js-libp2p/modules/_libp2p_crypto.html>
|
320 | 33 |
|
321 |
| -## License |
| 34 | +# License |
322 | 35 |
|
323 | 36 | Licensed under either of
|
324 | 37 |
|
325 | 38 | - Apache 2.0, ([LICENSE-APACHE](LICENSE-APACHE) / <http://www.apache.org/licenses/LICENSE-2.0>)
|
326 | 39 | - MIT ([LICENSE-MIT](LICENSE-MIT) / <http://opensource.org/licenses/MIT>)
|
327 | 40 |
|
328 |
| -## Contribution |
| 41 | +# Contribution |
329 | 42 |
|
330 | 43 | 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.
|
0 commit comments