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