UNPKG

19.8 kBMarkdownView Raw
1# js-nacl: Pure-Javascript High-level API to Emscripten-compiled libsodium routines
2
3A high-level Javascript API wrapping an
4[Emscripten](https://github.com/kripken/emscripten)-compiled
5[libsodium](http://libsodium.org/), a cryptographic library based on
6[NaCl](http://nacl.cr.yp.to/). Includes both in-browser and node.js
7support.
8
9The paper "[The security impact of a new cryptographic
10library](http://cr.yp.to/highspeed/coolnacl-20120725.pdf)" is an
11excellent summary of the motivation behind the NaCl API and library
12design.
13
14Using this library in the browser requires support for the newish
15`window.crypto.getRandomValues` API.
16
17**WARNING**: This code will not run in Safari version 5.1.x; or, at
18least, will not run when Safari's Javascript debug mode is *disabled*.
19Symptoms include corruption during hash calculation, failures when
20unboxing, and failures when producing and verifying signatures. Safari
217.0 seems to be just fine, however. I don't know exactly at which
22version Safari started working: I don't have access to enough of a
23range of systems. The code has run fine on Chrome and Firefox across
24all the versions I've tried.
25
26## Changes
27
28Version 1.3.0: Updated from libsodium 1.0.11 to stable-2018-11-19.
29Added `crypto_box_seal` and `crypto_box_seal_open`. Switched from
30using the Emscripten SDK to using a Dockerized Emscripten to produce
31the built version of the library. Because this enables WASM by
32default, the approach to handling of `requested_total_memory` is now
33different; see below.
34
35Version 1.2.2: Updated from libsodium 1.0.10 to 1.0.11.
36
37Version 1.2.1: Repaired a mistake where I had failed to export the new
38names `crypto_sign_seed_keypair` and `crypto_box_seed_keypair`.
39
40Version 1.2.0: js-nacl is now based around libsodium rather than the
41plain NaCl tarball. Functions `crypto_sign_keypair_from_seed` and
42`crypto_box_keypair_from_seed` have been renamed to their libsodium
43names, `crypto_sign_seed_keypair` and `crypto_box_seed_keypair`
44respectively; the old names are still available as aliases, though
45**deprecated**, to be removed in a future version.
46
47Version 1.1.0: **API change.** The `nacl_factory.instantiate` function
48now expects a callback as its first argument. It calls the callback
49with the `nacl` instance containing the API functions, and returns no
50useful value.
51
52Version 0.5.0: **API change.** Instead of being provided with a module
53`nacl`, with API functions available directly, library importers are
54given `nacl_factory` with a single function `instantiate`, which
55returns a `nacl` instance containing the API functions.
56
57## NPM Package
58
59This library is [registered on
60npmjs.org](https://npmjs.org/package/js-nacl). To install it:
61
62 npm install js-nacl
63
64## Building the library
65
66The git checkout includes a pre-compiled version of the library, so
67you won't need Emscripten unless you want to change something about
68the underlying C-language library itself.
69
70Essentially, the source checkout contains everything you will need to
71use the library in both the browser and in node.js.
72
73If you do find yourself wanting to build the library, see the
74instructions in
75[BUILDING.md](https://github.com/tonyg/js-nacl/blob/master/BUILDING.md).
76
77## Using the library
78
79In the browser, include the `lib/nacl_factory.js` script:
80
81 <script src="lib/nacl_factory.js"></script>
82 ...
83 <script>
84 nacl_factory.instantiate(function (nacl) {
85 alert(nacl.to_hex(nacl.random_bytes(16)));
86 });
87 </script>
88
89In node.js, require the `lib/nacl_factory.js` module:
90
91 var nacl_factory = require("./lib/nacl_factory.js");
92 nacl_factory.instantiate(function (nacl) {
93 ...
94 console.log(nacl.to_hex(nacl.random_bytes(16)));
95 });
96
97Or if you have installed the library via `npm`,
98
99 var nacl_factory = require("js-nacl");
100 nacl_factory.instantiate(function (nacl) {
101 ...
102 console.log(nacl.to_hex(nacl.random_bytes(16)));
103 });
104
105In addition, since version 1.3.0, the `instantiate` function returns a
106`Promise` that yields the `nacl` object.
107
108## Instantiating the NaCl module
109
110Pass `nacl_factory.instantiate` a callback function expecting a single
111argument, the `nacl` module instance.
112
113The `nacl_factory.instantiate` function expects also a second optional
114argument, a dictionary of optional configuration values.
115
116Each call to `nacl_factory.instantiate()` creates an entirely fresh
117module instance, complete with its own private heap area. **Since
118v1.3.0:** The heap should automatically grow as required, and should
119no longer require manual ahead-of-time configuration.
120
121It's fine to instantiate the module more than once in a single
122program, though beware of the large amount of memory potentially taken
123up by each instance. The memory assigned to each module instance will
124not be released until the instance is garbage collected.
125
126If you notice memory leaks across multiple uses of a *single* module
127instance, please report them, with a test case if at all possible.
128
129## Strings vs. Binary Data
130
131The library enforces a strict distinction between strings and binary
132data. Binary data is represented using instances of
133[`Uint8Array`](https://developer.mozilla.org/en-US/docs/JavaScript/Typed_arrays/Uint8Array).
134
135### nacl.to_hex(Uint8Array) → String
136
137Returns a lower-case hexadecimal representation of the given binary
138data.
139
140### nacl.from_hex(String) → Uint8Array
141
142Converts a lower- or upper-case hexadecimal representation of binary
143data into the equivalent Uint8Array.
144
145### nacl.encode_utf8(String) → Uint8Array
146
147Returns the binary equivalent of the argument, encoded using UTF-8.
148
149### nacl.encode_latin1(String) → Uint8Array
150
151Returns the binary equivalent of the argument, encoded using Latin1
152(an 8-bit clean encoding). If any of the character codes in the
153argument string are greater than 255, an exception is thrown.
154
155### nacl.decode_utf8(Uint8Array) → String
156
157Decodes the binary data in the argument using the UTF-8 encoding,
158producing the corresponding string.
159
160### nacl.decode_latin1(Uint8Array) → String
161
162Decodes the binary data in the argument using the Latin1 8-bit clean
163encoding, producing the corresponding string.
164
165## Hashing: crypto_hash
166
167Follows the [NaCl crypto_hash API](http://nacl.cr.yp.to/hash.html).
168
169### nacl.crypto\_hash(Uint8Array) → Uint8Array
170
171Computes the SHA-512 hash of its argument.
172
173While SHA-512 is recommended, the SHA-256 function is also available,
174as `nacl.crypto\_hash\_sha256`.
175
176### nacl.crypto\_hash\_string(String) → Uint8Array
177
178Encodes its argument using `nacl.encode_utf8`, and then calls
179`crypto_hash`.
180
181## Public-key authenticated encryption: crypto_box
182
183Follows the [NaCl crypto_box API](http://nacl.cr.yp.to/box.html).
184
185You do not need to perform any padding of any arguments to these
186functions; the API given here is most similar to the "C++" API in the
187NaCl documentation.
188
189**Make sure to follow the instructions regarding nonce selection given
190in the "Security model" section of the NaCl API documentation!**
191
192 senderKeypair = nacl.crypto_box_keypair();
193 recipientKeypair = nacl.crypto_box_keypair();
194 message = nacl.encode_utf8("Hello!");
195
196 nonce = nacl.crypto_box_random_nonce();
197 packet = nacl.crypto_box(message, nonce, recipientKeypair.boxPk, senderKeypair.boxSk);
198
199 decoded = nacl.crypto_box_open(packet, nonce, senderKeypair.boxPk, recipientKeypair.boxSk);
200
201 "Hello!" === nacl.decode_utf8(decoded); // always true
202
203### nacl.crypto\_box\_keypair() → {"boxPk": Uint8Array, "boxSk": Uint8Array}
204
205Creates a fresh random keypair. `boxPk` is the public key and `boxSk`
206is the secret key.
207
208### nacl.crypto\_box\_random\_nonce() → Uint8Array
209
210Returns a fresh randomly-chosen nonce suitable for use with
211`crypto_box`.
212
213### nacl.crypto\_box(msgBin, nonceBin, recipientPublicKeyBin, senderSecretKeyBin) → Uint8Array
214
215Places `msg` in an authenticated, encrypted box that can only be
216verified and decrypted by the secret key corresponding to
217`recipientPublicKey`.
218
219### nacl.crypto\_box\_open(ciphertextBin, nonceBin, senderPublicKeyBin, recipientSecretKeyBin) → Uint8Array
220
221Verifies and decrypts a box from `crypto_box`. Throws an exception if
222the verification fails or any of the inputs are invalid.
223
224### nacl.crypto\_box\_precompute(publicKeyBin, secretKeyBin) → {"boxK": Uint8Array}
225
226Precomputes a shared secret between two parties. See the documentation
227for `crypto_box_beforenm` at the NaCl website.
228
229### nacl.crypto\_box\_precomputed(msgBin, nonceBin, {"boxK": Uint8Array}) → Uint8Array<br>nacl.crypto\_box\_open\_precomputed(ciphertextBin, nonceBin, {"boxK": Uint8Array}) → Uint8Array
230
231Precomputed-secret variants of `crypto_box` and `crypto_box_open`.
232
233## Secret-key authenticated encryption: crypto_secretbox
234
235Follows the [NaCl crypto_secretbox API](http://nacl.cr.yp.to/secretbox.html).
236
237You do not need to perform any padding of any arguments to these
238functions; the API given here is most similar to the "C++" API in the
239NaCl documentation.
240
241**Make sure to follow the instructions regarding nonce selection given
242in the "Security model" section of the NaCl API documentation!**
243
244 k = ...;
245 m = nacl.encode_utf8("message");
246 n = nacl.crypto_secretbox_random_nonce();
247 c = nacl.crypto_secretbox(m, n, k);
248 m1 = nacl.crypto_secretbox_open(c, n, k);
249 "message" === nacl.decode_utf8(m1); // always true
250
251### nacl.crypto\_secretbox\_random\_nonce() → Uint8Array
252
253Returns a fresh randomly-chosen nonce suitable for use with
254`crypto_secretbox`.
255
256### nacl.crypto\_secretbox(msgBin, nonceBin, keyBin) → Uint8Array
257
258Places `msg` in an authenticated, encrypted box that can only be
259verified and decrypted by someone who knows `keyBin`. The `keyBin`
260Uint8Array must be `nacl.crypto_secretbox_KEYBYTES` bytes long.
261
262### nacl.crypto\_secretbox\_open(ciphertextBin, nonceBin, keyBin) → Uint8Array
263
264Verifies and decrypts a packet from `crypto_secretbox`. Throws an
265exception if the verification fails or any of the inputs are invalid.
266
267## Anonymous authenticated encryption: crypto_box_seal
268
269Uses a freshly-created ephemeral box keypair to send an "anonymous"
270message to a specific recipient, who is identified by their public box
271key, and who may decrypt the message using the matching box keypair.
272
273### nacl.crypto\_box\_seal(msgBin, recipientPublicKeyBin) → Uint8Array
274
275Places `msgBin` in an authenticated, encrypted box that can only be
276verified and decrypted by the secret key corresponding to
277`recipientPublicKeyBin`.
278
279### nacl.crypto\_box\_seal\_open(ciphertextBin, recipientPublicKeyBin, recipientSecretKeyBin) → Uint8Array
280
281Verifies and decrypts a box from `crypto_box_seal`. Throws an
282exception if the verification fails or any of the inputs are invalid.
283Unlike `crypto_box_open`, no nonce is required, and the *recipient's*
284public key is supplied instead of the *sender's*. The sender remains
285anonymous.
286
287## Secret-key encryption: crypto_stream
288
289Follows the [NaCl crypto_stream API](http://nacl.cr.yp.to/stream.html).
290
291**Make sure to follow the instructions regarding nonce selection given
292in the "Security model" section of the NaCl API documentation!**
293
294Since this style of secret-key encryption is symmetric,
295`nacl.crypto_stream_xor` is suitable for decryption as well as
296encryption:
297
298 k = ...;
299 m = nacl.encode_utf8("message");
300 n = nacl.crypto_stream_random_nonce();
301 c = nacl.crypto_stream_xor(m, n, k);
302 m1 = nacl.crypto_stream_xor(c, n, k);
303 "message" === nacl.decode_utf8(m1); // always true
304
305### nacl.crypto\_stream\_random\_nonce() → Uint8Array
306
307Returns a fresh randomly-chosen nonce suitable for use with
308`crypto_stream`.
309
310### nacl.crypto\_stream(lenInt, nonceBin, keyBin) → Uint8Array
311
312Returns a `lenInt`-byte length keystream based on the given nonce and
313key. The key must be `nacl.crypto_stream_KEYBYTES` bytes long.
314
315### nacl.crypto\_stream\_xor(msgBin, nonceBin, keyBin) → Uint8Array
316
317Returns `msgBin.length` bytes of ciphertext (or plaintext, depending
318on the contents of `msgBin`) produced by XORing `msgBin` with the
319result of `nacl.crypto_stream(msgBin.length, nonceBin, keyBin)`.
320
321## Secret-key single-message authentication: crypto_onetimeauth
322
323Follows the [NaCl crypto_onetimeauth API](http://nacl.cr.yp.to/onetimeauth.html).
324
325## Secret-key message authentication: crypto_auth
326
327Follows the [NaCl crypto_auth API](http://nacl.cr.yp.to/auth.html).
328
329## Signatures: crypto_sign
330
331Follows the [NaCl crypto_sign API](http://nacl.cr.yp.to/sign.html).
332
333Note that this uses the version of [Ed25519](http://ed25519.cr.yp.to/)
334from [SUPERCOP](http://bench.cr.yp.to/supercop.html), and *not* the
335old prototype implementation from the nacl 20110221 release.
336
337The SUPERCOP Ed25519 signature scheme used is compatible with
338libsodium and most other bindings and wrappers of libsodium and nacl.
339
340### nacl.crypto\_sign\_keypair() → {"signPk": Uint8Array, "signSk": Uint8Array}
341
342Creates a fresh random keypair. `signPk` is the public key and
343`signSk` is the secret key.
344
345 k = nacl.crypto_sign_keypair();
346 m = nacl.encode_utf8("message");
347 signed_m = nacl.crypto_sign(m, k.signSk);
348 m1 = nacl.crypto_sign_open(signed_m, k.signPk);
349 "message" === nacl.decode_utf8(m1); // always true
350
351### nacl.crypto\_sign(msgBin, signerSecretKey) → Uint8Array
352
353Produces a signature-wrapped version of `msgBin`.
354
355### nacl.crypto\_sign\_open(packetBin, signerPublicKey) → (Uint8Array || null)
356
357Verifies the signature on the given `packetBin`, and if it is valid,
358extracts the carried message and returns it. If the signature could
359not be verified, returns `null`.
360
361### nacl.crypto\_sign\_detached(msgBin, signerSecretKey) → Uint8Array
362
363**WARNING: Experimental.** Produces a "detached" signature that,
364unlike `crypto_sign`, excludes the actual message body. The result can
365be used with `crypto_sign_verify_detached`.
366
367The returned detached signature will be `nacl.crypto_sign_BYTES` in
368length.
369
370### nacl.crypto\_sign\_verify\_detached(detachedSignatureBin, msgBin, signerPublicKey) → (true || false)
371
372**WARNING: Experimental.** Given a "detached" signature from
373`crypto_sign_detached`, along with the original message and the
374signer's public signing key, returns `true` if the signature is valid,
375and `false` otherwise.
376
377## Derived Keys
378
379**WARNING: Experimental**
380
381If you see yourself wanting to use these, you will need to know why
382[PBKDF2](http://en.wikipedia.org/wiki/PBKDF2) and
383[scrypt](http://www.tarsnap.com/scrypt.html) are of crucial
384importance.
385
386You might like to explore the use of these functions in tandem with
387`scrypt.crypto_scrypt` from
388[js-scrypt](https://github.com/tonyg/js-scrypt).
389
390It is not generally safe to supply (for example) a user's passphrase
391directly to these procedures without using PBKDF2, scrypt or something
392similar beforehand.
393
394### nacl.crypto\_sign\_seed\_keypair(Uint8Array) → {"signPk": Uint8Array, "signSk": Uint8Array}
395
396Produces a *signing* keypair from its argument. A given binary input
397will always produce the same keypair as output.
398
399The input must be 32 bytes long. As
400[Brian Warner puts it](https://blog.mozilla.org/warner/2011/11/29/ed25519-keys/),
401"Ed25519 keys start life as a 32-byte (256-bit) uniformly random
402binary seed" such as might be produced by sha256, or better yet,
403PBKDF2 or scrypt.
404
405Make sure to read and understand the warnings relating to passphrases,
406PBKDF2 and scrypt at the beginning of this section.
407
408Compatible with [PyNaCl](https://github.com/warner/pynacl)'s
409`crypto_sign_keypair_fromseed` and
410[racl](https://github.com/tonyg/racl)'s `bytes->crypto-sign-keypair`.
411
412(Prior to v1.2.0, known as `nacl.crypto_sign_keypair_from_seed`.)
413
414### nacl.crypto\_box\_seed\_keypair(Uint8Array) → {"boxPk": Uint8Array, "boxSk": Uint8Array}
415
416Produces an *encrypted authenticated box* keypair from its argument. A
417given binary input will always produce the same keypair as output.
418
419The input may be of any length. The input is hashed once with sha512,
420and the first 32 bytes of the result are taken as the 32-byte secret
421key, which is then passed to `nacl.crypto_box_keypair_from_raw_sk`.
422
423Make sure to read and understand the warnings relating to passphrases,
424PBKDF2 and scrypt at the beginning of this section.
425
426Compatible with [racl](https://github.com/tonyg/racl)'s
427`bytes->crypto-box-keypair`.
428
429(Prior to v1.2.0, known as `nacl.crypto_box_keypair_from_seed`.)
430
431### nacl.crypto\_box\_keypair\_from\_raw\_sk(Uint8Array) → {"boxPk": Uint8Array, "boxSk": Uint8Array}
432
433Produces an *encrypted authenticated box* keypair from its argument. A
434given binary input will always produce the same keypair as output.
435
436The input must be 32 bytes long, and could be a random 32-byte value,
437or the output of sha256, or better yet, the output of PBKDF2 or
438scrypt.
439
440Make sure to read and understand the warnings relating to passphrases,
441PBKDF2 and scrypt at the beginning of this section.
442
443Compatible with [racl](https://github.com/tonyg/racl)'s
444`crypto-box-sk->pk`.
445
446## Low-level tools
447
448### nacl.crypto\_scalarmult(Uint8Array, Uint8Array) → Uint8Array
449
450Expects two binaries, the first of length
451`nacl.crypto_scalarmult_SCALARBYTES` (representing an integer), and
452the second of length `nacl.crypto_scalarmult_BYTES` (representing a
453group element). The two are multiplied using the underlying NaCl
454`crypto_scalarmult` primitive, and the resulting
455`nacl.crypto_scalarmult_BYTES`-length group element binary is
456returned.
457
458### nacl.crypto\_scalarmult\_base(Uint8Array) → Uint8Array
459
460As `nacl.crypto_scalarmult`, but multiplies the
461`nacl.crypto_scalarmult_SCALARBYTES`-length argument by a standard
462group element, returning the result.
463
464## License
465
466js-nacl is written by Tony Garnock-Jones <tonygarnockjones@gmail.com>
467and is licensed under the [MIT
468license](http://opensource.org/licenses/MIT):
469
470> Copyright &copy; 2013-2016 Tony Garnock-Jones.
471>
472> Permission is hereby granted, free of charge, to any person
473> obtaining a copy of this software and associated documentation files
474> (the "Software"), to deal in the Software without restriction,
475> including without limitation the rights to use, copy, modify, merge,
476> publish, distribute, sublicense, and/or sell copies of the Software,
477> and to permit persons to whom the Software is furnished to do so,
478> subject to the following conditions:
479>
480> The above copyright notice and this permission notice shall be
481> included in all copies or substantial portions of the Software.
482>
483> THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
484> EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
485> MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
486> NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
487> BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
488> ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
489> CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
490> SOFTWARE.
491
492js-nacl relies on libsodium, which is released under the
493[ISC license](https://en.wikipedia.org/wiki/ISC_license):
494
495> Copyright (c) 2013-2016
496> Frank Denis <j at pureftpd dot org>
497>
498> Permission to use, copy, modify, and/or distribute this software for any
499> purpose with or without fee is hereby granted, provided that the above
500> copyright notice and this permission notice appear in all copies.
501>
502> THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
503> WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
504> MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
505> ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
506> WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
507> ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
508> OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
509
510libsodium in turn relies on NaCl itself, which is public domain code
511by Daniel J. Bernstein and others.