README.md (14363B)
1 TweetNaCl.js 2 ============ 3 4 Port of [TweetNaCl](http://tweetnacl.cr.yp.to) / [NaCl](http://nacl.cr.yp.to/) 5 to JavaScript for modern browsers and Node.js. Public domain. 6 7 [![Build Status](https://travis-ci.org/dchest/tweetnacl-js.svg?branch=master) 8 ](https://travis-ci.org/dchest/tweetnacl-js) 9 10 Demo: <https://dchest.github.io/tweetnacl-js/> 11 12 Documentation 13 ============= 14 15 * [Overview](#overview) 16 * [Audits](#audits) 17 * [Installation](#installation) 18 * [Examples](#examples) 19 * [Usage](#usage) 20 * [Public-key authenticated encryption (box)](#public-key-authenticated-encryption-box) 21 * [Secret-key authenticated encryption (secretbox)](#secret-key-authenticated-encryption-secretbox) 22 * [Scalar multiplication](#scalar-multiplication) 23 * [Signatures](#signatures) 24 * [Hashing](#hashing) 25 * [Random bytes generation](#random-bytes-generation) 26 * [Constant-time comparison](#constant-time-comparison) 27 * [System requirements](#system-requirements) 28 * [Development and testing](#development-and-testing) 29 * [Benchmarks](#benchmarks) 30 * [Contributors](#contributors) 31 * [Who uses it](#who-uses-it) 32 33 34 Overview 35 -------- 36 37 The primary goal of this project is to produce a translation of TweetNaCl to 38 JavaScript which is as close as possible to the original C implementation, plus 39 a thin layer of idiomatic high-level API on top of it. 40 41 There are two versions, you can use either of them: 42 43 * `nacl.js` is the port of TweetNaCl with minimum differences from the 44 original + high-level API. 45 46 * `nacl-fast.js` is like `nacl.js`, but with some functions replaced with 47 faster versions. (Used by default when importing NPM package.) 48 49 50 Audits 51 ------ 52 53 TweetNaCl.js has been audited by [Cure53](https://cure53.de/) in January-February 54 2017 (audit was sponsored by [Deletype](https://deletype.com)): 55 56 > The overall outcome of this audit signals a particularly positive assessment 57 > for TweetNaCl-js, as the testing team was unable to find any security 58 > problems in the library. It has to be noted that this is an exceptionally 59 > rare result of a source code audit for any project and must be seen as a true 60 > testament to a development proceeding with security at its core. 61 > 62 > To reiterate, the TweetNaCl-js project, the source code was found to be 63 > bug-free at this point. 64 > 65 > [...] 66 > 67 > In sum, the testing team is happy to recommend the TweetNaCl-js project as 68 > likely one of the safer and more secure cryptographic tools among its 69 > competition. 70 71 [Read full audit report](https://cure53.de/tweetnacl.pdf) 72 73 74 Installation 75 ------------ 76 77 You can install TweetNaCl.js via a package manager: 78 79 [Yarn](https://yarnpkg.com/): 80 81 $ yarn add tweetnacl 82 83 [NPM](https://www.npmjs.org/): 84 85 $ npm install tweetnacl 86 87 or [download source code](https://github.com/dchest/tweetnacl-js/releases). 88 89 90 Examples 91 -------- 92 You can find usage examples in our [wiki](https://github.com/dchest/tweetnacl-js/wiki/Examples). 93 94 95 Usage 96 ----- 97 98 All API functions accept and return bytes as `Uint8Array`s. If you need to 99 encode or decode strings, use functions from 100 <https://github.com/dchest/tweetnacl-util-js> or one of the more robust codec 101 packages. 102 103 In Node.js v4 and later `Buffer` objects are backed by `Uint8Array`s, so you 104 can freely pass them to TweetNaCl.js functions as arguments. The returned 105 objects are still `Uint8Array`s, so if you need `Buffer`s, you'll have to 106 convert them manually; make sure to convert using copying: `Buffer.from(array)` 107 (or `new Buffer(array)` in Node.js v4 or earlier), instead of sharing: 108 `Buffer.from(array.buffer)` (or `new Buffer(array.buffer)` Node 4 or earlier), 109 because some functions return subarrays of their buffers. 110 111 112 ### Public-key authenticated encryption (box) 113 114 Implements *x25519-xsalsa20-poly1305*. 115 116 #### nacl.box.keyPair() 117 118 Generates a new random key pair for box and returns it as an object with 119 `publicKey` and `secretKey` members: 120 121 { 122 publicKey: ..., // Uint8Array with 32-byte public key 123 secretKey: ... // Uint8Array with 32-byte secret key 124 } 125 126 127 #### nacl.box.keyPair.fromSecretKey(secretKey) 128 129 Returns a key pair for box with public key corresponding to the given secret 130 key. 131 132 #### nacl.box(message, nonce, theirPublicKey, mySecretKey) 133 134 Encrypts and authenticates message using peer's public key, our secret key, and 135 the given nonce, which must be unique for each distinct message for a key pair. 136 137 Returns an encrypted and authenticated message, which is 138 `nacl.box.overheadLength` longer than the original message. 139 140 #### nacl.box.open(box, nonce, theirPublicKey, mySecretKey) 141 142 Authenticates and decrypts the given box with peer's public key, our secret 143 key, and the given nonce. 144 145 Returns the original message, or `null` if authentication fails. 146 147 #### nacl.box.before(theirPublicKey, mySecretKey) 148 149 Returns a precomputed shared key which can be used in `nacl.box.after` and 150 `nacl.box.open.after`. 151 152 #### nacl.box.after(message, nonce, sharedKey) 153 154 Same as `nacl.box`, but uses a shared key precomputed with `nacl.box.before`. 155 156 #### nacl.box.open.after(box, nonce, sharedKey) 157 158 Same as `nacl.box.open`, but uses a shared key precomputed with `nacl.box.before`. 159 160 #### Constants 161 162 ##### nacl.box.publicKeyLength = 32 163 164 Length of public key in bytes. 165 166 ##### nacl.box.secretKeyLength = 32 167 168 Length of secret key in bytes. 169 170 ##### nacl.box.sharedKeyLength = 32 171 172 Length of precomputed shared key in bytes. 173 174 ##### nacl.box.nonceLength = 24 175 176 Length of nonce in bytes. 177 178 ##### nacl.box.overheadLength = 16 179 180 Length of overhead added to box compared to original message. 181 182 183 ### Secret-key authenticated encryption (secretbox) 184 185 Implements *xsalsa20-poly1305*. 186 187 #### nacl.secretbox(message, nonce, key) 188 189 Encrypts and authenticates message using the key and the nonce. The nonce must 190 be unique for each distinct message for this key. 191 192 Returns an encrypted and authenticated message, which is 193 `nacl.secretbox.overheadLength` longer than the original message. 194 195 #### nacl.secretbox.open(box, nonce, key) 196 197 Authenticates and decrypts the given secret box using the key and the nonce. 198 199 Returns the original message, or `null` if authentication fails. 200 201 #### Constants 202 203 ##### nacl.secretbox.keyLength = 32 204 205 Length of key in bytes. 206 207 ##### nacl.secretbox.nonceLength = 24 208 209 Length of nonce in bytes. 210 211 ##### nacl.secretbox.overheadLength = 16 212 213 Length of overhead added to secret box compared to original message. 214 215 216 ### Scalar multiplication 217 218 Implements *x25519*. 219 220 #### nacl.scalarMult(n, p) 221 222 Multiplies an integer `n` by a group element `p` and returns the resulting 223 group element. 224 225 #### nacl.scalarMult.base(n) 226 227 Multiplies an integer `n` by a standard group element and returns the resulting 228 group element. 229 230 #### Constants 231 232 ##### nacl.scalarMult.scalarLength = 32 233 234 Length of scalar in bytes. 235 236 ##### nacl.scalarMult.groupElementLength = 32 237 238 Length of group element in bytes. 239 240 241 ### Signatures 242 243 Implements [ed25519](http://ed25519.cr.yp.to). 244 245 #### nacl.sign.keyPair() 246 247 Generates new random key pair for signing and returns it as an object with 248 `publicKey` and `secretKey` members: 249 250 { 251 publicKey: ..., // Uint8Array with 32-byte public key 252 secretKey: ... // Uint8Array with 64-byte secret key 253 } 254 255 #### nacl.sign.keyPair.fromSecretKey(secretKey) 256 257 Returns a signing key pair with public key corresponding to the given 258 64-byte secret key. The secret key must have been generated by 259 `nacl.sign.keyPair` or `nacl.sign.keyPair.fromSeed`. 260 261 #### nacl.sign.keyPair.fromSeed(seed) 262 263 Returns a new signing key pair generated deterministically from a 32-byte seed. 264 The seed must contain enough entropy to be secure. This method is not 265 recommended for general use: instead, use `nacl.sign.keyPair` to generate a new 266 key pair from a random seed. 267 268 #### nacl.sign(message, secretKey) 269 270 Signs the message using the secret key and returns a signed message. 271 272 #### nacl.sign.open(signedMessage, publicKey) 273 274 Verifies the signed message and returns the message without signature. 275 276 Returns `null` if verification failed. 277 278 #### nacl.sign.detached(message, secretKey) 279 280 Signs the message using the secret key and returns a signature. 281 282 #### nacl.sign.detached.verify(message, signature, publicKey) 283 284 Verifies the signature for the message and returns `true` if verification 285 succeeded or `false` if it failed. 286 287 #### Constants 288 289 ##### nacl.sign.publicKeyLength = 32 290 291 Length of signing public key in bytes. 292 293 ##### nacl.sign.secretKeyLength = 64 294 295 Length of signing secret key in bytes. 296 297 ##### nacl.sign.seedLength = 32 298 299 Length of seed for `nacl.sign.keyPair.fromSeed` in bytes. 300 301 ##### nacl.sign.signatureLength = 64 302 303 Length of signature in bytes. 304 305 306 ### Hashing 307 308 Implements *SHA-512*. 309 310 #### nacl.hash(message) 311 312 Returns SHA-512 hash of the message. 313 314 #### Constants 315 316 ##### nacl.hash.hashLength = 64 317 318 Length of hash in bytes. 319 320 321 ### Random bytes generation 322 323 #### nacl.randomBytes(length) 324 325 Returns a `Uint8Array` of the given length containing random bytes of 326 cryptographic quality. 327 328 **Implementation note** 329 330 TweetNaCl.js uses the following methods to generate random bytes, 331 depending on the platform it runs on: 332 333 * `window.crypto.getRandomValues` (WebCrypto standard) 334 * `window.msCrypto.getRandomValues` (Internet Explorer 11) 335 * `crypto.randomBytes` (Node.js) 336 337 If the platform doesn't provide a suitable PRNG, the following functions, 338 which require random numbers, will throw exception: 339 340 * `nacl.randomBytes` 341 * `nacl.box.keyPair` 342 * `nacl.sign.keyPair` 343 344 Other functions are deterministic and will continue working. 345 346 If a platform you are targeting doesn't implement secure random number 347 generator, but you somehow have a cryptographically-strong source of entropy 348 (not `Math.random`!), and you know what you are doing, you can plug it into 349 TweetNaCl.js like this: 350 351 nacl.setPRNG(function(x, n) { 352 // ... copy n random bytes into x ... 353 }); 354 355 Note that `nacl.setPRNG` *completely replaces* internal random byte generator 356 with the one provided. 357 358 359 ### Constant-time comparison 360 361 #### nacl.verify(x, y) 362 363 Compares `x` and `y` in constant time and returns `true` if their lengths are 364 non-zero and equal, and their contents are equal. 365 366 Returns `false` if either of the arguments has zero length, or arguments have 367 different lengths, or their contents differ. 368 369 370 System requirements 371 ------------------- 372 373 TweetNaCl.js supports modern browsers that have a cryptographically secure 374 pseudorandom number generator and typed arrays, including the latest versions 375 of: 376 377 * Chrome 378 * Firefox 379 * Safari (Mac, iOS) 380 * Internet Explorer 11 381 382 Other systems: 383 384 * Node.js 385 386 387 Development and testing 388 ------------------------ 389 390 Install NPM modules needed for development: 391 392 $ npm install 393 394 To build minified versions: 395 396 $ npm run build 397 398 Tests use minified version, so make sure to rebuild it every time you change 399 `nacl.js` or `nacl-fast.js`. 400 401 ### Testing 402 403 To run tests in Node.js: 404 405 $ npm run test-node 406 407 By default all tests described here work on `nacl.min.js`. To test other 408 versions, set environment variable `NACL_SRC` to the file name you want to test. 409 For example, the following command will test fast minified version: 410 411 $ NACL_SRC=nacl-fast.min.js npm run test-node 412 413 To run full suite of tests in Node.js, including comparing outputs of 414 JavaScript port to outputs of the original C version: 415 416 $ npm run test-node-all 417 418 To prepare tests for browsers: 419 420 $ npm run build-test-browser 421 422 and then open `test/browser/test.html` (or `test/browser/test-fast.html`) to 423 run them. 424 425 To run tests in both Node and Electron: 426 427 $ npm test 428 429 ### Benchmarking 430 431 To run benchmarks in Node.js: 432 433 $ npm run bench 434 $ NACL_SRC=nacl-fast.min.js npm run bench 435 436 To run benchmarks in a browser, open `test/benchmark/bench.html` (or 437 `test/benchmark/bench-fast.html`). 438 439 440 Benchmarks 441 ---------- 442 443 For reference, here are benchmarks from MacBook Pro (Retina, 13-inch, Mid 2014) 444 laptop with 2.6 GHz Intel Core i5 CPU (Intel) in Chrome 53/OS X and Xiaomi Redmi 445 Note 3 smartphone with 1.8 GHz Qualcomm Snapdragon 650 64-bit CPU (ARM) in 446 Chrome 52/Android: 447 448 | | nacl.js Intel | nacl-fast.js Intel | nacl.js ARM | nacl-fast.js ARM | 449 | ------------- |:-------------:|:-------------------:|:-------------:|:-----------------:| 450 | salsa20 | 1.3 MB/s | 128 MB/s | 0.4 MB/s | 43 MB/s | 451 | poly1305 | 13 MB/s | 171 MB/s | 4 MB/s | 52 MB/s | 452 | hash | 4 MB/s | 34 MB/s | 0.9 MB/s | 12 MB/s | 453 | secretbox 1K | 1113 op/s | 57583 op/s | 334 op/s | 14227 op/s | 454 | box 1K | 145 op/s | 718 op/s | 37 op/s | 368 op/s | 455 | scalarMult | 171 op/s | 733 op/s | 56 op/s | 380 op/s | 456 | sign | 77 op/s | 200 op/s | 20 op/s | 61 op/s | 457 | sign.open | 39 op/s | 102 op/s | 11 op/s | 31 op/s | 458 459 (You can run benchmarks on your devices by clicking on the links at the bottom 460 of the [home page](https://tweetnacl.js.org)). 461 462 In short, with *nacl-fast.js* and 1024-byte messages you can expect to encrypt and 463 authenticate more than 57000 messages per second on a typical laptop or more than 464 14000 messages per second on a $170 smartphone, sign about 200 and verify 100 465 messages per second on a laptop or 60 and 30 messages per second on a smartphone, 466 per CPU core (with Web Workers you can do these operations in parallel), 467 which is good enough for most applications. 468 469 470 Contributors 471 ------------ 472 473 See AUTHORS.md file. 474 475 476 Third-party libraries based on TweetNaCl.js 477 ------------------------------------------- 478 479 * [forward-secrecy](https://github.com/alax/forward-secrecy) — Axolotl ratchet implementation 480 * [nacl-stream](https://github.com/dchest/nacl-stream-js) - streaming encryption 481 * [tweetnacl-auth-js](https://github.com/dchest/tweetnacl-auth-js) — implementation of [`crypto_auth`](http://nacl.cr.yp.to/auth.html) 482 * [tweetnacl-sealed-box](https://github.com/whs/tweetnacl-sealed-box) — implementation of [`sealed boxes`](https://download.libsodium.org/doc/public-key_cryptography/sealed_boxes.html) 483 * [chloride](https://github.com/dominictarr/chloride) - unified API for various NaCl modules 484 485 486 Who uses it 487 ----------- 488 489 Some notable users of TweetNaCl.js: 490 491 * [GitHub](https://github.com) 492 * [MEGA](https://github.com/meganz/webclient) 493 * [Stellar](https://www.stellar.org/) 494 * [miniLock](https://github.com/kaepora/miniLock)