├── .gitignore ├── LICENSE ├── README.md ├── compare-symbols.sh ├── crypto_aead.js ├── crypto_aead_xchacha20poly1305.js ├── crypto_auth.js ├── crypto_box.js ├── crypto_generichash.js ├── crypto_kdf.js ├── crypto_kx.js ├── crypto_secretbox.js ├── crypto_secretstream.js ├── crypto_shorthash.js ├── crypto_sign.js ├── crypto_stream.js ├── documented-symbols ├── example.js ├── fixtures ├── crypto_kdf.json └── crypto_sign.json ├── index.js ├── package.json └── randombytes_buf.js /.gitignore: -------------------------------------------------------------------------------- 1 | node_modules 2 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | Copyright 2017 Mathias Buus & Emil Bay 2 | 3 | Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: 4 | 5 | The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. 6 | 7 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 8 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # sodium-test 2 | 3 | Test harness for Javascript `libsodium` implementations 4 | 5 | ```sh 6 | npm install sodium-test 7 | ``` 8 | 9 | ## Usage 10 | 11 | ```js 12 | require('sodium-test')(require('sodium-native')) 13 | 14 | ``` 15 | 16 | The above will test that `sodium-native` passes all the `sodium-test` tests and 17 | write results in TAP format to `stdio`. 18 | 19 | ## API 20 | 21 | `harness(sodiumApi)` 22 | 23 | Will run tests on `sodiumApi` and assert whether it conforms to the libsodium 24 | API. Individual subAPI's can be tested, and all follow the same pattern, eg. 25 | `require('randombytes_buf')(sodiumApi)`. 26 | 27 | Findings are written to `stdio`. 28 | 29 | ## License 30 | 31 | [MIT](LICENSE.md) 32 | -------------------------------------------------------------------------------- /compare-symbols.sh: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env bash 2 | 3 | LIB_SYMBOLS=$(cat documented-symbols | sed -e '/^\s*$/d' -e '/^#.*/d') 4 | NODE_SYMBOLS=$(node -e 'Object.keys(require("sodium-native")).forEach(d => console.log(d))') 5 | 6 | diff --side-by-side --suppress-common-lines <(echo "$LIB_SYMBOLS" | sort) <(echo "$NODE_SYMBOLS" | sort) 7 | -------------------------------------------------------------------------------- /crypto_aead.js: -------------------------------------------------------------------------------- 1 | const tape = require('tape') 2 | 3 | const m = new Uint8Array(Buffer.from("Ladies and Gentlemen of the class of '99: If I could offer you only one tip for the future, sunscreen would be it.")) 4 | 5 | const firstkey = new Uint8Array([ 6 | 0x80, 0x81, 0x82, 0x83, 0x84, 0x85, 0x86, 0x87, 7 | 0x88, 0x89, 0x8a, 0x8b, 0x8c, 0x8d, 0x8e, 0x8f, 8 | 0x90, 0x91, 0x92, 0x93, 0x94, 0x95, 0x96, 0x97, 9 | 0x98, 0x99, 0x9a, 0x9b, 0x9c, 0x9d, 0x9e, 0x9f 10 | ]) 11 | 12 | const nonce = new Uint8Array([ 13 | 0x07, 0x00, 0x00, 0x00, 0x40, 0x41, 0x42, 0x43, 14 | 0x44, 0x45, 0x46, 0x47 15 | ]) 16 | 17 | const exp = [ 18 | new Uint8Array([ 19 | 0xd3, 0x1a, 0x8d, 0x34, 0x64, 0x8e, 0x60, 0xdb, 20 | 0x7b, 0x86, 0xaf, 0xbc, 0x53, 0xef, 0x7e, 0xc2, 21 | 0xa4, 0xad, 0xed, 0x51, 0x29, 0x6e, 0x08, 0xfe, 22 | 0xa9, 0xe2, 0xb5, 0xa7, 0x36, 0xee, 0x62, 0xd6, 23 | 0x3d, 0xbe, 0xa4, 0x5e, 0x8c, 0xa9, 0x67, 0x12, 24 | 0x82, 0xfa, 0xfb, 0x69, 0xda, 0x92, 0x72, 0x8b, 25 | 0x1a, 0x71, 0xde, 0x0a, 0x9e, 0x06, 0x0b, 0x29, 26 | 0x05, 0xd6, 0xa5, 0xb6, 0x7e, 0xcd, 0x3b, 0x36, 27 | 0x92, 0xdd, 0xbd, 0x7f, 0x2d, 0x77, 0x8b, 0x8c, 28 | 0x98, 0x03, 0xae, 0xe3, 0x28, 0x09, 0x1b, 0x58, 29 | 0xfa, 0xb3, 0x24, 0xe4, 0xfa, 0xd6, 0x75, 0x94, 30 | 0x55, 0x85, 0x80, 0x8b, 0x48, 0x31, 0xd7, 0xbc, 31 | 0x3f, 0xf4, 0xde, 0xf0, 0x8e, 0x4b, 0x7a, 0x9d, 32 | 0xe5, 0x76, 0xd2, 0x65, 0x86, 0xce, 0xc6, 0x4b, 33 | 0x61, 0x16, 0x1a, 0xe1, 0x0b, 0x59, 0x4f, 0x09, 34 | 0xe2, 0x6a, 0x7e, 0x90, 0x2e, 0xcb, 0xd0, 0x60, 35 | 0x06, 0x91]), 36 | new Uint8Array([ 37 | 0xd3, 0x1a, 0x8d, 0x34, 0x64, 0x8e, 0x60, 0xdb, 38 | 0x7b, 0x86, 0xaf, 0xbc, 0x53, 0xef, 0x7e, 0xc2, 39 | 0xa4, 0xad, 0xed, 0x51, 0x29, 0x6e, 0x08, 0xfe, 40 | 0xa9, 0xe2, 0xb5, 0xa7, 0x36, 0xee, 0x62, 0xd6, 41 | 0x3d, 0xbe, 0xa4, 0x5e, 0x8c, 0xa9, 0x67, 0x12, 42 | 0x82, 0xfa, 0xfb, 0x69, 0xda, 0x92, 0x72, 0x8b, 43 | 0x1a, 0x71, 0xde, 0x0a, 0x9e, 0x06, 0x0b, 0x29, 44 | 0x05, 0xd6, 0xa5, 0xb6, 0x7e, 0xcd, 0x3b, 0x36, 45 | 0x92, 0xdd, 0xbd, 0x7f, 0x2d, 0x77, 0x8b, 0x8c, 46 | 0x98, 0x03, 0xae, 0xe3, 0x28, 0x09, 0x1b, 0x58, 47 | 0xfa, 0xb3, 0x24, 0xe4, 0xfa, 0xd6, 0x75, 0x94, 48 | 0x55, 0x85, 0x80, 0x8b, 0x48, 0x31, 0xd7, 0xbc, 49 | 0x3f, 0xf4, 0xde, 0xf0, 0x8e, 0x4b, 0x7a, 0x9d, 50 | 0xe5, 0x76, 0xd2, 0x65, 0x86, 0xce, 0xc6, 0x4b, 51 | 0x61, 0x16, 0x6a, 0x23, 0xa4, 0x68, 0x1f, 0xd5, 52 | 0x94, 0x56, 0xae, 0xa1, 0xd2, 0x9f, 0x82, 0x47, 53 | 0x72, 0x16]), 54 | new Uint8Array([ 55 | 0xd3, 0x1a, 0x8d, 0x34, 0x64, 0x8e, 0x60, 0xdb, 56 | 0x7b, 0x86, 0xaf, 0xbc, 0x53, 0xef, 0x7e, 0xc2, 57 | 0xa4, 0xad, 0xed, 0x51, 0x29, 0x6e, 0x08, 0xfe, 58 | 0xa9, 0xe2, 0xb5, 0xa7, 0x36, 0xee, 0x62, 0xd6, 59 | 0x3d, 0xbe, 0xa4, 0x5e, 0x8c, 0xa9, 0x67, 0x12, 60 | 0x82, 0xfa, 0xfb, 0x69, 0xda, 0x92, 0x72, 0x8b, 61 | 0x1a, 0x71, 0xde, 0x0a, 0x9e, 0x06, 0x0b, 0x29, 62 | 0x05, 0xd6, 0xa5, 0xb6, 0x7e, 0xcd, 0x3b, 0x36, 63 | 0x92, 0xdd, 0xbd, 0x7f, 0x2d, 0x77, 0x8b, 0x8c, 64 | 0x98, 0x03, 0xae, 0xe3, 0x28, 0x09, 0x1b, 0x58, 65 | 0xfa, 0xb3, 0x24, 0xe4, 0xfa, 0xd6, 0x75, 0x94, 66 | 0x55, 0x85, 0x80, 0x8b, 0x48, 0x31, 0xd7, 0xbc, 67 | 0x3f, 0xf4, 0xde, 0xf0, 0x8e, 0x4b, 0x7a, 0x9d, 68 | 0xe5, 0x76, 0xd2, 0x65, 0x86, 0xce, 0xc6, 0x4b, 69 | 0x61, 0x16, 0x6a, 0x23, 0xa4, 0x68, 0x1f, 0xd5, 70 | 0x94, 0x56, 0xae, 0xa1, 0xd2, 0x9f, 0x82, 0x47, 71 | 0x72, 0x16]) 72 | ] 73 | 74 | module.exports = function (sodium) { 75 | tape('crypto_aead_chacha20poly1305_ietf', function (t) { 76 | const ad = new Uint8Array([ 0x50, 0x51, 0x52, 0x53, 0xc0, 0xc1, 0xc2, 0xc3, 0xc4, 0xc5, 0xc6, 0xc7 ]) 77 | const c = new Uint8Array(m.byteLength + sodium.crypto_aead_chacha20poly1305_ietf_ABYTES) 78 | const detached_c = new Uint8Array(m.byteLength) 79 | const mac = new Uint8Array(sodium.crypto_aead_chacha20poly1305_ietf_ABYTES) 80 | const m2 = new Uint8Array(m.byteLength) 81 | let found_clen 82 | let found_maclen 83 | let m2len 84 | let i 85 | 86 | found_clen = sodium.crypto_aead_chacha20poly1305_ietf_encrypt(c, m, ad, null, nonce, firstkey) 87 | t.equal(found_clen, m.byteLength + sodium.crypto_aead_chacha20poly1305_ietf_ABYTES, 'found_clen is properly set') 88 | t.same(c, exp[0], 'ciphertext matches expected result') 89 | 90 | found_clen = sodium.crypto_aead_chacha20poly1305_ietf_encrypt_detached(detached_c, 91 | mac, 92 | m, 93 | ad, 94 | null, nonce, firstkey) 95 | 96 | t.same(detached_c, c.subarray(0, m.byteLength), 'detached ciphertext passes') 97 | t.same(mac, c.subarray(m.byteLength), 'detached mac passes') 98 | m2len = sodium.crypto_aead_chacha20poly1305_ietf_decrypt(m2, null, c, ad, nonce, firstkey) 99 | 100 | t.assert(m2len >= 0, 'sodium.crypto_aead_chacha20poly1305_ietf_decrypt() succeeded') 101 | t.equal(m2len, m.byteLength, 'm2len is properly set') 102 | t.same(m2, m, 'm == m2') 103 | m2.fill(0) 104 | 105 | t.doesNotThrow(() => sodium.crypto_aead_chacha20poly1305_ietf_decrypt_detached(m2, null, detached_c, mac, ad, nonce, firstkey), 106 | 'sodium.crypto_aead_chacha20poly1305_ietf_decrypt_detached() succeeded') 107 | 108 | t.same(m, m2, 'detached m == m2') 109 | 110 | for (i = 0; i < c.byteLength; i++) { 111 | c[i] ^= (i + 1) 112 | try { 113 | sodium.crypto_aead_chacha20poly1305_ietf_decrypt(m2, null, c, ad, nonce, firstkey) 114 | t.fail() 115 | } catch (e) { 116 | if (Buffer.compare(m, m2.subarray(0, m.byteLength)) === 0) t.fail('message can be forged') 117 | } 118 | c[i] ^= (i + 1) 119 | } 120 | 121 | found_clen = sodium.crypto_aead_chacha20poly1305_ietf_encrypt(c, m, new Uint8Array(0), null, nonce, firstkey) 122 | t.equal(found_clen, c.byteLength, 'clen is properly set (adlen=0)') 123 | t.same(c, exp[1], 'ciphertext matches expected result') 124 | 125 | m2len = sodium.crypto_aead_chacha20poly1305_ietf_decrypt(m2, null, c, new Uint8Array(0), nonce, firstkey) 126 | 127 | t.assert(m2len >= 0, 'sodium.crypto_aead_chacha20poly1305_ietf_decrypt() passed (adlen=0)') 128 | t.equal(m2len, m.byteLength, 'm2len is properly set (adlen=0)\n') 129 | 130 | t.ok(Buffer.compare(m, m2.subarray(0, m.byteLength)) === 0, 'm == m2 (adlen=0)') 131 | 132 | t.throws(() => sodium.crypto_aead_chacha20poly1305_ietf_decrypt(m2, null, new Uint8Array(0), new Uint8Array(0), nonce, firstkey), 133 | "sodium.crypto_aead_chacha20poly1305_ietf_decrypt() shouldn't work with an empty ciphertext") 134 | 135 | c.set(m) 136 | found_clen = sodium.crypto_aead_chacha20poly1305_ietf_encrypt(c, c.subarray(0, m.byteLength), new Uint8Array(0), null, nonce, firstkey) 137 | 138 | t.equal(found_clen, c.byteLength, 'clen is properly set (adlen=0)') 139 | t.same(c, exp[2], 'ciphertext matches expected result') 140 | 141 | m2len = sodium.crypto_aead_chacha20poly1305_ietf_decrypt(c.subarray(0, m.byteLength), 142 | null, c, new Uint8Array(0), nonce, firstkey) 143 | 144 | t.assert(m2len >= 0, 'sodium.crypto_aead_chacha20poly1305_ietf_decrypt() passed (adlen=0)') 145 | t.equal(m2len, m.byteLength, 'm2len is properly set (adlen=0)') 146 | 147 | t.ok(Buffer.compare(m, c.subarray(0, m.byteLength)) === 0, 'm == c (adlen=0)\n') 148 | 149 | const c2 = new Uint8Array(c) 150 | const mac2 = new Uint8Array(mac) 151 | sodium.crypto_aead_chacha20poly1305_ietf_encrypt_detached(c, mac, c, new Uint8Array(0), null, nonce, firstkey) 152 | sodium.crypto_aead_chacha20poly1305_ietf_encrypt_detached(c2, mac2, c2, null, null, nonce, firstkey) 153 | 154 | t.deepEqual(c, c2, 'null ad gives correct ciphertext') 155 | t.deepEqual(mac, mac2, 'null ad gives correct mac') 156 | 157 | sodium.crypto_aead_chacha20poly1305_ietf_decrypt_detached(c, null, c, mac, new Uint8Array(0), nonce, firstkey) 158 | sodium.crypto_aead_chacha20poly1305_ietf_decrypt_detached(c2, null, c2, mac, null, nonce, firstkey) 159 | 160 | t.deepEqual(c, c2, 'null ad gives correct plaintext') 161 | 162 | t.assert(sodium.crypto_aead_chacha20poly1305_ietf_KEYBYTES > 0) 163 | t.equal(sodium.crypto_aead_chacha20poly1305_ietf_KEYBYTES, 32) 164 | t.assert(sodium.crypto_aead_chacha20poly1305_ietf_NPUBBYTES > 0) 165 | t.equal(sodium.crypto_aead_chacha20poly1305_ietf_NSECBYTES, 0) 166 | t.equal(sodium.crypto_aead_chacha20poly1305_ietf_NPUBBYTES, 12) 167 | t.equal(sodium.crypto_aead_chacha20poly1305_ietf_MESSAGEBYTES_MAX, Number.MAX_SAFE_INTEGER) 168 | 169 | t.end() 170 | }) 171 | 172 | require('./crypto_aead_xchacha20poly1305')(sodium) 173 | } 174 | -------------------------------------------------------------------------------- /crypto_aead_xchacha20poly1305.js: -------------------------------------------------------------------------------- 1 | const tape = require('tape') 2 | 3 | const exp = [ 4 | new Uint8Array([ 5 | 0xf8, 0xeb, 0xea, 0x48, 0x75, 0x04, 0x40, 0x66, 6 | 0xfc, 0x16, 0x2a, 0x06, 0x04, 0xe1, 0x71, 0xfe, 7 | 0xec, 0xfb, 0x3d, 0x20, 0x42, 0x52, 0x48, 0x56, 8 | 0x3b, 0xcf, 0xd5, 0xa1, 0x55, 0xdc, 0xc4, 0x7b, 9 | 0xbd, 0xa7, 0x0b, 0x86, 0xe5, 0xab, 0x9b, 0x55, 10 | 0x00, 0x2b, 0xd1, 0x27, 0x4c, 0x02, 0xdb, 0x35, 11 | 0x32, 0x1a, 0xcd, 0x7a, 0xf8, 0xb2, 0xe2, 0xd2, 12 | 0x50, 0x15, 0xe1, 0x36, 0xb7, 0x67, 0x94, 0x58, 13 | 0xe9, 0xf4, 0x32, 0x43, 0xbf, 0x71, 0x9d, 0x63, 14 | 0x9b, 0xad, 0xb5, 0xfe, 0xac, 0x03, 0xf8, 0x0a, 15 | 0x19, 0xa9, 0x6e, 0xf1, 0x0c, 0xb1, 0xd1, 0x53, 16 | 0x33, 0xa8, 0x37, 0xb9, 0x09, 0x46, 0xba, 0x38, 17 | 0x54, 0xee, 0x74, 0xda, 0x3f, 0x25, 0x85, 0xef, 18 | 0xc7, 0xe1, 0xe1, 0x70, 0xe1, 0x7e, 0x15, 0xe5, 19 | 0x63, 0xe7, 0x76, 0x01, 0xf4, 0xf8, 0x5c, 0xaf, 20 | 0xa8, 0xe5, 0x87, 0x76, 0x14, 0xe1, 0x43, 0xe6, 21 | 0x84, 0x20 22 | ]), 23 | new Uint8Array([ 24 | 0xf8, 0xeb, 0xea, 0x48, 0x75, 0x04, 0x40, 0x66, 25 | 0xfc, 0x16, 0x2a, 0x06, 0x04, 0xe1, 0x71, 0xfe, 26 | 0xec, 0xfb, 0x3d, 0x20, 0x42, 0x52, 0x48, 0x56, 27 | 0x3b, 0xcf, 0xd5, 0xa1, 0x55, 0xdc, 0xc4, 0x7b, 28 | 0xbd, 0xa7, 0x0b, 0x86, 0xe5, 0xab, 0x9b, 0x55, 29 | 0x00, 0x2b, 0xd1, 0x27, 0x4c, 0x02, 0xdb, 0x35, 30 | 0x32, 0x1a, 0xcd, 0x7a, 0xf8, 0xb2, 0xe2, 0xd2, 31 | 0x50, 0x15, 0xe1, 0x36, 0xb7, 0x67, 0x94, 0x58, 32 | 0xe9, 0xf4, 0x32, 0x43, 0xbf, 0x71, 0x9d, 0x63, 33 | 0x9b, 0xad, 0xb5, 0xfe, 0xac, 0x03, 0xf8, 0x0a, 34 | 0x19, 0xa9, 0x6e, 0xf1, 0x0c, 0xb1, 0xd1, 0x53, 35 | 0x33, 0xa8, 0x37, 0xb9, 0x09, 0x46, 0xba, 0x38, 36 | 0x54, 0xee, 0x74, 0xda, 0x3f, 0x25, 0x85, 0xef, 37 | 0xc7, 0xe1, 0xe1, 0x70, 0xe1, 0x7e, 0x15, 0xe5, 38 | 0x63, 0xe7, 0xe0, 0x96, 0xe0, 0x33, 0xd9, 0x1b, 39 | 0x63, 0xf7, 0xac, 0x92, 0xe9, 0x97, 0x2e, 0x0d, 40 | 0x43, 0xe5 41 | ]), 42 | new Uint8Array([ 43 | 0xf8, 0xeb, 0xea, 0x48, 0x75, 0x04, 0x40, 0x66, 44 | 0xfc, 0x16, 0x2a, 0x06, 0x04, 0xe1, 0x71, 0xfe, 45 | 0xec, 0xfb, 0x3d, 0x20, 0x42, 0x52, 0x48, 0x56, 46 | 0x3b, 0xcf, 0xd5, 0xa1, 0x55, 0xdc, 0xc4, 0x7b, 47 | 0xbd, 0xa7, 0x0b, 0x86, 0xe5, 0xab, 0x9b, 0x55, 48 | 0x00, 0x2b, 0xd1, 0x27, 0x4c, 0x02, 0xdb, 0x35, 49 | 0x32, 0x1a, 0xcd, 0x7a, 0xf8, 0xb2, 0xe2, 0xd2, 50 | 0x50, 0x15, 0xe1, 0x36, 0xb7, 0x67, 0x94, 0x58, 51 | 0xe9, 0xf4, 0x32, 0x43, 0xbf, 0x71, 0x9d, 0x63, 52 | 0x9b, 0xad, 0xb5, 0xfe, 0xac, 0x03, 0xf8, 0x0a, 53 | 0x19, 0xa9, 0x6e, 0xf1, 0x0c, 0xb1, 0xd1, 0x53, 54 | 0x33, 0xa8, 0x37, 0xb9, 0x09, 0x46, 0xba, 0x38, 55 | 0x54, 0xee, 0x74, 0xda, 0x3f, 0x25, 0x85, 0xef, 56 | 0xc7, 0xe1, 0xe1, 0x70, 0xe1, 0x7e, 0x15, 0xe5, 57 | 0x63, 0xe7, 0xe0, 0x96, 0xe0, 0x33, 0xd9, 0x1b, 58 | 0x63, 0xf7, 0xac, 0x92, 0xe9, 0x97, 0x2e, 0x0d, 59 | 0x43, 0xe5 60 | ]) 61 | ] 62 | 63 | module.exports = crypto_aead_xchacha20poly1305_ietf 64 | 65 | function crypto_aead_xchacha20poly1305_ietf (sodium) { 66 | tape('crypto_aead_xchacha20poly1305_ietf', t => { 67 | const MLEN = 114 68 | const ADLEN = 12 69 | const CLEN = (MLEN + sodium.crypto_aead_xchacha20poly1305_ietf_ABYTES) 70 | const firstkey = new Uint8Array([ 71 | 0x80, 0x81, 0x82, 0x83, 0x84, 0x85, 0x86, 0x87, 72 | 0x88, 0x89, 0x8a, 0x8b, 0x8c, 0x8d, 0x8e, 0x8f, 73 | 0x90, 0x91, 0x92, 0x93, 0x94, 0x95, 0x96, 0x97, 74 | 0x98, 0x99, 0x9a, 0x9b, 0x9c, 0x9d, 0x9e, 0x9f 75 | ]) 76 | 77 | const MESSAGE = "Ladies and Gentlemen of the class of '99: If I could offer you only one tip for the future, sunscreen would be it." 78 | 79 | const m = new Uint8Array(MLEN); 80 | const nonce = new Uint8Array([ 81 | 0x07, 0x00, 0x00, 0x00, 0x40, 0x41, 0x42, 0x43, 0x44, 0x45, 0x46, 0x47, 82 | 0x48, 0x49, 0x4a, 0x4b, 0x4c, 0x4d, 0x4e, 0x4f, 0x50, 0x51, 0x52, 0x53 83 | ]) 84 | 85 | const ad = new Uint8Array([ 0x50, 0x51, 0x52, 0x53, 0xc0, 0xc1, 0xc2, 0xc3, 0xc4, 0xc5, 0xc6, 0xc7 ]) 86 | const c = new Uint8Array(CLEN); 87 | const detached_c = new Uint8Array(MLEN); 88 | const key2 = new Uint8Array(sodium.crypto_aead_xchacha20poly1305_ietf_KEYBYTES); 89 | const mac = new Uint8Array(sodium.crypto_aead_xchacha20poly1305_ietf_ABYTES); 90 | const m2 = new Uint8Array(MLEN); 91 | let found_clen; 92 | let found_maclen; 93 | let m2len; 94 | let i; 95 | 96 | t.assert(MESSAGE.length === MLEN) 97 | m.set([ 98 | 0x4c, 0x61, 0x64, 0x69, 0x65, 0x73, 0x20, 0x61, 0x6e, 0x64, 0x20, 0x47, 0x65, 99 | 0x6e, 0x74, 0x6c, 0x65, 0x6d, 0x65, 0x6e, 0x20, 0x6f, 0x66, 0x20, 0x74, 0x68, 100 | 0x65, 0x20, 0x63, 0x6c, 0x61, 0x73, 0x73, 0x20, 0x6f, 0x66, 0x20, 0x27, 0x39, 101 | 0x39, 0x3a, 0x20, 0x49, 0x66, 0x20, 0x49, 0x20, 0x63, 0x6f, 0x75, 0x6c, 0x64, 102 | 0x20, 0x6f, 0x66, 0x66, 0x65, 0x72, 0x20, 0x79, 0x6f, 0x75, 0x20, 0x6f, 0x6e, 103 | 0x6c, 0x79, 0x20, 0x6f, 0x6e, 0x65, 0x20, 0x74, 0x69, 0x70, 0x20, 0x66, 0x6f, 104 | 0x72, 0x20, 0x74, 0x68, 0x65, 0x20, 0x66, 0x75, 0x74, 0x75, 0x72, 0x65, 0x2c, 105 | 0x20, 0x73, 0x75, 0x6e, 0x73, 0x63, 0x72, 0x65, 0x65, 0x6e, 0x20, 0x77, 0x6f, 106 | 0x75, 0x6c, 0x64, 0x20, 0x62, 0x65, 0x20, 0x69, 0x74, 0x2e 107 | ]) 108 | 109 | found_clen = sodium.crypto_aead_xchacha20poly1305_ietf_encrypt(c, m, ad, null, nonce, firstkey); 110 | 111 | t.assert(found_clen === MLEN + sodium.crypto_aead_xchacha20poly1305_ietf_ABYTES, "found_clen should be properly set") 112 | t.same(c, exp[0]) 113 | 114 | // found_maclen = sodium.crypto_aead_xchacha20poly1305_ietf_encrypt_detached(detached_c, mac, m, ad, null, nonce, firstkey); 115 | // t.assert(found_maclen === sodium.crypto_aead_xchacha20poly1305_ietf_ABYTES, "found_maclen should be properly set") 116 | // t.same(detached_c, c.subarray(0, MLEN), "detached ciphertext is good\n") 117 | 118 | t.throws(() => sodium.crypto_aead_xchacha20poly1305_ietf_decrypt(Buffer.alloc(0), null, c, ad, nonce, firstkey), 119 | "null message throws") 120 | 121 | t.throws(() => sodium.crypto_aead_xchacha20poly1305_ietf_decrypt(Buffer.alloc(0), null, c, ad, nonce, firstkey), 122 | "short message throws") 123 | 124 | t.doesNotThrow(() => m2len = sodium.crypto_aead_xchacha20poly1305_ietf_decrypt(m2, null, c, ad, nonce, firstkey), 125 | "sodium.crypto_aead_xchacha20poly1305_ietf_decrypt() should pass") 126 | 127 | t.equal(m2len, MLEN, "m2len is properly set") 128 | t.same(m, m2, "m === m2"); 129 | 130 | // m2.fill(0) 131 | // t.doesNotThrow(() => sodium.crypto_aead_xchacha20poly1305_ietf_decrypt_detached(m2, null, c.subarray(0, MLEN), mac, ad, nonce, firstkey), 132 | // "sodium.crypto_aead_xchacha20poly1305_ietf_decrypt_detached() should pass") 133 | 134 | // t.same(m, m2, "m === m2"); 135 | 136 | for (i = 0; i < CLEN; i++) { 137 | c[i] ^= (i + 1); 138 | 139 | try { 140 | sodium.crypto_aead_xchacha20poly1305_ietf_decrypt(m2, null, c, ad, nonce, firstkey) 141 | if (Buffer.compare(m, m2) !== 0) throw new Error() 142 | t.fail('message can be forged') 143 | } catch { 144 | c[i] ^= (i + 1) 145 | } 146 | } 147 | 148 | found_clen = sodium.crypto_aead_xchacha20poly1305_ietf_encrypt(c, m, null, null, nonce, firstkey); 149 | t.equal(found_clen, CLEN, "found_clen is properly set (adlen = 0)") 150 | t.same(c, exp[1]) 151 | 152 | t.doesNotThrow(() => m2len = sodium.crypto_aead_xchacha20poly1305_ietf_decrypt(m2, null, c, null, nonce, firstkey), 153 | "sodium.crypto_aead_xchacha20poly1305_ietf_decrypt() should pass (adlen=0)\n") 154 | 155 | t.equal(m2len, MLEN, "m2len is properly set (adlen=0)") 156 | t.same(m, m2, "m === m2 (adlen=0)") 157 | 158 | m2len = 1 159 | t.throws(() => sodium.crypto_aead_xchacha20poly1305_ietf_decrypt( 160 | m2.subarray(0, 1), null, Buffer.alloc(32), 161 | sodium.randombytes_uniform(sodium.crypto_aead_xchacha20poly1305_ietf_ABYTES), 162 | null, nonce, firstkey), 163 | "sodium.crypto_aead_xchacha20poly1305_ietf_decrypt() throws with a short ciphertext") 164 | 165 | t.throws(() => sodium.crypto_aead_xchacha20poly1305_ietf_decrypt(m2, null, c.subarray(0, 0), null, nonce, firstkey), 166 | "sodium.crypto_aead_xchacha20poly1305_ietf_decrypt() worked with an empty ciphertext") 167 | 168 | c.set(m) 169 | found_clen = sodium.crypto_aead_xchacha20poly1305_ietf_encrypt(c, c.subarray(0, MLEN), null, null, nonce, firstkey) 170 | 171 | t.equal(found_clen, CLEN, "clen is properly set (adlen=0)") 172 | t.same(c, exp[2]) 173 | 174 | t.doesNotThrow(() => m2len = sodium.crypto_aead_xchacha20poly1305_ietf_decrypt(c.subarray(0, MLEN), null, c, null, nonce, firstkey), 175 | "sodium.crypto_aead_xchacha20poly1305_ietf_decrypt() should pass (adlen=0)") 176 | 177 | t.equal(m2len, MLEN, "m2len is properly set (adlen=0)") 178 | t.same(m, c.subarray(0, MLEN), "m === c (adlen=0)") 179 | 180 | sodium.crypto_aead_xchacha20poly1305_ietf_keygen(key2) 181 | t.throws(() => sodium.crypto_aead_xchacha20poly1305_ietf_decrypt(c, null, c, null, nonce, key2), 182 | "sodium.crypto_aead_xchacha20poly1305_ietf_decrypt() with a wrong key should have failed") 183 | 184 | t.equal(sodium.crypto_aead_xchacha20poly1305_ietf_ABYTES, 16) 185 | t.equal(sodium.crypto_aead_xchacha20poly1305_ietf_KEYBYTES, 32) 186 | t.equal(sodium.crypto_aead_xchacha20poly1305_ietf_NPUBBYTES, 24) 187 | t.equal(sodium.crypto_aead_xchacha20poly1305_ietf_NSECBYTES, 0) 188 | t.equal(sodium.crypto_aead_xchacha20poly1305_ietf_MESSAGEBYTES_MAX, 4294967279) 189 | 190 | t.end() 191 | }) 192 | } 193 | -------------------------------------------------------------------------------- /crypto_auth.js: -------------------------------------------------------------------------------- 1 | 2 | const tape = require('tape') 3 | 4 | module.exports = function (sodium) { 5 | tape('crypto_auth #1', t => { 6 | // "Test Case 2" from RFC 4231 7 | const key = stringToArray("Jefe", 32) 8 | const c = stringToArray("what do ya want for nothing?") 9 | const c1 = stringToArray("wwhat do ya want for nothing") 10 | 11 | const a = new Uint8Array(sodium.crypto_auth_BYTES) 12 | 13 | const exp = [ 14 | new Uint8Array([ 15 | 0x16, 0x4b, 0x7a, 0x7b, 0xfc, 0xf8, 0x19, 0xe2, 16 | 0xe3, 0x95, 0xfb, 0xe7, 0x3b, 0x56, 0xe0, 0xa3, 17 | 0x87, 0xbd, 0x64, 0x22, 0x2e, 0x83, 0x1f, 0xd6, 18 | 0x10, 0x27, 0x0c, 0xd7, 0xea, 0x25, 0x05, 0x54 19 | ]), 20 | new Uint8Array([ 21 | 0x7b, 0x9d, 0x83, 0x38, 0xeb, 0x1e, 0x3d, 0xdd, 22 | 0xba, 0x8a, 0x9a, 0x35, 0x08, 0xd0, 0x34, 0xa1, 23 | 0xec, 0xbe, 0x75, 0x11, 0x37, 0xfa, 0x1b, 0xcb, 24 | 0xa0, 0xf9, 0x2a, 0x3e, 0x6d, 0xfc, 0x79, 0x80, 25 | ]), 26 | new Uint8Array([ 27 | 0xb9, 0xd1, 0x4c, 0x51, 0xa6, 0xd4, 0xdd, 0x41, 28 | 0x60, 0x4e, 0xb0, 0x6c, 0x9c, 0x24, 0x0f, 0x1f, 29 | 0x64, 0xf1, 0x43, 0xb5, 0xcf, 0xde, 0xa3, 0x71, 30 | 0x29, 0xb2, 0x8b, 0xb7, 0x5d, 0x13, 0x71, 0xd3 31 | ]) 32 | ] 33 | 34 | sodium.crypto_auth(a, c, key) 35 | t.deepEqual(a, exp[0]) 36 | t.assert(sodium.crypto_auth_verify(exp[0], c, key)) 37 | 38 | a.fill(0) 39 | sodium.crypto_auth(a, c1, key) 40 | t.deepEqual(a, exp[1]) 41 | t.assert(sodium.crypto_auth_verify(exp[1], c1, key)) 42 | 43 | // Empty message tests 44 | a.fill(0) 45 | sodium.crypto_auth(a, new Uint8Array(0), key) 46 | t.deepEqual(a, exp[2]) 47 | t.assert(sodium.crypto_auth_verify(exp[2], new Uint8Array(0), key)) 48 | t.end() 49 | }) 50 | 51 | tape('crypto_auth', function (t) { 52 | const key = stringToArray('Jefe', 32) 53 | const c = stringToArray('what do ya want for nothing?') 54 | const a = new Uint8Array(sodium.crypto_auth_BYTES) 55 | const expected = new Uint8Array([ 56 | 0x16, 0x4b, 0x7a, 0x7b, 0xfc, 0xf8, 0x19, 0xe2, 0xe3, 0x95, 0xfb, 0xe7, 57 | 0x3b, 0x56, 0xe0, 0xa3, 0x87, 0xbd, 0x64, 0x22, 0x2e, 0x83, 0x1f, 0xd6, 58 | 0x10, 0x27, 0x0c, 0xd7, 0xea, 0x25, 0x05, 0x54 59 | ]) 60 | 61 | sodium.crypto_auth(a, c, key) 62 | 63 | t.deepEqual(a, expected) 64 | t.ok(sodium.crypto_auth_verify(a, c, key)) 65 | 66 | c[Math.floor(Math.random() * c.length)] += 1 67 | t.notOk(sodium.crypto_auth_verify(a, c, key)) 68 | 69 | t.end() 70 | }) 71 | 72 | tape('wrong keylength', t => { 73 | const a = new Uint8Array(32) 74 | const c = new Uint8Array(0) 75 | 76 | for (let i = 0; i < 128; i++) { 77 | if (i === 32) continue 78 | const k = new Uint8Array(i) 79 | try { 80 | sodium.crypto_auth(a, c, k) 81 | t.fail('failed on test #' + i) 82 | } catch (e) { 83 | try { 84 | sodium.crypto_auth_verify(a, c, k) 85 | t.fail('failed on test #' + i) 86 | } catch (e) { 87 | try { 88 | sodium.crypto_auth_verify(k, c, a) 89 | t.fail('failed on test #' + i) 90 | } catch {} 91 | } 92 | } 93 | } 94 | 95 | t.pass("should not accept bad input length") 96 | t.end() 97 | }) 98 | 99 | tape('crypto_auth constants', t => { 100 | t.equal(sodium.crypto_auth_BYTES, 32) 101 | t.equal(sodium.crypto_auth_KEYBYTES, 32) 102 | t.end() 103 | }) 104 | 105 | tape('rfc4231 test case #6', t => { 106 | const keys = [ 107 | new Uint8Array([ 108 | 0x0b, 0x0b, 0x0b, 0x0b, 0x0b, 0x0b, 0x0b, 0x0b, 109 | 0x0b, 0x0b, 0x0b, 0x0b, 0x0b, 0x0b, 0x0b, 0x0b, 110 | 0x0b, 0x0b, 0x0b, 0x0b, 0x00, 0x00, 0x00, 0x00, 111 | 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 112 | ]), 113 | new Uint8Array([ 114 | 0x4a, 0x65, 0x66, 0x65, 0x00, 0x00, 0x00, 0x00, 115 | 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 116 | 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 117 | 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 118 | ]), 119 | new Uint8Array([ 120 | 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 121 | 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 122 | 0xaa, 0xaa, 0xaa, 0xaa, 0x00, 0x00, 0x00, 0x00, 123 | 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 124 | ]), 125 | new Uint8Array([ 126 | 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 127 | 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f, 0x10, 128 | 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17, 0x18, 129 | 0x19, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 130 | ]), 131 | ] 132 | 133 | const data = [ 134 | new Uint8Array([ 135 | 0x48, 0x69, 0x20, 0x54, 0x68, 0x65, 0x72, 0x65 136 | ]), 137 | new Uint8Array([ 138 | 0x77, 0x68, 0x61, 0x74, 0x20, 0x64, 0x6f, 0x20, 139 | 0x79, 0x61, 0x20, 0x77, 0x61, 0x6e, 0x74, 0x20, 140 | 0x66, 0x6f, 0x72, 0x20, 0x6e, 0x6f, 0x74, 0x68, 141 | 0x69, 0x6e, 0x67, 0x3f 142 | ]), 143 | new Uint8Array([ 144 | 0xdd, 0xdd, 0xdd, 0xdd, 0xdd, 0xdd, 0xdd, 0xdd, 145 | 0xdd, 0xdd, 0xdd, 0xdd, 0xdd, 0xdd, 0xdd, 0xdd, 146 | 0xdd, 0xdd, 0xdd, 0xdd, 0xdd, 0xdd, 0xdd, 0xdd, 147 | 0xdd, 0xdd, 0xdd, 0xdd, 0xdd, 0xdd, 0xdd, 0xdd, 148 | 0xdd, 0xdd, 0xdd, 0xdd, 0xdd, 0xdd, 0xdd, 0xdd, 149 | 0xdd, 0xdd, 0xdd, 0xdd, 0xdd, 0xdd, 0xdd, 0xdd, 150 | 0xdd, 0xdd 151 | ]), 152 | new Uint8Array([ 153 | 0xcd, 0xcd, 0xcd, 0xcd, 0xcd, 0xcd, 0xcd, 0xcd, 154 | 0xcd, 0xcd, 0xcd, 0xcd, 0xcd, 0xcd, 0xcd, 0xcd, 155 | 0xcd, 0xcd, 0xcd, 0xcd, 0xcd, 0xcd, 0xcd, 0xcd, 156 | 0xcd, 0xcd, 0xcd, 0xcd, 0xcd, 0xcd, 0xcd, 0xcd, 157 | 0xcd, 0xcd, 0xcd, 0xcd, 0xcd, 0xcd, 0xcd, 0xcd, 158 | 0xcd, 0xcd, 0xcd, 0xcd, 0xcd, 0xcd, 0xcd, 0xcd, 159 | 0xcd, 0xcd 160 | ]), 161 | ] 162 | 163 | const exp = [ 164 | new Uint8Array([ 165 | 0x87, 0xaa, 0x7c, 0xde, 0xa5, 0xef, 0x61, 0x9d, 166 | 0x4f, 0xf0, 0xb4, 0x24, 0x1a, 0x1d, 0x6c, 0xb0, 167 | 0x23, 0x79, 0xf4, 0xe2, 0xce, 0x4e, 0xc2, 0x78, 168 | 0x7a, 0xd0, 0xb3, 0x05, 0x45, 0xe1, 0x7c, 0xde 169 | ]), 170 | new Uint8Array([ 171 | 0x16, 0x4b, 0x7a, 0x7b, 0xfc, 0xf8, 0x19, 0xe2, 172 | 0xe3, 0x95, 0xfb, 0xe7, 0x3b, 0x56, 0xe0, 0xa3, 173 | 0x87, 0xbd, 0x64, 0x22, 0x2e, 0x83, 0x1f, 0xd6, 174 | 0x10, 0x27, 0x0c, 0xd7, 0xea, 0x25, 0x05, 0x54 175 | ]), 176 | new Uint8Array([ 177 | 0xfa, 0x73, 0xb0, 0x08, 0x9d, 0x56, 0xa2, 0x84, 178 | 0xef, 0xb0, 0xf0, 0x75, 0x6c, 0x89, 0x0b, 0xe9, 179 | 0xb1, 0xb5, 0xdb, 0xdd, 0x8e, 0xe8, 0x1a, 0x36, 180 | 0x55, 0xf8, 0x3e, 0x33, 0xb2, 0x27, 0x9d, 0x39 181 | ]), 182 | new Uint8Array([ 183 | 0xb0, 0xba, 0x46, 0x56, 0x37, 0x45, 0x8c, 0x69, 184 | 0x90, 0xe5, 0xa8, 0xc5, 0xf6, 0x1d, 0x4a, 0xf7, 185 | 0xe5, 0x76, 0xd9, 0x7f, 0xf9, 0x4b, 0x87, 0x2d, 186 | 0xe7, 0x6f, 0x80, 0x50, 0x36, 0x1e, 0xe3, 0xdb 187 | ]), 188 | ] 189 | 190 | const a = new Uint8Array(sodium.crypto_auth_BYTES) 191 | 192 | for (let i = 0; i < keys.length; i++) { 193 | sodium.crypto_auth(a, data[i], keys[i]) 194 | t.same(a, exp[i]) 195 | t.assert(sodium.crypto_auth_verify(exp[i], data[i], keys[i])) 196 | } 197 | 198 | t.end() 199 | }) 200 | } 201 | 202 | function stringToArray (s, size = s.length) { 203 | const array = new Uint8Array(size) 204 | array.set(s.split('').map((c) => c.charCodeAt(0))) 205 | return array 206 | } 207 | -------------------------------------------------------------------------------- /crypto_box.js: -------------------------------------------------------------------------------- 1 | var tape = require('tape') 2 | 3 | const seed = Buffer.from([ 4 | 0x77, 0x07, 0x6d, 0x0a, 0x73, 0x18, 0xa5, 5 | 0x7d, 0x3c, 0x16, 0xc1, 0x72, 0x51, 0xb2, 6 | 0x66, 0x45, 0xdf, 0x4c, 0x2f, 0x87, 0xeb, 7 | 0xc0, 0x99, 0x2a, 0xb1, 0x77, 0xfb, 0xa5, 8 | 0x1d, 0xb9, 0x2c, 0x2a 9 | ]) 10 | 11 | const exp_pk = Buffer.from([ 12 | 0xed, 0x77, 0x49, 0xb4, 0xd9, 0x89, 0xf6, 0x95, 13 | 0x7f, 0x3b, 0xfd, 0xe6, 0xc5, 0x67, 0x67, 0xe9, 14 | 0x88, 0xe2, 0x1c, 0x9f, 0x87, 0x84, 0xd9, 0x1d, 15 | 0x61, 0x00, 0x11, 0xcd, 0x55, 0x3f, 0x9b, 0x06 16 | ]) 17 | 18 | const exp_sk = Buffer.from([ 19 | 0xac, 0xcd, 0x44, 0xeb, 0x8e, 0x93, 0x31, 0x9c, 20 | 0x05, 0x70, 0xbc, 0x11, 0x00, 0x5c, 0x0e, 0x01, 21 | 0x89, 0xd3, 0x4f, 0xf0, 0x2f, 0x6c, 0x17, 0x77, 22 | 0x34, 0x11, 0xad, 0x19, 0x12, 0x93, 0xc9, 0x8f 23 | ]) 24 | 25 | module.exports = function (sodium) { 26 | tape('crypto_box_keypair generate key-pair', function (t) { 27 | var pubKey = Buffer.alloc(sodium.crypto_box_PUBLICKEYBYTES) 28 | sodium.randombytes_buf(pubKey) 29 | 30 | var secret = Buffer.alloc(sodium.crypto_box_SECRETKEYBYTES) 31 | sodium.randombytes_buf(secret) 32 | 33 | var pubKeyCopy = Buffer.alloc(sodium.crypto_box_PUBLICKEYBYTES) 34 | pubKey.copy(pubKeyCopy) 35 | 36 | var secretCopy = Buffer.alloc(sodium.crypto_box_SECRETKEYBYTES) 37 | secret.copy(secretCopy) 38 | 39 | sodium.crypto_box_keypair(pubKey, secret) 40 | t.notEqual(pubKey, pubKeyCopy) 41 | t.notEqual(secret, secretCopy) 42 | 43 | t.end() 44 | }) 45 | 46 | tape('crypto_box_seal/crypto_box_seal_open self-decrypt', function (t) { 47 | var pubKey = Buffer.alloc(sodium.crypto_box_PUBLICKEYBYTES) 48 | var secret = Buffer.alloc(sodium.crypto_box_SECRETKEYBYTES) 49 | 50 | sodium.crypto_box_keypair(pubKey, secret) 51 | 52 | var msg = Buffer.from('hello world') 53 | var cipher = Buffer.alloc(sodium.crypto_box_SEALBYTES + msg.length) 54 | sodium.crypto_box_seal(cipher, msg, pubKey) 55 | 56 | var out = Buffer.alloc(cipher.length - sodium.crypto_box_SEALBYTES) 57 | sodium.crypto_box_seal_open(out, cipher, pubKey, secret) 58 | t.same(out.toString(), msg.toString()) 59 | t.end() 60 | }) 61 | 62 | tape('crypto_box_seal_open cross-decrypt', function (t) { 63 | var pubKey = Buffer.from( 64 | 'e0bb844ae3f48bb04323c8dfe7c34cf86608db2e2112f927953060c80506287f', 'hex') 65 | var secret = Buffer.from( 66 | '036a9de1ecc9d152cf39fed1b3e15bf761ae39a299031adc011cc9809041abfa', 'hex') 67 | var cipher = Buffer.from( 68 | '249912e916ad8bcf96a3f9b750da2703' + 69 | '2eccdf83b5cff0d6a59a8bbe0bcd5823' + 70 | '5de9fbca55bd5416c754e5e0e0fe2f0c' + 71 | '4e50df0cb302f1c4378f80', 'hex') 72 | 73 | var out = Buffer.alloc(cipher.length - sodium.crypto_box_SEALBYTES) 74 | sodium.crypto_box_seal_open(out, cipher, pubKey, secret) 75 | t.same(out.toString(), 'hello world') 76 | t.end() 77 | }) 78 | 79 | tape('crypto_box_seed_keypair', function (t) { 80 | const sk = Buffer.alloc(32) 81 | const pk = Buffer.alloc(32) 82 | 83 | sodium.crypto_box_seed_keypair(pk, sk, seed) 84 | 85 | t.same(pk, exp_pk) 86 | t.same(sk, exp_sk) 87 | 88 | t.end() 89 | }) 90 | 91 | tape('crypto_box_easy', (t) => { 92 | const alicesk = new Uint8Array([ 93 | 0x77, 0x07, 0x6d, 0x0a, 0x73, 0x18, 0xa5, 0x7d, 0x3c, 0x16, 0xc1, 0x72, 94 | 0x51, 0xb2, 0x66, 0x45, 0xdf, 0x4c, 0x2f, 0x87, 0xeb, 0xc0, 0x99, 0x2a, 95 | 0xb1, 0x77, 0xfb, 0xa5, 0x1d, 0xb9, 0x2c, 0x2a 96 | ]) 97 | const bobpk = new Uint8Array([ 98 | 0xde, 0x9e, 0xdb, 0x7d, 0x7b, 0x7d, 0xc1, 0xb4, 0xd3, 0x5b, 0x61, 0xc2, 99 | 0xec, 0xe4, 0x35, 0x37, 0x3f, 0x83, 0x43, 0xc8, 0x5b, 0x78, 0x67, 0x4d, 100 | 0xad, 0xfc, 0x7e, 0x14, 0x6f, 0x88, 0x2b, 0x4f 101 | ]) 102 | const nonce = new Uint8Array([ 103 | 0x69, 0x69, 0x6e, 0xe9, 0x55, 0xb6, 0x2b, 0x73, 0xcd, 0x62, 0xbd, 0xa8, 104 | 0x75, 0xfc, 0x73, 0xd6, 0x82, 0x19, 0xe0, 0x03, 0x6b, 0x7a, 0x0b, 0x37 105 | ]) 106 | const m = new Uint8Array([ 107 | 0xbe, 0x07, 0x5f, 0xc5, 0x3c, 0x81, 0xf2, 0xd5, 0xcf, 0x14, 0x13, 0x16, 108 | 0xeb, 0xeb, 0x0c, 0x7b, 0x52, 0x28, 0xc5, 0x2a, 0x4c, 0x62, 0xcb, 0xd4, 109 | 0x4b, 0x66, 0x84, 0x9b, 0x64, 0x24, 0x4f, 0xfc, 0xe5, 0xec, 0xba, 0xaf, 110 | 0x33, 0xbd, 0x75, 0x1a, 0x1a, 0xc7, 0x28, 0xd4, 0x5e, 0x6c, 0x61, 0x29, 111 | 0x6c, 0xdc, 0x3c, 0x01, 0x23, 0x35, 0x61, 0xf4, 0x1d, 0xb6, 0x6c, 0xce, 112 | 0x31, 0x4a, 0xdb, 0x31, 0x0e, 0x3b, 0xe8, 0x25, 0x0c, 0x46, 0xf0, 0x6d, 113 | 0xce, 0xea, 0x3a, 0x7f, 0xa1, 0x34, 0x80, 0x57, 0xe2, 0xf6, 0x55, 0x6a, 114 | 0xd6, 0xb1, 0x31, 0x8a, 0x02, 0x4a, 0x83, 0x8f, 0x21, 0xaf, 0x1f, 0xde, 115 | 0x04, 0x89, 0x77, 0xeb, 0x48, 0xf5, 0x9f, 0xfd, 0x49, 0x24, 0xca, 0x1c, 116 | 0x60, 0x90, 0x2e, 0x52, 0xf0, 0xa0, 0x89, 0xbc, 0x76, 0x89, 0x70, 0x40, 117 | 0xe0, 0x82, 0xf9, 0x37, 0x76, 0x38, 0x48, 0x64, 0x5e, 0x07, 0x05 118 | ]) 119 | 120 | const c = new Uint8Array(147) 121 | sodium.crypto_box_easy(c, m, nonce, bobpk, alicesk) 122 | 123 | const expected1 = new Uint8Array([ 124 | 0xf3, 0xff, 0xc7, 0x70, 0x3f, 0x94, 0x00, 0xe5, 0x2a, 0x7d, 0xfb, 0x4b, 125 | 0x3d, 0x33, 0x05, 0xd9, 0x8e, 0x99, 0x3b, 0x9f, 0x48, 0x68, 0x12, 0x73, 126 | 0xc2, 0x96, 0x50, 0xba, 0x32, 0xfc, 0x76, 0xce, 0x48, 0x33, 0x2e, 0xa7, 127 | 0x16, 0x4d, 0x96, 0xa4, 0x47, 0x6f, 0xb8, 0xc5, 0x31, 0xa1, 0x18, 0x6a, 128 | 0xc0, 0xdf, 0xc1, 0x7c, 0x98, 0xdc, 0xe8, 0x7b, 0x4d, 0xa7, 0xf0, 0x11, 129 | 0xec, 0x48, 0xc9, 0x72, 0x71, 0xd2, 0xc2, 0x0f, 0x9b, 0x92, 0x8f, 0xe2, 130 | 0x27, 0x0d, 0x6f, 0xb8, 0x63, 0xd5, 0x17, 0x38, 0xb4, 0x8e, 0xee, 0xe3, 131 | 0x14, 0xa7, 0xcc, 0x8a, 0xb9, 0x32, 0x16, 0x45, 0x48, 0xe5, 0x26, 0xae, 132 | 0x90, 0x22, 0x43, 0x68, 0x51, 0x7a, 0xcf, 0xea, 0xbd, 0x6b, 0xb3, 0x73, 133 | 0x2b, 0xc0, 0xe9, 0xda, 0x99, 0x83, 0x2b, 0x61, 0xca, 0x01, 0xb6, 0xde, 134 | 0x56, 0x24, 0x4a, 0x9e, 0x88, 0xd5, 0xf9, 0xb3, 0x79, 0x73, 0xf6, 0x22, 135 | 0xa4, 0x3d, 0x14, 0xa6, 0x59, 0x9b, 0x1f, 0x65, 0x4c, 0xb4, 0x5a, 0x74, 136 | 0xe3, 0x55, 0xa5 137 | ]) 138 | 139 | t.deepEqual(c, expected1, 'encrypts correctly') 140 | 141 | // This test isn't found upstream, but it seems necessary to have at least 142 | // one crypto_box_open_easy() working since the next test diverges. 143 | const o = new Uint8Array(131) 144 | t.ok(sodium.crypto_box_open_easy(o, expected1, nonce, bobpk, alicesk)) 145 | t.deepEqual(o, m, 'decrypts correctly') 146 | 147 | const guardPage = new Uint8Array(0) 148 | 149 | t.doesNotThrow(() => sodium.crypto_box_easy( 150 | c.subarray(0, sodium.crypto_box_MACBYTES), 151 | guardPage, 152 | nonce, 153 | bobpk, 154 | alicesk 155 | )) 156 | 157 | const expected2 = new Uint8Array([ 158 | 0x25, 0x39, 0x12, 0x1d, 0x8e, 0x23, 0x4e, 0x65, 0x2d, 0x65, 0x1f, 0xa4, 159 | 0xc8, 0xcf, 0xf8, 0x80, 0x8e 160 | ]) 161 | 162 | t.deepEqual(c.subarray(0, expected2.length), expected2) 163 | 164 | t.ok(sodium.crypto_box_open_easy( 165 | new Uint8Array(0), 166 | c.subarray(0, sodium.crypto_box_MACBYTES), 167 | nonce, 168 | bobpk, 169 | alicesk 170 | )) 171 | 172 | c[Math.floor(Math.random() * sodium.crypto_box_MACBYTES)] += 1 173 | 174 | t.notOk(sodium.crypto_box_open_easy(new Uint8Array(0), c.subarray(0, sodium.crypto_box_MACBYTES), nonce, bobpk, alicesk)) 175 | 176 | t.end() 177 | }) 178 | 179 | tape('crypto_box2', t => { 180 | const small_order_p = new Uint8Array([ 181 | 0xe0, 0xeb, 0x7a, 0x7c, 0x3b, 0x41, 0xb8, 0xae, 0x16, 0x56, 0xe3, 182 | 0xfa, 0xf1, 0x9f, 0xc4, 0x6a, 0xda, 0x09, 0x8d, 0xeb, 0x9c, 0x32, 183 | 0xb1, 0xfd, 0x86, 0x62, 0x05, 0x16, 0x5f, 0x49, 0xb8, 0x00 184 | ]) 185 | 186 | const alicepk = new Uint8Array(sodium.crypto_box_PUBLICKEYBYTES) 187 | const alicesk = new Uint8Array(sodium.crypto_box_SECRETKEYBYTES) 188 | const bobpk = new Uint8Array(sodium.crypto_box_PUBLICKEYBYTES) 189 | const bobsk = new Uint8Array(sodium.crypto_box_SECRETKEYBYTES) 190 | const mac = new Uint8Array(sodium.crypto_box_MACBYTES) 191 | const nonce = new Uint8Array(sodium.crypto_box_NONCEBYTES) 192 | const m_size = 7 + Math.floor(Math.random() * 1000) 193 | const m = new Uint8Array(m_size) 194 | const m2 = new Uint8Array(m_size) 195 | const c = new Uint8Array(sodium.crypto_box_MACBYTES + m_size) 196 | 197 | sodium.crypto_box_keypair(alicepk, alicesk) 198 | sodium.crypto_box_keypair(bobpk, bobsk) 199 | 200 | const mlen = Math.floor(Math.random() * m_size) + 1 201 | sodium.randombytes_buf(m.subarray(0, mlen)) 202 | sodium.randombytes_buf(nonce.subarray(0, sodium.crypto_box_NONCEBYTES)) 203 | 204 | t.doesNotThrow(() => sodium.crypto_box_easy(c.subarray(0, mlen + sodium.crypto_box_MACBYTES), m.subarray(0, mlen), nonce, bobpk, alicesk)) 205 | 206 | t.ok(sodium.crypto_box_open_easy(m2.subarray(0, mlen), c.subarray(0, mlen + sodium.crypto_box_MACBYTES), nonce, alicepk, bobsk)) 207 | t.deepEqual(m.subarray(0, mlen), m2.subarray(0, mlen)) 208 | 209 | for (let i = sodium.crypto_box_MACBYTES; i < mlen + sodium.crypto_box_MACBYTES - 1; i++) { 210 | if (sodium.crypto_box_open_easy(m2.subarray(0, i - sodium.crypto_box_MACBYTES), c.subarray(0, i), nonce, alicepk, bobsk)) { 211 | t.fail('short open() should fail.') 212 | } 213 | } 214 | 215 | c.set(m.subarray(0, mlen)) 216 | t.doesNotThrow(() => sodium.crypto_box_easy(c.subarray(0, mlen + sodium.crypto_box_MACBYTES), c.subarray(0, mlen), nonce, bobpk, alicesk)) 217 | 218 | t.notDeepEqual(m.subarray(0, mlen), c.subarray(0, mlen)) 219 | t.notDeepEqual(m.subarray(0, mlen), c.subarray(sodium.crypto_box_MACBYTES, sodium.crypto_box_MACBYTES + mlen)) 220 | 221 | t.assert(sodium.crypto_box_open_easy(c.subarray(0, mlen), c.subarray(0, mlen + sodium.crypto_box_MACBYTES), nonce, alicepk, bobsk)) 222 | 223 | t.end() 224 | }) 225 | } 226 | -------------------------------------------------------------------------------- /crypto_generichash.js: -------------------------------------------------------------------------------- 1 | var tape = require('tape') 2 | 3 | module.exports = function (sodium) { 4 | tape('crypto_generichash', function (t) { 5 | var buf = Buffer.from('Hello, World!') 6 | 7 | var out = Buffer.alloc(sodium.crypto_generichash_BYTES) 8 | sodium.crypto_generichash(out, buf) 9 | 10 | t.same(out.toString('hex'), '511bc81dde11180838c562c82bb35f3223f46061ebde4a955c27b3f489cf1e03', 'hashed buffer') 11 | 12 | var min = Buffer.alloc(sodium.crypto_generichash_BYTES_MIN) 13 | sodium.crypto_generichash(min, buf) 14 | 15 | t.same(min.toString('hex'), '3895c59e4aeb0903396b5be3fbec69fe', 'hashed buffer min') 16 | 17 | var max = Buffer.alloc(sodium.crypto_generichash_BYTES_MAX) 18 | sodium.crypto_generichash(max, buf) 19 | 20 | var res = '7dfdb888af71eae0e6a6b751e8e3413d767ef4fa52a7993daa9ef097f7aa3d949199c113caa37c94f80cf3b22f7d9d6e4f5def4ff927830cffe4857c34be3d89' 21 | t.same(max.toString('hex'), res, 'hashed buffer max') 22 | 23 | t.end() 24 | }) 25 | 26 | tape('crypto_generichash with key', function (t) { 27 | var buf = Buffer.from('Hello, World!') 28 | var key = Buffer.alloc(sodium.crypto_generichash_KEYBYTES) 29 | 30 | key.fill('lo') 31 | 32 | var out = Buffer.alloc(sodium.crypto_generichash_BYTES) 33 | sodium.crypto_generichash(out, buf, key) 34 | 35 | t.same(out.toString('hex'), 'f4113fe33d43c24c54627d40efa1a78838d4a6d689fd6e83c213848904fffa8c', 'hashed buffer') 36 | 37 | var min = Buffer.alloc(sodium.crypto_generichash_BYTES_MIN) 38 | sodium.crypto_generichash(min, buf, key) 39 | 40 | t.same(min.toString('hex'), 'c8226257b0d1c3dcf4bbc3ef79574689', 'hashed buffer min') 41 | 42 | var max = Buffer.alloc(sodium.crypto_generichash_BYTES_MAX) 43 | sodium.crypto_generichash(max, buf, key) 44 | 45 | var res = '763eda46f4c6c61abb4310eb8a488950e9e0667b2fca03c463dc7489e94f065b7af6063fe86b0441c3eb9052800121d55730412abb2cbe0761b1d66f9b047c1c' 46 | t.same(max.toString('hex'), res, 'hashed buffer max') 47 | 48 | t.end() 49 | }) 50 | 51 | tape('crypto_generichash_instance', function (t) { 52 | var isntance = sodium.crypto_generichash_instance() 53 | var buf = Buffer.from('Hej, Verden') 54 | 55 | for (var i = 0; i < 10; i++) isntance.update(buf) 56 | 57 | var out = Buffer.alloc(sodium.crypto_generichash_BYTES) 58 | isntance.final(out) 59 | 60 | t.same(out.toString('hex'), 'cbc20f347f5dfe37dc13231cbf7eaa4ec48e585ec055a96839b213f62bd8ce00', 'streaming hash') 61 | t.end() 62 | }) 63 | 64 | tape('crypto_generichash_instance with key', function (t) { 65 | var key = Buffer.alloc(sodium.crypto_generichash_KEYBYTES) 66 | key.fill('lo') 67 | 68 | var isntance = sodium.crypto_generichash_instance(key) 69 | var buf = Buffer.from('Hej, Verden') 70 | 71 | for (var i = 0; i < 10; i++) isntance.update(buf) 72 | 73 | var out = Buffer.alloc(sodium.crypto_generichash_BYTES) 74 | isntance.final(out) 75 | 76 | t.same(out.toString('hex'), '405f14acbeeb30396b8030f78e6a84bab0acf08cb1376aa200a500f669f675dc', 'streaming keyed hash') 77 | t.end() 78 | }) 79 | 80 | tape('crypto_generichash_instance with hash length', function (t) { 81 | var isntance = sodium.crypto_generichash_instance(null, sodium.crypto_generichash_BYTES_MIN) 82 | var buf = Buffer.from('Hej, Verden') 83 | 84 | for (var i = 0; i < 10; i++) isntance.update(buf) 85 | 86 | var out = Buffer.alloc(sodium.crypto_generichash_BYTES_MIN) 87 | isntance.final(out) 88 | 89 | t.same(out.toString('hex'), 'decacdcc3c61948c79d9f8dee5b6aa99', 'streaming short hash') 90 | t.end() 91 | }) 92 | 93 | tape('crypto_generichash_instance with key and hash length', function (t) { 94 | var key = Buffer.alloc(sodium.crypto_generichash_KEYBYTES) 95 | key.fill('lo') 96 | 97 | var isntance = sodium.crypto_generichash_instance(key, sodium.crypto_generichash_BYTES_MIN) 98 | var buf = Buffer.from('Hej, Verden') 99 | 100 | for (var i = 0; i < 10; i++) isntance.update(buf) 101 | 102 | var out = Buffer.alloc(sodium.crypto_generichash_BYTES_MIN) 103 | isntance.final(out) 104 | 105 | t.same(out.toString('hex'), 'fb43f0ab6872cbfd39ec4f8a1bc6fb37', 'streaming short keyed hash') 106 | t.end() 107 | }) 108 | 109 | tape('crypto_generichash_batch', function (t) { 110 | var buf = Buffer.from('Hej, Verden') 111 | var batch = [] 112 | for (var i = 0; i < 10; i++) batch.push(buf) 113 | 114 | var out = Buffer.alloc(sodium.crypto_generichash_BYTES) 115 | sodium.crypto_generichash_batch(out, batch) 116 | 117 | t.same(out.toString('hex'), 'cbc20f347f5dfe37dc13231cbf7eaa4ec48e585ec055a96839b213f62bd8ce00', 'batch hash') 118 | t.end() 119 | }) 120 | 121 | tape('crypto_generichash_batch with key', function (t) { 122 | var key = Buffer.alloc(sodium.crypto_generichash_KEYBYTES) 123 | key.fill('lo') 124 | 125 | var buf = Buffer.from('Hej, Verden') 126 | var batch = [] 127 | for (var i = 0; i < 10; i++) batch.push(buf) 128 | 129 | var out = Buffer.alloc(sodium.crypto_generichash_BYTES) 130 | sodium.crypto_generichash_batch(out, batch, key) 131 | 132 | t.same(out.toString('hex'), '405f14acbeeb30396b8030f78e6a84bab0acf08cb1376aa200a500f669f675dc', 'batch keyed hash') 133 | t.end() 134 | }) 135 | } 136 | -------------------------------------------------------------------------------- /crypto_kdf.js: -------------------------------------------------------------------------------- 1 | var tape = require('tape') 2 | 3 | module.exports = function (sodium) { 4 | tape('crypto_kdf_keygen', function (t) { 5 | var key = Buffer.alloc(sodium.crypto_kdf_KEYBYTES + 1) 6 | key[sodium.crypto_kdf_KEYBYTES] = 0xdb 7 | 8 | t.throws(function () { 9 | sodium.crypto_kdf_keygen(Buffer.alloc(1)) 10 | }) 11 | 12 | sodium.crypto_kdf_keygen(key.subarray(0, sodium.crypto_kdf_KEYBYTES)) 13 | 14 | t.notEqual(key, Buffer.alloc(key.length)) 15 | t.equal(key[sodium.crypto_kdf_KEYBYTES], 0xdb) 16 | t.end() 17 | }) 18 | 19 | tape('crypto_kdf_derive_from_key', function (t) { 20 | var key = Buffer.alloc(sodium.crypto_kdf_KEYBYTES) 21 | 22 | sodium.crypto_kdf_keygen(key) 23 | 24 | var subkey = Buffer.alloc(sodium.crypto_kdf_BYTES_MIN) 25 | 26 | sodium.crypto_kdf_derive_from_key(subkey, 0, Buffer.from('context_'), key) 27 | t.notEqual(subkey, Buffer.alloc(subkey.length)) 28 | 29 | var subkey2 = Buffer.alloc(sodium.crypto_kdf_BYTES_MIN) 30 | 31 | sodium.crypto_kdf_derive_from_key(subkey2, 1, Buffer.from('context_'), key) 32 | t.notEqual(subkey, subkey2) 33 | 34 | sodium.crypto_kdf_derive_from_key(subkey2, 0, Buffer.from('context_'), key) 35 | t.same(subkey, subkey2) 36 | 37 | t.end() 38 | }) 39 | 40 | tape('test vectors', function (assert) { 41 | var fixtures = require('./fixtures/crypto_kdf.json') 42 | 43 | for (var i = 0; i < fixtures.length; i++) { 44 | var key = Buffer.from(fixtures[i].key, 'hex') 45 | var subkeyLen = fixtures[i].subkey_len 46 | var id = fixtures[i].id 47 | var context = Buffer.from(fixtures[i].context, 'hex') 48 | 49 | var shouldError = fixtures[i].error 50 | 51 | var actual = Buffer.alloc(subkeyLen) 52 | 53 | try { 54 | sodium.crypto_kdf_derive_from_key(actual, id, context, key) 55 | var expected = Buffer.from(fixtures[i].subkey, 'hex') 56 | if (Buffer.compare(actual, expected) !== 0) { 57 | assert.fail('Failed on fixture #' + i) 58 | } 59 | } catch (ex) { 60 | if (shouldError === false) assert.fail('Failed on fixture #' + i) 61 | } 62 | } 63 | 64 | assert.pass('Passed all fixtures') 65 | assert.end() 66 | }) 67 | 68 | tape('constants', function (t) { 69 | t.ok(sodium.crypto_kdf_PRIMITIVE) 70 | t.ok(sodium.crypto_kdf_BYTES_MAX > 0) 71 | t.ok(sodium.crypto_kdf_BYTES_MIN <= sodium.crypto_kdf_BYTES_MAX) 72 | t.ok(sodium.crypto_kdf_CONTEXTBYTES > 0) 73 | t.ok(sodium.crypto_kdf_KEYBYTES >= 16) 74 | t.end() 75 | }) 76 | } 77 | -------------------------------------------------------------------------------- /crypto_kx.js: -------------------------------------------------------------------------------- 1 | const test = require('tape') 2 | 3 | var exp = [ 4 | Buffer.from('0e0216223f147143d32615a91189c288c1728cba3cc5f9f621b1026e03d83129', 'hex'), 5 | Buffer.from('cb2f5160fc1f7e05a55ef49d340b48da2e5a78099d53393351cd579dd42503d6', 'hex') 6 | ] 7 | 8 | module.exports = function (sodium) { 9 | test('crypto_kx', t => { 10 | const seed = Buffer.alloc(sodium.crypto_kx_SEEDBYTES) 11 | const client_pk = Buffer.alloc(sodium.crypto_kx_PUBLICKEYBYTES) 12 | const client_sk = Buffer.alloc(sodium.crypto_kx_SECRETKEYBYTES) 13 | const hex = Buffer.alloc(65) 14 | let i 15 | 16 | for (i = 0; i < sodium.crypto_kx_SEEDBYTES; i++) seed[i] = i 17 | 18 | sodium.crypto_kx_seed_keypair(client_pk, client_sk, seed) 19 | 20 | t.same(client_pk, exp[0]) 21 | t.same(client_sk, exp[1]) 22 | 23 | t.equal(sodium.crypto_kx_SEEDBYTES, 32) 24 | t.equal(sodium.crypto_kx_PUBLICKEYBYTES, 32) 25 | t.equal(sodium.crypto_kx_SECRETKEYBYTES, 32) 26 | 27 | t.end() 28 | }) 29 | } 30 | -------------------------------------------------------------------------------- /crypto_secretbox.js: -------------------------------------------------------------------------------- 1 | var tape = require('tape') 2 | 3 | module.exports = function (sodium) { 4 | tape('crypto_secretbox_easy', function (t) { 5 | var message = Buffer.from('Hej, Verden!') 6 | var output = Buffer.alloc(message.length + sodium.crypto_secretbox_MACBYTES) 7 | 8 | var key = Buffer.alloc(sodium.crypto_secretbox_KEYBYTES) 9 | sodium.randombytes_buf(key) 10 | 11 | var nonce = Buffer.alloc(sodium.crypto_secretbox_NONCEBYTES) 12 | sodium.randombytes_buf(nonce) 13 | 14 | t.throws(function () { 15 | sodium.crypto_secretbox_easy(Buffer.alloc(0), message, nonce, key) 16 | }, 'throws if output is too small') 17 | 18 | t.throws(function () { 19 | sodium.crypto_secretbox_easy(Buffer.alloc(message.length), message, nonce, key) 20 | }, 'throws if output is too small') 21 | 22 | sodium.crypto_secretbox_easy(output, message, nonce, key) 23 | t.notEqual(output, Buffer.alloc(output.length)) 24 | 25 | var result = Buffer.alloc(output.length - sodium.crypto_secretbox_MACBYTES) 26 | t.notOk(sodium.crypto_secretbox_open_easy(result, output, Buffer.alloc(sodium.crypto_secretbox_NONCEBYTES), key), 'could not decrypt') 27 | t.ok(sodium.crypto_secretbox_open_easy(result, output, nonce, key), 'could decrypt') 28 | 29 | t.same(result, message, 'decrypted message is correct') 30 | 31 | t.end() 32 | }) 33 | 34 | tape('crypto_secretbox_easy overwrite buffer', function (t) { 35 | var output = Buffer.alloc(Buffer.byteLength('Hej, Verden!') + sodium.crypto_secretbox_MACBYTES) 36 | output.write('Hej, Verden!', sodium.crypto_secretbox_MACBYTES) 37 | 38 | var key = Buffer.alloc(sodium.crypto_secretbox_KEYBYTES) 39 | sodium.randombytes_buf(key) 40 | 41 | var nonce = Buffer.alloc(sodium.crypto_secretbox_NONCEBYTES) 42 | sodium.randombytes_buf(nonce) 43 | 44 | sodium.crypto_secretbox_easy(output, output.slice(sodium.crypto_secretbox_MACBYTES), nonce, key) 45 | t.notEqual(output, Buffer.alloc(output.length)) 46 | 47 | t.ok(sodium.crypto_secretbox_open_easy(output.slice(sodium.crypto_secretbox_MACBYTES), output, nonce, key), 'could decrypt') 48 | t.same(output.slice(sodium.crypto_secretbox_MACBYTES), Buffer.from('Hej, Verden!'), 'decrypted message is correct') 49 | 50 | t.end() 51 | }) 52 | 53 | tape('crypto_secretbox_detached', function (t) { 54 | var message = Buffer.from('Hej, Verden!') 55 | var output = Buffer.alloc(message.length) 56 | var mac = Buffer.alloc(sodium.crypto_secretbox_MACBYTES) 57 | 58 | var key = Buffer.alloc(sodium.crypto_secretbox_KEYBYTES) 59 | sodium.randombytes_buf(key) 60 | 61 | var nonce = Buffer.alloc(sodium.crypto_secretbox_NONCEBYTES) 62 | sodium.randombytes_buf(nonce) 63 | 64 | sodium.crypto_secretbox_detached(output, mac, message, nonce, key) 65 | 66 | t.notEqual(mac, Buffer.alloc(mac.length), 'mac not blank') 67 | t.notEqual(output, Buffer.alloc(output.length), 'output not blank') 68 | 69 | var result = Buffer.alloc(output.length) 70 | 71 | t.notOk(sodium.crypto_secretbox_open_detached(result, output, mac, nonce, Buffer.alloc(key.length)), 'could not decrypt') 72 | t.ok(sodium.crypto_secretbox_open_detached(result, output, mac, nonce, key), 'could decrypt') 73 | 74 | t.same(result, message, 'decrypted message is correct') 75 | 76 | t.end() 77 | }) 78 | } 79 | -------------------------------------------------------------------------------- /crypto_secretstream.js: -------------------------------------------------------------------------------- 1 | /* eslint-disable camelcase */ 2 | const test = require('tape') 3 | 4 | function getRandomInt (min, max) { 5 | min = Math.ceil(min) 6 | max = Math.floor(max) 7 | return Math.floor(Math.random() * (max - min) + min) // The maximum is exclusive and the minimum is inclusive 8 | } 9 | 10 | module.exports = function (sodium) { 11 | const NONCE_OFFSET = sodium.crypto_secretstream_xchacha20poly1305_KEYBYTES 12 | const PAD_OFFSET = NONCE_OFFSET + 12 13 | 14 | test('secretstream', (t) => { 15 | const state = new Uint8Array(sodium.crypto_secretstream_xchacha20poly1305_STATEBYTES) 16 | const statesave = new Uint8Array(sodium.crypto_secretstream_xchacha20poly1305_STATEBYTES) 17 | const state_copy = new Uint8Array(sodium.crypto_secretstream_xchacha20poly1305_STATEBYTES) 18 | const header = new Uint8Array(sodium.crypto_secretstream_xchacha20poly1305_HEADERBYTES) 19 | const tag = new Uint8Array(1) 20 | 21 | const ad_len = getRandomInt(0, 100) 22 | const m1_len = getRandomInt(0, 1000) 23 | const m2_len = getRandomInt(0, 1000) 24 | const m3_len = getRandomInt(0, 1000) 25 | 26 | const c1 = new Uint8Array(m1_len + sodium.crypto_secretstream_xchacha20poly1305_ABYTES) 27 | const c2 = new Uint8Array(m2_len + sodium.crypto_secretstream_xchacha20poly1305_ABYTES) 28 | const c3 = new Uint8Array(m3_len + sodium.crypto_secretstream_xchacha20poly1305_ABYTES) 29 | const csave = new Uint8Array((m1_len | m2_len | m3_len) + sodium.crypto_secretstream_xchacha20poly1305_ABYTES) 30 | 31 | const ad = new Uint8Array(ad_len) 32 | const m1 = new Uint8Array(m1_len) 33 | const m2 = new Uint8Array(m2_len) 34 | const m3 = new Uint8Array(m3_len) 35 | 36 | sodium.randombytes_buf(ad) 37 | sodium.randombytes_buf(m1) 38 | sodium.randombytes_buf(m2) 39 | sodium.randombytes_buf(m3) 40 | 41 | const m1_ = new Uint8Array(m1) 42 | const m2_ = new Uint8Array(m2) 43 | const m3_ = new Uint8Array(m3) 44 | 45 | const k = new Uint8Array(sodium.crypto_secretstream_xchacha20poly1305_KEYBYTES) 46 | sodium.crypto_secretstream_xchacha20poly1305_keygen(k) 47 | 48 | /* push */ 49 | 50 | let ret = sodium.crypto_secretstream_xchacha20poly1305_init_push(state, header, k) 51 | // t.equal(ret, 'init_push failed') 52 | 53 | ret = sodium.crypto_secretstream_xchacha20poly1305_push(state, c1, m1, null, sodium.crypto_secretstream_xchacha20poly1305_TAG_MESSAGE) // how can ad be null here? 54 | t.equal(ret, m1_len + sodium.crypto_secretstream_xchacha20poly1305_ABYTES) 55 | 56 | ret = sodium.crypto_secretstream_xchacha20poly1305_push(state, c2, m2, ad, sodium.crypto_secretstream_xchacha20poly1305_TAG_MESSAGE) 57 | t.equal(ret, m2_len + sodium.crypto_secretstream_xchacha20poly1305_ABYTES) 58 | 59 | ret = sodium.crypto_secretstream_xchacha20poly1305_push(state, c3, m3, ad, sodium.crypto_secretstream_xchacha20poly1305_TAG_FINAL) 60 | t.ok(ret, 'third push failed') 61 | 62 | /* pull */ 63 | 64 | sodium.crypto_secretstream_xchacha20poly1305_init_pull(state, header, k) 65 | 66 | ret = sodium.crypto_secretstream_xchacha20poly1305_pull(state, m1, tag, c1, null) 67 | t.equal(ret, m1_len, 'first pull passed') 68 | t.equal(tag[0], sodium.crypto_secretstream_xchacha20poly1305_TAG_MESSAGE[0], 'tag pull failed') 69 | t.same(m1, m1_, 'failed m1 memcmp') 70 | 71 | ret = sodium.crypto_secretstream_xchacha20poly1305_pull(state, m2, tag, c2, ad) 72 | t.equal(ret, m2_len, 'second pull failed') 73 | t.equal(tag[0], sodium.crypto_secretstream_xchacha20poly1305_TAG_MESSAGE[0], 'second tag pull failed') 74 | t.same(m2, m2_, 'failed m2 memcmp') 75 | 76 | if (ad_len > 0) { 77 | t.throws(() => { sodium.crypto_secretstream_xchacha20poly1305_pull(state, m3, tag, c3) }) 78 | } 79 | 80 | ret = sodium.crypto_secretstream_xchacha20poly1305_pull(state, m3, tag, c3, ad) 81 | t.equal(ret, m3_len, 'failed fourth pull') 82 | t.equal(tag[0], sodium.crypto_secretstream_xchacha20poly1305_TAG_FINAL[0], 'failed final tag pull') 83 | t.same(m3, m3_, 'failed m3 memcmp') 84 | 85 | /* previous with FINAL tag */ 86 | t.throws(() => { 87 | sodium.crypto_secretstream_xchacha20poly1305_pull(state, m3, tag, c3, ad) 88 | }) 89 | 90 | /* previous without a tag */ 91 | t.throws(() => { 92 | sodium.crypto_secretstream_xchacha20poly1305_pull(state, m2, tag, c2, null) 93 | }) 94 | 95 | /* short ciphertext */ 96 | t.throws(() => { 97 | sodium.crypto_secretstream_xchacha20poly1305_pull(state, m2, tag, 98 | c2.subarray(0, getRandomInt(0, sodium.crypto_secretstream_xchacha20poly1305_ABYTES))) 99 | }) 100 | 101 | t.throws(() => { 102 | sodium.crypto_secretstream_xchacha20poly1305_pull(state, m2, tag, c2, null) 103 | }) 104 | 105 | /* empty ciphertext */ 106 | t.throws(() => { 107 | sodium.crypto_secretstream_xchacha20poly1305_pull(state, m2, tag, 108 | c2.subarray(0, sodium.crypto_secretstream_xchacha20poly1305_ABYTES)) 109 | }) 110 | 111 | /* without explicit rekeying */ 112 | 113 | ret = sodium.crypto_secretstream_xchacha20poly1305_init_push(state, header, k) 114 | ret = sodium.crypto_secretstream_xchacha20poly1305_push(state, c1, m1, null, sodium.crypto_secretstream_xchacha20poly1305_TAG_MESSAGE) 115 | t.equal(ret, m1_len + sodium.crypto_secretstream_xchacha20poly1305_ABYTES) 116 | ret = sodium.crypto_secretstream_xchacha20poly1305_push(state, c2, m2, null, sodium.crypto_secretstream_xchacha20poly1305_TAG_MESSAGE) 117 | t.equal(ret, m2_len + sodium.crypto_secretstream_xchacha20poly1305_ABYTES) 118 | 119 | ret = sodium.crypto_secretstream_xchacha20poly1305_init_pull(state, header, k) 120 | ret = sodium.crypto_secretstream_xchacha20poly1305_pull(state, m1, tag, c1, null) 121 | t.equal(ret, m1_len) 122 | ret = sodium.crypto_secretstream_xchacha20poly1305_pull(state, m2, tag, c2, null) 123 | t.equal(ret, m2_len) 124 | 125 | /* with explicit rekeying */ 126 | 127 | ret = sodium.crypto_secretstream_xchacha20poly1305_init_push(state, header, k) 128 | ret = sodium.crypto_secretstream_xchacha20poly1305_push(state, c1, m1, null, sodium.crypto_secretstream_xchacha20poly1305_TAG_MESSAGE) 129 | t.equal(ret, m1_len + sodium.crypto_secretstream_xchacha20poly1305_ABYTES) 130 | 131 | sodium.crypto_secretstream_xchacha20poly1305_rekey(state) 132 | 133 | ret = sodium.crypto_secretstream_xchacha20poly1305_push(state, c2, m2, null, sodium.crypto_secretstream_xchacha20poly1305_TAG_MESSAGE) 134 | t.equal(ret, m2_len + sodium.crypto_secretstream_xchacha20poly1305_ABYTES) 135 | 136 | ret = sodium.crypto_secretstream_xchacha20poly1305_init_pull(state, header, k) 137 | ret = sodium.crypto_secretstream_xchacha20poly1305_pull(state, m1, tag, c1, null) 138 | t.equal(ret, m1_len) 139 | 140 | t.throws(() => { 141 | sodium.crypto_secretstream_xchacha20poly1305_pull(state, m2, tag, c2, null) 142 | }) 143 | 144 | sodium.crypto_secretstream_xchacha20poly1305_rekey(state) 145 | 146 | ret = sodium.crypto_secretstream_xchacha20poly1305_pull(state, m2, tag, c2, null) 147 | t.equal(ret, m2_len) 148 | 149 | /* with explicit rekeying using TAG_REKEY */ 150 | 151 | sodium.crypto_secretstream_xchacha20poly1305_init_push(state, header, k) 152 | 153 | statesave.set(state) 154 | 155 | ret = sodium.crypto_secretstream_xchacha20poly1305_push(state, c1, m1, null, sodium.crypto_secretstream_xchacha20poly1305_TAG_REKEY) 156 | t.equal(ret, m1_len + sodium.crypto_secretstream_xchacha20poly1305_ABYTES) 157 | 158 | ret = sodium.crypto_secretstream_xchacha20poly1305_push(state, c2, m2, null, sodium.crypto_secretstream_xchacha20poly1305_TAG_MESSAGE) 159 | t.equal(ret, m2_len + sodium.crypto_secretstream_xchacha20poly1305_ABYTES) 160 | 161 | csave.subarray(0, m2_len + sodium.crypto_secretstream_xchacha20poly1305_ABYTES).set(c2.subarray(0, m2_len + sodium.crypto_secretstream_xchacha20poly1305_ABYTES)) 162 | 163 | sodium.crypto_secretstream_xchacha20poly1305_init_pull(state, header, k) 164 | ret = sodium.crypto_secretstream_xchacha20poly1305_pull(state, m1, tag, c1, null) 165 | t.equal(ret, m1_len) 166 | t.equal(tag[0], sodium.crypto_secretstream_xchacha20poly1305_TAG_REKEY[0]) 167 | 168 | ret = sodium.crypto_secretstream_xchacha20poly1305_pull(state, m2, tag, c2, null) 169 | t.equal(ret, m2_len) 170 | t.equal(tag[0], sodium.crypto_secretstream_xchacha20poly1305_TAG_MESSAGE[0]) 171 | 172 | state.set(statesave) 173 | 174 | ret = sodium.crypto_secretstream_xchacha20poly1305_push(state, c1, m1, null, sodium.crypto_secretstream_xchacha20poly1305_TAG_MESSAGE) 175 | t.equal(ret, m1_len + sodium.crypto_secretstream_xchacha20poly1305_ABYTES) 176 | 177 | ret = sodium.crypto_secretstream_xchacha20poly1305_push(state, c2, m2, null, sodium.crypto_secretstream_xchacha20poly1305_TAG_MESSAGE) 178 | t.equal(ret, m2_len + sodium.crypto_secretstream_xchacha20poly1305_ABYTES) 179 | t.notSame( 180 | csave.subarray(0, m2_len + sodium.crypto_secretstream_xchacha20poly1305_ABYTES), 181 | c2.subarray(0, m2_len + sodium.crypto_secretstream_xchacha20poly1305_ABYTES) 182 | ) 183 | 184 | /* New stream */ 185 | 186 | sodium.crypto_secretstream_xchacha20poly1305_init_push(state, header, k) 187 | 188 | ret = sodium.crypto_secretstream_xchacha20poly1305_push(state, c1, m1, null, 189 | sodium.crypto_secretstream_xchacha20poly1305_TAG_PUSH) 190 | t.equal(ret, m1_len + sodium.crypto_secretstream_xchacha20poly1305_ABYTES) 191 | 192 | /* Force a counter overflow, check that the key has been updated 193 | * even though the tag was not changed to REKEY */ 194 | 195 | const nonce = state.subarray(NONCE_OFFSET, PAD_OFFSET) 196 | for (let i = 0; i < 4; i++) { 197 | nonce[i] = 0xff 198 | } 199 | state_copy.set(state) 200 | 201 | ret = sodium.crypto_secretstream_xchacha20poly1305_push(state, c2, m2, ad, sodium.crypto_secretstream_xchacha20poly1305_TAG_MESSAGE) 202 | t.equal(ret, m2_len + sodium.crypto_secretstream_xchacha20poly1305_ABYTES) 203 | t.notSame(state_copy.subarray(0, NONCE_OFFSET), state.subarray(0, NONCE_OFFSET)) 204 | t.notSame(state_copy.subarray(NONCE_OFFSET, PAD_OFFSET), state.subarray(NONCE_OFFSET, PAD_OFFSET)) 205 | t.equal(state.subarray(NONCE_OFFSET, PAD_OFFSET)[0], 1) 206 | t.ok(sodium.sodium_is_zero(state.subarray(NONCE_OFFSET + 1, NONCE_OFFSET + 4))) 207 | 208 | sodium.crypto_secretstream_xchacha20poly1305_init_pull(state, header, k) 209 | 210 | ret = sodium.crypto_secretstream_xchacha20poly1305_pull(state, m1, tag, c1, null) 211 | t.equal(ret, m1_len) 212 | t.equal(tag[0], sodium.crypto_secretstream_xchacha20poly1305_TAG_PUSH[0]) 213 | t.same(m1, m1_) 214 | 215 | for (let i = 0; i < 4; i++) { 216 | nonce[i] = 0xff 217 | } 218 | 219 | ret = sodium.crypto_secretstream_xchacha20poly1305_pull(state, m2, tag, c2, ad) 220 | t.equal(ret, m2_len) 221 | t.equal(tag[0], sodium.crypto_secretstream_xchacha20poly1305_TAG_MESSAGE[0]) 222 | t.same(m2, m2_) 223 | 224 | t.end() 225 | }) 226 | } 227 | -------------------------------------------------------------------------------- /crypto_shorthash.js: -------------------------------------------------------------------------------- 1 | var test = require('tape') 2 | 3 | var vectors = [ // generated from https://github.com/jedisct1/siphash-js/blob/master/test/index.js 4 | ['aON1dHrq90SbG8Hx', 'v7LyiwuCrB7EgAibPve6Yg2gLmggxE6j7ocR37EudrH_P9XX2rQK', [147, 73, 50, 63, 71, 98, 203, 42]], 5 | ['YOT4AG5F7ONRW5na', '4Ks1pPO_2wGYR-gfJShqUO-FirA9c5cF4oKwvStp2Ix5hHUg2klPofVJ8TZoBdFfgTh8', [138, 27, 129, 27, 185, 163, 160, 153]], 6 | ['63UlqXfSckA3Dv8S', 'bMQudI8yVdDx5ScGQCMQy4K_QXYCq1w1eC', [6, 78, 44, 167, 186, 29, 113, 244]], 7 | ['P3hpmZEuwfDO_uZ-', 'Wh8yRitk__n4MsETCTRFrB4bjWRtPjUZVLPnywlvv5nTMA2C71', [241, 171, 151, 44, 166, 163, 156, 234]], 8 | ['d9oTrpd-a_Na4b6w', 'f-NT', [182, 147, 203, 88, 65, 57, 119, 203]], 9 | ['fe88HBnyyEiuIJ8G', 'KSWP9sFkhSdGsha0Fmd5raCf_eA5gnV1', [218, 10, 3, 10, 16, 50, 241, 229]], 10 | ['o6LxtnACG0RGQ3z-', 'k8zMl', [16, 158, 19, 145, 214, 142, 177, 55]], 11 | ['AHGkoQQ6xdf90MD9', 'HC9bz8XUYkan0jxYSaj0vP-cs324Y4PrnAXutwKBgIko5oOOOViJSjLD2m8WenV8HdF78J', [157, 186, 255, 238, 165, 21, 187, 163]], 12 | ['TlVmpfbZMFkeuENo', '5is', [166, 36, 114, 58, 101, 106, 79, 30]], 13 | ['iBLscVfsPM1xrSFJ', 'J-aH-', [14, 91, 64, 158, 190, 247, 72, 26]], 14 | ['hUehErdKolgd0erH', 'DhS94w_07-vaAXo_msv8Fk57slIHnuxy3iv4Yymh5k', [45, 207, 192, 24, 158, 243, 93, 68]], 15 | ['B-aq-09jmO0z_PUD', '1p2IMG4A1NMyWsfUS02VK8fOEhn', [161, 224, 65, 80, 91, 44, 131, 177]], 16 | ['fyNYE8SMJvYrDgao', 'HWCtQs19BHZcH', [122, 114, 254, 14, 124, 226, 23, 173]], 17 | ['5vQHK_yJlJez45N5', '8YJwfpxwbH9h-N27i-uTUUK2Vt', [142, 216, 87, 77, 16, 17, 8, 199]], 18 | ['q7Oo0g9DDjLJ_pyV', 'jQFAHtrTUDaCaSIcis5h2j4fyOJpJGfdZBMTO5GOAAB4AwZtutDenNZ', [230, 111, 182, 25, 233, 231, 14, 141]], 19 | ['IUle6P8g2uyX_8ms', 'hOKGFGrsAux60CQmbOjQd-EzQBKUjLbDUhhtsKt3ZY4', [64, 247, 102, 236, 211, 145, 4, 152]], 20 | ['-bZa23onpInwqNWG', 'DNbtZuulH9', [247, 2, 142, 172, 208, 100, 60, 127]], 21 | ['1xjmLXTmVJwse8M-', 'j1_Hh', [197, 81, 6, 184, 57, 173, 83, 126]], 22 | ['Ey7hygEVd8RxZdtX', 'GNRDNJDu00L', [137, 196, 184, 4, 146, 27, 188, 191]], 23 | ['weTzikz4EGUbhSgC', 'g1SXT7b4Zz6q2tQykV1tZS', [105, 39, 69, 220, 198, 210, 96, 240]], 24 | ['OjSaplYVoQPDXG7S', 'QCk4v3D9s6R471p0xa--Vv00vzIaMpJ1S48Qnz6uzhmtke99HmWcY9vapyjdWVS', [183, 208, 142, 194, 95, 247, 239, 122]], 25 | ['4g2ZB-SA-HlqJT7D', 'N5Ht5QIk6KziyTE4-q5eNkqGdQgg8fxkr4w-ARqRgdaZd3XpbePGGb4jPFo3', [127, 245, 152, 248, 155, 148, 212, 127]], 26 | ['CXOF2EKm5CDPYpNC', 'xkY0T8bPF4JFq6Mu0K5YtFp7KfOni', [124, 172, 24, 66, 198, 236, 234, 226]], 27 | ['ID4UzFBiztXW--b0', 'qyICNMPaivgDmX', [46, 95, 156, 18, 186, 88, 188, 122]], 28 | ['TaGesMDe_0UNGzcp', 'nlNv', [103, 245, 211, 70, 87, 104, 0, 17]], 29 | ['lMDS8Vcs-8aCV9hJ', 'KW44Qk', [69, 47, 130, 50, 196, 101, 206, 62]], 30 | ['BmQCaB-c777zvFsc', 'o-tr2zQVbtrmkH4rCCAXoXFt8KwAWo4YFpK', [123, 168, 235, 94, 113, 233, 190, 213]], 31 | ['OQlCpJOLmsouyme1', 'aRk9nyHhXlad-TpIemD2VTRiHVlzSysY7uKof9ApR5DejFjT-Bmdzl_z', [89, 201, 222, 238, 50, 99, 249, 215]], 32 | ['t6Wl3FKDhr9FAMzz', 'BLu17bk_iQtpGv1N4A', [80, 7, 121, 129, 115, 84, 153, 140]], 33 | ['XU5km7La0ujNVvlV', 'OUEAH4yu6SXQ4I8zjn07NuB_AudmoewXc39HqgN8rc', [220, 180, 100, 142, 210, 176, 72, 108]], 34 | ['zDKBNpM2cdf0HwkK', 'dEqgpqTRc', [221, 42, 57, 242, 197, 147, 27, 81]], 35 | ['yZGrKEShM0z7Vvns', 'sgUtgxRQpMl_o6iuZqomKhJxaSBCD_NBHa2lqX3cWfq8byu', [211, 179, 114, 59, 129, 223, 168, 65]], 36 | ['4-wM8GXg1a7hyerE', 'djJ3-b2', [157, 165, 254, 119, 109, 239, 114, 115]], 37 | ['jD3Y4PgdExHU2JaY', 'uQC59dKTf3unOGu-Lg9IgmC8MTSg-BcH-', [249, 179, 174, 181, 118, 232, 40, 255]], 38 | ['dZhRW8ubIZovieQg', 'GCbxph1HICSKgHLafk_8TRjGdZa7jnJOu', [73, 24, 76, 226, 201, 86, 43, 223]], 39 | ['P9hudzT3H87QzC9E', 'Vfeo26fUa3sLk6BNM', [31, 150, 174, 223, 224, 214, 127, 107]], 40 | ['ocfdt04Np8Bs5hn9', 'dQiaUqksbXOWmBPt2kBn0ARiVkr3r4mBwypQq', [203, 253, 155, 6, 148, 92, 81, 212]], 41 | ['UuQ68x330IdojsLI', 'pb6-OdmVdQ1gLP8E1szvlf0T6aOQp-EQHPW-tAKQ8Xj', [23, 158, 11, 26, 216, 251, 17, 229]], 42 | ['T4ec6Q68QKiuIARL', 'BeLjFIoODtDg5vLMLBN1Sae', [250, 103, 43, 65, 80, 229, 66, 116]], 43 | ['xmZBUpwjJwnXZAp6', 'WS2F3Nzg2s7TqVIygm8W1tQyNc6DFy', [186, 206, 177, 250, 182, 139, 138, 19]], 44 | ['4qB6m0d_ryzb3w6q', '2Nr1sd1phWDB9gnuYOLUsjvX9jxntScWyRlX3Nj_xs8MV10LGgSgfRBKVGnO', [97, 101, 207, 79, 55, 205, 142, 253]], 45 | ['SmVONU3BEODnkbdM', 'G4WIU3UrBqbN6_nccFrIyx_TdXx-W80YzWw', [33, 147, 134, 20, 73, 169, 2, 107]], 46 | ['zseM9_-0y7B9URxM', 'us8B1DmHxOF10ue3jm2VfoJ250h364zRd2U8VIm2Lbkf3OWprSUpLF4ePjdj5aS', [80, 47, 98, 151, 139, 175, 78, 166]], 47 | ['WY_sEWLFAybHSwX4', 'vLJyXNkHCYGHWsvhXcU2sWYzgFYlWF7A_ZjFg8kJ4wwuJ', [132, 67, 168, 204, 90, 10, 169, 235]], 48 | ['maWrEov1bBjSq2Zn', 'sCP9zPakZ_wZ8hcQu-G6nN', [136, 204, 107, 221, 66, 198, 31, 201]], 49 | ['tXInZHO-x4AWxKTp', 'JQUM_O-E4-YI6dhxo', [36, 245, 166, 183, 31, 222, 192, 96]], 50 | ['OqaQt_b1hvU-atC3', 'X7Ou8cKo17xHlq_5gwM56GZrCSJBReeA60pDj2hUer6', [169, 107, 175, 79, 116, 24, 153, 93]], 51 | ['nHdnXHGmGknC8FfC', 'cRupnAESNmU', [18, 200, 205, 81, 7, 32, 8, 213]], 52 | ['59n9lAJdrxIz3joe', 'WBPr', [75, 153, 152, 122, 242, 233, 165, 255]], 53 | ['q-PAAgkE9z2xed85', 'AFOQD_H7MO3q3cxLa7TOUd89kpH03SpjpqmzY6AX16-uZFYcZZBb8D', [45, 4, 101, 133, 174, 99, 42, 4]], 54 | ['tBzStZxn2ZqlQfBf', 'nZdIaI7-bdqqh6aU7w4HfDCByX-x4_3q9Jf', [253, 49, 199, 224, 50, 253, 75, 144]], 55 | ['rH8Nn75LyYC0hjVG', 'IrDPpL-dkoh6VTy7pOtKKdAD9dLwUnE-', [76, 2, 97, 127, 190, 74, 74, 5]], 56 | ['F-pI7AhpS1V-48eT', 'Ao7hV41P08Zq4C1szyOVN7K1iWW8z', [121, 76, 85, 13, 162, 105, 174, 114]], 57 | ['Khje_RmXXmJ3CAb1', 'TvMx3ISTfIQ', [237, 102, 92, 182, 242, 45, 27, 178]], 58 | ['G1KRzk-KMqCk-kbD', 'imHZWdBz01lGR3m1zuO74berNn68uFZR3kcoWEaMhVjJ1g', [165, 3, 34, 126, 199, 101, 203, 184]], 59 | ['wJhnTtBLcy_1rZay', 'qbZ6oK0a4eWf2ud1sEnKLeguOmYsbG4aOTdlMdrf', [226, 169, 14, 147, 180, 88, 90, 132]], 60 | ['vVl9fhjkwASu2WXe', '8-CjQylw18IKWgAL2mMxo', [30, 193, 202, 34, 74, 172, 72, 42]], 61 | ['m2Qx2Dtbvwv3qjNJ', 'WrIqIIsHqbgm3Qfg03QvaVG9G6fz2zxjnfNZUVuX8XUtjz4LQuj3VZNh', [237, 163, 64, 58, 187, 234, 117, 106]], 62 | ['5R1maUgHiPQ0ZoaD', 'SZJ6uMXnMuLll2xOfHcy_DE', [209, 26, 182, 131, 19, 180, 5, 55]], 63 | ['dDBufcmObAK1dKYw', 'ayjd0F5mqWsVF0MtUNJYo8S8GhuCsMCnEU6k3H9z0f8', [126, 244, 206, 245, 56, 4, 39, 63]], 64 | ['o_YPVOjQ7Xw0G9OD', 'UPF-HW1hJukwdVvhCl7IZJzy7a', [30, 211, 48, 214, 88, 189, 59, 33]], 65 | ['oule-vFYlFJfsXU3', '8ORL7DUv28-yVfUw_cJ3imWP-iXrQRmzZRp0jtspwW_qm-rXmc1aBsbvbAut8', [66, 62, 243, 87, 153, 23, 230, 113]], 66 | ['kEPlQxhC27GQcJeb', 'wL-dAWvwZapITZZvgW46', [153, 83, 52, 252, 33, 23, 48, 216]], 67 | ['GFilE6NpBPWE25uB', 'RzoQCcd5NVeDbd2cx', [144, 101, 221, 104, 142, 244, 87, 216]], 68 | ['sENqlFHs0NvkY28u', 'Gm2ojB-BJBdL', [75, 226, 42, 7, 94, 14, 215, 52]], 69 | ['mxiOr15qouOEhzHS', 'SChjLg6SXpEb9', [174, 64, 56, 79, 211, 158, 21, 229]], 70 | ['pFL_Sbx5RW0fuPHO', 'hdb8HqaxEN99N4V1STTpnR4kr9F-lONwKp2TcOCopBFnDrjITz3jHPM4WKIYyw59US', [108, 66, 228, 165, 111, 142, 78, 201]], 71 | ['sMgAXpCtVqeFm14R', 'dNPnh6shnGYEZuN0id', [101, 147, 101, 20, 126, 33, 84, 255]], 72 | ['nTu9mRGqYc1SOPk7', 'ogL8VEqgoMkh6YNgTzvF4f87wHvmRhzncGPunN2ZJ5p3qUqZeJ3', [253, 16, 23, 144, 34, 207, 28, 82]], 73 | ['d5jDH8Ppk82zj_vd', '5sfq9Q_0P0H', [197, 245, 4, 89, 247, 26, 240, 77]], 74 | ['bEEUPVwdHlYwYL6o', 'AGoiVTE9foWm2MZqsn3dfS1XQiQW0QJwLXi6oXR2L9nMnPCPG_oF', [186, 203, 217, 87, 4, 177, 20, 242]], 75 | ['JbKhWuTfRMWb4hFD', 'NTNhYIahQ769TsCDwFyfOYZ8x6np58jg9hMAHFH-BMv7hBwESi596D4aDuyPabFGbqcG', [60, 79, 166, 97, 146, 213, 223, 59]], 76 | ['hvCtw1q_GJUBFW_X', 'uL5zgFM9WUTyO25dzVCmSVOxbpV70ZPurKK-CPUAmP', [127, 4, 233, 105, 7, 183, 123, 61]], 77 | ['hWxh0P6EXlm4yYKA', 'NUgrOoTOfqaB6JDZj', [96, 255, 249, 149, 117, 178, 189, 183]], 78 | ['TLHDMak8qeH3ABaV', 'HW-7PPunyMCinXt8QjQUuJUzZZQs1-T9ADR-6y', [46, 167, 85, 216, 34, 240, 131, 74]], 79 | ['uE4OfzzqHVDH8lbd', '8KCUyGtkcG-T8gA3lpplC13LsnFZ', [18, 9, 33, 96, 47, 132, 243, 76]], 80 | ['ocjA0Quge9vdCDbH', 'tLlU03I9CDBbP1Pnl6KM3MW34TNzuuZYv0u-uU-l7RtFF0OmGoySyg_yc7vWswGkz', [124, 174, 227, 126, 197, 91, 232, 11]], 81 | ['TDVmxGeyDULfxyrz', 'A57Y0_L6K4TTzQx1-Yr1E6fVAZi31RyipeK0Q4uqwXXfRLo4tz2a5PSqN3-bdQ4f2', [53, 212, 137, 227, 12, 85, 50, 251]], 82 | ['8OhqW3sA7s1vqEDr', 'jlFquRWvL07TyLjW9ZNk81gxkvs4u1WLkNhOQVLOjFjw3iecMjun5Yk0xcruo', [147, 130, 134, 67, 235, 29, 115, 34]], 83 | ['9kPcY6rfhPzSzEGn', 'nS1kAxpsghzJJXiCzhNycDk2_EJ_yIT97fV2kxXTtfZ9p0', [178, 109, 176, 237, 184, 79, 209, 89]], 84 | ['AJJ_yoEL8WyEtA1U', 'vFNErhfCk1TZiTFMA6J8D', [26, 63, 142, 247, 30, 50, 167, 102]], 85 | ['PBr4drRAJTaWv5Um', '5quc8Vd2rHVNk2NoDxk3TL', [150, 113, 209, 153, 101, 74, 42, 2]], 86 | ['MnODoRJI2FgZrvLs', 'gqJ_7HnrfiqYkenyvhe53SB1vTBgMiMB3kxF5', [205, 11, 216, 157, 130, 39, 60, 161]], 87 | ['iSxQPJpp_s0ws-4b', 'K-J', [46, 78, 209, 241, 112, 90, 91, 181]], 88 | ['ZMm2tCGDJ04A3I_6', 'gw-wcFYO1G2KEqJagWAic2l2d1FoTVXVT', [22, 60, 166, 216, 76, 146, 36, 22]], 89 | ['Hxf6qsSIV6blPdB1', 'GTWOerCQdUMkL6it6hEEPKBcOe_9f_B618ivjeM3BKfjzRQ8rvcGjUUJnsljerca6', [122, 74, 100, 36, 79, 173, 4, 91]], 90 | ['U5gXdMrRYUdxuDjK', 'siy9CxY2BbhazTqBWwFrtBLh', [79, 92, 248, 231, 189, 215, 27, 51]], 91 | ['YJiK_B-TENJsVnd_', 'Ohyz8XU06XWewcgTX-PffLVdatU3UFl6CYe', [22, 147, 91, 237, 188, 184, 70, 223]], 92 | ['J7wVNfLdkCCtndH5', '1Vw163YqXwP8cPXIy5dSkcIoClBep7gWb0qGJzHM8h_hzk2GFtZyLKk', [123, 221, 220, 145, 75, 144, 103, 74]], 93 | ['elId3b7ZyOg6HVif', 'N89kQR7VMUgF4DyWhpTo_ZW2lERbNqFa1RdXjaUctO1FdevDAZaA', [39, 244, 17, 57, 240, 193, 34, 112]], 94 | ['ydBueYO29jaUsEVU', 'HMcnfvYjjz8Uf8bUhxXlAYHcyO7x5NHE_gc3bcWSMWJD2JdryrUBBdYj1', [252, 15, 32, 244, 143, 126, 130, 34]], 95 | ['fVprx-PzTSx6CUcX', 'Q', [253, 22, 240, 135, 62, 55, 219, 1]], 96 | ['9ORMwecQjlob9aTT', '2cpq2XTWPk5sVLlN4OR5y6X_rTRFNUURgrwnWDg76u927cYud6PS-17UTgd3TO9g3K4', [15, 124, 108, 136, 56, 254, 85, 250]], 97 | ['-V3BEGXuTWtFOMv4', '8l6qcZXfG9iSywi1IgwJ_PkZh0Bg2iR1cbGps_sWPdKXbIvDDX-3IeTTg', [111, 8, 18, 99, 6, 72, 56, 232]], 98 | ['Cbvx4_KdboiNHs6P', 'nzUo0UnqKn05adw5g0jtBN703bUgb8UxywfC93I7KN', [85, 17, 95, 157, 77, 25, 206, 45]], 99 | ['SDPzfgeqkvmi62JH', 'Z6kJuDD-8FSz1VwOuPeoSJ6X-4hpib563UjYxtFcB4SvhQr-Hstg5OhMi4iZZ', [153, 35, 172, 58, 141, 180, 95, 97]], 100 | ['mBJlhP6D3M2raEjD', 'ogtg66jr2KLCFO2RvodOXw0mt4XS6BOnLhBI_gDV0', [85, 231, 198, 97, 240, 108, 230, 150]], 101 | ['Sz-mxKc7KGM7SDaf', 'ecQ-7-3VddOdMSeKUbZE1t6Aa67pYGXjQeOckq1l50GkvfomFr', [18, 241, 24, 133, 142, 74, 218, 178]], 102 | ['_5ck5scojT4oyJEq', '43oLkeixGHShTMUhtI', [35, 190, 107, 33, 2, 165, 11, 34]], 103 | ['48ulC82W4qv49InN', '8HQyT55TtmGahy6w', [2, 70, 28, 124, 164, 101, 100, 185]], 104 | ['-exgd5coAHqBu3ga', 'vRfqYthbUNh', [48, 188, 141, 96, 138, 114, 132, 143]], 105 | ['hJEBugObOX06pplH', 'oYYZ-v', [153, 112, 89, 5, 46, 138, 209, 254]], 106 | ['eSDsC63oTtVfi_F7', 'BVmyPas409CmRHiRRiTPjJL87KgJefuDK6lEh5isghLl7l3a4Xmxa', [21, 198, 30, 251, 173, 36, 165, 82]], 107 | ['KZtUPWMUr469RWL8', 'F9K6TUd6j7Dm25rAS7cqOKDtSnnxj0hYKVTMFQ6CfA5218gPeZo', [203, 233, 183, 39, 57, 54, 60, 173]], 108 | ['0TeBxGk-V7RPSZML', 'kmL1fKqHwAoxI1b_ap8I9fGZMmcx3gIMiglxLLPFWOoDNUGe', [193, 7, 13, 148, 71, 231, 166, 135]], 109 | ['PWYY82PNqwshPHiv', 'Ya4LyHqxIxK8GaND9FIzqugleh-QELha_ntbRJixl6hZI5m3RfdrcntjiPJ', [27, 177, 64, 55, 129, 165, 132, 108]], 110 | ['PtCub86vGwNj1tcv', 'qR08eqAeNrrUYDl18C-wttqMDk', [66, 134, 247, 100, 38, 3, 7, 125]], 111 | ['3eqQxzhNdv2kJqy5', '0wxAd9NT-Z8xFzomFwgMqMVbaUg', [36, 191, 165, 105, 211, 159, 155, 13]], 112 | ['MgEjpTNPFFwes6Sm', '7SCVGNJYZhtnbiLZAE5TrsL5K1X', [208, 79, 201, 49, 48, 3, 227, 199]], 113 | ['vSofRAYxXUU1qjhl', 'HATE-YsASxySRkK5aJR4yV0mxx1YAuEgM5tUqyJDc7cLL', [61, 205, 183, 24, 68, 135, 7, 74]], 114 | ['kIUe96sZ6LV464T_', 'rjwrCOQAzLFbIM_3M7KfDQ1A6r3nkebk-dgqORG0Uy-n89_apYNLVTbdr3yuzXKOTfkRh', [83, 214, 143, 126, 145, 218, 225, 186]], 115 | ['8wao85IcCu1mC-Rc', 'AdVncBX6wkLXqMQPol3tNDPd5HJ', [161, 223, 243, 36, 219, 75, 215, 63]], 116 | ['NRVNeO5wysG3DRuU', 'Mr8vhiVPo5GpI6sho4R09k8D-vFgcghF3-kF', [246, 119, 57, 225, 254, 189, 182, 180]], 117 | ['VHJZOECxfyxVyufk', 'TMB3UMDEIs-vj_9aDBNDzT6HkHcwQQhr4EnG6A1AD9JkHENVAAQnS7s', [117, 85, 69, 116, 56, 27, 123, 62]], 118 | ['TUfnTd3pmaJzSdD4', 'VoRGCJgaGEhPSGRl0EPKWIzN7CRpD49CiyjC7y_4xRpppMNlR4v', [3, 116, 140, 4, 113, 208, 78, 186]], 119 | ['-I1YgwmWxehyB6kv', 'IplQLxea3JGywQn3XMNWrqVbE', [137, 251, 109, 201, 11, 101, 132, 97]], 120 | ['4ic5nM5lbfMOXDRR', 'TfVtpOoAQt1IxL0qJtAQoCJJThyxncIagOvKSpxjD7RDmh7YQBHWPkuv5lpSzpN', [192, 203, 84, 99, 85, 184, 122, 44]], 121 | ['NYOq6hIu2C-aZPhE', 'QQa0EWIHXqbrkq3nBeXt6yEj12z', [40, 199, 197, 21, 82, 53, 100, 58]], 122 | ['nC93tajnfzk6bMtM', 'p9gbEB4nMHXDqmOC413rI4Z', [200, 140, 102, 143, 89, 170, 219, 32]], 123 | ['ZCCkYIbGOzXa5GRO', '2f9VGQeb4AtW6SwPjAGxxjyHNw3-MZj2BfxttNLxM0Tv_rpXO8TUH4YASb', [0, 174, 100, 194, 149, 35, 81, 12]], 124 | ['oapO2W6hces4Pfkc', 'oEyf5eqpM-N7LBp3C5vejvO7M87OzT4MHdwJz', [140, 195, 199, 20, 207, 60, 104, 240]], 125 | ['__daPiDXrnPpS7eO', '1_tnhApr6nZbWIEPja0jAJ6LbTvD6oAEvPyrLYQ', [255, 244, 76, 119, 124, 124, 146, 214]], 126 | ['5iIExqPt5W-ZpudD', 'jNbLiDmQdN5X7HEOfgnAi5A7s1pGXwP41hX1Z', [149, 68, 125, 203, 174, 150, 66, 31]], 127 | ['gD_J-R8tOb977BtL', 'f7A81Qbh8gQhfRpOmtz5-ZJqBxiQJ6myBhGfqK7BVaGBL_W2MvfB', [106, 38, 140, 196, 141, 190, 232, 110]], 128 | ['ZxHO4JJ8p45jTUXU', 'fs4Oy8mPZS6919SZ7gDyKIILDkXnPt8SsXkfBd-Mnm4wO6alw-veQD9', [209, 53, 104, 100, 102, 136, 84, 134]], 129 | ['2bVzT0moojGNQgIX', 'nuyb-AgYY-rsmhtdav3LC7meSPy1dCosjSw0YAvgP', [1, 201, 247, 25, 104, 147, 148, 252]], 130 | ['FicyyNT0BRua05i9', 'TG4leSS_mcrZ_L68GKFdxc4-McFCCtdG7QpbPu_MolD5luE6n3dKlPzb9MvfvkiZKi', [136, 150, 66, 224, 178, 235, 114, 238]], 131 | ['g5Qaf7mQAIxuHR0O', 'A6u5gtb1yMSiGlWVt3exYsRS', [169, 20, 115, 32, 43, 71, 21, 193]], 132 | ['aOACI6GP6u4WFyxp', '1eEx55L3E9MZga7l1WzpnKfI', [177, 26, 15, 27, 217, 101, 69, 195]], 133 | ['Rr2jLg-asIQrlaRJ', 'rgALEbs', [163, 103, 250, 90, 4, 46, 69, 32]], 134 | ['p8qW0oYzj5zi55s5', 'V1ZCoK73ifwcnzPjQEN7Q79MtZCskcpqiE3gfbqYPYRmy-q0lPxopkZZp2lNWKkpL_q5z', [29, 121, 240, 174, 51, 38, 238, 123]], 135 | ['wA0cNUJOhIMpiopE', 'U2RE2L2zZysyOTcsj5_JosVDaMRtUxkRWVCeBH0AeodMvYGBcHizhxc2QM89', [40, 230, 148, 164, 7, 168, 3, 46]], 136 | ['zBCN1w4ypWCEfpwC', 'VRcTwONsyRQIy2ymVniMmry', [184, 177, 56, 54, 152, 189, 120, 222]], 137 | ['i8cumEDwOxSXT0gL', 'ifKav', [53, 190, 193, 228, 179, 41, 246, 171]], 138 | ['g3EswbaCSNMsegzm', 'rTFnEuEDlwBB0Dw_q3-FUSaTCEjWe0pOPZDIWD35Us08Qa-nulc57YjDoGphUfBamq', [157, 64, 119, 179, 60, 147, 48, 17]], 139 | ['iYsckWoQTk5ap8YO', 'wIyTqa43-_GiZlHJ8UXcD_tnqKikH5DZUWxdQ1xjYMyzCr2JvKKRBm8BbcDl_Q8p', [96, 237, 170, 183, 48, 45, 116, 106]], 140 | ['Iyk5MoAjoWq4n8bG', 'IV2N5MC6kvk95ykEzb3jj0A7Sv0jjif45SR1avc0bRWot2aW', [99, 23, 149, 225, 242, 204, 47, 7]], 141 | ['NfzdRXCegRRsHHYj', '5uLBPbyFQqiv', [136, 45, 110, 192, 36, 204, 171, 218]], 142 | ['YiJTXegVwaNDtlpl', 'DbwKoF3CI5kd2JRKwfyuLpeGd6sFhqI0t43C2ph', [188, 126, 147, 191, 9, 114, 107, 60]], 143 | ['ZuUlFM-yEzZ9XHKj', 'errecd71', [158, 231, 84, 47, 149, 227, 92, 111]], 144 | ['EtEXELa6V_NSjvEh', 'yrTjrRuW8mJc3utw2JUH7iIW-J5vF3t9GC1-ZvRmO8UXNsG8-I3Iqgtinzoabqqbs1yvR', [186, 52, 144, 215, 104, 246, 174, 71]], 145 | ['q2uA_VwMnaBtAgTx', 'uJOymuDgBBS9Ec56JRGmKYsMHoGLCKA5wzwhtYf-g8-IT7UsAX1JHFGSV0EF', [176, 65, 188, 134, 212, 6, 97, 186]], 146 | ['4RmqR10QiIZDDKNO', 'oWY0Aj2CDCWuEFhdNHq2RFcGJD0sSRxK5K', [114, 28, 238, 228, 122, 40, 82, 13]], 147 | ['a9DfUPCLyQ_yrNIa', '5G-6AVe7CBJl-NuuUN_7TN', [95, 206, 124, 185, 194, 207, 227, 111]], 148 | ['8oB5yG87C2v5j0_4', '1S-aiUNRJ2c', [123, 42, 242, 79, 90, 36, 208, 81]], 149 | ['ZA2ZT22NXwD_UvTM', 'UpV3pLYniWPm-PnWUAbBNeO4V-zuuw6IZQ1ZprLsC_LjGdSJP7rZCnoPz', [189, 209, 102, 128, 246, 141, 212, 109]], 150 | ['ycz6aiuQFGKxZVsM', 'fBuJp4_A_hiq--4uBhxjXfT3nRaYEJ8azW2_FKooXdSVRv2Y03VoWzPzG', [241, 127, 162, 199, 73, 10, 75, 24]], 151 | ['eAmt0pClMyL8Sk69', 'JFzXjfJhEMUCYEDrBKRM9OFFK0PSX', [176, 167, 43, 60, 16, 69, 194, 2]], 152 | ['CTFnU2nwy9s1_kBj', 'hEHqR0idFTzbvG193aLYj6y2DFPi2UKQut_A--43PdN1XF', [6, 84, 156, 248, 125, 55, 230, 121]], 153 | ['CAhom0f872WEDXP6', 'dmX', [203, 98, 175, 172, 19, 3, 244, 177]], 154 | ['aON1dHrq90SbG8Hx', 'v7LyiwuCrB7EgAibPve6Yg2gLmggxE6j7ocR37EudrH_P9XX2rQK', [147, 73, 50, 63, 71, 98, 203, 42]] 155 | ] 156 | 157 | module.exports = function (sodium) { 158 | test('constants', function (assert) { 159 | assert.ok(sodium.crypto_shorthash_PRIMITIVE) 160 | assert.ok(sodium.crypto_shorthash_KEYBYTES > 0) 161 | assert.ok(sodium.crypto_shorthash_BYTES > 0) 162 | assert.end() 163 | }) 164 | 165 | test('crypto_shorthash fixtures', function (assert) { 166 | run(assert) 167 | }) 168 | 169 | test('crypto_shorthash fixtures (wasm)', function (assert) { 170 | if (!sodium.crypto_shorthash_WASM_SUPPORTED) { 171 | assert.pass('wasm not supported') 172 | assert.end() 173 | return 174 | } 175 | 176 | assert.ok(sodium.crypto_shorthash_WASM_LOADED) 177 | run(assert) 178 | }) 179 | 180 | function run (assert) { 181 | for (var i = 0; i < vectors.length; i++) { 182 | var v = vectors[i] 183 | var key = Buffer.from(v[0]) 184 | var message = Buffer.from(v[1]) 185 | var expected = Buffer.from(v[2]) 186 | var out = Buffer.alloc(sodium.crypto_shorthash_BYTES) 187 | 188 | sodium.crypto_shorthash(out, message, key) 189 | if (Buffer.compare(out, expected) !== 0) { 190 | assert.fail('Failed on fixture #' + i) 191 | assert.end() 192 | return 193 | } 194 | } 195 | 196 | assert.pass('Passed all fixtures') 197 | assert.end() 198 | } 199 | } 200 | -------------------------------------------------------------------------------- /crypto_sign.js: -------------------------------------------------------------------------------- 1 | var test = require('tape') 2 | var fixtures = require('./fixtures/crypto_sign.json') 3 | 4 | module.exports = function (sodium) { 5 | test('crypto_sign_open fixtures', function (assert) { 6 | for (var i = 0; i < fixtures.length; i++) { 7 | var publicKey = new Uint8Array(fixtures[i][1]) 8 | var message = new Uint8Array(fixtures[i][3]) 9 | var signed = new Uint8Array([].concat(fixtures[i][2], fixtures[i][3])) 10 | 11 | if (!sodium.crypto_sign_open(message, signed, publicKey)) { 12 | assert.fail('Failed on fixture #' + i) 13 | assert.end() 14 | return 15 | } 16 | } 17 | 18 | assert.pass('Passed all fixtures') 19 | assert.end() 20 | }) 21 | 22 | test('crypto_sign fixtures', function (assert) { 23 | var fixtures = require('./fixtures/crypto_sign.json') 24 | 25 | for (var i = 0; i < fixtures.length; i++) { 26 | var secretKey = new Uint8Array([].concat(fixtures[i][0], fixtures[i][1])) 27 | var message = new Uint8Array(fixtures[i][3]) 28 | 29 | var expected = new Uint8Array([].concat(fixtures[i][2], fixtures[i][3])) 30 | var actual = new Uint8Array(sodium.crypto_sign_BYTES + message.length) 31 | 32 | sodium.crypto_sign(actual, message, secretKey) 33 | 34 | if (Buffer.compare(actual, expected) !== 0) { 35 | assert.fail('Failed on fixture #' + i) 36 | assert.end() 37 | return 38 | } 39 | } 40 | 41 | assert.pass('Passed all fixtures') 42 | assert.end() 43 | }) 44 | 45 | test('crypto_sign_verify_detached fixtures', function (assert) { 46 | var fixtures = require('./fixtures/crypto_sign.json') 47 | 48 | for (var i = 0; i < fixtures.length; i++) { 49 | var publicKey = new Uint8Array(fixtures[i][1]) 50 | var message = new Uint8Array(fixtures[i][3]) 51 | var signature = new Uint8Array(fixtures[i][2]) 52 | 53 | if (!sodium.crypto_sign_verify_detached(signature, message, publicKey)) { 54 | assert.fail('Failed on fixture #' + i) 55 | assert.end() 56 | return 57 | } 58 | } 59 | 60 | assert.pass('Passed all fixtures') 61 | assert.end() 62 | }) 63 | 64 | test('crypto_sign_detached fixtures', function (assert) { 65 | var fixtures = require('./fixtures/crypto_sign.json') 66 | 67 | for (var i = 0; i < fixtures.length; i++) { 68 | var secretKey = new Uint8Array([].concat(fixtures[i][0], fixtures[i][1])) 69 | var message = new Uint8Array(fixtures[i][3]) 70 | 71 | var expected = new Uint8Array(fixtures[i][2]) 72 | var actual = new Uint8Array(sodium.crypto_sign_BYTES) 73 | 74 | sodium.crypto_sign_detached(actual, message, secretKey) 75 | 76 | if (Buffer.compare(actual, expected) !== 0) { 77 | assert.fail('Failed on fixture #' + i) 78 | assert.end() 79 | return 80 | } 81 | } 82 | 83 | assert.pass('Passed all fixtures') 84 | assert.end() 85 | }) 86 | 87 | test('libsodium', assert => { 88 | let sig = new Uint8Array(sodium.crypto_sign_BYTES) 89 | let sm = new Uint8Array(1024 + sodium.crypto_sign_BYTES) 90 | let skpk = new Uint8Array(sodium.crypto_sign_SECRETKEYBYTES) 91 | let pk = new Uint8Array(sodium.crypto_sign_PUBLICKEYBYTES) 92 | let sk = new Uint8Array(sodium.crypto_sign_SECRETKEYBYTES) 93 | let smlen 94 | let i 95 | let test 96 | 97 | sig.fill(0) 98 | 99 | var pass = true 100 | for (i = 0; i < fixtures.length; i++) { 101 | test = parseTest(fixtures[i]) 102 | 103 | skpk.set(test.sk) 104 | skpk.set(test.pk, sodium.crypto_sign_SEEDBYTES) 105 | 106 | smlen = sodium.crypto_sign(sm.subarray(0, test.m.byteLength + sodium.crypto_sign_BYTES), test.m, skpk) 107 | pass &= smlen === sodium.crypto_sign_BYTES + test.m.byteLength 108 | pass &= Buffer.compare(test.sig, sm.subarray(0, 64)) === 0 109 | pass &= sodium.crypto_sign_open(test.m, sm.subarray(0, smlen), test.pk) 110 | 111 | sodium.crypto_sign_detached(sig, test.m, skpk) 112 | 113 | pass &= sig.byteLength !== 0 && sig.byteLength <= sodium.crypto_sign_BYTES 114 | pass &= Buffer.compare(test.sig, sig) === 0 115 | pass &= sodium.crypto_sign_verify_detached(sig, test.m.subarray(0, i), test.pk) 116 | 117 | if (!pass) assert.fail('failed on fixture #' + i) 118 | } 119 | assert.pass('passed all fixtures') 120 | 121 | for (let j = 1; j < 8; j++) { 122 | sig[63] ^= (j << 5) 123 | 124 | assert.notOk(sodium.crypto_sign_verify_detached(sig, test.m.subarray(0, i), test.pk)) 125 | 126 | sig[63] ^= (j << 5) 127 | } 128 | 129 | pk.fill(0) 130 | assert.notOk(sodium.crypto_sign_verify_detached(sig, test.m.subarray(0, i), pk)) 131 | 132 | sig.subarray(0, 32).fill(0xff) 133 | sig[0] = 0xdb 134 | 135 | assert.notOk(sodium.crypto_sign_verify_detached(sig, test.m.subarray(0, i), pk)) 136 | sodium.crypto_sign_detached(sig, test.m.subarray(0, i), skpk) 137 | 138 | hex2bin(pk, '3eee494fb9eac773144e34b0c755affaf33ea782c0722e5ea8b150e61209ab36') 139 | assert.notOk(sodium.crypto_sign_verify_detached(sig, test.m.subarray(0, i), pk)) 140 | 141 | hex2bin(pk, '0200000000000000000000000000000000000000000000000000000000000000') 142 | assert.notOk(sodium.crypto_sign_verify_detached(sig, test.m.subarray(0, i), pk)) 143 | 144 | hex2bin(pk, '0500000000000000000000000000000000000000000000000000000000000000') 145 | assert.notOk(sodium.crypto_sign_verify_detached(sig, test.m.subarray(0, i), pk)) 146 | 147 | const keypair_seed = new Uint8Array([ 148 | 0x42, 0x11, 0x51, 0xa4, 0x59, 0xfa, 0xea, 0xde, 0x3d, 0x24, 0x71, 149 | 0x15, 0xf9, 0x4a, 0xed, 0xae, 0x42, 0x31, 0x81, 0x24, 0x09, 0x5a, 150 | 0xfa, 0xbe, 0x4d, 0x14, 0x51, 0xa5, 0x59, 0xfa, 0xed, 0xee 151 | ]) 152 | 153 | assert.doesNotThrow(() => sodium.crypto_sign_seed_keypair(pk, sk, keypair_seed)) 154 | assert.doesNotThrow(() => sodium.crypto_sign_keypair(pk, sk)) 155 | 156 | assert.assert(sodium.crypto_sign_BYTES > 0) 157 | assert.assert(sodium.crypto_sign_SEEDBYTES > 0) 158 | assert.assert(sodium.crypto_sign_PUBLICKEYBYTES > 0) 159 | assert.assert(sodium.crypto_sign_SECRETKEYBYTES > 0) 160 | assert.equal(sodium.crypto_sign_BYTES, 64) 161 | assert.equal(sodium.crypto_sign_SEEDBYTES, 32) 162 | assert.equal(sodium.crypto_sign_PUBLICKEYBYTES, 32) 163 | assert.equal(sodium.crypto_sign_SECRETKEYBYTES, 64) 164 | 165 | assert.end() 166 | }) 167 | 168 | test('ed25519 convert', (assert) => { 169 | const keypair_seed = new Uint8Array([ 170 | 0x42, 0x11, 0x51, 0xa4, 0x59, 0xfa, 0xea, 0xde, 0x3d, 0x24, 0x71, 171 | 0x15, 0xf9, 0x4a, 0xed, 0xae, 0x42, 0x31, 0x81, 0x24, 0x09, 0x5a, 172 | 0xfa, 0xbe, 0x4d, 0x14, 0x51, 0xa5, 0x59, 0xfa, 0xed, 0xee 173 | ]) 174 | 175 | const ed25519_pk = new Uint8Array(sodium.crypto_sign_PUBLICKEYBYTES) 176 | const ed25519_skpk = new Uint8Array(sodium.crypto_sign_SECRETKEYBYTES) 177 | const curve25519_pk = new Uint8Array(sodium.crypto_scalarmult_BYTES) 178 | const curve25519_pk2 = new Uint8Array(sodium.crypto_scalarmult_BYTES) 179 | const curve25519_sk = new Uint8Array(sodium.crypto_scalarmult_BYTES) 180 | const curve25519_pk_hex = new Uint8Array(sodium.crypto_scalarmult_BYTES * 2 + 1) 181 | const curve25519_sk_hex = new Uint8Array(sodium.crypto_scalarmult_BYTES * 2 + 1) 182 | 183 | assert.ok(sodium.crypto_sign_SEEDBYTES <= sodium.crypto_hash_sha512_BYTES) 184 | 185 | sodium.crypto_sign_seed_keypair(ed25519_pk, ed25519_skpk, keypair_seed) 186 | sodium.crypto_sign_ed25519_pk_to_curve25519(curve25519_pk, ed25519_pk) 187 | sodium.crypto_sign_ed25519_sk_to_curve25519(curve25519_sk, ed25519_skpk) 188 | 189 | const expected_pk = new Uint8Array([ 190 | 0xf1, 0x81, 0x4f, 0x0e, 0x8f, 0xf1, 0x04, 0x3d, 0x8a, 0x44, 0xd2, 0x5b, 191 | 0xab, 0xff, 0x3c, 0xed, 0xca, 0xe6, 0xc2, 0x2c, 0x3e, 0xda, 0xa4, 0x8f, 192 | 0x85, 0x7a, 0xe7, 0x0d, 0xe2, 0xba, 0xae, 0x50 193 | ]) 194 | 195 | const expected_sk = new Uint8Array([ 196 | 0x80, 0x52, 0x03, 0x03, 0x76, 0xd4, 0x71, 0x12, 0xbe, 0x7f, 0x73, 0xed, 197 | 0x7a, 0x01, 0x92, 0x93, 0xdd, 0x12, 0xad, 0x91, 0x0b, 0x65, 0x44, 0x55, 198 | 0x79, 0x8b, 0x46, 0x67, 0xd7, 0x3d, 0xe1, 0x66 199 | ]) 200 | 201 | assert.deepEqual(curve25519_pk, expected_pk) 202 | assert.deepEqual(curve25519_sk, expected_sk) 203 | 204 | for (let i = 0; i < 500; i++) { 205 | sodium.crypto_sign_keypair(ed25519_pk, ed25519_skpk) 206 | sodium.crypto_sign_ed25519_pk_to_curve25519(curve25519_pk, ed25519_pk) 207 | 208 | sodium.crypto_sign_ed25519_sk_to_curve25519(curve25519_sk, ed25519_skpk) 209 | sodium.crypto_scalarmult_base(curve25519_pk2, curve25519_sk) 210 | if (Buffer.compare(curve25519_pk, curve25519_pk2) !== 0) assert.fail() 211 | } 212 | assert.pass('passed all cases') 213 | 214 | ed25519_pk.fill(0) 215 | assert.throws(() => { 216 | sodium.crypto_sign_ed25519_pk_to_curve25519(curve25519_pk, ed25519_pk) 217 | }) 218 | 219 | assert.throws(() => { 220 | ed25519_pk[0] = 2 221 | sodium.crypto_sign_ed25519_pk_to_curve25519(curve25519_pk, ed25519_pk) 222 | }) 223 | 224 | assert.throws(() => { 225 | ed25519_pk[0] = 5 226 | sodium.crypto_sign_ed25519_pk_to_curve25519(curve25519_pk, ed25519_pk) 227 | }) 228 | 229 | assert.end() 230 | }) 231 | } 232 | 233 | function parseTest (t) { 234 | return { 235 | sk: new Uint8Array(t[0]), 236 | pk: new Uint8Array(t[1]), 237 | sig: new Uint8Array(t[2]), 238 | m: new Uint8Array(t[3]) 239 | } 240 | } 241 | 242 | function hex2bin (buf, hex) { 243 | for (let i = 0; i < hex.length / 2; i++) { 244 | buf[i] = Number('0x' + hex.slice(2 * i, 2 * i + 1)) 245 | } 246 | } 247 | -------------------------------------------------------------------------------- /crypto_stream.js: -------------------------------------------------------------------------------- 1 | var tape = require('tape') 2 | 3 | module.exports = function (sodium) { 4 | tape('crypto_stream', function (t) { 5 | var buf = Buffer.alloc(50) 6 | var nonce = random(sodium.crypto_stream_NONCEBYTES) 7 | var key = random(sodium.crypto_stream_KEYBYTES) 8 | 9 | sodium.crypto_stream(buf, nonce, key) 10 | 11 | t.notEquals(buf, Buffer.alloc(50), 'contains noise now') 12 | var copy = Buffer.from(buf.toString('hex'), 'hex') 13 | 14 | sodium.crypto_stream(buf, nonce, key) 15 | t.same(buf, copy, 'predictable from nonce, key') 16 | 17 | t.end() 18 | }) 19 | 20 | tape('crypto_stream_xor', function (t) { 21 | var message = Buffer.from('Hello, World!') 22 | var nonce = random(sodium.crypto_stream_NONCEBYTES) 23 | var key = random(sodium.crypto_stream_KEYBYTES) 24 | 25 | sodium.crypto_stream_xor(message, message, nonce, key) 26 | 27 | t.notEquals(message, Buffer.from('Hello, World!'), 'encrypted') 28 | 29 | sodium.crypto_stream_xor(message, message, nonce, key) 30 | 31 | t.same(message, Buffer.from('Hello, World!'), 'decrypted') 32 | 33 | t.end() 34 | }) 35 | 36 | tape('crypto_stream_xor_instance', function (t) { 37 | var message = Buffer.from('Hello, world!') 38 | var nonce = random(sodium.crypto_stream_NONCEBYTES) 39 | var key = random(sodium.crypto_stream_KEYBYTES) 40 | 41 | var out = Buffer.alloc(message.length) 42 | 43 | var inst = sodium.crypto_stream_xor_instance(nonce, key) 44 | 45 | for (var i = 0; i < message.length; i++) { 46 | inst.update(out.slice(i), message.slice(i, i + 1)) 47 | } 48 | 49 | sodium.crypto_stream_xor(out, out, nonce, key) 50 | t.same(out, message, 'decrypted') 51 | t.end() 52 | }) 53 | 54 | tape('crypto_stream_xor_instance with empty buffers', function (t) { 55 | var message = Buffer.from('Hello, world!') 56 | var nonce = random(sodium.crypto_stream_NONCEBYTES) 57 | var key = random(sodium.crypto_stream_KEYBYTES) 58 | 59 | var out = Buffer.alloc(message.length) 60 | 61 | var inst = sodium.crypto_stream_xor_instance(nonce, key) 62 | 63 | inst.update(Buffer.alloc(0), Buffer.alloc(0)) 64 | 65 | for (var i = 0; i < message.length; i++) { 66 | inst.update(out.slice(i), message.slice(i, i + 1)) 67 | inst.update(Buffer.alloc(0), Buffer.alloc(0)) 68 | } 69 | 70 | sodium.crypto_stream_xor(out, out, nonce, key) 71 | t.same(out, message, 'decrypted') 72 | t.end() 73 | }) 74 | 75 | tape('crypto_stream_xor_instance long stream', function (t) { 76 | var nonce = random(sodium.crypto_stream_NONCEBYTES) 77 | var key = random(sodium.crypto_stream_KEYBYTES) 78 | 79 | var encrypt = sodium.crypto_stream_xor_instance(nonce, key) 80 | var decrypt = sodium.crypto_stream_xor_instance(nonce, key) 81 | var plain = [] 82 | var encrypted = [] 83 | var decrypted = [] 84 | 85 | for (var i = 0; i < 1000; i++) { 86 | var next = random(61) 87 | plain.push(next) 88 | 89 | var enc = Buffer.alloc(61) 90 | encrypt.update(enc, next) 91 | encrypted.push(enc) 92 | 93 | var dec = Buffer.alloc(61) 94 | decrypt.update(dec, enc) 95 | decrypted.push(dec) 96 | } 97 | 98 | var enc2 = Buffer.alloc(1000 * 61) 99 | sodium.crypto_stream_xor(enc2, Buffer.concat(plain), nonce, key) 100 | 101 | t.same(Buffer.concat(encrypted), enc2, 'same as encrypting all at once') 102 | t.same(Buffer.concat(decrypted), Buffer.concat(plain), 'decrypts') 103 | t.end() 104 | }) 105 | 106 | tape('crypto_stream_xor_instance long stream (random chunks)', function (t) { 107 | var nonce = random(sodium.crypto_stream_NONCEBYTES) 108 | var key = random(sodium.crypto_stream_KEYBYTES) 109 | 110 | var encrypt = sodium.crypto_stream_xor_instance(nonce, key) 111 | var decrypt = sodium.crypto_stream_xor_instance(nonce, key) 112 | var plain = [] 113 | var encrypted = [] 114 | var decrypted = [] 115 | 116 | for (var i = 0; i < 10000; i++) { 117 | var len = Math.floor(Math.random() * 256) 118 | var next = random(len) 119 | plain.push(next) 120 | 121 | var enc = Buffer.alloc(len) 122 | encrypt.update(enc, next) 123 | encrypted.push(enc) 124 | 125 | var dec = Buffer.alloc(len) 126 | decrypt.update(dec, enc) 127 | decrypted.push(dec) 128 | } 129 | 130 | var enc2 = Buffer.alloc(Buffer.concat(plain).length) 131 | sodium.crypto_stream_xor(enc2, Buffer.concat(plain), nonce, key) 132 | 133 | t.same(Buffer.concat(encrypted), enc2, 'same as encrypting all at once') 134 | t.same(Buffer.concat(decrypted), Buffer.concat(plain), 'decrypts') 135 | t.end() 136 | }) 137 | 138 | tape('crypto_stream_xor_instance long stream (random chunks) with empty buffers', function (t) { 139 | var nonce = random(sodium.crypto_stream_NONCEBYTES) 140 | var key = random(sodium.crypto_stream_KEYBYTES) 141 | 142 | var encrypt = sodium.crypto_stream_xor_instance(nonce, key) 143 | var decrypt = sodium.crypto_stream_xor_instance(nonce, key) 144 | var plain = [] 145 | var encrypted = [] 146 | var decrypted = [] 147 | 148 | for (var i = 0; i < 10000; i++) { 149 | var len = Math.floor(Math.random() * 256) 150 | var next = random(len) 151 | plain.push(next) 152 | 153 | encrypt.update(Buffer.alloc(0), Buffer.alloc(0)) 154 | 155 | var enc = Buffer.alloc(len) 156 | encrypt.update(enc, next) 157 | encrypted.push(enc) 158 | 159 | var dec = Buffer.alloc(len) 160 | decrypt.update(dec, enc) 161 | decrypted.push(dec) 162 | decrypt.update(Buffer.alloc(0), Buffer.alloc(0)) 163 | } 164 | 165 | var enc2 = Buffer.alloc(Buffer.concat(plain).length) 166 | sodium.crypto_stream_xor(enc2, Buffer.concat(plain), nonce, key) 167 | 168 | t.same(Buffer.concat(encrypted), enc2, 'same as encrypting all at once') 169 | t.same(Buffer.concat(decrypted), Buffer.concat(plain), 'decrypts') 170 | t.end() 171 | }) 172 | 173 | tape('crypto_stream_chacha20', function (t) { 174 | var buf = Buffer.alloc(50) 175 | var nonce = random(sodium.crypto_stream_chacha20_NONCEBYTES) 176 | var key = random(sodium.crypto_stream_chacha20_KEYBYTES) 177 | 178 | sodium.crypto_stream_chacha20(buf, nonce, key) 179 | 180 | t.notEquals(buf, Buffer.alloc(50), 'contains noise now') 181 | var copy = Buffer.from(buf.toString('hex'), 'hex') 182 | 183 | sodium.crypto_stream_chacha20(buf, nonce, key) 184 | t.same(buf, copy, 'predictable from nonce, key') 185 | 186 | t.end() 187 | }) 188 | 189 | tape('crypto_stream_chacha20_xor', function (t) { 190 | var message = Buffer.from('Hello, World!') 191 | var nonce = random(sodium.crypto_stream_chacha20_NONCEBYTES) 192 | var key = random(sodium.crypto_stream_chacha20_KEYBYTES) 193 | 194 | sodium.crypto_stream_chacha20_xor(message, message, nonce, key) 195 | 196 | t.notEquals(message, Buffer.from('Hello, World!'), 'encrypted') 197 | 198 | sodium.crypto_stream_chacha20_xor(message, message, nonce, key) 199 | 200 | t.same(message, Buffer.from('Hello, World!'), 'decrypted') 201 | 202 | t.end() 203 | }) 204 | 205 | tape('crypto_stream_chacha20_xor_instance', function (t) { 206 | var message = Buffer.from('Hello, world!') 207 | var nonce = random(sodium.crypto_stream_chacha20_NONCEBYTES) 208 | var key = random(sodium.crypto_stream_chacha20_KEYBYTES) 209 | 210 | var out = Buffer.alloc(message.length) 211 | 212 | var inst = sodium.crypto_stream_chacha20_xor_instance(nonce, key) 213 | 214 | for (var i = 0; i < message.length; i++) { 215 | inst.update(out.slice(i), message.slice(i, i + 1)) 216 | } 217 | 218 | sodium.crypto_stream_chacha20_xor(out, out, nonce, key) 219 | t.same(out, message, 'decrypted') 220 | t.end() 221 | }) 222 | 223 | tape('crypto_stream_chacha20_xor_instance with empty buffers', function (t) { 224 | var message = Buffer.from('Hello, world!') 225 | var nonce = random(sodium.crypto_stream_chacha20_NONCEBYTES) 226 | var key = random(sodium.crypto_stream_chacha20_KEYBYTES) 227 | 228 | var out = Buffer.alloc(message.length) 229 | 230 | var inst = sodium.crypto_stream_chacha20_xor_instance(nonce, key) 231 | 232 | inst.update(Buffer.alloc(0), Buffer.alloc(0)) 233 | 234 | for (var i = 0; i < message.length; i++) { 235 | inst.update(out.slice(i), message.slice(i, i + 1)) 236 | inst.update(Buffer.alloc(0), Buffer.alloc(0)) 237 | } 238 | 239 | sodium.crypto_stream_chacha20_xor(out, out, nonce, key) 240 | t.same(out, message, 'decrypted') 241 | t.end() 242 | }) 243 | 244 | tape('crypto_stream_chacha20_xor_instance long stream', function (t) { 245 | var nonce = random(sodium.crypto_stream_chacha20_NONCEBYTES) 246 | var key = random(sodium.crypto_stream_chacha20_KEYBYTES) 247 | 248 | var encrypt = sodium.crypto_stream_chacha20_xor_instance(nonce, key) 249 | var decrypt = sodium.crypto_stream_chacha20_xor_instance(nonce, key) 250 | var plain = [] 251 | var encrypted = [] 252 | var decrypted = [] 253 | 254 | for (var i = 0; i < 1000; i++) { 255 | var next = random(61) 256 | plain.push(next) 257 | 258 | var enc = Buffer.alloc(61) 259 | encrypt.update(enc, next) 260 | encrypted.push(enc) 261 | 262 | var dec = Buffer.alloc(61) 263 | decrypt.update(dec, enc) 264 | decrypted.push(dec) 265 | } 266 | 267 | var enc2 = Buffer.alloc(1000 * 61) 268 | sodium.crypto_stream_chacha20_xor(enc2, Buffer.concat(plain), nonce, key) 269 | 270 | t.same(Buffer.concat(encrypted), enc2, 'same as encrypting all at once') 271 | t.same(Buffer.concat(decrypted), Buffer.concat(plain), 'decrypts') 272 | t.end() 273 | }) 274 | 275 | tape('crypto_stream_chacha20_xor_instance long stream (random chunks)', function (t) { 276 | var nonce = random(sodium.crypto_stream_chacha20_NONCEBYTES) 277 | var key = random(sodium.crypto_stream_chacha20_KEYBYTES) 278 | 279 | var encrypt = sodium.crypto_stream_chacha20_xor_instance(nonce, key) 280 | var decrypt = sodium.crypto_stream_chacha20_xor_instance(nonce, key) 281 | var plain = [] 282 | var encrypted = [] 283 | var decrypted = [] 284 | 285 | for (var i = 0; i < 10000; i++) { 286 | var len = Math.floor(Math.random() * 256) 287 | var next = random(len) 288 | plain.push(next) 289 | 290 | var enc = Buffer.alloc(len) 291 | encrypt.update(enc, next) 292 | encrypted.push(enc) 293 | 294 | var dec = Buffer.alloc(len) 295 | decrypt.update(dec, enc) 296 | decrypted.push(dec) 297 | } 298 | 299 | var enc2 = Buffer.alloc(Buffer.concat(plain).length) 300 | sodium.crypto_stream_chacha20_xor(enc2, Buffer.concat(plain), nonce, key) 301 | 302 | t.same(Buffer.concat(encrypted), enc2, 'same as encrypting all at once') 303 | t.same(Buffer.concat(decrypted), Buffer.concat(plain), 'decrypts') 304 | t.end() 305 | }) 306 | 307 | tape('crypto_stream_chacha20_xor_instance long stream (random chunks) with empty buffers', function (t) { 308 | var nonce = random(sodium.crypto_stream_chacha20_NONCEBYTES) 309 | var key = random(sodium.crypto_stream_chacha20_KEYBYTES) 310 | 311 | var encrypt = sodium.crypto_stream_chacha20_xor_instance(nonce, key) 312 | var decrypt = sodium.crypto_stream_chacha20_xor_instance(nonce, key) 313 | var plain = [] 314 | var encrypted = [] 315 | var decrypted = [] 316 | 317 | for (var i = 0; i < 10000; i++) { 318 | var len = Math.floor(Math.random() * 256) 319 | var next = random(len) 320 | plain.push(next) 321 | 322 | encrypt.update(Buffer.alloc(0), Buffer.alloc(0)) 323 | 324 | var enc = Buffer.alloc(len) 325 | encrypt.update(enc, next) 326 | encrypted.push(enc) 327 | 328 | var dec = Buffer.alloc(len) 329 | decrypt.update(dec, enc) 330 | decrypted.push(dec) 331 | decrypt.update(Buffer.alloc(0), Buffer.alloc(0)) 332 | } 333 | 334 | var enc2 = Buffer.alloc(Buffer.concat(plain).length) 335 | sodium.crypto_stream_chacha20_xor(enc2, Buffer.concat(plain), nonce, key) 336 | 337 | t.same(Buffer.concat(encrypted), enc2, 'same as encrypting all at once') 338 | t.same(Buffer.concat(decrypted), Buffer.concat(plain), 'decrypts') 339 | t.end() 340 | }) 341 | 342 | tape('crypto_stream_chacha20_ietf', function (t) { 343 | var buf = Buffer.alloc(50) 344 | var nonce = random(sodium.crypto_stream_chacha20_ietf_NONCEBYTES) 345 | var key = random(sodium.crypto_stream_chacha20_ietf_KEYBYTES) 346 | 347 | sodium.crypto_stream_chacha20_ietf(buf, nonce, key) 348 | 349 | t.notEquals(buf, Buffer.alloc(50), 'contains noise now') 350 | var copy = Buffer.from(buf.toString('hex'), 'hex') 351 | 352 | sodium.crypto_stream_chacha20_ietf(buf, nonce, key) 353 | t.same(buf, copy, 'predictable from nonce, key') 354 | 355 | t.end() 356 | }) 357 | 358 | tape('crypto_stream_chacha20_ietf_xor', function (t) { 359 | var message = Buffer.from('Hello, World!') 360 | var nonce = random(sodium.crypto_stream_chacha20_ietf_NONCEBYTES) 361 | var key = random(sodium.crypto_stream_chacha20_ietf_KEYBYTES) 362 | 363 | sodium.crypto_stream_chacha20_ietf_xor(message, message, nonce, key) 364 | 365 | t.notEquals(message, Buffer.from('Hello, World!'), 'encrypted') 366 | 367 | sodium.crypto_stream_chacha20_ietf_xor(message, message, nonce, key) 368 | 369 | t.same(message, Buffer.from('Hello, World!'), 'decrypted') 370 | 371 | t.end() 372 | }) 373 | 374 | tape('crypto_stream_chacha20_ietf_xor_instance', function (t) { 375 | var message = Buffer.from('Hello, world!') 376 | var nonce = random(sodium.crypto_stream_chacha20_ietf_NONCEBYTES) 377 | var key = random(sodium.crypto_stream_chacha20_ietf_KEYBYTES) 378 | 379 | var out = Buffer.alloc(message.length) 380 | 381 | var inst = sodium.crypto_stream_chacha20_ietf_xor_instance(nonce, key) 382 | 383 | for (var i = 0; i < message.length; i++) { 384 | inst.update(out.slice(i), message.slice(i, i + 1)) 385 | } 386 | 387 | sodium.crypto_stream_chacha20_ietf_xor(out, out, nonce, key) 388 | t.same(out, message, 'decrypted') 389 | t.end() 390 | }) 391 | 392 | tape('crypto_stream_chacha20_ietf_xor_instance with empty buffers', function (t) { 393 | var message = Buffer.from('Hello, world!') 394 | var nonce = random(sodium.crypto_stream_chacha20_ietf_NONCEBYTES) 395 | var key = random(sodium.crypto_stream_chacha20_ietf_KEYBYTES) 396 | 397 | var out = Buffer.alloc(message.length) 398 | 399 | var inst = sodium.crypto_stream_chacha20_ietf_xor_instance(nonce, key) 400 | 401 | inst.update(Buffer.alloc(0), Buffer.alloc(0)) 402 | 403 | for (var i = 0; i < message.length; i++) { 404 | inst.update(out.slice(i), message.slice(i, i + 1)) 405 | inst.update(Buffer.alloc(0), Buffer.alloc(0)) 406 | } 407 | 408 | sodium.crypto_stream_chacha20_ietf_xor(out, out, nonce, key) 409 | t.same(out, message, 'decrypted') 410 | t.end() 411 | }) 412 | 413 | tape('crypto_stream_chacha20_ietf_xor_instance long stream', function (t) { 414 | var nonce = random(sodium.crypto_stream_chacha20_ietf_NONCEBYTES) 415 | var key = random(sodium.crypto_stream_chacha20_ietf_KEYBYTES) 416 | 417 | var encrypt = sodium.crypto_stream_chacha20_ietf_xor_instance(nonce, key) 418 | var decrypt = sodium.crypto_stream_chacha20_ietf_xor_instance(nonce, key) 419 | var plain = [] 420 | var encrypted = [] 421 | var decrypted = [] 422 | 423 | for (var i = 0; i < 1000; i++) { 424 | var next = random(61) 425 | plain.push(next) 426 | 427 | var enc = Buffer.alloc(61) 428 | encrypt.update(enc, next) 429 | encrypted.push(enc) 430 | 431 | var dec = Buffer.alloc(61) 432 | decrypt.update(dec, enc) 433 | decrypted.push(dec) 434 | } 435 | 436 | var enc2 = Buffer.alloc(1000 * 61) 437 | sodium.crypto_stream_chacha20_ietf_xor(enc2, Buffer.concat(plain), nonce, key) 438 | 439 | t.same(Buffer.concat(encrypted), enc2, 'same as encrypting all at once') 440 | t.same(Buffer.concat(decrypted), Buffer.concat(plain), 'decrypts') 441 | t.end() 442 | }) 443 | 444 | tape('crypto_stream_chacha20_ietf_xor_instance long stream (random chunks)', function (t) { 445 | var nonce = random(sodium.crypto_stream_chacha20_ietf_NONCEBYTES) 446 | var key = random(sodium.crypto_stream_chacha20_ietf_KEYBYTES) 447 | 448 | var encrypt = sodium.crypto_stream_chacha20_ietf_xor_instance(nonce, key) 449 | var decrypt = sodium.crypto_stream_chacha20_ietf_xor_instance(nonce, key) 450 | var plain = [] 451 | var encrypted = [] 452 | var decrypted = [] 453 | 454 | for (var i = 0; i < 10000; i++) { 455 | var len = Math.floor(Math.random() * 256) 456 | var next = random(len) 457 | plain.push(next) 458 | 459 | var enc = Buffer.alloc(len) 460 | encrypt.update(enc, next) 461 | encrypted.push(enc) 462 | 463 | var dec = Buffer.alloc(len) 464 | decrypt.update(dec, enc) 465 | decrypted.push(dec) 466 | } 467 | 468 | var enc2 = Buffer.alloc(Buffer.concat(plain).length) 469 | sodium.crypto_stream_chacha20_ietf_xor(enc2, Buffer.concat(plain), nonce, key) 470 | 471 | t.same(Buffer.concat(encrypted), enc2, 'same as encrypting all at once') 472 | t.same(Buffer.concat(decrypted), Buffer.concat(plain), 'decrypts') 473 | t.end() 474 | }) 475 | 476 | tape('crypto_stream_chacha20_ietf_xor_instance long stream (random chunks) with empty buffers', function (t) { 477 | var nonce = random(sodium.crypto_stream_chacha20_ietf_NONCEBYTES) 478 | var key = random(sodium.crypto_stream_chacha20_ietf_KEYBYTES) 479 | 480 | var encrypt = sodium.crypto_stream_chacha20_ietf_xor_instance(nonce, key) 481 | var decrypt = sodium.crypto_stream_chacha20_ietf_xor_instance(nonce, key) 482 | var plain = [] 483 | var encrypted = [] 484 | var decrypted = [] 485 | 486 | for (var i = 0; i < 10000; i++) { 487 | var len = Math.floor(Math.random() * 256) 488 | var next = random(len) 489 | plain.push(next) 490 | 491 | encrypt.update(Buffer.alloc(0), Buffer.alloc(0)) 492 | 493 | var enc = Buffer.alloc(len) 494 | encrypt.update(enc, next) 495 | encrypted.push(enc) 496 | 497 | var dec = Buffer.alloc(len) 498 | decrypt.update(dec, enc) 499 | decrypted.push(dec) 500 | decrypt.update(Buffer.alloc(0), Buffer.alloc(0)) 501 | } 502 | 503 | var enc2 = Buffer.alloc(Buffer.concat(plain).length) 504 | sodium.crypto_stream_chacha20_ietf_xor(enc2, Buffer.concat(plain), nonce, key) 505 | 506 | t.same(Buffer.concat(encrypted), enc2, 'same as encrypting all at once') 507 | t.same(Buffer.concat(decrypted), Buffer.concat(plain), 'decrypts') 508 | t.end() 509 | }) 510 | 511 | const tests = [ 512 | ['0000000000000000000000000000000000000000000000000000000000000000', '000000000000000000000000', 0, '76b8e0ada0f13d90405d6ae55386bd28bdd219b8a08ded1aa836efcc8b770dc7da41597c5157488d7724e03fb8d84a376a43b8f41518a11cc387b669b2ee65869f07e7be5551387a98ba977c732d080dcb0f29a048e3656912c6533e32ee7aed29b721769ce64e43d57133b074d839d531ed1f28510afb45ace10a1f4b794d6f2d09a0e663266ce1ae7ed1081968a0758e718e997bd362c6b0c34634a9a0b35d'], 513 | ['0000000000000000000000000000000000000000000000000000000000000000', '000000000000000000000000', 1, '9f07e7be5551387a98ba977c732d080dcb0f29a048e3656912c6533e32ee7aed29b721769ce64e43d57133b074d839d531ed1f28510afb45ace10a1f4b794d6f2d09a0e663266ce1ae7ed1081968a0758e718e997bd362c6b0c34634a9a0b35d012737681f7b5d0f281e3afde458bc1e73d2d313c9cf94c05ff3716240a248f21320a058d7b3566bd520daaa3ed2bf0ac5b8b120fb852773c3639734b45c91a4'], 514 | ['0000000000000000000000000000000000000000000000000000000000000001', '000000000000000000000000', 1, '3aeb5224ecf849929b9d828db1ced4dd832025e8018b8160b82284f3c949aa5a8eca00bbb4a73bdad192b5c42f73f2fd4e273644c8b36125a64addeb006c13a096d68b9ff7b57e7090f880392effd5b297a83bbaf2fbe8cf5d4618965e3dc776cd430d9b4e7eda8a767fb0e860319aadb5fd96a855de1fbfc92cb0489190cfdd87da6dbf1f736a2d499941ca097e5170bd685578611323120cebf296181ed4f5'], 515 | ['00ff000000000000000000000000000000000000000000000000000000000000', '000000000000000000000000', 2, '72d54dfbf12ec44b362692df94137f328fea8da73990265ec1bbbea1ae9af0ca13b25aa26cb4a648cb9b9d1be65b2c0924a66c54d545ec1b7374f4872e99f096bf74dbd52cc4fc95ceb6097fe5e65358c9dbc0a5ecbf7894a132a9a54ae3e951f2e9f209aa9c3d9a877ac9dab62433d2961a17d103e455dfb7337c90f6857aad233065955a212b5c7a8eab4dc8a629e5b6b8ba914afd06de7177054b33d21c96'], 516 | ['0000000000000000000000000000000000000000000000000000000000000000', '000000000000000000000002', 0, 'c2c64d378cd536374ae204b9ef933fcd1a8b2288b3dfa49672ab765b54ee27c78a970e0e955c14f3a88e741b97c286f75f8fc299e8148362fa198a39531bed6d1a91288c874ec254f322c2a197340c55bb3e9b3998f7de2309486a0bb494abd20c9c5ef99c1370d61e77f408ac5514f49202bcc6828d45409d2d1416f8ae106b06ebd2541256264fa415bd54cb12e1d4449ed85299a1b7a249b75ff6c89b2e3f'], 517 | ['000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f', '000000090000004a00000000', 1, '10f1e7e4d13b5915500fdd1fa32071c4c7d1f4c733c068030422aa9ac3d46c4ed2826446079faa0914c2d705d98b02a2b5129cd1de164eb9cbd083e8a2503c4e0a88837739d7bf4ef8ccacb0ea2bb9d69d56c394aa351dfda5bf459f0a2e9fe8e721f89255f9c486bf21679c683d4f9c5cf2fa27865526005b06ca374c86af3bdcbfbdcb83be65862ed5c20eae5a43241d6a92da6dca9a156be25297f51c2718'], 518 | ['000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f', '000000090000004a00000000', 0xfeffffff, '75924bad7831b25662dbac54b46827990b6168ae990e7bd7e1fd2ad282bf23ef052c7d1a0a6c1ef862070943a0d4da24705fbc006dfb85e2af18c0a264d772a44c70fbedac9d6a6867ff6be0a32826507f2c784101583211c9e2453d4cc8b283d5e86682bd4bf511271b91dbd351415f5a009d1f78b64085a9a4341be7d42e2679d57e2747097f0129950e2c9e9ca1356022d45da252af71ac37f351a2e77911'] 519 | ] 520 | 521 | const vectors = [ 522 | '8a010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101', 523 | '8adc91fd040404040404040404040404040404040404040404040404040404040404040404040404040404040404040404040404040404040404040404040404040404040404040404040404040404040404040404040404040404040404040404040404040404040404040404040404040404040404040404040404040404040404040404040404040404040404040404040404040404040404040404040404', 524 | '8adc91fd9ff4f0070707070707070707070707070707070707070707070707070707070707070707070707070707070707070707070707070707070707070707070707070707070707070707070707070707070707070707070707070707070707070707070707070707070707070707070707070707070707070707070707070707070707070707070707070707070707070707070707070707070707070707', 525 | '8adc91fd9ff4f0f51b0f0a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0a', 526 | '8adc91fd9ff4f0f51b0fad50ff0d0d0d0d0d0d0d0d0d0d0d0d0d0d0d0d0d0d0d0d0d0d0d0d0d0d0d0d0d0d0d0d0d0d0d0d0d0d0d0d0d0d0d0d0d0d0d0d0d0d0d0d0d0d0d0d0d0d0d0d0d0d0d0d0d0d0d0d0d0d0d0d0d0d0d0d0d0d0d0d0d0d0d0d0d0d0d0d0d0d0d0d0d0d0d0d0d0d0d0d0d0d0d0d0d0d0d0d0d0d0d0d0d0d0d0d0d0d0d0d0d0d0d0d0d0d0d0d0d0d0d0d0d0d0d0d0d0d0d0d0d0d0d0d0d0d0d', 527 | '8adc91fd9ff4f0f51b0fad50ff15d637101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010', 528 | '8adc91fd9ff4f0f51b0fad50ff15d637e40efd131313131313131313131313131313131313131313131313131313131313131313131313131313131313131313131313131313131313131313131313131313131313131313131313131313131313131313131313131313131313131313131313131313131313131313131313131313131313131313131313131313131313131313131313131313131313131313', 529 | '8adc91fd9ff4f0f51b0fad50ff15d637e40efda206cc161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616', 530 | '8adc91fd9ff4f0f51b0fad50ff15d637e40efda206cc52c783191919191919191919191919191919191919191919191919191919191919191919191919191919191919191919191919191919191919191919191919191919191919191919191919191919191919191919191919191919191919191919191919191919191919191919191919191919191919191919191919191919191919191919191919191919', 531 | '8adc91fd9ff4f0f51b0fad50ff15d637e40efda206cc52c783a742001c1c1c1c1c1c1c1c1c1c1c1c1c1c1c1c1c1c1c1c1c1c1c1c1c1c1c1c1c1c1c1c1c1c1c1c1c1c1c1c1c1c1c1c1c1c1c1c1c1c1c1c1c1c1c1c1c1c1c1c1c1c1c1c1c1c1c1c1c1c1c1c1c1c1c1c1c1c1c1c1c1c1c1c1c1c1c1c1c1c1c1c1c1c1c1c1c1c1c1c1c1c1c1c1c1c1c1c1c1c1c1c1c1c1c1c1c1c1c1c1c1c1c1c1c1c1c1c1c1c1c1c', 532 | '8adc91fd9ff4f0f51b0fad50ff15d637e40efda206cc52c783a74200503c151f1f1f1f1f1f1f1f1f1f1f1f1f1f1f1f1f1f1f1f1f1f1f1f1f1f1f1f1f1f1f1f1f1f1f1f1f1f1f1f1f1f1f1f1f1f1f1f1f1f1f1f1f1f1f1f1f1f1f1f1f1f1f1f1f1f1f1f1f1f1f1f1f1f1f1f1f1f1f1f1f1f1f1f1f1f1f1f1f1f1f1f1f1f1f1f1f1f1f1f1f1f1f1f1f1f1f1f1f1f1f1f1f1f1f1f1f1f1f1f1f1f1f1f1f1f1f1f1f', 533 | '8adc91fd9ff4f0f51b0fad50ff15d637e40efda206cc52c783a74200503c1582cd98222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222', 534 | '8adc91fd9ff4f0f51b0fad50ff15d637e40efda206cc52c783a74200503c1582cd9833367d252525252525252525252525252525252525252525252525252525252525252525252525252525252525252525252525252525252525252525252525252525252525252525252525252525252525252525252525252525252525252525252525252525252525252525252525252525252525252525252525252525', 535 | '8adc91fd9ff4f0f51b0fad50ff15d637e40efda206cc52c783a74200503c1582cd9833367d0a54d5282828282828282828282828282828282828282828282828282828282828282828282828282828282828282828282828282828282828282828282828282828282828282828282828282828282828282828282828282828282828282828282828282828282828282828282828282828282828282828282828', 536 | '8adc91fd9ff4f0f51b0fad50ff15d637e40efda206cc52c783a74200503c1582cd9833367d0a54d57d3c9e2b2b2b2b2b2b2b2b2b2b2b2b2b2b2b2b2b2b2b2b2b2b2b2b2b2b2b2b2b2b2b2b2b2b2b2b2b2b2b2b2b2b2b2b2b2b2b2b2b2b2b2b2b2b2b2b2b2b2b2b2b2b2b2b2b2b2b2b2b2b2b2b2b2b2b2b2b2b2b2b2b2b2b2b2b2b2b2b2b2b2b2b2b2b2b2b2b2b2b2b2b2b2b2b2b2b2b2b2b2b2b2b2b2b2b2b2b', 537 | '8adc91fd9ff4f0f51b0fad50ff15d637e40efda206cc52c783a74200503c1582cd9833367d0a54d57d3c9e998f492e2e2e2e2e2e2e2e2e2e2e2e2e2e2e2e2e2e2e2e2e2e2e2e2e2e2e2e2e2e2e2e2e2e2e2e2e2e2e2e2e2e2e2e2e2e2e2e2e2e2e2e2e2e2e2e2e2e2e2e2e2e2e2e2e2e2e2e2e2e2e2e2e2e2e2e2e2e2e2e2e2e2e2e2e2e2e2e2e2e2e2e2e2e2e2e2e2e2e2e2e2e2e2e2e2e2e2e2e2e2e2e2e2e', 538 | '8adc91fd9ff4f0f51b0fad50ff15d637e40efda206cc52c783a74200503c1582cd9833367d0a54d57d3c9e998f490ee69c313131313131313131313131313131313131313131313131313131313131313131313131313131313131313131313131313131313131313131313131313131313131313131313131313131313131313131313131313131313131313131313131313131313131313131313131313131', 539 | '8adc91fd9ff4f0f51b0fad50ff15d637e40efda206cc52c783a74200503c1582cd9833367d0a54d57d3c9e998f490ee69ca34c1f343434343434343434343434343434343434343434343434343434343434343434343434343434343434343434343434343434343434343434343434343434343434343434343434343434343434343434343434343434343434343434343434343434343434343434343434', 540 | '8adc91fd9ff4f0f51b0fad50ff15d637e40efda206cc52c783a74200503c1582cd9833367d0a54d57d3c9e998f490ee69ca34c1ff9e939373737373737373737373737373737373737373737373737373737373737373737373737373737373737373737373737373737373737373737373737373737373737373737373737373737373737373737373737373737373737373737373737373737373737373737', 541 | '8adc91fd9ff4f0f51b0fad50ff15d637e40efda206cc52c783a74200503c1582cd9833367d0a54d57d3c9e998f490ee69ca34c1ff9e939a755843a3a3a3a3a3a3a3a3a3a3a3a3a3a3a3a3a3a3a3a3a3a3a3a3a3a3a3a3a3a3a3a3a3a3a3a3a3a3a3a3a3a3a3a3a3a3a3a3a3a3a3a3a3a3a3a3a3a3a3a3a3a3a3a3a3a3a3a3a3a3a3a3a3a3a3a3a3a3a3a3a3a3a3a3a3a3a3a3a3a3a3a3a3a3a3a3a3a3a3a3a3a', 542 | '8adc91fd9ff4f0f51b0fad50ff15d637e40efda206cc52c783a74200503c1582cd9833367d0a54d57d3c9e998f490ee69ca34c1ff9e939a75584c52d693d3d3d3d3d3d3d3d3d3d3d3d3d3d3d3d3d3d3d3d3d3d3d3d3d3d3d3d3d3d3d3d3d3d3d3d3d3d3d3d3d3d3d3d3d3d3d3d3d3d3d3d3d3d3d3d3d3d3d3d3d3d3d3d3d3d3d3d3d3d3d3d3d3d3d3d3d3d3d3d3d3d3d3d3d3d3d3d3d3d3d3d3d3d3d3d3d3d3d', 543 | '8adc91fd9ff4f0f51b0fad50ff15d637e40efda206cc52c783a74200503c1582cd9833367d0a54d57d3c9e998f490ee69ca34c1ff9e939a75584c52d690a35d4404040404040404040404040404040404040404040404040404040404040404040404040404040404040404040404040404040404040404040404040404040404040404040404040404040404040404040404040404040404040404040404040' 544 | ] 545 | 546 | tape('constants', function (assert) { 547 | assert.ok(sodium.crypto_stream_chacha20_ietf_KEYBYTES > 0) 548 | assert.ok(sodium.crypto_stream_chacha20_ietf_NONCEBYTES > 0) 549 | assert.ok(sodium.crypto_stream_chacha20_ietf_MESSAGEBYTES_MAX > 0) 550 | assert.end() 551 | }) 552 | 553 | tape('crypto_stream_chacha20_ietf', function (assert) { 554 | const key = Buffer.alloc(sodium.crypto_stream_chacha20_ietf_KEYBYTES) 555 | const nonce = Buffer.alloc(sodium.crypto_stream_chacha20_ietf_NONCEBYTES) 556 | 557 | const out = Buffer.alloc(160) 558 | 559 | for (var i = 0; i < tests.length; i++) { 560 | key.write(tests[i][0], 0, key.byteLength, 'hex') 561 | nonce.write(tests[i][1], 0, nonce.byteLength, 'hex') 562 | out.fill(0) 563 | sodium.crypto_stream_chacha20_ietf_xor_ic(out, out, nonce, tests[i][2], key) 564 | assert.deepEquals(out, Buffer.from(tests[i][3], 'hex'), 'crypto_stream_chacha20_ietf_xor_ic vector ' + i) 565 | for (let plen = 0; plen < out.byteLength; plen++) { 566 | const part = Buffer.alloc(plen) 567 | sodium.crypto_stream_chacha20_ietf_xor_ic(part, out.subarray(0, plen), nonce, tests[i][2], key) 568 | if (part.every(b => b === 0) === false) return assert.fail() 569 | } 570 | } 571 | 572 | for (let plen = 1, i = 0; plen < 66; plen += 3, i++) { 573 | out.fill(plen & 0xff) 574 | sodium.crypto_stream_chacha20_ietf(out.subarray(0, plen), nonce, key) 575 | if (out.equals(Buffer.from(vectors[i], 'hex')) === false) return assert.fail() 576 | } 577 | 578 | sodium.randombytes_buf(out) 579 | sodium.crypto_stream_chacha20_ietf(out, nonce, key) 580 | assert.deepEquals(out, Buffer.from('8adc91fd9ff4f0f51b0fad50ff15d637e40efda206cc52c783a74200503c1582cd9833367d0a54d57d3c9e998f490ee69ca34c1ff9e939a75584c52d690a35d410f1e7e4d13b5915500fdd1fa32071c4c7d1f4c733c068030422aa9ac3d46c4ed2826446079faa0914c2d705d98b02a2b5129cd1de164eb9cbd083e8a2503c4e0a88837739d7bf4ef8ccacb0ea2bb9d69d56c394aa351dfda5bf459f0a2e9fe8', 'hex')) 581 | 582 | assert.doesNotThrow(() => sodium.crypto_stream_chacha20_ietf(out.subarray(0, 0), nonce, key)) 583 | assert.doesNotThrow(() => sodium.crypto_stream_chacha20_ietf_xor(out.subarray(0, 0), Buffer.alloc(0), nonce, key)) 584 | assert.doesNotThrow(() => sodium.crypto_stream_chacha20_ietf_xor(out.subarray(0, 0), Buffer.alloc(0), nonce, key)) 585 | assert.doesNotThrow(() => sodium.crypto_stream_chacha20_ietf_xor_ic(out.subarray(0, 0), Buffer.alloc(0), nonce, 1, key)) 586 | 587 | out.fill(0x42) 588 | sodium.crypto_stream_chacha20_ietf_xor(out, out, nonce, key) 589 | assert.deepEquals(out, Buffer.from('c89ed3bfddb6b2b7594def12bd579475a64cbfe0448e1085c1e50042127e57c08fda71743f4816973f7edcdbcd0b4ca4dee10e5dbbab7be517c6876f2b48779652b3a5a693791b57124d9f5de16233868593b68571822a414660e8d881962e0c90c0260445dde84b568095479bc940e0f750de939c540cfb8992c1aae0127e0c48cac1357b95fd0cba8eeef2a869fb94df1481d6e8775fbfe7fd07dd486cddaa', 'hex')) 590 | 591 | sodium.crypto_stream_chacha20_ietf_xor_ic(out, out, nonce, 0, key) 592 | assert.deepEquals(out, Buffer.from('42424242424242424242424242424242424242424242424242424242424242424242424242424242424242424242424242424242424242424242424242424242424242424242424242424242424242424242424242424242424242424242424242424242424242424242424242424242424242424242424242424242424242424242424242424242424242424242424242424242424242424242424242424242', 'hex')) 593 | 594 | sodium.crypto_stream_chacha20_ietf_xor_ic(out, out, nonce, 1, key) 595 | assert.deepEquals(out, Buffer.from('52b3a5a693791b57124d9f5de16233868593b68571822a414660e8d881962e0c90c0260445dde84b568095479bc940e0f750de939c540cfb8992c1aae0127e0c48cac1357b95fd0cba8eeef2a869fb94df1481d6e8775fbfe7fd07dd486cddaaa563bad017bb86c4fd6325de2a7f0dde1eb0b865c4176442194488750ec4ed799efdff89c1fc27c46c97804cec1801665f28d0982f88d85729a010d5b75e655a', 'hex')) 596 | 597 | assert.end() 598 | }) 599 | 600 | function random (n) { 601 | var buf = Buffer.alloc(n) 602 | sodium.randombytes_buf(buf) 603 | return buf 604 | } 605 | } 606 | -------------------------------------------------------------------------------- /documented-symbols: -------------------------------------------------------------------------------- 1 | # v1.0.15 2 | # Helpers 3 | sodium_memcmp 4 | sodium_bin2hex 5 | sodium_hex2bin 6 | sodium_bin2base64 7 | sodium_base64_VARIANT_ORIGINAL 8 | sodium_base64_VARIANT_ORIGINAL_NO_PADDING 9 | sodium_base64_VARIANT_URLSAFE 10 | sodium_base64_VARIANT_URLSAFE_NO_PADDING 11 | sodium_base64_encoded_len 12 | sodium_base642bin 13 | sodium_increment 14 | sodium_add 15 | sodium_compare 16 | sodium_is_zero 17 | # padding 18 | sodium_pad 19 | sodium_unpad 20 | # secure memory 21 | sodium_memzero 22 | sodium_mlock 23 | sodium_munlock 24 | sodium_malloc 25 | sodium_allocarray 26 | sodium_free 27 | sodium_mprotect_noaccess 28 | sodium_mprotect_readonly 29 | sodium_mprotect_readwrite 30 | # random 31 | randombytes_random 32 | randombytes_uniform 33 | randombytes_buf 34 | randombytes_buf_deterministic 35 | randombytes_SEEDBYTES 36 | randombytes_keygen 37 | randombytes_close 38 | randombytes_stir 39 | 40 | # secret key 41 | ## auth enc 42 | crypto_secretbox_easy 43 | crypto_secretbox_open_easy 44 | crypto_secretbox_detached 45 | crypto_secretbox_open_detached 46 | crypto_secretbox_keygen 47 | crypto_secretbox_KEYBYTES 48 | crypto_secretbox_MACBYTES 49 | crypto_secretbox_NONCEBYTES 50 | ## enc stream 51 | crypto_secretstream_xchacha20poly1305_keygen 52 | crypto_secretstream_xchacha20poly1305_init_push 53 | crypto_secretstream_xchacha20poly1305_push 54 | crypto_secretstream_xchacha20poly1305_init_pull 55 | crypto_secretstream_xchacha20poly1305_pull 56 | crypto_secretstream_xchacha20poly1305_rekey 57 | crypto_secretstream_xchacha20poly1305_ABYTES 58 | crypto_secretstream_xchacha20poly1305_HEADERBYTES 59 | crypto_secretstream_xchacha20poly1305_KEYBYTES 60 | crypto_secretstream_xchacha20poly1305_MESSAGEBYTES_MAX 61 | crypto_secretstream_xchacha20poly1305_TAG_MESSAGE 62 | crypto_secretstream_xchacha20poly1305_TAG_PUSH 63 | crypto_secretstream_xchacha20poly1305_TAG_REKEY 64 | crypto_secretstream_xchacha20poly1305_TAG_FINAL 65 | ## enc seq 66 | ## auth 67 | crypto_auth 68 | crypto_auth_verify 69 | crypto_auth_keygen 70 | crypto_auth_BYTES 71 | crypto_auth_KEYBYTES 72 | 73 | ## AEAD 74 | ### chacha20-poly1305 75 | #### orig 76 | crypto_aead_chacha20poly1305_encrypt 77 | crypto_aead_chacha20poly1305_decrypt 78 | crypto_aead_chacha20poly1305_encrypt_detached 79 | crypto_aead_chacha20poly1305_decrypt_detached 80 | crypto_aead_chacha20poly1305_keygen 81 | crypto_aead_chacha20poly1305_KEYBYTES 82 | crypto_aead_chacha20poly1305_NPUBBYTES 83 | crypto_aead_chacha20poly1305_ABYTES 84 | #### ietf 85 | crypto_aead_chacha20poly1305_ietf_encrypt 86 | crypto_aead_chacha20poly1305_ietf_decrypt 87 | crypto_aead_chacha20poly1305_ietf_encrypt_detached 88 | crypto_aead_chacha20poly1305_ietf_decrypt_detached 89 | crypto_aead_chacha20poly1305_ietf_keygen 90 | crypto_aead_chacha20poly1305_IETF_ABYTES 91 | crypto_aead_chacha20poly1305_IETF_KEYBYTES 92 | crypto_aead_chacha20poly1305_IETF_NPUBBYTES 93 | #### xchacha 94 | crypto_aead_xchacha20poly1305_ietf_encrypt 95 | crypto_aead_xchacha20poly1305_ietf_decrypt 96 | crypto_aead_xchacha20poly1305_ietf_encrypt_detached 97 | crypto_aead_xchacha20poly1305_ietf_decrypt_detached 98 | crypto_aead_xchacha20poly1305_ietf_keygen 99 | crypto_aead_xchacha20poly1305_ietf_KEYBYTES 100 | crypto_aead_xchacha20poly1305_ietf_NPUBBYTES 101 | crypto_aead_xchacha20poly1305_ietf_ABYTES 102 | ### aes256-gcm 103 | crypto_aead_aes256gcm_is_available 104 | crypto_aead_aes256gcm_encrypt 105 | crypto_aead_aes256gcm_decrypt 106 | crypto_aead_aes256gcm_encrypt_detached 107 | crypto_aead_aes256gcm_decrypt_detached 108 | crypto_aead_aes256gcm_keygen 109 | crypto_aead_aes256gcm_KEYBYTES 110 | crypto_aead_aes256gcm_NPUBBYTES 111 | crypto_aead_aes256gcm_ABYTES 112 | #### aes256-gcm with precomputed. 113 | crypto_aead_aes256gcm_beforenm 114 | crypto_aead_aes256gcm_encrypt_afternm 115 | crypto_aead_aes256gcm_decrypt_afternm 116 | crypto_aead_aes256gcm_encrypt_detached_afternm 117 | crypto_aead_aes256gcm_decrypt_detached_afternm 118 | crypto_aead_aes256gcm_KEYBYTES 119 | crypto_aead_aes256gcm_NPUBBYTES 120 | crypto_aead_aes256gcm_ABYTES 121 | 122 | # public key 123 | ## auth 124 | crypto_box_keypair 125 | crypto_box_seed_keypair 126 | crypto_scalarmult_base 127 | crypto_box_easy 128 | crypto_box_open_easy 129 | crypto_box_detached 130 | crypto_box_open_detached 131 | crypto_box_beforenm 132 | crypto_box_easy_afternm 133 | crypto_box_open_easy_afternm 134 | crypto_box_detached_afternm 135 | crypto_box_open_detached_afternm 136 | crypto_box_PUBLICKEYBYTES 137 | crypto_box_SECRETKEYBYTES 138 | crypto_box_MACBYTES 139 | crypto_box_NONCEBYTES 140 | crypto_box_SEEDBYTES 141 | crypto_box_BEFORENMBYTES 142 | ## sigs 143 | crypto_sign_keypair 144 | crypto_sign_seed_keypair 145 | crypto_sign 146 | crypto_sign_open 147 | crypto_sign_detached 148 | crypto_sign_verify_detached 149 | crypto_sign_init 150 | crypto_sign_update 151 | crypto_sign_final_create 152 | crypto_sign_final_verify 153 | crypto_sign_ed25519_sk_to_seed 154 | crypto_sign_ed25519_sk_to_pk 155 | crypto_sign_PUBLICKEYBYTES 156 | crypto_sign_SECRETKEYBYTES 157 | crypto_sign_BYTES 158 | crypto_sign_SEEDBYTES 159 | ## sealed boxes 160 | crypto_box_seal 161 | crypto_box_seal_open 162 | crypto_box_SEALBYTES 163 | 164 | # hashing 165 | ## generic hashing 166 | crypto_generichash 167 | crypto_generichash_init 168 | crypto_generichash_update 169 | crypto_generichash_final 170 | crypto_generichash_keygen 171 | crypto_generichash_BYTES 172 | crypto_generichash_BYTES_MIN 173 | crypto_generichash_BYTES_MAX 174 | crypto_generichash_KEYBYTES 175 | crypto_generichash_KEYBYTES_MIN 176 | crypto_generichash_KEYBYTES_MAX 177 | 178 | ## sip 179 | crypto_shorthash 180 | crypto_shorthash_BYTES 181 | crypto_shorthash_KEYBYTES 182 | 183 | # pwd hashing 184 | ## argon2 185 | crypto_pwhash 186 | crypto_pwhash_str 187 | crypto_pwhash_str_verify 188 | crypto_pwhash_str_needs_rehash 189 | crypto_pwhash_ALG_ARGON2I13 190 | crypto_pwhash_ALG_ARGON2ID13 191 | crypto_pwhash_ALG_DEFAULT 192 | crypto_pwhash_BYTES_MAX 193 | crypto_pwhash_BYTES_MIN 194 | crypto_pwhash_MEMLIMIT_INTERACTIVE 195 | crypto_pwhash_MEMLIMIT_MAX 196 | crypto_pwhash_MEMLIMIT_MIN 197 | crypto_pwhash_MEMLIMIT_MODERATE 198 | crypto_pwhash_MEMLIMIT_SENSITIVE 199 | crypto_pwhash_OPSLIMIT_INTERACTIVE 200 | crypto_pwhash_OPSLIMIT_MAX 201 | crypto_pwhash_OPSLIMIT_MIN 202 | crypto_pwhash_OPSLIMIT_MODERATE 203 | crypto_pwhash_OPSLIMIT_SENSITIVE 204 | crypto_pwhash_PASSWD_MAX 205 | crypto_pwhash_PASSWD_MIN 206 | crypto_pwhash_SALTBYTES 207 | crypto_pwhash_STRBYTES 208 | crypto_pwhash_STRPREFIX 209 | 210 | # kdf 211 | crypto_kdf_keygen 212 | crypto_kdf_derive_from_key 213 | crypto_kdf_PRIMITIVE 214 | crypto_kdf_BYTES_MIN 215 | crypto_kdf_BYTES_MAX 216 | crypto_kdf_CONTEXTBYTES 217 | crypto_kdf_KEYBYTES 218 | ## Unsure if these are for completeness or meant 219 | ## misuseresistant 220 | crypto_core_hchacha20 221 | crypto_core_hchacha20_KEYBYTES 222 | crypto_core_hchacha20_INPUTBYTES 223 | crypto_core_hchacha20_OUTPUTBYTES 224 | crypto_core_hchacha20_CONSTBYTES 225 | 226 | # kx 227 | crypto_kx_keypair 228 | crypto_kx_seed_keypair 229 | crypto_kx_client_session_keys 230 | crypto_kx_server_session_keys 231 | crypto_kx_PUBLICKEYBYTES 232 | crypto_kx_SECRETKEYBYTES 233 | crypto_kx_SEEDBYTES 234 | crypto_kx_SESSIONKEYBYTES 235 | crypto_kx_PRIMITIVE 236 | 237 | # advanced 238 | ## sha2 239 | crypto_hash_sha256 240 | crypto_hash_sha256_init 241 | crypto_hash_sha256_update 242 | crypto_hash_sha256_final 243 | crypto_hash_sha512 244 | crypto_hash_sha512_init 245 | crypto_hash_sha512_update 246 | crypto_hash_sha512_final 247 | crypto_hash_sha256_BYTES 248 | crypto_hash_sha512_BYTES 249 | 250 | ## hmac-sha2 251 | crypto_auth_hmacsha256 252 | crypto_auth_hmacsha256_verify 253 | crypto_auth_hmacsha256_init 254 | crypto_auth_hmacsha256_update 255 | crypto_auth_hmacsha256_final 256 | crypto_auth_hmacsha256_keygen 257 | crypto_auth_hmacsha512 258 | crypto_auth_hmacsha512_verify 259 | crypto_auth_hmacsha512_init 260 | crypto_auth_hmacsha512_update 261 | crypto_auth_hmacsha512_final 262 | crypto_auth_hmacsha512_keygen 263 | crypto_auth_hmacsha512256 264 | crypto_auth_hmacsha512256_verify 265 | crypto_auth_hmacsha512256_init 266 | crypto_auth_hmacsha512256_update 267 | crypto_auth_hmacsha512256_final 268 | crypto_auth_hmacsha512256_keygen 269 | crypto_auth_hmacsha256_BYTES 270 | crypto_auth_hmacsha256_KEYBYTES 271 | crypto_auth_hmacsha512_BYTES 272 | crypto_auth_hmacsha512_KEYBYTES 273 | crypto_auth_hmacsha512256_BYTES 274 | crypto_auth_hmacsha512256_KEYBYTES 275 | 276 | ## scrypt 277 | crypto_pwhash_scryptsalsa208sha256 278 | crypto_pwhash_scryptsalsa208sha256_str 279 | crypto_pwhash_scryptsalsa208sha256_str_verify 280 | crypto_pwhash_scryptsalsa208sha256_ll 281 | crypto_pwhash_scryptsalsa208sha256_BYTES_MIN 282 | crypto_pwhash_scryptsalsa208sha256_BYTES_MAX 283 | crypto_pwhash_scryptsalsa208sha256_PASSWD_MIN 284 | crypto_pwhash_scryptsalsa208sha256_PASSWD_MAX 285 | crypto_pwhash_scryptsalsa208sha256_SALTBYTES 286 | crypto_pwhash_scryptsalsa208sha256_STRBYTES 287 | crypto_pwhash_scryptsalsa208sha256_STRPREFIX 288 | crypto_pwhash_scryptsalsa208sha256_OPSLIMIT_MIN 289 | crypto_pwhash_scryptsalsa208sha256_OPSLIMIT_MAX 290 | crypto_pwhash_scryptsalsa208sha256_MEMLIMIT_MIN 291 | crypto_pwhash_scryptsalsa208sha256_MEMLIMIT_MAX 292 | crypto_pwhash_scryptsalsa208sha256_OPSLIMIT_INTERACTIVE 293 | crypto_pwhash_scryptsalsa208sha256_MEMLIMIT_INTERACTIVE 294 | crypto_pwhash_scryptsalsa208sha256_OPSLIMIT_SENSITIVE 295 | crypto_pwhash_scryptsalsa208sha256_MEMLIMIT_SENSITIVE 296 | 297 | ## dh 298 | crypto_scalarmult_base 299 | crypto_scalarmult 300 | crypto_scalarmult_BYTES 301 | crypto_scalarmult_SCALARBYTES 302 | 303 | ## ota 304 | crypto_onetimeauth 305 | crypto_onetimeauth_verify 306 | crypto_onetimeauth_init 307 | crypto_onetimeauth_update 308 | crypto_onetimeauth_final 309 | crypto_onetimeauth_keygen 310 | crypto_onetimeauth_BYTES 311 | crypto_onetimeauth_KEYBYTES 312 | 313 | ## stream 314 | ### chacha20 315 | crypto_stream_chacha20 316 | crypto_stream_chacha20_xor 317 | crypto_stream_chacha20_xor_ic 318 | crypto_stream_chacha20_ietf 319 | crypto_stream_chacha20_ietf_xor 320 | crypto_stream_chacha20_ietf_xor_ic 321 | crypto_stream_chacha20_KEYBYTES 322 | crypto_stream_chacha20_NONCEBYTES 323 | crypto_stream_chacha20_ietf_KEYBYTES 324 | crypto_stream_chacha20_ietf_NONCEBYTES 325 | 326 | ### xchacha20 327 | crypto_stream_xchacha20 328 | crypto_stream_xchacha20_xor 329 | crypto_stream_xchacha20_xor_ic 330 | crypto_stream_xchacha20_keygen 331 | crypto_stream_xchacha20_KEYBYTES 332 | crypto_stream_xchacha20_NONCEBYTES 333 | 334 | ### salsa20 335 | crypto_stream_salsa20 336 | crypto_stream_salsa20_xor 337 | crypto_stream_salsa20_xor_ic 338 | crypto_stream_salsa20_keygen 339 | crypto_stream_salsa20_KEYBYTES 340 | crypto_stream_salsa20_NONCEBYTES 341 | crypto_stream_salsa2012 342 | crypto_stream_salsa2012_xor 343 | crypto_stream_salsa2012_keygen 344 | crypto_stream_salsa208 345 | crypto_stream_salsa208_xor 346 | crypto_stream_salsa208_keygen 347 | 348 | ### xsalsa20 349 | crypto_stream 350 | crypto_stream_xor 351 | crypto_stream_keygen 352 | crypto_stream_KEYBYTES 353 | crypto_stream_NONCEBYTES 354 | crypto_stream_PRIMITIVE 355 | 356 | ## convert 357 | crypto_sign_ed25519_pk_to_curve25519 358 | crypto_sign_ed25519_sk_to_curve25519 359 | 360 | ## custom rng 361 | randombytes_set_implementation 362 | -------------------------------------------------------------------------------- /example.js: -------------------------------------------------------------------------------- 1 | require('.')(require('sodium-native')) 2 | -------------------------------------------------------------------------------- /fixtures/crypto_kdf.json: -------------------------------------------------------------------------------- 1 | [ 2 | {"error": false, "id":0, "context":"4b44462074657374", "key":"000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f", "subkey_len":64, "subkey":"a0c724404728c8bb95e5433eb6a9716171144d61efb23e74b873fcbeda51d8071b5d70aae12066dfc94ce943f145aa176c055040c3dd73b0a15e36254d450614"}, 3 | {"error": false, "id":1, "context":"4b44462074657374", "key":"000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f", "subkey_len":64, "subkey":"02507f144fa9bf19010bf7c70b235b4c2663cc00e074f929602a5e2c10a780757d2a3993d06debc378a90efdac196dd841817b977d67b786804f6d3cd585bab5"}, 4 | {"error": false, "id":2, "context":"4b44462074657374", "key":"000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f", "subkey_len":64, "subkey":"1944da61ff18dc2028c3578ac85be904931b83860896598f62468f1cb5471c6a344c945dbc62c9aaf70feb62472d17775ea5db6ed5494c68b7a9a59761f39614"}, 5 | {"error": false, "id":3, "context":"4b44462074657374", "key":"000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f", "subkey_len":64, "subkey":"131c0ca1633ed074986215b264f6e0474f362c52b029effc7b0f75977ee89cc95d85c3db87f7e399197a25411592beeeb7e5128a74646a460ecd6deb4994b71e"}, 6 | {"error": false, "id":4, "context":"4b44462074657374", "key":"000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f", "subkey_len":64, "subkey":"a7023a0bf9be245d078aed26bcde0465ff0cc0961196a5482a0ff4ff8b4015971e13611f50529cb408f5776b14a90e7c3dd9160a22211db64ff4b5c0b9953680"}, 7 | {"error": false, "id":5, "context":"4b44462074657374", "key":"000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f", "subkey_len":64, "subkey":"50f49313f3a05b2e565c13feedb44daa675cafd42c2b2cf9edbce9c949fbfc3f175dcb738671509ae2ea66fb85e552394d479afa7fa3affe8791744796b94176"}, 8 | {"error": false, "id":6, "context":"4b44462074657374", "key":"000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f", "subkey_len":64, "subkey":"13b58d6d69780089293862cd59a1a8a4ef79bb850e3f3ba41fb22446a7dd1dc4da4667d37b33bf1225dcf8173c4c349a5d911c5bd2db9c5905ed70c11e809e3b"}, 9 | {"error": false, "id":7, "context":"4b44462074657374", "key":"000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f", "subkey_len":64, "subkey":"15d44b4b44ffa006eeceeb508c98a970aaa573d65905687b9e15854dec6d49c612757e149f78268f727660dedf9abce22a9691feb20a01b0525f4b47a3cf19db"}, 10 | {"error": false, "id":8, "context":"4b44462074657374", "key":"000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f", "subkey_len":64, "subkey":"9aebba11c5428ae8225716369e30a48943be39159a899f804e9963ef78822e186c21fe95bb0b85e60ef03a6f58d0b9d06e91f79d0ab998450b8810c73ca935b4"}, 11 | {"error": false, "id":9, "context":"4b44462074657374", "key":"000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f", "subkey_len":64, "subkey":"70f9b83e463fb441e7a4c43275125cd5b19d8e2e4a5d179a39f5db10bbce745a199104563d308cf8d4c6b27bbb759ded232f5bdb7c367dd632a9677320dfe416"}, 12 | {"error": true, "id":0, "context":"4b44462074657374", "key":"000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f", "subkey_len":0, "subkey":null}, 13 | {"error": true, "id":1, "context":"4b44462074657374", "key":"000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f", "subkey_len":1, "subkey":null}, 14 | {"error": true, "id":2, "context":"4b44462074657374", "key":"000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f", "subkey_len":2, "subkey":null}, 15 | {"error": true, "id":3, "context":"4b44462074657374", "key":"000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f", "subkey_len":3, "subkey":null}, 16 | {"error": true, "id":4, "context":"4b44462074657374", "key":"000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f", "subkey_len":4, "subkey":null}, 17 | {"error": true, "id":5, "context":"4b44462074657374", "key":"000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f", "subkey_len":5, "subkey":null}, 18 | {"error": true, "id":6, "context":"4b44462074657374", "key":"000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f", "subkey_len":6, "subkey":null}, 19 | {"error": true, "id":7, "context":"4b44462074657374", "key":"000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f", "subkey_len":7, "subkey":null}, 20 | {"error": true, "id":8, "context":"4b44462074657374", "key":"000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f", "subkey_len":8, "subkey":null}, 21 | {"error": true, "id":9, "context":"4b44462074657374", "key":"000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f", "subkey_len":9, "subkey":null}, 22 | {"error": true, "id":10, "context":"4b44462074657374", "key":"000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f", "subkey_len":10, "subkey":null}, 23 | {"error": true, "id":11, "context":"4b44462074657374", "key":"000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f", "subkey_len":11, "subkey":null}, 24 | {"error": true, "id":12, "context":"4b44462074657374", "key":"000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f", "subkey_len":12, "subkey":null}, 25 | {"error": true, "id":13, "context":"4b44462074657374", "key":"000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f", "subkey_len":13, "subkey":null}, 26 | {"error": true, "id":14, "context":"4b44462074657374", "key":"000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f", "subkey_len":14, "subkey":null}, 27 | {"error": true, "id":15, "context":"4b44462074657374", "key":"000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f", "subkey_len":15, "subkey":null}, 28 | {"error": false, "id":16, "context":"4b44462074657374", "key":"000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f", "subkey_len":16, "subkey":"a529216624ef9161e4cf117272aafff2"}, 29 | {"error": false, "id":17, "context":"4b44462074657374", "key":"000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f", "subkey_len":17, "subkey":"068bd6940b80c6cc2530a68c31d9f4e323"}, 30 | {"error": false, "id":18, "context":"4b44462074657374", "key":"000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f", "subkey_len":18, "subkey":"0acf4f6c74a590c8a1c0997ec9a1a3f48b2a"}, 31 | {"error": false, "id":19, "context":"4b44462074657374", "key":"000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f", "subkey_len":19, "subkey":"ac17a37ce74c0efece75f9337de20795dbadcc"}, 32 | {"error": false, "id":20, "context":"4b44462074657374", "key":"000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f", "subkey_len":20, "subkey":"268214dc9477a2e3c1022829f934ab992a5a3d84"}, 33 | {"error": false, "id":21, "context":"4b44462074657374", "key":"000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f", "subkey_len":21, "subkey":"33b76197b4531665e494760909eda1cc570e7da9bb"}, 34 | {"error": false, "id":22, "context":"4b44462074657374", "key":"000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f", "subkey_len":22, "subkey":"3d4efbc569ca7f858ad4f49c56b820986a406e6eebbc"}, 35 | {"error": false, "id":23, "context":"4b44462074657374", "key":"000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f", "subkey_len":23, "subkey":"983fea27520f507c40231f9557908f07c095bdf4a4ce5d"}, 36 | {"error": false, "id":24, "context":"4b44462074657374", "key":"000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f", "subkey_len":24, "subkey":"94d678717625e011995c7355f2092267dee47bf0722dd380"}, 37 | {"error": false, "id":25, "context":"4b44462074657374", "key":"000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f", "subkey_len":25, "subkey":"198901896c4f51e74ffa8b2805415c6eaba5accfc85a6e6b34"}, 38 | {"error": false, "id":26, "context":"4b44462074657374", "key":"000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f", "subkey_len":26, "subkey":"4ffabb81d49021f85ef5d2a713ab02ae86bc2e7d1522f5e077fe"}, 39 | {"error": false, "id":27, "context":"4b44462074657374", "key":"000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f", "subkey_len":27, "subkey":"eebc3d55b3f4fc8b64d2474063254da7db98e7398dfdd510e28075"}, 40 | {"error": false, "id":28, "context":"4b44462074657374", "key":"000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f", "subkey_len":28, "subkey":"22c134b9d664e1bdb14dc309a936bf1512b19e4f5175642efb1a0df7"}, 41 | {"error": false, "id":29, "context":"4b44462074657374", "key":"000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f", "subkey_len":29, "subkey":"4b179762bfc8e27a9e575113faa76247b9c046d6f22d5a02e2910a299b"}, 42 | {"error": false, "id":30, "context":"4b44462074657374", "key":"000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f", "subkey_len":30, "subkey":"abc45eb2b031307b8822c7e59a43f4108850c34a7445936bc848422251c4"}, 43 | {"error": false, "id":31, "context":"4b44462074657374", "key":"000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f", "subkey_len":31, "subkey":"d6565bd3265b6373f4f6a6b6458e981006da5e9d532ce94ca4737e188995e9"}, 44 | {"error": false, "id":32, "context":"4b44462074657374", "key":"000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f", "subkey_len":32, "subkey":"154b291f11196737f8b7f491e4ca11764e0227d34f94295408a869f007aa8618"}, 45 | {"error": false, "id":33, "context":"4b44462074657374", "key":"000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f", "subkey_len":33, "subkey":"e9dd395570e09ebb523ffc6ba098a38b17bc4944f14bd3725bdd7edbd8bcff54fb"}, 46 | {"error": false, "id":34, "context":"4b44462074657374", "key":"000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f", "subkey_len":34, "subkey":"7248294d37159e85bacde68c7762a673794c91b811e05f4e3b9e3ecc82bfcf63a2cd"}, 47 | {"error": false, "id":35, "context":"4b44462074657374", "key":"000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f", "subkey_len":35, "subkey":"d060ee4d93f8de6d9ae60fca9596413455183a1f83c7a2381227cec8f7a217e4072f85"}, 48 | {"error": false, "id":36, "context":"4b44462074657374", "key":"000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f", "subkey_len":36, "subkey":"20790290347b9b0f413a954f40e52e270b3b45417e96c8733161672188701c08dd76cc3d"}, 49 | {"error": false, "id":37, "context":"4b44462074657374", "key":"000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f", "subkey_len":37, "subkey":"7674188112a1ab8d3926d468be8e51d788ce4144bb20ff842034e4d1ddab3929a4f1a13a74"}, 50 | {"error": false, "id":38, "context":"4b44462074657374", "key":"000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f", "subkey_len":38, "subkey":"a2ab1f980a47472d8a539f20410cc9bf143d941331ab2259ea73684c0608939c5b23e9cbcb3d"}, 51 | {"error": false, "id":39, "context":"4b44462074657374", "key":"000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f", "subkey_len":39, "subkey":"f4cfbe3050f15ebbaf8d2f3bf3a678c01fc21ee1f4be07d0744c7fbf4835ea9d9472a3d785c24c"}, 52 | {"error": false, "id":40, "context":"4b44462074657374", "key":"000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f", "subkey_len":40, "subkey":"66efa5dfe3efd4cc8ca25f2d622c97a20a192d7add965f26b002b7eb81aae4203c0e5f07fd945845"}, 53 | {"error": false, "id":41, "context":"4b44462074657374", "key":"000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f", "subkey_len":41, "subkey":"ad5d8031055c96dc9db10285206d7edc38d3af85736df8a3b5fdd30a318e80c28d9b26c95a60fa3e68"}, 54 | {"error": false, "id":42, "context":"4b44462074657374", "key":"000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f", "subkey_len":42, "subkey":"9107c8a57a2c9ca40158f33ca0bfb64c095d2f21ca98bb7138477599330a36cdfc2ae5751e370d0e024e"}, 55 | {"error": false, "id":43, "context":"4b44462074657374", "key":"000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f", "subkey_len":43, "subkey":"b0c190177358b955ebebc5e0b86ec91dde3b6f1982ea4d68ec5ec3bdd6527c362e5275600b263601c98452"}, 56 | {"error": false, "id":44, "context":"4b44462074657374", "key":"000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f", "subkey_len":44, "subkey":"31bfaaad4adde0f87d87372e398c42cb7befe065ab2957ebb91ef9dc534b410783899b2e1e84221286f3bab4"}, 57 | {"error": false, "id":45, "context":"4b44462074657374", "key":"000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f", "subkey_len":45, "subkey":"2258dd1f3e516cb8e3d1f6c45808573c365192f073698939721af8961a02a8bdd002a31fd239b9498663a01f27"}, 58 | {"error": false, "id":46, "context":"4b44462074657374", "key":"000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f", "subkey_len":46, "subkey":"7c7a88016610493bb44a9432a88b50f97e2e94383972ff95da826692d96c52d82f86899b3561ec9c95a8b1bf3213"}, 59 | {"error": false, "id":47, "context":"4b44462074657374", "key":"000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f", "subkey_len":47, "subkey":"3929dc7473be4c633be9e08801a8abd284dc0c6154c5c81a4c18259699dd86753c5e14fbd723be46ebb04f4ab3058c"}, 60 | {"error": false, "id":48, "context":"4b44462074657374", "key":"000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f", "subkey_len":48, "subkey":"30b720220015fa60daa69c83f9754d772b1b2dd12ab6baaa2f4edab458d4d251c1cddb8c4a554f3eb13969316b890fbd"}, 61 | {"error": false, "id":49, "context":"4b44462074657374", "key":"000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f", "subkey_len":49, "subkey":"33fa2412a5c3294d49e964419e96d043a2099a72b3351e3bed0f07e12255c95b509ea9bf2963a4c0fe9cc2314dbc44f673"}, 62 | {"error": false, "id":50, "context":"4b44462074657374", "key":"000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f", "subkey_len":50, "subkey":"ca891d2c82a6a8f833dc1a05f190bab6de221307eab1dd2c88341d4d2537a2fc0056b0d04d8104fd3fe89e1ea20877893e81"}, 63 | {"error": false, "id":51, "context":"4b44462074657374", "key":"000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f", "subkey_len":51, "subkey":"fd78ac89a64d03672ad99d663f2613d15277cda1636e334a1706b7211ff1f3a3b3d2e671e391c75e3d242c482ce7e1b8b427ed"}, 64 | {"error": false, "id":52, "context":"4b44462074657374", "key":"000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f", "subkey_len":52, "subkey":"36a6072743d3aafd3ee89344b9ef92cb58a2853ae92b20283520439fcb55afffd3d4b5e4e8c92a85d3cf74497bdcf68bbf1fcf93"}, 65 | {"error": false, "id":53, "context":"4b44462074657374", "key":"000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f", "subkey_len":53, "subkey":"a90afcfaffec1105ad05fdaa9473fb5daf1bf8fb376b7326db46ef4c120c553188c69131933371d409eb56d66d5adca618e1dac65b"}, 66 | {"error": false, "id":54, "context":"4b44462074657374", "key":"000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f", "subkey_len":54, "subkey":"9b990d1fcddbdb5e5c7a48a6a2a666e02e7d4d4a814ece40660d99e1c02d5f023c56ae82526fc6dc8c933d0add92fc376efcddd55a42"}, 67 | {"error": false, "id":55, "context":"4b44462074657374", "key":"000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f", "subkey_len":55, "subkey":"ec545dcf456d1b0907c07418a42bf2b3d668b4797ba6874bf0d563f5f429a820f02177dd4d05e639a06807c9619fee54ffe07712493543"}, 68 | {"error": false, "id":56, "context":"4b44462074657374", "key":"000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f", "subkey_len":56, "subkey":"b0106957626894586682a275f69ed4533e2f94334cc0430394b68d82679aca00dd579e712bdd2d7f5bbce9a050269739bd8427b75b06027f"}, 69 | {"error": false, "id":57, "context":"4b44462074657374", "key":"000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f", "subkey_len":57, "subkey":"05751bfeebb480c9bca0d25d8197e2673845f405d7fb9793e29169ac19956c525f6e637f3d5ea50597b04342afed4ca16f988b4f21a34f1902"}, 70 | {"error": false, "id":58, "context":"4b44462074657374", "key":"000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f", "subkey_len":58, "subkey":"7b4e4294d3f64085b5c09be73548f1f5cb5c6f04e57ce6cdd3077e2fb37640bf1ca0c6393b87d48a6b7e3e42628bd30fca132ded03ce51f71d9d"}, 71 | {"error": false, "id":59, "context":"4b44462074657374", "key":"000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f", "subkey_len":59, "subkey":"082d248862cbfd71a634769a4b1cf52a4af47ace5b9ea4d583ca52207efc7234a6d321788130cbdec122579ad03afe00bc68c9fb3f68dd0532a96f"}, 72 | {"error": false, "id":60, "context":"4b44462074657374", "key":"000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f", "subkey_len":60, "subkey":"a2b39b4428d981013e8a9c0e41b3eed504983fc18dc4b60332b1ab28b9705228147bdb95cc17889d5f0f9cfb7fd16f9d414b1a829346a8922e945b40"}, 73 | {"error": false, "id":61, "context":"4b44462074657374", "key":"000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f", "subkey_len":61, "subkey":"efbf0f8bda1b9ef24fe389f1cf0c0c8a08bca03fc95badabb79a487d8ce1351683f59183aa6229f880d69ad60114ac128f69b2be250109972ab1f3fc3b"}, 74 | {"error": false, "id":62, "context":"4b44462074657374", "key":"000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f", "subkey_len":62, "subkey":"dfe0ba2a6de25fa06b47375e9d9cf6c6fa1493a8a2a81c28d6e09bc161057b445659db76e92e349ff44f34a2a9e3bcaa6b84b21bae56f1499c170ab81af0"}, 75 | {"error": false, "id":63, "context":"4b44462074657374", "key":"000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f", "subkey_len":63, "subkey":"02f9cbdb10759314515b01379c474ad74a1b575137bd3949776dbcfc3e18060cb13ee1f6dcf86035768fc7be63e01de321cacbfade209900dd94273fd8e176"}, 76 | {"error": false, "id":64, "context":"4b44462074657374", "key":"000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f", "subkey_len":64, "subkey":"06ae14308eeeda62a00cb6d5edf18d1707029515db98f472bbf0617419301b1d4f4f2ab65849446be46f87e1d31c6c74283897b9976f70d8a16253ac927e0d9f"}, 77 | {"error": true, "id":65, "context":"4b44462074657374", "key":"000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f", "subkey_len":65, "subkey":null} 78 | ] 79 | -------------------------------------------------------------------------------- /index.js: -------------------------------------------------------------------------------- 1 | module.exports = function (sodium) { 2 | require('./randombytes_buf')(sodium) 3 | require('./crypto_sign')(sodium) 4 | require('./crypto_box')(sodium) 5 | require('./crypto_kx')(sodium) 6 | require('./crypto_kdf')(sodium) 7 | require('./crypto_generichash')(sodium) 8 | require('./crypto_shorthash')(sodium) 9 | require('./crypto_stream')(sodium) 10 | require('./crypto_secretbox')(sodium) 11 | require('./crypto_secretstream')(sodium) 12 | require('./crypto_aead')(sodium) 13 | require('./crypto_auth')(sodium) 14 | } 15 | -------------------------------------------------------------------------------- /package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "sodium-test", 3 | "version": "0.11.1", 4 | "description": "Test harness for Javascript libsodium implementations", 5 | "main": "index.js", 6 | "dependencies": { 7 | "buffer-byte-frequency": "^1.0.1", 8 | "tape": "^4.6.3" 9 | }, 10 | "devDependencies": { 11 | "standard": "^10.0.1" 12 | }, 13 | "scripts": { 14 | "test": "standard" 15 | }, 16 | "repository": { 17 | "type": "git", 18 | "url": "git+https://github.com/sodium-friends/sodium-test.git" 19 | }, 20 | "keywords": [ 21 | "libsodium", 22 | "sodium", 23 | "sodium-friends", 24 | "tests" 25 | ], 26 | "author": "Emil Bay ", 27 | "license": "MIT", 28 | "bugs": { 29 | "url": "https://github.com/sodium-friends/sodium-test/issues" 30 | }, 31 | "homepage": "https://github.com/sodium-friends/sodium-test#readme" 32 | } 33 | -------------------------------------------------------------------------------- /randombytes_buf.js: -------------------------------------------------------------------------------- 1 | var test = require('tape') 2 | var freq = require('buffer-byte-frequency') 3 | 4 | module.exports = function (sodium) { 5 | test.skip('Various test cases', function (assert) { 6 | sodium.randombytes_buf(Buffer.alloc(0)) 7 | sodium.randombytes_buf(new Uint8Array(16)) 8 | 9 | assert.throws(function () { 10 | sodium.randombytes_buf([]) 11 | }) 12 | 13 | assert.end() 14 | }) 15 | 16 | test('Generates random bytes', function (assert) { 17 | var bufConst = Buffer.alloc(64) 18 | sodium.randombytes_buf(bufConst) 19 | 20 | var buf1 = Buffer.alloc(64) 21 | for (var i = 0; i < 1e4; i++) { 22 | sodium.randombytes_buf(buf1) 23 | if (Buffer.compare(buf1, bufConst) === 0) { 24 | assert.fail('Constant buffer should not be equal') 25 | assert.end() 26 | return 27 | } 28 | } 29 | 30 | assert.pass('Generated unique buffers') 31 | assert.end() 32 | }) 33 | 34 | test('Exceed quota', function (assert) { 35 | var buf = Buffer.alloc(1 << 17) 36 | sodium.randombytes_buf(buf) 37 | 38 | freq(buf) 39 | .map(function (cnt) { 40 | return (cnt / 256) | 0 41 | }) 42 | .forEach(function (cnt) { 43 | if (cnt < 1 && cnt > 3) assert.fail('Statistically unreasonable') 44 | }) 45 | 46 | assert.end() 47 | }) 48 | } 49 | --------------------------------------------------------------------------------