Compare commits
64 Commits
Author | SHA1 | Date | |
---|---|---|---|
|
f19e6c8172 | ||
|
ae2df3305e | ||
|
6c584231e6 | ||
|
426ca77d47 | ||
|
25c97802f4 | ||
|
87ff2a56bd | ||
|
7ef6e52870 | ||
|
0227f45c6b | ||
|
ca32540960 | ||
|
51093efbc5 | ||
|
f79aed4eee | ||
|
3eb1d64460 | ||
|
7febc97986 | ||
|
66494ec3b5 | ||
|
35f38a6c10 | ||
|
125384f26a | ||
|
d432fe295d | ||
|
97200f90da | ||
|
656d6d251e | ||
|
61b6e6916a | ||
|
ab004d8022 | ||
|
ce5ac41ecd | ||
|
a82160d51b | ||
|
a546f3e51d | ||
|
a338ae9f9d | ||
|
e4693065fd | ||
|
44e5985630 | ||
|
f11ff5a727 | ||
|
9c30d3ead8 | ||
|
ddcdae69a1 | ||
|
80dd633012 | ||
|
d8d59d0443 | ||
|
ef00ddc878 | ||
|
cc52e58504 | ||
|
7b518f7b2c | ||
|
74a1067746 | ||
|
919896d2bb | ||
|
f3a80cb6f5 | ||
|
40f9b887f4 | ||
|
2ca6264f50 | ||
|
9d65d19e86 | ||
|
30c3342156 | ||
|
930e77ad32 | ||
|
e9ac929b5a | ||
|
e77c70ef71 | ||
|
4bb40aa43d | ||
|
fc90cbedba | ||
|
63fb70028e | ||
|
f033af88bd | ||
|
b44f83f0a8 | ||
|
51f8fbc2d3 | ||
|
f790621e60 | ||
|
4e42b942a5 | ||
|
49587c3d7f | ||
|
92aee452df | ||
|
e1ca83f1bd | ||
|
c81ef709d1 | ||
|
4e1c69ba13 | ||
|
5159d68fa9 | ||
|
5ccdcdee17 | ||
|
48081c6896 | ||
|
b1741bfdae | ||
|
f7de366eec | ||
|
51e11143e5 |
1
.gitignore
vendored
1
.gitignore
vendored
@ -1 +1,2 @@
|
|||||||
node_modules
|
node_modules
|
||||||
|
package-lock.json
|
||||||
|
18
.travis.yml
Normal file
18
.travis.yml
Normal file
@ -0,0 +1,18 @@
|
|||||||
|
language: node_js
|
||||||
|
node_js:
|
||||||
|
- lts/*
|
||||||
|
env:
|
||||||
|
global:
|
||||||
|
- MOZ_HEADLESS=1
|
||||||
|
services:
|
||||||
|
- xvfb
|
||||||
|
addons:
|
||||||
|
firefox: latest
|
||||||
|
chrome: stable
|
||||||
|
cache:
|
||||||
|
npm: false
|
||||||
|
|
||||||
|
script:
|
||||||
|
- npm test
|
||||||
|
- xvfb-run --auto-servernum npm run test-browser -- --browser chrome
|
||||||
|
- xvfb-run --auto-servernum npm run test-browser -- --browser firefox
|
39
README.md
39
README.md
@ -1,31 +1,29 @@
|
|||||||
# sodium-javascript
|
# `sodium-javascript`
|
||||||
|
|
||||||
WIP - a pure javascript version of [sodium-native](https://github.com/mafintosh/sodium-native).
|
[![Build Status](https://travis-ci.org/sodium-friends/sodium-javascript.svg?branch=master)](https://travis-ci.org/sodium-friends/sodium-javascript)
|
||||||
|
|
||||||
|
> WIP - a pure javascript version of [sodium-native](https://github.com/sodium-friends/sodium-native).
|
||||||
Based on tweetnacl
|
Based on tweetnacl
|
||||||
|
|
||||||
```
|
|
||||||
npm install sodium-javascript
|
|
||||||
```
|
|
||||||
|
|
||||||
## Usage
|
## Usage
|
||||||
|
|
||||||
``` js
|
``` js
|
||||||
var sodium = require('sodium-javascript')
|
const sodium = require('sodium-javascript')
|
||||||
|
|
||||||
var key = new Buffer(sodium.crypto_secretbox_KEYBYTES)
|
const key = Buffer.alloc(sodium.crypto_secretbox_KEYBYTES)
|
||||||
var nonce = new Buffer(sodium.crypto_secretbox_NONCEBYTES)
|
const nonce = Buffer.alloc(sodium.crypto_secretbox_NONCEBYTES)
|
||||||
|
|
||||||
sodium.randombytes_buf(key)
|
sodium.randombytes_buf(key)
|
||||||
sodium.randombytes_buf(nonce)
|
sodium.randombytes_buf(nonce)
|
||||||
|
|
||||||
var message = new Buffer('Hello, World!')
|
const message = Buffer.from('Hello, World!')
|
||||||
var cipher = new Buffer(message.length + sodium.crypto_secretbox_MACBYTES)
|
const cipher = Buffer.alloc(message.length + sodium.crypto_secretbox_MACBYTES)
|
||||||
|
|
||||||
sodium.crypto_secretbox_easy(cipher, message, nonce, key)
|
sodium.crypto_secretbox_easy(cipher, message, nonce, key)
|
||||||
|
|
||||||
console.log('Encrypted:', cipher)
|
console.log('Encrypted:', cipher)
|
||||||
|
|
||||||
var plainText = new Buffer(cipher.length - sodium.crypto_secretbox_MACBYTES)
|
const plainText = Buffer.alloc(cipher.length - sodium.crypto_secretbox_MACBYTES)
|
||||||
|
|
||||||
sodium.crypto_secretbox_open_easy(plainText, cipher, nonce, key)
|
sodium.crypto_secretbox_open_easy(plainText, cipher, nonce, key)
|
||||||
|
|
||||||
@ -34,9 +32,20 @@ console.log('Plaintext:', plainText.toString())
|
|||||||
|
|
||||||
## API
|
## API
|
||||||
|
|
||||||
See [sodium-native](https://github.com/mafintosh/sodium-native).
|
See [sodium-native](https://github.com/sodium-friends/sodium-native).
|
||||||
This is a work in progress so all functions are not implemented yet.
|
This is a work in progress so not all functions are implemented yet.
|
||||||
|
|
||||||
|
This module is organised into individual submodules which can be required
|
||||||
|
independently for smaller bundles in the browser. To leverage automatic
|
||||||
|
switching between `sodium-javascript` and `sodium-native`, see
|
||||||
|
[`sodium-universal`](https://github.com/sodium-friends/sodium-universal).
|
||||||
|
|
||||||
|
## Install
|
||||||
|
|
||||||
|
```
|
||||||
|
npm install sodium-javascript
|
||||||
|
```
|
||||||
|
|
||||||
## License
|
## License
|
||||||
|
|
||||||
MIT
|
[MIT](LICENSE)
|
||||||
|
160
crypto_aead.js
Normal file
160
crypto_aead.js
Normal file
@ -0,0 +1,160 @@
|
|||||||
|
/* eslint-disable camelcase */
|
||||||
|
const { crypto_stream_chacha20_ietf, crypto_stream_chacha20_ietf_xor_ic } = require('./crypto_stream_chacha20')
|
||||||
|
const { crypto_verify_16 } = require('./crypto_verify')
|
||||||
|
const Poly1305 = require('./internal/poly1305')
|
||||||
|
const assert = require('nanoassert')
|
||||||
|
|
||||||
|
const crypto_aead_chacha20poly1305_ietf_KEYBYTES = 32
|
||||||
|
const crypto_aead_chacha20poly1305_ietf_NSECBYTES = 0
|
||||||
|
const crypto_aead_chacha20poly1305_ietf_NPUBBYTES = 12
|
||||||
|
const crypto_aead_chacha20poly1305_ietf_ABYTES = 16
|
||||||
|
const crypto_aead_chacha20poly1305_ietf_MESSAGEBYTES_MAX = Number.MAX_SAFE_INTEGER
|
||||||
|
|
||||||
|
const _pad0 = new Uint8Array(16)
|
||||||
|
|
||||||
|
function crypto_aead_chacha20poly1305_ietf_encrypt (c, m, ad, nsec, npub, k) {
|
||||||
|
if (ad === null) return crypto_aead_chacha20poly1305_ietf_encrypt(c, m, new Uint8Array(0), nsec, npub, k)
|
||||||
|
|
||||||
|
assert(c.byteLength === m.byteLength + crypto_aead_chacha20poly1305_ietf_ABYTES,
|
||||||
|
"ciphertext should be 'crypto_aead_chacha20poly1305_ietf_ABYTES' longer than message")
|
||||||
|
assert(npub.byteLength === crypto_aead_chacha20poly1305_ietf_NPUBBYTES,
|
||||||
|
"npub should be 'crypto_aead_chacha20poly1305_ietf_NPUBBYTES' long")
|
||||||
|
assert(k.byteLength === crypto_aead_chacha20poly1305_ietf_KEYBYTES,
|
||||||
|
"k should be 'crypto_aead_chacha20poly1305_ietf_KEYBYTES' long")
|
||||||
|
assert(m.byteLength <= crypto_aead_chacha20poly1305_ietf_MESSAGEBYTES_MAX, 'message is too large')
|
||||||
|
|
||||||
|
const ret = crypto_aead_chacha20poly1305_ietf_encrypt_detached(c.subarray(0, m.byteLength),
|
||||||
|
c.subarray(m.byteLength), m, ad, nsec, npub, k)
|
||||||
|
|
||||||
|
return m.byteLength + ret
|
||||||
|
}
|
||||||
|
|
||||||
|
function crypto_aead_chacha20poly1305_ietf_encrypt_detached (c, mac, m, ad, nsec, npub, k) {
|
||||||
|
if (ad === null) return crypto_aead_chacha20poly1305_ietf_encrypt_detached(c, mac, m, new Uint8Array(0), nsec, npub, k)
|
||||||
|
|
||||||
|
assert(c.byteLength === m.byteLength, 'ciphertext should be same length than message')
|
||||||
|
assert(npub.byteLength === crypto_aead_chacha20poly1305_ietf_NPUBBYTES,
|
||||||
|
"npub should be 'crypto_aead_chacha20poly1305_ietf_NPUBBYTES' long")
|
||||||
|
assert(k.byteLength === crypto_aead_chacha20poly1305_ietf_KEYBYTES,
|
||||||
|
"k should be 'crypto_aead_chacha20poly1305_ietf_KEYBYTES' long")
|
||||||
|
assert(m.byteLength <= crypto_aead_chacha20poly1305_ietf_MESSAGEBYTES_MAX, 'message is too large')
|
||||||
|
assert(mac.byteLength <= crypto_aead_chacha20poly1305_ietf_ABYTES,
|
||||||
|
"mac should be 'crypto_aead_chacha20poly1305_ietf_ABYTES' long")
|
||||||
|
|
||||||
|
const block0 = new Uint8Array(64)
|
||||||
|
var slen = new Uint8Array(8)
|
||||||
|
|
||||||
|
crypto_stream_chacha20_ietf(block0, npub, k)
|
||||||
|
const poly = new Poly1305(block0)
|
||||||
|
block0.fill(0)
|
||||||
|
|
||||||
|
poly.update(ad, 0, ad.byteLength)
|
||||||
|
poly.update(_pad0, 0, (0x10 - ad.byteLength) & 0xf)
|
||||||
|
|
||||||
|
crypto_stream_chacha20_ietf_xor_ic(c, m, npub, 1, k)
|
||||||
|
|
||||||
|
poly.update(c, 0, m.byteLength)
|
||||||
|
poly.update(_pad0, 0, (0x10 - m.byteLength) & 0xf)
|
||||||
|
|
||||||
|
write64LE(slen, 0, ad.byteLength)
|
||||||
|
poly.update(slen, 0, slen.byteLength)
|
||||||
|
|
||||||
|
write64LE(slen, 0, m.byteLength)
|
||||||
|
poly.update(slen, 0, slen.byteLength)
|
||||||
|
|
||||||
|
poly.finish(mac, 0)
|
||||||
|
slen.fill(0)
|
||||||
|
|
||||||
|
return crypto_aead_chacha20poly1305_ietf_ABYTES
|
||||||
|
}
|
||||||
|
|
||||||
|
function crypto_aead_chacha20poly1305_ietf_decrypt (m, nsec, c, ad, npub, k) {
|
||||||
|
if (ad === null) return crypto_aead_chacha20poly1305_ietf_decrypt(m, nsec, c, new Uint8Array(0), npub, k)
|
||||||
|
|
||||||
|
assert(m.byteLength === c.byteLength - crypto_aead_chacha20poly1305_ietf_ABYTES,
|
||||||
|
"message should be 'crypto_aead_chacha20poly1305_ietf_ABYTES' shorter than ciphertext")
|
||||||
|
assert(npub.byteLength === crypto_aead_chacha20poly1305_ietf_NPUBBYTES,
|
||||||
|
"npub should be 'crypto_aead_chacha20poly1305_ietf_NPUBBYTES' long")
|
||||||
|
assert(k.byteLength === crypto_aead_chacha20poly1305_ietf_KEYBYTES,
|
||||||
|
"k should be 'crypto_aead_chacha20poly1305_ietf_KEYBYTES' long")
|
||||||
|
assert(m.byteLength <= crypto_aead_chacha20poly1305_ietf_MESSAGEBYTES_MAX, 'message is too large')
|
||||||
|
|
||||||
|
if (c.byteLength < crypto_aead_chacha20poly1305_ietf_ABYTES) throw new Error('could not verify data')
|
||||||
|
|
||||||
|
crypto_aead_chacha20poly1305_ietf_decrypt_detached(
|
||||||
|
m, nsec,
|
||||||
|
c.subarray(0, c.byteLength - crypto_aead_chacha20poly1305_ietf_ABYTES),
|
||||||
|
c.subarray(c.byteLength - crypto_aead_chacha20poly1305_ietf_ABYTES),
|
||||||
|
ad, npub, k)
|
||||||
|
|
||||||
|
return c.byteLength - crypto_aead_chacha20poly1305_ietf_ABYTES
|
||||||
|
}
|
||||||
|
|
||||||
|
function crypto_aead_chacha20poly1305_ietf_decrypt_detached (m, nsec, c, mac, ad, npub, k) {
|
||||||
|
if (ad === null) return crypto_aead_chacha20poly1305_ietf_decrypt_detached(m, nsec, c, mac, new Uint8Array(0), npub, k)
|
||||||
|
|
||||||
|
assert(c.byteLength === m.byteLength, 'message should be same length than ciphertext')
|
||||||
|
assert(npub.byteLength === crypto_aead_chacha20poly1305_ietf_NPUBBYTES,
|
||||||
|
"npub should be 'crypto_aead_chacha20poly1305_ietf_NPUBBYTES' long")
|
||||||
|
assert(k.byteLength === crypto_aead_chacha20poly1305_ietf_KEYBYTES,
|
||||||
|
"k should be 'crypto_aead_chacha20poly1305_ietf_KEYBYTES' long")
|
||||||
|
assert(m.byteLength <= crypto_aead_chacha20poly1305_ietf_MESSAGEBYTES_MAX, 'message is too large')
|
||||||
|
assert(mac.byteLength <= crypto_aead_chacha20poly1305_ietf_ABYTES,
|
||||||
|
"mac should be 'crypto_aead_chacha20poly1305_ietf_ABYTES' long")
|
||||||
|
|
||||||
|
const block0 = new Uint8Array(64)
|
||||||
|
const slen = new Uint8Array(8)
|
||||||
|
const computed_mac = new Uint8Array(crypto_aead_chacha20poly1305_ietf_ABYTES)
|
||||||
|
|
||||||
|
crypto_stream_chacha20_ietf(block0, npub, k)
|
||||||
|
const poly = new Poly1305(block0)
|
||||||
|
block0.fill(0)
|
||||||
|
|
||||||
|
poly.update(ad, 0, ad.byteLength)
|
||||||
|
poly.update(_pad0, 0, (0x10 - ad.byteLength) & 0xf)
|
||||||
|
|
||||||
|
const mlen = c.byteLength
|
||||||
|
poly.update(c, 0, mlen)
|
||||||
|
poly.update(_pad0, 0, (0x10 - mlen) & 0xf)
|
||||||
|
|
||||||
|
write64LE(slen, 0, ad.byteLength)
|
||||||
|
poly.update(slen, 0, slen.byteLength)
|
||||||
|
|
||||||
|
write64LE(slen, 0, mlen)
|
||||||
|
poly.update(slen, 0, slen.byteLength)
|
||||||
|
|
||||||
|
poly.finish(computed_mac, 0)
|
||||||
|
|
||||||
|
assert(computed_mac.byteLength === 16)
|
||||||
|
const ret = crypto_verify_16(computed_mac, 0, mac, 0)
|
||||||
|
|
||||||
|
computed_mac.fill(0)
|
||||||
|
slen.fill(0)
|
||||||
|
|
||||||
|
if (!ret) {
|
||||||
|
m.fill(0)
|
||||||
|
throw new Error('could not verify data')
|
||||||
|
}
|
||||||
|
|
||||||
|
crypto_stream_chacha20_ietf_xor_ic(m, c, npub, 1, k)
|
||||||
|
}
|
||||||
|
|
||||||
|
function write64LE (buf, offset, int) {
|
||||||
|
buf.fill(0, 0, 8)
|
||||||
|
|
||||||
|
const view = new DataView(buf.buffer, buf.byteOffset, buf.byteLength)
|
||||||
|
view.setUint32(offset, int & 0xffffffff, true)
|
||||||
|
view.setUint32(offset + 4, (int / 2 ** 32) & 0xffffffff, true)
|
||||||
|
}
|
||||||
|
|
||||||
|
module.exports = {
|
||||||
|
crypto_aead_chacha20poly1305_ietf_encrypt,
|
||||||
|
crypto_aead_chacha20poly1305_ietf_encrypt_detached,
|
||||||
|
crypto_aead_chacha20poly1305_ietf_decrypt,
|
||||||
|
crypto_aead_chacha20poly1305_ietf_decrypt_detached,
|
||||||
|
crypto_aead_chacha20poly1305_ietf_ABYTES,
|
||||||
|
crypto_aead_chacha20poly1305_ietf_KEYBYTES,
|
||||||
|
crypto_aead_chacha20poly1305_ietf_NPUBBYTES,
|
||||||
|
crypto_aead_chacha20poly1305_ietf_NSECBYTES,
|
||||||
|
crypto_aead_chacha20poly1305_ietf_MESSAGEBYTES_MAX
|
||||||
|
}
|
35
crypto_auth.js
Normal file
35
crypto_auth.js
Normal file
@ -0,0 +1,35 @@
|
|||||||
|
/* eslint-disable camelcase */
|
||||||
|
const { crypto_verify_32 } = require('./crypto_verify')
|
||||||
|
const Sha512 = require('sha512-universal')
|
||||||
|
const assert = require('nanoassert')
|
||||||
|
|
||||||
|
const crypto_auth_BYTES = 32
|
||||||
|
const crypto_auth_KEYBYTES = 32
|
||||||
|
|
||||||
|
function crypto_auth (out, input, k) {
|
||||||
|
assert(out.byteLength === crypto_auth_BYTES, "out should be 'crypto_auth_BYTES' in length")
|
||||||
|
assert(k.byteLength === crypto_auth_KEYBYTES, "key should be 'crypto_auth_KEYBYTES' in length")
|
||||||
|
|
||||||
|
const out0 = new Uint8Array(64)
|
||||||
|
const hmac = Sha512.HMAC(k)
|
||||||
|
hmac.update(input)
|
||||||
|
hmac.digest(out0)
|
||||||
|
|
||||||
|
out.set(out0.subarray(0, 32))
|
||||||
|
}
|
||||||
|
|
||||||
|
function crypto_auth_verify (h, input, k) {
|
||||||
|
assert(h.byteLength === crypto_auth_BYTES, "h should be 'crypto_auth_BYTES' in length")
|
||||||
|
assert(k.byteLength === crypto_auth_KEYBYTES, "key should be 'crypto_auth_KEYBYTES' in length")
|
||||||
|
|
||||||
|
const correct = Sha512.HMAC(k).update(input).digest()
|
||||||
|
|
||||||
|
return crypto_verify_32(h, 0, correct, 0)
|
||||||
|
}
|
||||||
|
|
||||||
|
module.exports = {
|
||||||
|
crypto_auth_BYTES,
|
||||||
|
crypto_auth_KEYBYTES,
|
||||||
|
crypto_auth,
|
||||||
|
crypto_auth_verify
|
||||||
|
}
|
200
crypto_box.js
Normal file
200
crypto_box.js
Normal file
@ -0,0 +1,200 @@
|
|||||||
|
/* eslint-disable camelcase */
|
||||||
|
const { crypto_hash_sha512 } = require('./crypto_hash')
|
||||||
|
const { crypto_scalarmult, crypto_scalarmult_base } = require('./crypto_scalarmult')
|
||||||
|
const { randombytes } = require('./randombytes')
|
||||||
|
const { crypto_generichash_batch } = require('./crypto_generichash')
|
||||||
|
const { crypto_stream_xsalsa20_MESSAGEBYTES_MAX } = require('./crypto_stream')
|
||||||
|
const {
|
||||||
|
crypto_secretbox_open_easy,
|
||||||
|
crypto_secretbox_easy,
|
||||||
|
crypto_secretbox_detached,
|
||||||
|
crypto_secretbox_open_detached
|
||||||
|
} = require('./crypto_secretbox')
|
||||||
|
const xsalsa20 = require('xsalsa20')
|
||||||
|
const assert = require('nanoassert')
|
||||||
|
|
||||||
|
const crypto_box_PUBLICKEYBYTES = 32
|
||||||
|
const crypto_box_SECRETKEYBYTES = 32
|
||||||
|
const crypto_box_NONCEBYTES = 24
|
||||||
|
const crypto_box_ZEROBYTES = 32
|
||||||
|
const crypto_box_BOXZEROBYTES = 16
|
||||||
|
const crypto_box_SEALBYTES = 48
|
||||||
|
const crypto_box_SEEDBYTES = 32
|
||||||
|
const crypto_box_BEFORENMBYTES = 32
|
||||||
|
const crypto_box_MACBYTES = 16
|
||||||
|
|
||||||
|
const crypto_box_curve25519xsalsa20poly1305_MACBYTES = 16
|
||||||
|
|
||||||
|
const crypto_box_MESSAGEBYTES_MAX =
|
||||||
|
crypto_stream_xsalsa20_MESSAGEBYTES_MAX -
|
||||||
|
crypto_box_curve25519xsalsa20poly1305_MACBYTES
|
||||||
|
|
||||||
|
module.exports = {
|
||||||
|
crypto_box_easy,
|
||||||
|
crypto_box_open_easy,
|
||||||
|
crypto_box_keypair,
|
||||||
|
crypto_box_seed_keypair,
|
||||||
|
crypto_box_seal,
|
||||||
|
crypto_box_seal_open,
|
||||||
|
crypto_box_PUBLICKEYBYTES,
|
||||||
|
crypto_box_SECRETKEYBYTES,
|
||||||
|
crypto_box_NONCEBYTES,
|
||||||
|
crypto_box_ZEROBYTES,
|
||||||
|
crypto_box_BOXZEROBYTES,
|
||||||
|
crypto_box_SEALBYTES,
|
||||||
|
crypto_box_SEEDBYTES,
|
||||||
|
crypto_box_BEFORENMBYTES,
|
||||||
|
crypto_box_MACBYTES
|
||||||
|
}
|
||||||
|
|
||||||
|
function crypto_box_keypair (pk, sk) {
|
||||||
|
check(pk, crypto_box_PUBLICKEYBYTES)
|
||||||
|
check(sk, crypto_box_SECRETKEYBYTES)
|
||||||
|
randombytes(sk, 32)
|
||||||
|
return crypto_scalarmult_base(pk, sk)
|
||||||
|
}
|
||||||
|
function crypto_box_seed_keypair (pk, sk, seed) {
|
||||||
|
assert(pk.byteLength === crypto_box_PUBLICKEYBYTES, "pk should be 'crypto_box_PUBLICKEYBYTES' bytes")
|
||||||
|
assert(sk.byteLength === crypto_box_SECRETKEYBYTES, "sk should be 'crypto_box_SECRETKEYBYTES' bytes")
|
||||||
|
assert(sk.byteLength === crypto_box_SEEDBYTES, "sk should be 'crypto_box_SEEDBYTES' bytes")
|
||||||
|
|
||||||
|
const hash = new Uint8Array(64)
|
||||||
|
crypto_hash_sha512(hash, seed, 32)
|
||||||
|
sk.set(hash.subarray(0, 32))
|
||||||
|
hash.fill(0)
|
||||||
|
|
||||||
|
return crypto_scalarmult_base(pk, sk)
|
||||||
|
}
|
||||||
|
|
||||||
|
function crypto_box_seal (c, m, pk) {
|
||||||
|
check(c, crypto_box_SEALBYTES + m.length)
|
||||||
|
check(pk, crypto_box_PUBLICKEYBYTES)
|
||||||
|
|
||||||
|
var epk = c.subarray(0, crypto_box_PUBLICKEYBYTES)
|
||||||
|
var esk = new Uint8Array(crypto_box_SECRETKEYBYTES)
|
||||||
|
crypto_box_keypair(epk, esk)
|
||||||
|
|
||||||
|
var n = new Uint8Array(crypto_box_NONCEBYTES)
|
||||||
|
crypto_generichash_batch(n, [epk, pk])
|
||||||
|
|
||||||
|
var s = new Uint8Array(crypto_box_PUBLICKEYBYTES)
|
||||||
|
crypto_scalarmult(s, esk, pk)
|
||||||
|
|
||||||
|
var k = new Uint8Array(crypto_box_BEFORENMBYTES)
|
||||||
|
var zero = new Uint8Array(16)
|
||||||
|
xsalsa20.core_hsalsa20(k, zero, s, xsalsa20.SIGMA)
|
||||||
|
|
||||||
|
crypto_secretbox_easy(c.subarray(epk.length), m, n, k)
|
||||||
|
|
||||||
|
cleanup(esk)
|
||||||
|
}
|
||||||
|
|
||||||
|
function crypto_box_seal_open (m, c, pk, sk) {
|
||||||
|
check(c, crypto_box_SEALBYTES)
|
||||||
|
check(m, c.length - crypto_box_SEALBYTES)
|
||||||
|
check(pk, crypto_box_PUBLICKEYBYTES)
|
||||||
|
check(sk, crypto_box_SECRETKEYBYTES)
|
||||||
|
|
||||||
|
var epk = c.subarray(0, crypto_box_PUBLICKEYBYTES)
|
||||||
|
|
||||||
|
var n = new Uint8Array(crypto_box_NONCEBYTES)
|
||||||
|
crypto_generichash_batch(n, [epk, pk])
|
||||||
|
|
||||||
|
var s = new Uint8Array(crypto_box_PUBLICKEYBYTES)
|
||||||
|
crypto_scalarmult(s, sk, epk)
|
||||||
|
|
||||||
|
var k = new Uint8Array(crypto_box_BEFORENMBYTES)
|
||||||
|
var zero = new Uint8Array(16)
|
||||||
|
xsalsa20.core_hsalsa20(k, zero, s, xsalsa20.SIGMA)
|
||||||
|
|
||||||
|
return crypto_secretbox_open_easy(m, c.subarray(epk.length), n, k)
|
||||||
|
}
|
||||||
|
|
||||||
|
function crypto_box_beforenm (k, pk, sk) {
|
||||||
|
const zero = new Uint8Array(16)
|
||||||
|
const s = new Uint8Array(32)
|
||||||
|
|
||||||
|
assert(crypto_scalarmult(s, sk, pk) === 0)
|
||||||
|
|
||||||
|
xsalsa20.core_hsalsa20(k, zero, s, xsalsa20.SIGMA)
|
||||||
|
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
|
||||||
|
function crypto_box_detached_afternm (c, mac, m, n, k) {
|
||||||
|
return crypto_secretbox_detached(c, mac, m, n, k)
|
||||||
|
}
|
||||||
|
|
||||||
|
function crypto_box_detached (c, mac, m, n, pk, sk) {
|
||||||
|
check(mac, crypto_box_MACBYTES)
|
||||||
|
check(n, crypto_box_NONCEBYTES)
|
||||||
|
check(pk, crypto_box_PUBLICKEYBYTES)
|
||||||
|
check(sk, crypto_box_SECRETKEYBYTES)
|
||||||
|
|
||||||
|
const k = new Uint8Array(crypto_box_BEFORENMBYTES)
|
||||||
|
|
||||||
|
assert(crypto_box_beforenm(k, pk, sk))
|
||||||
|
|
||||||
|
const ret = crypto_box_detached_afternm(c, mac, m, n, k)
|
||||||
|
cleanup(k)
|
||||||
|
|
||||||
|
return ret
|
||||||
|
}
|
||||||
|
|
||||||
|
function crypto_box_easy (c, m, n, pk, sk) {
|
||||||
|
assert(
|
||||||
|
c.length >= m.length + crypto_box_MACBYTES,
|
||||||
|
"c should be at least 'm.length + crypto_box_MACBYTES' bytes"
|
||||||
|
)
|
||||||
|
assert(
|
||||||
|
m.length <= crypto_box_MESSAGEBYTES_MAX,
|
||||||
|
"m should be at most 'crypto_box_MESSAGEBYTES_MAX' bytes"
|
||||||
|
)
|
||||||
|
|
||||||
|
return crypto_box_detached(
|
||||||
|
c.subarray(crypto_box_MACBYTES, m.length + crypto_box_MACBYTES),
|
||||||
|
c.subarray(0, crypto_box_MACBYTES),
|
||||||
|
m,
|
||||||
|
n,
|
||||||
|
pk,
|
||||||
|
sk
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
function crypto_box_open_detached_afternm (m, c, mac, n, k) {
|
||||||
|
return crypto_secretbox_open_detached(m, c, mac, n, k)
|
||||||
|
}
|
||||||
|
|
||||||
|
function crypto_box_open_detached (m, c, mac, n, pk, sk) {
|
||||||
|
const k = new Uint8Array(crypto_box_BEFORENMBYTES)
|
||||||
|
assert(crypto_box_beforenm(k, pk, sk))
|
||||||
|
|
||||||
|
const ret = crypto_box_open_detached_afternm(m, c, mac, n, k)
|
||||||
|
cleanup(k)
|
||||||
|
|
||||||
|
return ret
|
||||||
|
}
|
||||||
|
|
||||||
|
function crypto_box_open_easy (m, c, n, pk, sk) {
|
||||||
|
assert(
|
||||||
|
c.length >= m.length + crypto_box_MACBYTES,
|
||||||
|
"c should be at least 'm.length + crypto_box_MACBYTES' bytes"
|
||||||
|
)
|
||||||
|
|
||||||
|
return crypto_box_open_detached(
|
||||||
|
m,
|
||||||
|
c.subarray(crypto_box_MACBYTES, m.length + crypto_box_MACBYTES),
|
||||||
|
c.subarray(0, crypto_box_MACBYTES),
|
||||||
|
n,
|
||||||
|
pk,
|
||||||
|
sk
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
function check (buf, len) {
|
||||||
|
if (!buf || (len && buf.length < len)) throw new Error('Argument must be a buffer' + (len ? ' of length ' + len : ''))
|
||||||
|
}
|
||||||
|
|
||||||
|
function cleanup (arr) {
|
||||||
|
for (let i = 0; i < arr.length; i++) arr[i] = 0
|
||||||
|
}
|
@ -1,5 +1,7 @@
|
|||||||
var blake2b = require('blake2b')
|
var blake2b = require('blake2b')
|
||||||
|
|
||||||
|
if (new Uint16Array([1])[0] !== 1) throw new Error('Big endian architecture is not supported.')
|
||||||
|
|
||||||
module.exports.crypto_generichash_PRIMITIVE = 'blake2b'
|
module.exports.crypto_generichash_PRIMITIVE = 'blake2b'
|
||||||
module.exports.crypto_generichash_BYTES_MIN = blake2b.BYTES_MIN
|
module.exports.crypto_generichash_BYTES_MIN = blake2b.BYTES_MIN
|
||||||
module.exports.crypto_generichash_BYTES_MAX = blake2b.BYTES_MAX
|
module.exports.crypto_generichash_BYTES_MAX = blake2b.BYTES_MAX
|
||||||
@ -29,6 +31,6 @@ module.exports.crypto_generichash_instance = function (key, outlen) {
|
|||||||
return blake2b(outlen, key)
|
return blake2b(outlen, key)
|
||||||
}
|
}
|
||||||
|
|
||||||
blake2b.ready(function (err) {
|
blake2b.ready(function (_) {
|
||||||
module.exports.crypto_generichash_WASM_LOADED = blake2b.WASM_LOADED
|
module.exports.crypto_generichash_WASM_LOADED = blake2b.WASM_LOADED
|
||||||
})
|
})
|
||||||
|
26
crypto_hash.js
Normal file
26
crypto_hash.js
Normal file
@ -0,0 +1,26 @@
|
|||||||
|
/* eslint-disable camelcase */
|
||||||
|
const sha512 = require('sha512-universal')
|
||||||
|
const assert = require('nanoassert')
|
||||||
|
|
||||||
|
if (new Uint16Array([1])[0] !== 1) throw new Error('Big endian architecture is not supported.')
|
||||||
|
|
||||||
|
const crypto_hash_sha512_BYTES = 64
|
||||||
|
const crypto_hash_BYTES = crypto_hash_sha512_BYTES
|
||||||
|
|
||||||
|
function crypto_hash_sha512 (out, m, n) {
|
||||||
|
assert(out.byteLength === crypto_hash_sha512_BYTES, "out must be 'crypto_hash_sha512_BYTES' bytes long")
|
||||||
|
|
||||||
|
sha512().update(m.subarray(0, n)).digest(out)
|
||||||
|
return 0
|
||||||
|
}
|
||||||
|
|
||||||
|
function crypto_hash (out, m, n) {
|
||||||
|
return crypto_hash_sha512(out, m, n)
|
||||||
|
}
|
||||||
|
|
||||||
|
module.exports = {
|
||||||
|
crypto_hash,
|
||||||
|
crypto_hash_sha512,
|
||||||
|
crypto_hash_sha512_BYTES,
|
||||||
|
crypto_hash_BYTES
|
||||||
|
}
|
19
crypto_hash_sha256.js
Normal file
19
crypto_hash_sha256.js
Normal file
@ -0,0 +1,19 @@
|
|||||||
|
/* eslint-disable camelcase */
|
||||||
|
const sha256 = require('sha256-universal')
|
||||||
|
const assert = require('nanoassert')
|
||||||
|
|
||||||
|
if (new Uint16Array([1])[0] !== 1) throw new Error('Big endian architecture is not supported.')
|
||||||
|
|
||||||
|
const crypto_hash_sha256_BYTES = 32
|
||||||
|
|
||||||
|
function crypto_hash_sha256 (out, m, n) {
|
||||||
|
assert(out.byteLength === crypto_hash_sha256_BYTES, "out must be 'crypto_hash_sha256_BYTES' bytes long")
|
||||||
|
|
||||||
|
sha256().update(m.subarray(0, n)).digest(out)
|
||||||
|
return 0
|
||||||
|
}
|
||||||
|
|
||||||
|
module.exports = {
|
||||||
|
crypto_hash_sha256,
|
||||||
|
crypto_hash_sha256_BYTES
|
||||||
|
}
|
@ -1,12 +1,13 @@
|
|||||||
var assert = require('nanoassert')
|
/* eslint-disable camelcase */
|
||||||
var randombytes_buf = require('./randombytes').randombytes_buf
|
const assert = require('nanoassert')
|
||||||
var blake2b = require('blake2b')
|
const randombytes_buf = require('./randombytes').randombytes_buf
|
||||||
|
const blake2b = require('blake2b')
|
||||||
|
|
||||||
module.exports.crypto_kdf_PRIMITIVE = 'blake2b'
|
module.exports.crypto_kdf_PRIMITIVE = 'blake2b'
|
||||||
module.exports.crypto_kdf_BYTES_MIN = 16
|
module.exports.crypto_kdf_BYTES_MIN = 16
|
||||||
module.exports.crypto_kdf_BYTES_MAX = 64
|
module.exports.crypto_kdf_BYTES_MAX = 64
|
||||||
module.exports.crypto_kdf_CONTEXTBYTES = 8
|
module.exports.crypto_kdf_CONTEXTBYTES = 8
|
||||||
module.exports.crypto_kdf_KEYBYTES = 64
|
module.exports.crypto_kdf_KEYBYTES = 32
|
||||||
|
|
||||||
function STORE64_LE (dest, int) {
|
function STORE64_LE (dest, int) {
|
||||||
var mul = 1
|
var mul = 1
|
||||||
@ -29,7 +30,7 @@ module.exports.crypto_kdf_derive_from_key = function crypto_kdf_derive_from_key
|
|||||||
STORE64_LE(salt, subkey_id)
|
STORE64_LE(salt, subkey_id)
|
||||||
|
|
||||||
var outlen = Math.min(subkey.length, module.exports.crypto_kdf_BYTES_MAX)
|
var outlen = Math.min(subkey.length, module.exports.crypto_kdf_BYTES_MAX)
|
||||||
blake2b(outlen, key, salt, ctx_padded, true)
|
blake2b(outlen, key.subarray(0, module.exports.crypto_kdf_KEYBYTES), salt, ctx_padded, true)
|
||||||
.final(subkey)
|
.final(subkey)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
34
crypto_kx.js
Normal file
34
crypto_kx.js
Normal file
@ -0,0 +1,34 @@
|
|||||||
|
/* eslint-disable camelcase */
|
||||||
|
const { crypto_scalarmult_base } = require('./crypto_scalarmult')
|
||||||
|
const { crypto_generichash } = require('./crypto_generichash')
|
||||||
|
const { randombytes_buf } = require('./randombytes')
|
||||||
|
const assert = require('nanoassert')
|
||||||
|
|
||||||
|
const crypto_kx_SEEDBYTES = 32
|
||||||
|
const crypto_kx_PUBLICKEYBYTES = 32
|
||||||
|
const crypto_kx_SECRETKEYBYTES = 32
|
||||||
|
|
||||||
|
function crypto_kx_keypair (pk, sk) {
|
||||||
|
assert(pk.byteLength === crypto_kx_PUBLICKEYBYTES, "pk must be 'crypto_kx_PUBLICKEYBYTES' bytes")
|
||||||
|
assert(sk.byteLength === crypto_kx_SECRETKEYBYTES, "sk must be 'crypto_kx_SECRETKEYBYTES' bytes")
|
||||||
|
|
||||||
|
randombytes_buf(sk, crypto_kx_SECRETKEYBYTES)
|
||||||
|
return crypto_scalarmult_base(pk, sk)
|
||||||
|
}
|
||||||
|
|
||||||
|
function crypto_kx_seed_keypair (pk, sk, seed) {
|
||||||
|
assert(pk.byteLength === crypto_kx_PUBLICKEYBYTES, "pk must be 'crypto_kx_PUBLICKEYBYTES' bytes")
|
||||||
|
assert(sk.byteLength === crypto_kx_SECRETKEYBYTES, "sk must be 'crypto_kx_SECRETKEYBYTES' bytes")
|
||||||
|
assert(seed.byteLength === crypto_kx_SEEDBYTES, "seed must be 'crypto_kx_SEEDBYTES' bytes")
|
||||||
|
|
||||||
|
crypto_generichash(sk, seed)
|
||||||
|
return crypto_scalarmult_base(pk, sk)
|
||||||
|
}
|
||||||
|
|
||||||
|
module.exports = {
|
||||||
|
crypto_kx_keypair,
|
||||||
|
crypto_kx_seed_keypair,
|
||||||
|
crypto_kx_SEEDBYTES,
|
||||||
|
crypto_kx_SECRETKEYBYTES,
|
||||||
|
crypto_kx_PUBLICKEYBYTES
|
||||||
|
}
|
36
crypto_onetimeauth.js
Normal file
36
crypto_onetimeauth.js
Normal file
@ -0,0 +1,36 @@
|
|||||||
|
/* eslint-disable camelcase */
|
||||||
|
const assert = require('nanoassert')
|
||||||
|
const Poly1305 = require('./internal/poly1305')
|
||||||
|
const { crypto_verify_16 } = require('./crypto_verify')
|
||||||
|
|
||||||
|
const crypto_onetimeauth_BYTES = 16
|
||||||
|
const crypto_onetimeauth_KEYBYTES = 32
|
||||||
|
const crypto_onetimeauth_PRIMITIVE = 'poly1305'
|
||||||
|
|
||||||
|
module.exports = {
|
||||||
|
crypto_onetimeauth,
|
||||||
|
crypto_onetimeauth_verify,
|
||||||
|
crypto_onetimeauth_BYTES,
|
||||||
|
crypto_onetimeauth_KEYBYTES,
|
||||||
|
crypto_onetimeauth_PRIMITIVE
|
||||||
|
}
|
||||||
|
|
||||||
|
function crypto_onetimeauth (mac, msg, key) {
|
||||||
|
assert(mac.byteLength === crypto_onetimeauth_BYTES, "mac must be 'crypto_onetimeauth_BYTES' bytes")
|
||||||
|
assert(msg.byteLength != null, 'msg must be buffer')
|
||||||
|
assert(key.byteLength === crypto_onetimeauth_KEYBYTES, "key must be 'crypto_onetimeauth_KEYBYTES' bytes")
|
||||||
|
|
||||||
|
var s = new Poly1305(key)
|
||||||
|
s.update(msg, 0, msg.byteLength)
|
||||||
|
s.finish(mac, 0)
|
||||||
|
}
|
||||||
|
|
||||||
|
function crypto_onetimeauth_verify (mac, msg, key) {
|
||||||
|
assert(mac.byteLength === crypto_onetimeauth_BYTES, "mac must be 'crypto_onetimeauth_BYTES' bytes")
|
||||||
|
assert(msg.byteLength != null, 'msg must be buffer')
|
||||||
|
assert(key.byteLength === crypto_onetimeauth_KEYBYTES, "key must be 'crypto_onetimeauth_KEYBYTES' bytes")
|
||||||
|
|
||||||
|
var tmp = new Uint8Array(16)
|
||||||
|
crypto_onetimeauth(tmp, msg, key)
|
||||||
|
return crypto_verify_16(mac, 0, tmp, 0)
|
||||||
|
}
|
76
crypto_scalarmult.js
Normal file
76
crypto_scalarmult.js
Normal file
@ -0,0 +1,76 @@
|
|||||||
|
/* eslint-disable camelcase, one-var */
|
||||||
|
const { _9, _121665, gf, inv25519, pack25519, unpack25519, sel25519, A, M, Z, S } = require('./internal/ed25519')
|
||||||
|
|
||||||
|
const crypto_scalarmult_BYTES = 32
|
||||||
|
const crypto_scalarmult_SCALARBYTES = 32
|
||||||
|
|
||||||
|
module.exports = {
|
||||||
|
crypto_scalarmult,
|
||||||
|
crypto_scalarmult_base,
|
||||||
|
crypto_scalarmult_BYTES,
|
||||||
|
crypto_scalarmult_SCALARBYTES
|
||||||
|
}
|
||||||
|
|
||||||
|
function crypto_scalarmult (q, n, p) {
|
||||||
|
check(q, crypto_scalarmult_BYTES)
|
||||||
|
check(n, crypto_scalarmult_SCALARBYTES)
|
||||||
|
check(p, crypto_scalarmult_BYTES)
|
||||||
|
var z = new Uint8Array(32)
|
||||||
|
var x = new Float64Array(80), r, i
|
||||||
|
var a = gf(), b = gf(), c = gf(),
|
||||||
|
d = gf(), e = gf(), f = gf()
|
||||||
|
for (i = 0; i < 31; i++) z[i] = n[i]
|
||||||
|
z[31] = (n[31] & 127) | 64
|
||||||
|
z[0] &= 248
|
||||||
|
unpack25519(x, p)
|
||||||
|
for (i = 0; i < 16; i++) {
|
||||||
|
b[i] = x[i]
|
||||||
|
d[i] = a[i] = c[i] = 0
|
||||||
|
}
|
||||||
|
a[0] = d[0] = 1
|
||||||
|
for (i = 254; i >= 0; --i) {
|
||||||
|
r = (z[i >>> 3] >>> (i & 7)) & 1
|
||||||
|
sel25519(a, b, r)
|
||||||
|
sel25519(c, d, r)
|
||||||
|
A(e, a, c)
|
||||||
|
Z(a, a, c)
|
||||||
|
A(c, b, d)
|
||||||
|
Z(b, b, d)
|
||||||
|
S(d, e)
|
||||||
|
S(f, a)
|
||||||
|
M(a, c, a)
|
||||||
|
M(c, b, e)
|
||||||
|
A(e, a, c)
|
||||||
|
Z(a, a, c)
|
||||||
|
S(b, a)
|
||||||
|
Z(c, d, f)
|
||||||
|
M(a, c, _121665)
|
||||||
|
A(a, a, d)
|
||||||
|
M(c, c, a)
|
||||||
|
M(a, d, f)
|
||||||
|
M(d, b, x)
|
||||||
|
S(b, e)
|
||||||
|
sel25519(a, b, r)
|
||||||
|
sel25519(c, d, r)
|
||||||
|
}
|
||||||
|
for (i = 0; i < 16; i++) {
|
||||||
|
x[i + 16] = a[i]
|
||||||
|
x[i + 32] = c[i]
|
||||||
|
x[i + 48] = b[i]
|
||||||
|
x[i + 64] = d[i]
|
||||||
|
}
|
||||||
|
var x32 = x.subarray(32)
|
||||||
|
var x16 = x.subarray(16)
|
||||||
|
inv25519(x32, x32)
|
||||||
|
M(x16, x16, x32)
|
||||||
|
pack25519(q, x16)
|
||||||
|
return 0
|
||||||
|
}
|
||||||
|
|
||||||
|
function crypto_scalarmult_base (q, n) {
|
||||||
|
return crypto_scalarmult(q, n, _9)
|
||||||
|
}
|
||||||
|
|
||||||
|
function check (buf, len) {
|
||||||
|
if (!buf || (len && buf.length < len)) throw new Error('Argument must be a buffer' + (len ? ' of length ' + len : ''))
|
||||||
|
}
|
111
crypto_secretbox.js
Normal file
111
crypto_secretbox.js
Normal file
@ -0,0 +1,111 @@
|
|||||||
|
/* eslint-disable camelcase */
|
||||||
|
const assert = require('nanoassert')
|
||||||
|
const { crypto_stream, crypto_stream_xor } = require('./crypto_stream')
|
||||||
|
const { crypto_onetimeauth, crypto_onetimeauth_verify, crypto_onetimeauth_BYTES, crypto_onetimeauth_KEYBYTES } = require('./crypto_onetimeauth')
|
||||||
|
|
||||||
|
const crypto_secretbox_KEYBYTES = 32
|
||||||
|
const crypto_secretbox_NONCEBYTES = 24
|
||||||
|
const crypto_secretbox_ZEROBYTES = 32
|
||||||
|
const crypto_secretbox_BOXZEROBYTES = 16
|
||||||
|
const crypto_secretbox_MACBYTES = 16
|
||||||
|
|
||||||
|
module.exports = {
|
||||||
|
crypto_secretbox,
|
||||||
|
crypto_secretbox_open,
|
||||||
|
crypto_secretbox_detached,
|
||||||
|
crypto_secretbox_open_detached,
|
||||||
|
crypto_secretbox_easy,
|
||||||
|
crypto_secretbox_open_easy,
|
||||||
|
crypto_secretbox_KEYBYTES,
|
||||||
|
crypto_secretbox_NONCEBYTES,
|
||||||
|
crypto_secretbox_ZEROBYTES,
|
||||||
|
crypto_secretbox_BOXZEROBYTES,
|
||||||
|
crypto_secretbox_MACBYTES
|
||||||
|
}
|
||||||
|
|
||||||
|
function crypto_secretbox (c, m, n, k) {
|
||||||
|
assert(c.byteLength === m.byteLength, "c must be 'm.byteLength' bytes")
|
||||||
|
const mlen = m.byteLength
|
||||||
|
assert(mlen >= crypto_secretbox_ZEROBYTES, "mlen must be at least 'crypto_secretbox_ZEROBYTES'")
|
||||||
|
assert(n.byteLength === crypto_secretbox_NONCEBYTES, "n must be 'crypto_secretbox_NONCEBYTES' bytes")
|
||||||
|
assert(k.byteLength === crypto_secretbox_KEYBYTES, "k must be 'crypto_secretbox_KEYBYTES' bytes")
|
||||||
|
|
||||||
|
crypto_stream_xor(c, m, n, k)
|
||||||
|
crypto_onetimeauth(
|
||||||
|
c.subarray(crypto_secretbox_BOXZEROBYTES, crypto_secretbox_BOXZEROBYTES + crypto_onetimeauth_BYTES),
|
||||||
|
c.subarray(crypto_secretbox_BOXZEROBYTES + crypto_onetimeauth_BYTES, c.byteLength),
|
||||||
|
c.subarray(0, crypto_onetimeauth_KEYBYTES)
|
||||||
|
)
|
||||||
|
c.fill(0, 0, crypto_secretbox_BOXZEROBYTES)
|
||||||
|
}
|
||||||
|
|
||||||
|
function crypto_secretbox_open (m, c, n, k) {
|
||||||
|
assert(c.byteLength === m.byteLength, "c must be 'm.byteLength' bytes")
|
||||||
|
const mlen = m.byteLength
|
||||||
|
assert(mlen >= crypto_secretbox_ZEROBYTES, "mlen must be at least 'crypto_secretbox_ZEROBYTES'")
|
||||||
|
assert(n.byteLength === crypto_secretbox_NONCEBYTES, "n must be 'crypto_secretbox_NONCEBYTES' bytes")
|
||||||
|
assert(k.byteLength === crypto_secretbox_KEYBYTES, "k must be 'crypto_secretbox_KEYBYTES' bytes")
|
||||||
|
|
||||||
|
const x = new Uint8Array(crypto_onetimeauth_KEYBYTES)
|
||||||
|
crypto_stream(x, n, k)
|
||||||
|
const validMac = crypto_onetimeauth_verify(
|
||||||
|
c.subarray(crypto_secretbox_BOXZEROBYTES, crypto_secretbox_BOXZEROBYTES + crypto_onetimeauth_BYTES),
|
||||||
|
c.subarray(crypto_secretbox_BOXZEROBYTES + crypto_onetimeauth_BYTES, c.byteLength),
|
||||||
|
x
|
||||||
|
)
|
||||||
|
|
||||||
|
if (validMac === false) return false
|
||||||
|
crypto_stream_xor(m, c, n, k)
|
||||||
|
m.fill(0, 0, 32)
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
|
||||||
|
function crypto_secretbox_detached (o, mac, msg, n, k) {
|
||||||
|
assert(o.byteLength === msg.byteLength, "o must be 'msg.byteLength' bytes")
|
||||||
|
assert(mac.byteLength === crypto_secretbox_MACBYTES, "mac must be 'crypto_secretbox_MACBYTES' bytes")
|
||||||
|
assert(n.byteLength === crypto_secretbox_NONCEBYTES, "n must be 'crypto_secretbox_NONCEBYTES' bytes")
|
||||||
|
assert(k.byteLength === crypto_secretbox_KEYBYTES, "k must be 'crypto_secretbox_KEYBYTES' bytes")
|
||||||
|
|
||||||
|
const tmp = new Uint8Array(msg.byteLength + mac.byteLength)
|
||||||
|
crypto_secretbox_easy(tmp, msg, n, k)
|
||||||
|
mac.set(tmp.subarray(0, mac.byteLength))
|
||||||
|
o.set(tmp.subarray(mac.byteLength))
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
|
||||||
|
function crypto_secretbox_open_detached (msg, o, mac, n, k) {
|
||||||
|
assert(o.byteLength === msg.byteLength, "o must be 'msg.byteLength' bytes")
|
||||||
|
assert(mac.byteLength === crypto_secretbox_MACBYTES, "mac must be 'crypto_secretbox_MACBYTES' bytes")
|
||||||
|
assert(n.byteLength === crypto_secretbox_NONCEBYTES, "n must be 'crypto_secretbox_NONCEBYTES' bytes")
|
||||||
|
assert(k.byteLength === crypto_secretbox_KEYBYTES, "k must be 'crypto_secretbox_KEYBYTES' bytes")
|
||||||
|
|
||||||
|
const tmp = new Uint8Array(o.byteLength + mac.byteLength)
|
||||||
|
tmp.set(mac)
|
||||||
|
tmp.set(o, mac.byteLength)
|
||||||
|
return crypto_secretbox_open_easy(msg, tmp, n, k)
|
||||||
|
}
|
||||||
|
|
||||||
|
function crypto_secretbox_easy (o, msg, n, k) {
|
||||||
|
assert(o.byteLength === msg.byteLength + crypto_secretbox_MACBYTES, "o must be 'msg.byteLength + crypto_secretbox_MACBYTES' bytes")
|
||||||
|
assert(n.byteLength === crypto_secretbox_NONCEBYTES, "n must be 'crypto_secretbox_NONCEBYTES' bytes")
|
||||||
|
assert(k.byteLength === crypto_secretbox_KEYBYTES, "k must be 'crypto_secretbox_KEYBYTES' bytes")
|
||||||
|
|
||||||
|
const m = new Uint8Array(crypto_secretbox_ZEROBYTES + msg.byteLength)
|
||||||
|
const c = new Uint8Array(m.byteLength)
|
||||||
|
m.set(msg, crypto_secretbox_ZEROBYTES)
|
||||||
|
crypto_secretbox(c, m, n, k)
|
||||||
|
o.set(c.subarray(crypto_secretbox_BOXZEROBYTES))
|
||||||
|
}
|
||||||
|
|
||||||
|
function crypto_secretbox_open_easy (msg, box, n, k) {
|
||||||
|
assert(box.byteLength === msg.byteLength + crypto_secretbox_MACBYTES, "box must be 'msg.byteLength + crypto_secretbox_MACBYTES' bytes")
|
||||||
|
assert(n.byteLength === crypto_secretbox_NONCEBYTES, "n must be 'crypto_secretbox_NONCEBYTES' bytes")
|
||||||
|
assert(k.byteLength === crypto_secretbox_KEYBYTES, "k must be 'crypto_secretbox_KEYBYTES' bytes")
|
||||||
|
|
||||||
|
const c = new Uint8Array(crypto_secretbox_BOXZEROBYTES + box.byteLength)
|
||||||
|
const m = new Uint8Array(c.byteLength)
|
||||||
|
c.set(box, crypto_secretbox_BOXZEROBYTES)
|
||||||
|
if (crypto_secretbox_open(m, c, n, k) === false) return false
|
||||||
|
msg.set(m.subarray(crypto_secretbox_ZEROBYTES))
|
||||||
|
return true
|
||||||
|
}
|
271
crypto_secretstream.js
Normal file
271
crypto_secretstream.js
Normal file
@ -0,0 +1,271 @@
|
|||||||
|
/* eslint-disable camelcase */
|
||||||
|
const assert = require('nanoassert')
|
||||||
|
const { randombytes_buf } = require('./randombytes')
|
||||||
|
const {
|
||||||
|
crypto_stream_chacha20_ietf,
|
||||||
|
crypto_stream_chacha20_ietf_xor,
|
||||||
|
crypto_stream_chacha20_ietf_xor_ic,
|
||||||
|
crypto_stream_chacha20_ietf_KEYBYTES
|
||||||
|
} = require('./crypto_stream_chacha20')
|
||||||
|
const { crypto_core_hchacha20, crypto_core_hchacha20_INPUTBYTES } = require('./internal/hchacha20')
|
||||||
|
const Poly1305 = require('./internal/poly1305')
|
||||||
|
const { sodium_increment, sodium_is_zero, sodium_memcmp } = require('./helpers')
|
||||||
|
|
||||||
|
const crypto_onetimeauth_poly1305_BYTES = 16
|
||||||
|
const crypto_secretstream_xchacha20poly1305_COUNTERBYTES = 4
|
||||||
|
const crypto_secretstream_xchacha20poly1305_INONCEBYTES = 8
|
||||||
|
const crypto_aead_xchacha20poly1305_ietf_KEYBYTES = 32
|
||||||
|
const crypto_secretstream_xchacha20poly1305_KEYBYTES = crypto_aead_xchacha20poly1305_ietf_KEYBYTES
|
||||||
|
const crypto_aead_xchacha20poly1305_ietf_NPUBBYTES = 24
|
||||||
|
const crypto_secretstream_xchacha20poly1305_HEADERBYTES = crypto_aead_xchacha20poly1305_ietf_NPUBBYTES
|
||||||
|
const crypto_aead_xchacha20poly1305_ietf_ABYTES = 16
|
||||||
|
const crypto_secretstream_xchacha20poly1305_ABYTES = 1 + crypto_aead_xchacha20poly1305_ietf_ABYTES
|
||||||
|
const crypto_secretstream_xchacha20poly1305_MESSAGEBYTES_MAX = Number.MAX_SAFE_INTEGER
|
||||||
|
const crypto_aead_chacha20poly1305_ietf_MESSAGEBYTES_MAX = Number.MAX_SAFE_INTEGER
|
||||||
|
const crypto_secretstream_xchacha20poly1305_TAGBYTES = 1
|
||||||
|
const crypto_secretstream_xchacha20poly1305_TAG_MESSAGE = new Uint8Array([0])
|
||||||
|
const crypto_secretstream_xchacha20poly1305_TAG_PUSH = new Uint8Array([1])
|
||||||
|
const crypto_secretstream_xchacha20poly1305_TAG_REKEY = new Uint8Array([2])
|
||||||
|
const crypto_secretstream_xchacha20poly1305_TAG_FINAL = new Uint8Array([crypto_secretstream_xchacha20poly1305_TAG_PUSH | crypto_secretstream_xchacha20poly1305_TAG_REKEY])
|
||||||
|
const crypto_secretstream_xchacha20poly1305_STATEBYTES = crypto_secretstream_xchacha20poly1305_KEYBYTES +
|
||||||
|
crypto_secretstream_xchacha20poly1305_INONCEBYTES + crypto_secretstream_xchacha20poly1305_COUNTERBYTES + 8
|
||||||
|
|
||||||
|
const KEY_OFFSET = 0
|
||||||
|
const NONCE_OFFSET = crypto_secretstream_xchacha20poly1305_KEYBYTES
|
||||||
|
const PAD_OFFSET = NONCE_OFFSET + crypto_secretstream_xchacha20poly1305_INONCEBYTES + crypto_secretstream_xchacha20poly1305_COUNTERBYTES
|
||||||
|
|
||||||
|
const _pad0 = new Uint8Array(16)
|
||||||
|
|
||||||
|
function STORE64_LE (dest, int) {
|
||||||
|
let mul = 1
|
||||||
|
let i = 0
|
||||||
|
dest[0] = int & 0xFF
|
||||||
|
while (++i < 8 && (mul *= 0x100)) {
|
||||||
|
dest[i] = (int / mul) & 0xFF
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
function crypto_secretstream_xchacha20poly1305_counter_reset (state) {
|
||||||
|
assert(state.byteLength === crypto_secretstream_xchacha20poly1305_STATEBYTES,
|
||||||
|
'state is should be crypto_secretstream_xchacha20poly1305_STATEBYTES long')
|
||||||
|
|
||||||
|
const nonce = state.subarray(NONCE_OFFSET, PAD_OFFSET)
|
||||||
|
for (let i = 0; i < crypto_secretstream_xchacha20poly1305_COUNTERBYTES; i++) {
|
||||||
|
nonce[i] = 0
|
||||||
|
}
|
||||||
|
nonce[0] = 1
|
||||||
|
}
|
||||||
|
|
||||||
|
function crypto_secretstream_xchacha20poly1305_keygen (k) {
|
||||||
|
assert(k.length === crypto_secretstream_xchacha20poly1305_KEYBYTES)
|
||||||
|
randombytes_buf(k)
|
||||||
|
}
|
||||||
|
|
||||||
|
function crypto_secretstream_xchacha20poly1305_init_push (state, out, key) {
|
||||||
|
assert(state.byteLength === crypto_secretstream_xchacha20poly1305_STATEBYTES,
|
||||||
|
'state is should be crypto_secretstream_xchacha20poly1305_STATEBYTES long')
|
||||||
|
assert(out instanceof Uint8Array && out.length === crypto_secretstream_xchacha20poly1305_HEADERBYTES, 'out not byte array of length crypto_secretstream_xchacha20poly1305_HEADERBYTES')
|
||||||
|
assert(key instanceof Uint8Array && key.length === crypto_secretstream_xchacha20poly1305_KEYBYTES, 'key not byte array of length crypto_secretstream_xchacha20poly1305_KEYBYTES')
|
||||||
|
|
||||||
|
const k = state.subarray(KEY_OFFSET, NONCE_OFFSET)
|
||||||
|
const nonce = state.subarray(NONCE_OFFSET, PAD_OFFSET)
|
||||||
|
const pad = state.subarray(PAD_OFFSET)
|
||||||
|
|
||||||
|
randombytes_buf(out, crypto_secretstream_xchacha20poly1305_HEADERBYTES)
|
||||||
|
crypto_core_hchacha20(k, out, key, null)
|
||||||
|
crypto_secretstream_xchacha20poly1305_counter_reset(state)
|
||||||
|
for (let i = 0; i < crypto_secretstream_xchacha20poly1305_INONCEBYTES; i++) {
|
||||||
|
nonce[i + crypto_secretstream_xchacha20poly1305_COUNTERBYTES] = out[i + crypto_core_hchacha20_INPUTBYTES]
|
||||||
|
}
|
||||||
|
pad.fill(0)
|
||||||
|
}
|
||||||
|
|
||||||
|
function crypto_secretstream_xchacha20poly1305_init_pull (state, _in, key) {
|
||||||
|
assert(state.byteLength === crypto_secretstream_xchacha20poly1305_STATEBYTES,
|
||||||
|
'state is should be crypto_secretstream_xchacha20poly1305_STATEBYTES long')
|
||||||
|
assert(_in instanceof Uint8Array && _in.length === crypto_secretstream_xchacha20poly1305_HEADERBYTES,
|
||||||
|
'_in not byte array of length crypto_secretstream_xchacha20poly1305_HEADERBYTES')
|
||||||
|
assert(key instanceof Uint8Array && key.length === crypto_secretstream_xchacha20poly1305_KEYBYTES,
|
||||||
|
'key not byte array of length crypto_secretstream_xchacha20poly1305_KEYBYTES')
|
||||||
|
|
||||||
|
const k = state.subarray(KEY_OFFSET, NONCE_OFFSET)
|
||||||
|
const nonce = state.subarray(NONCE_OFFSET, PAD_OFFSET)
|
||||||
|
const pad = state.subarray(PAD_OFFSET)
|
||||||
|
|
||||||
|
crypto_core_hchacha20(k, _in, key, null)
|
||||||
|
crypto_secretstream_xchacha20poly1305_counter_reset(state)
|
||||||
|
|
||||||
|
for (let i = 0; i < crypto_secretstream_xchacha20poly1305_INONCEBYTES; i++) {
|
||||||
|
nonce[i + crypto_secretstream_xchacha20poly1305_COUNTERBYTES] = _in[i + crypto_core_hchacha20_INPUTBYTES]
|
||||||
|
}
|
||||||
|
pad.fill(0)
|
||||||
|
}
|
||||||
|
|
||||||
|
function crypto_secretstream_xchacha20poly1305_rekey (state) {
|
||||||
|
assert(state.byteLength === crypto_secretstream_xchacha20poly1305_STATEBYTES,
|
||||||
|
'state is should be crypto_secretstream_xchacha20poly1305_STATEBYTES long')
|
||||||
|
|
||||||
|
const k = state.subarray(KEY_OFFSET, NONCE_OFFSET)
|
||||||
|
const nonce = state.subarray(NONCE_OFFSET, PAD_OFFSET)
|
||||||
|
|
||||||
|
const new_key_and_inonce = new Uint8Array(
|
||||||
|
crypto_stream_chacha20_ietf_KEYBYTES + crypto_secretstream_xchacha20poly1305_INONCEBYTES)
|
||||||
|
let i
|
||||||
|
for (i = 0; i < crypto_stream_chacha20_ietf_KEYBYTES; i++) {
|
||||||
|
new_key_and_inonce[i] = k[i]
|
||||||
|
}
|
||||||
|
for (i = 0; i < crypto_secretstream_xchacha20poly1305_INONCEBYTES; i++) {
|
||||||
|
new_key_and_inonce[crypto_stream_chacha20_ietf_KEYBYTES + i] =
|
||||||
|
nonce[crypto_secretstream_xchacha20poly1305_COUNTERBYTES + i]
|
||||||
|
}
|
||||||
|
crypto_stream_chacha20_ietf_xor(new_key_and_inonce, new_key_and_inonce, nonce, k)
|
||||||
|
for (i = 0; i < crypto_stream_chacha20_ietf_KEYBYTES; i++) {
|
||||||
|
k[i] = new_key_and_inonce[i]
|
||||||
|
}
|
||||||
|
for (i = 0; i < crypto_secretstream_xchacha20poly1305_INONCEBYTES; i++) {
|
||||||
|
nonce[crypto_secretstream_xchacha20poly1305_COUNTERBYTES + i] =
|
||||||
|
new_key_and_inonce[crypto_stream_chacha20_ietf_KEYBYTES + i]
|
||||||
|
}
|
||||||
|
crypto_secretstream_xchacha20poly1305_counter_reset(state)
|
||||||
|
}
|
||||||
|
|
||||||
|
function crypto_secretstream_xchacha20poly1305_push (state, out, m, ad, tag) {
|
||||||
|
assert(state.byteLength === crypto_secretstream_xchacha20poly1305_STATEBYTES,
|
||||||
|
'state is should be crypto_secretstream_xchacha20poly1305_STATEBYTES long')
|
||||||
|
if (!ad) ad = new Uint8Array(0)
|
||||||
|
|
||||||
|
const k = state.subarray(KEY_OFFSET, NONCE_OFFSET)
|
||||||
|
const nonce = state.subarray(NONCE_OFFSET, PAD_OFFSET)
|
||||||
|
|
||||||
|
const block = new Uint8Array(64)
|
||||||
|
const slen = new Uint8Array(8)
|
||||||
|
|
||||||
|
assert(crypto_secretstream_xchacha20poly1305_MESSAGEBYTES_MAX <=
|
||||||
|
crypto_aead_chacha20poly1305_ietf_MESSAGEBYTES_MAX)
|
||||||
|
|
||||||
|
crypto_stream_chacha20_ietf(block, nonce, k)
|
||||||
|
const poly = new Poly1305(block)
|
||||||
|
block.fill(0)
|
||||||
|
|
||||||
|
poly.update(ad, 0, ad.byteLength)
|
||||||
|
poly.update(_pad0, 0, (0x10 - ad.byteLength) & 0xf)
|
||||||
|
|
||||||
|
block[0] = tag[0]
|
||||||
|
crypto_stream_chacha20_ietf_xor_ic(block, block, nonce, 1, k)
|
||||||
|
|
||||||
|
poly.update(block, 0, block.byteLength)
|
||||||
|
out[0] = block[0]
|
||||||
|
|
||||||
|
const c = out.subarray(1, out.byteLength)
|
||||||
|
crypto_stream_chacha20_ietf_xor_ic(c, m, nonce, 2, k)
|
||||||
|
poly.update(c, 0, m.byteLength)
|
||||||
|
poly.update(_pad0, 0, (0x10 - block.byteLength + m.byteLength) & 0xf)
|
||||||
|
|
||||||
|
STORE64_LE(slen, ad.byteLength)
|
||||||
|
poly.update(slen, 0, slen.byteLength)
|
||||||
|
STORE64_LE(slen, block.byteLength + m.byteLength)
|
||||||
|
poly.update(slen, 0, slen.byteLength)
|
||||||
|
|
||||||
|
const mac = out.subarray(1 + m.byteLength, out.byteLength)
|
||||||
|
poly.finish(mac, 0)
|
||||||
|
|
||||||
|
assert(crypto_onetimeauth_poly1305_BYTES >=
|
||||||
|
crypto_secretstream_xchacha20poly1305_INONCEBYTES)
|
||||||
|
xor_buf(nonce.subarray(crypto_secretstream_xchacha20poly1305_COUNTERBYTES, nonce.length),
|
||||||
|
mac, crypto_secretstream_xchacha20poly1305_INONCEBYTES)
|
||||||
|
sodium_increment(nonce)
|
||||||
|
|
||||||
|
if ((tag[0] & crypto_secretstream_xchacha20poly1305_TAG_REKEY) !== 0 ||
|
||||||
|
sodium_is_zero(nonce.subarray(0, crypto_secretstream_xchacha20poly1305_COUNTERBYTES))) {
|
||||||
|
crypto_secretstream_xchacha20poly1305_rekey(state)
|
||||||
|
}
|
||||||
|
|
||||||
|
return crypto_secretstream_xchacha20poly1305_ABYTES + m.byteLength
|
||||||
|
}
|
||||||
|
|
||||||
|
function crypto_secretstream_xchacha20poly1305_pull (state, m, tag, _in, ad) {
|
||||||
|
assert(state.byteLength === crypto_secretstream_xchacha20poly1305_STATEBYTES,
|
||||||
|
'state is should be crypto_secretstream_xchacha20poly1305_STATEBYTES long')
|
||||||
|
if (!ad) ad = new Uint8Array(0)
|
||||||
|
|
||||||
|
const k = state.subarray(KEY_OFFSET, NONCE_OFFSET)
|
||||||
|
const nonce = state.subarray(NONCE_OFFSET, PAD_OFFSET)
|
||||||
|
|
||||||
|
const block = new Uint8Array(64)
|
||||||
|
const slen = new Uint8Array(8)
|
||||||
|
const mac = new Uint8Array(crypto_onetimeauth_poly1305_BYTES)
|
||||||
|
|
||||||
|
assert(_in.byteLength >= crypto_secretstream_xchacha20poly1305_ABYTES,
|
||||||
|
'ciphertext is too short.')
|
||||||
|
|
||||||
|
const mlen = _in.byteLength - crypto_secretstream_xchacha20poly1305_ABYTES
|
||||||
|
crypto_stream_chacha20_ietf(block, nonce, k)
|
||||||
|
const poly = new Poly1305(block)
|
||||||
|
block.fill(0) // sodium_memzero(block, sizeof block);
|
||||||
|
|
||||||
|
poly.update(ad, 0, ad.byteLength)
|
||||||
|
poly.update(_pad0, 0, (0x10 - ad.byteLength) & 0xf)
|
||||||
|
|
||||||
|
block.fill(0) // memset(block, 0, sizeof block);
|
||||||
|
block[0] = _in[0]
|
||||||
|
crypto_stream_chacha20_ietf_xor_ic(block, block, nonce, 1, k)
|
||||||
|
|
||||||
|
tag[0] = block[0]
|
||||||
|
block[0] = _in[0]
|
||||||
|
poly.update(block, 0, block.byteLength)
|
||||||
|
|
||||||
|
const c = _in.subarray(1, _in.length)
|
||||||
|
poly.update(c, 0, mlen)
|
||||||
|
|
||||||
|
poly.update(_pad0, 0, (0x10 - block.byteLength + mlen) & 0xf)
|
||||||
|
|
||||||
|
STORE64_LE(slen, ad.byteLength)
|
||||||
|
poly.update(slen, 0, slen.byteLength)
|
||||||
|
STORE64_LE(slen, block.byteLength + m.byteLength)
|
||||||
|
poly.update(slen, 0, slen.byteLength)
|
||||||
|
|
||||||
|
poly.finish(mac, 0)
|
||||||
|
const stored_mac = _in.subarray(1 + mlen, _in.length)
|
||||||
|
|
||||||
|
if (!sodium_memcmp(mac, stored_mac)) {
|
||||||
|
mac.fill(0)
|
||||||
|
throw new Error('MAC could not be verified.')
|
||||||
|
}
|
||||||
|
|
||||||
|
crypto_stream_chacha20_ietf_xor_ic(m, c.subarray(0, m.length), nonce, 2, k)
|
||||||
|
xor_buf(nonce.subarray(crypto_secretstream_xchacha20poly1305_COUNTERBYTES, nonce.length),
|
||||||
|
mac, crypto_secretstream_xchacha20poly1305_INONCEBYTES)
|
||||||
|
sodium_increment(nonce)
|
||||||
|
|
||||||
|
if ((tag & crypto_secretstream_xchacha20poly1305_TAG_REKEY) !== 0 ||
|
||||||
|
sodium_is_zero(nonce.subarray(0, crypto_secretstream_xchacha20poly1305_COUNTERBYTES))) {
|
||||||
|
crypto_secretstream_xchacha20poly1305_rekey(state)
|
||||||
|
}
|
||||||
|
|
||||||
|
return mlen
|
||||||
|
}
|
||||||
|
|
||||||
|
function xor_buf (out, _in, n) {
|
||||||
|
for (let i = 0; i < n; i++) {
|
||||||
|
out[i] ^= _in[i]
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
module.exports = {
|
||||||
|
crypto_secretstream_xchacha20poly1305_keygen,
|
||||||
|
crypto_secretstream_xchacha20poly1305_init_push,
|
||||||
|
crypto_secretstream_xchacha20poly1305_init_pull,
|
||||||
|
crypto_secretstream_xchacha20poly1305_rekey,
|
||||||
|
crypto_secretstream_xchacha20poly1305_push,
|
||||||
|
crypto_secretstream_xchacha20poly1305_pull,
|
||||||
|
crypto_secretstream_xchacha20poly1305_STATEBYTES,
|
||||||
|
crypto_secretstream_xchacha20poly1305_ABYTES,
|
||||||
|
crypto_secretstream_xchacha20poly1305_HEADERBYTES,
|
||||||
|
crypto_secretstream_xchacha20poly1305_KEYBYTES,
|
||||||
|
crypto_secretstream_xchacha20poly1305_MESSAGEBYTES_MAX,
|
||||||
|
crypto_secretstream_xchacha20poly1305_TAGBYTES,
|
||||||
|
crypto_secretstream_xchacha20poly1305_TAG_MESSAGE,
|
||||||
|
crypto_secretstream_xchacha20poly1305_TAG_PUSH,
|
||||||
|
crypto_secretstream_xchacha20poly1305_TAG_REKEY,
|
||||||
|
crypto_secretstream_xchacha20poly1305_TAG_FINAL
|
||||||
|
}
|
@ -1,17 +1,14 @@
|
|||||||
var siphash = require('siphash24')
|
var siphash = require('siphash24')
|
||||||
|
|
||||||
|
if (new Uint16Array([1])[0] !== 1) throw new Error('Big endian architecture is not supported.')
|
||||||
|
|
||||||
exports.crypto_shorthash_PRIMITIVE = 'siphash24'
|
exports.crypto_shorthash_PRIMITIVE = 'siphash24'
|
||||||
exports.crypto_shorthash_BYTES = siphash.BYTES
|
exports.crypto_shorthash_BYTES = siphash.BYTES
|
||||||
exports.crypto_shorthash_KEYBYTES = siphash.KEYBYTES
|
exports.crypto_shorthash_KEYBYTES = siphash.KEYBYTES
|
||||||
exports.crypto_shorthash_WASM_SUPPORTED = siphash.WASM_SUPPORTED
|
exports.crypto_shorthash_WASM_SUPPORTED = siphash.WASM_SUPPORTED
|
||||||
exports.crypto_shorthash_WASM_LOADED = siphash.WASM_LOADED
|
exports.crypto_shorthash_WASM_LOADED = siphash.WASM_LOADED
|
||||||
exports.crypto_shorthash_ready = siphash.ready
|
|
||||||
exports.crypto_shorthash = shorthash
|
exports.crypto_shorthash = shorthash
|
||||||
|
|
||||||
siphash.ready(function () {
|
|
||||||
exports.crypto_shorthash_WASM_LOADED = siphash.WASM_LOADED
|
|
||||||
})
|
|
||||||
|
|
||||||
function shorthash (out, data, key, noAssert) {
|
function shorthash (out, data, key, noAssert) {
|
||||||
siphash(data, key, out, noAssert)
|
siphash(data, key, out, noAssert)
|
||||||
}
|
}
|
||||||
|
469
crypto_sign.js
Normal file
469
crypto_sign.js
Normal file
@ -0,0 +1,469 @@
|
|||||||
|
/* eslint-disable camelcase, one-var */
|
||||||
|
const { crypto_verify_32 } = require('./crypto_verify')
|
||||||
|
const { crypto_hash } = require('./crypto_hash')
|
||||||
|
const {
|
||||||
|
gf, gf0, gf1, D, D2,
|
||||||
|
X, Y, I, A, Z, M, S,
|
||||||
|
sel25519, pack25519,
|
||||||
|
inv25519, unpack25519
|
||||||
|
} = require('./internal/ed25519')
|
||||||
|
const { randombytes } = require('./randombytes')
|
||||||
|
const { crypto_scalarmult_BYTES } = require('./crypto_scalarmult.js')
|
||||||
|
const { crypto_hash_sha512_BYTES } = require('./crypto_hash.js')
|
||||||
|
const assert = require('nanoassert')
|
||||||
|
|
||||||
|
const crypto_sign_ed25519_PUBLICKEYBYTES = 32
|
||||||
|
const crypto_sign_ed25519_SECRETKEYBYTES = 64
|
||||||
|
const crypto_sign_ed25519_SEEDBYTES = 32
|
||||||
|
const crypto_sign_ed25519_BYTES = 64
|
||||||
|
|
||||||
|
const crypto_sign_BYTES = crypto_sign_ed25519_BYTES
|
||||||
|
const crypto_sign_PUBLICKEYBYTES = crypto_sign_ed25519_PUBLICKEYBYTES
|
||||||
|
const crypto_sign_SECRETKEYBYTES = crypto_sign_ed25519_SECRETKEYBYTES
|
||||||
|
const crypto_sign_SEEDBYTES = crypto_sign_ed25519_SEEDBYTES
|
||||||
|
|
||||||
|
module.exports = {
|
||||||
|
crypto_sign_keypair,
|
||||||
|
crypto_sign_seed_keypair,
|
||||||
|
crypto_sign,
|
||||||
|
crypto_sign_detached,
|
||||||
|
crypto_sign_open,
|
||||||
|
crypto_sign_verify_detached,
|
||||||
|
crypto_sign_BYTES,
|
||||||
|
crypto_sign_PUBLICKEYBYTES,
|
||||||
|
crypto_sign_SECRETKEYBYTES,
|
||||||
|
crypto_sign_SEEDBYTES,
|
||||||
|
crypto_sign_ed25519_PUBLICKEYBYTES,
|
||||||
|
crypto_sign_ed25519_SECRETKEYBYTES,
|
||||||
|
crypto_sign_ed25519_SEEDBYTES,
|
||||||
|
crypto_sign_ed25519_BYTES,
|
||||||
|
crypto_sign_ed25519_pk_to_curve25519,
|
||||||
|
crypto_sign_ed25519_sk_to_curve25519,
|
||||||
|
crypto_sign_ed25519_sk_to_pk,
|
||||||
|
unpackneg,
|
||||||
|
pack
|
||||||
|
}
|
||||||
|
|
||||||
|
function set25519 (r, a) {
|
||||||
|
for (let i = 0; i < 16; i++) r[i] = a[i] | 0
|
||||||
|
}
|
||||||
|
|
||||||
|
function pow2523 (o, i) {
|
||||||
|
var c = gf()
|
||||||
|
var a
|
||||||
|
for (a = 0; a < 16; a++) c[a] = i[a]
|
||||||
|
for (a = 250; a >= 0; a--) {
|
||||||
|
S(c, c)
|
||||||
|
if (a !== 1) M(c, c, i)
|
||||||
|
}
|
||||||
|
for (a = 0; a < 16; a++) o[a] = c[a]
|
||||||
|
}
|
||||||
|
|
||||||
|
function add (p, q) {
|
||||||
|
var a = gf(), b = gf(), c = gf(),
|
||||||
|
d = gf(), e = gf(), f = gf(),
|
||||||
|
g = gf(), h = gf(), t = gf()
|
||||||
|
|
||||||
|
Z(a, p[1], p[0])
|
||||||
|
Z(t, q[1], q[0])
|
||||||
|
M(a, a, t)
|
||||||
|
A(b, p[0], p[1])
|
||||||
|
A(t, q[0], q[1])
|
||||||
|
M(b, b, t)
|
||||||
|
M(c, p[3], q[3])
|
||||||
|
M(c, c, D2)
|
||||||
|
M(d, p[2], q[2])
|
||||||
|
A(d, d, d)
|
||||||
|
Z(e, b, a)
|
||||||
|
Z(f, d, c)
|
||||||
|
A(g, d, c)
|
||||||
|
A(h, b, a)
|
||||||
|
|
||||||
|
M(p[0], e, f)
|
||||||
|
M(p[1], h, g)
|
||||||
|
M(p[2], g, f)
|
||||||
|
M(p[3], e, h)
|
||||||
|
}
|
||||||
|
|
||||||
|
function cswap (p, q, b) {
|
||||||
|
var i
|
||||||
|
for (i = 0; i < 4; i++) {
|
||||||
|
sel25519(p[i], q[i], b)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
function pack (r, p) {
|
||||||
|
var tx = gf(), ty = gf(), zi = gf()
|
||||||
|
inv25519(zi, p[2])
|
||||||
|
M(tx, p[0], zi)
|
||||||
|
M(ty, p[1], zi)
|
||||||
|
pack25519(r, ty)
|
||||||
|
r[31] ^= par25519(tx) << 7
|
||||||
|
}
|
||||||
|
|
||||||
|
function scalarmult (p, q, s) {
|
||||||
|
// don't mutate q
|
||||||
|
var h = [gf(q[0]), gf(q[1]), gf(q[2]), gf(q[3])]
|
||||||
|
var b, i
|
||||||
|
set25519(p[0], gf0)
|
||||||
|
set25519(p[1], gf1)
|
||||||
|
set25519(p[2], gf1)
|
||||||
|
set25519(p[3], gf0)
|
||||||
|
for (i = 255; i >= 0; --i) {
|
||||||
|
b = (s[(i / 8) | 0] >> (i & 7)) & 1
|
||||||
|
cswap(p, h, b)
|
||||||
|
add(h, p)
|
||||||
|
add(p, p)
|
||||||
|
cswap(p, h, b)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
function scalarbase (p, s) {
|
||||||
|
var q = [gf(), gf(), gf(), gf()]
|
||||||
|
set25519(q[0], X)
|
||||||
|
set25519(q[1], Y)
|
||||||
|
set25519(q[2], gf1)
|
||||||
|
M(q[3], X, Y)
|
||||||
|
scalarmult(p, q, s)
|
||||||
|
}
|
||||||
|
|
||||||
|
function crypto_sign_keypair (pk, sk, seeded) {
|
||||||
|
check(pk, crypto_sign_PUBLICKEYBYTES)
|
||||||
|
check(sk, crypto_sign_SECRETKEYBYTES)
|
||||||
|
|
||||||
|
var d = new Uint8Array(64)
|
||||||
|
var p = [gf(), gf(), gf(), gf()]
|
||||||
|
var i
|
||||||
|
|
||||||
|
if (!seeded) randombytes(sk, 32)
|
||||||
|
crypto_hash(d, sk, 32)
|
||||||
|
d[0] &= 248
|
||||||
|
d[31] &= 127
|
||||||
|
d[31] |= 64
|
||||||
|
|
||||||
|
scalarbase(p, d)
|
||||||
|
pack(pk, p)
|
||||||
|
|
||||||
|
for (i = 0; i < 32; i++) sk[i + 32] = pk[i]
|
||||||
|
}
|
||||||
|
|
||||||
|
function crypto_sign_seed_keypair (pk, sk, seed) {
|
||||||
|
check(seed, crypto_sign_SEEDBYTES)
|
||||||
|
sk.set(seed)
|
||||||
|
return crypto_sign_keypair(pk, sk, true)
|
||||||
|
}
|
||||||
|
|
||||||
|
var L = new Float64Array([0xed, 0xd3, 0xf5, 0x5c, 0x1a, 0x63, 0x12, 0x58, 0xd6, 0x9c, 0xf7, 0xa2, 0xde, 0xf9, 0xde, 0x14, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0x10])
|
||||||
|
|
||||||
|
function modL (r, x) {
|
||||||
|
var carry, i, j, k
|
||||||
|
for (i = 63; i >= 32; --i) {
|
||||||
|
carry = 0
|
||||||
|
for (j = i - 32, k = i - 12; j < k; ++j) {
|
||||||
|
x[j] += carry - 16 * x[i] * L[j - (i - 32)]
|
||||||
|
carry = (x[j] + 128) >> 8
|
||||||
|
x[j] -= carry * 256
|
||||||
|
}
|
||||||
|
x[j] += carry
|
||||||
|
x[i] = 0
|
||||||
|
}
|
||||||
|
carry = 0
|
||||||
|
for (j = 0; j < 32; j++) {
|
||||||
|
x[j] += carry - (x[31] >> 4) * L[j]
|
||||||
|
carry = x[j] >> 8
|
||||||
|
x[j] &= 255
|
||||||
|
}
|
||||||
|
for (j = 0; j < 32; j++) x[j] -= carry * L[j]
|
||||||
|
for (i = 0; i < 32; i++) {
|
||||||
|
x[i + 1] += x[i] >> 8
|
||||||
|
r[i] = x[i] & 255
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
function reduce (r) {
|
||||||
|
var x = new Float64Array(64)
|
||||||
|
for (let i = 0; i < 64; i++) x[i] = r[i]
|
||||||
|
for (let i = 0; i < 64; i++) r[i] = 0
|
||||||
|
modL(r, x)
|
||||||
|
}
|
||||||
|
|
||||||
|
// Note: difference from C - smlen returned, not passed as argument.
|
||||||
|
function crypto_sign (sm, m, sk) {
|
||||||
|
check(sm, crypto_sign_BYTES + m.length)
|
||||||
|
check(m, 0)
|
||||||
|
check(sk, crypto_sign_SECRETKEYBYTES)
|
||||||
|
var n = m.length
|
||||||
|
|
||||||
|
var d = new Uint8Array(64), h = new Uint8Array(64), r = new Uint8Array(64)
|
||||||
|
var i, j, x = new Float64Array(64)
|
||||||
|
var p = [gf(), gf(), gf(), gf()]
|
||||||
|
|
||||||
|
crypto_hash(d, sk, 32)
|
||||||
|
d[0] &= 248
|
||||||
|
d[31] &= 127
|
||||||
|
d[31] |= 64
|
||||||
|
|
||||||
|
var smlen = n + 64
|
||||||
|
for (i = 0; i < n; i++) sm[64 + i] = m[i]
|
||||||
|
for (i = 0; i < 32; i++) sm[32 + i] = d[32 + i]
|
||||||
|
|
||||||
|
crypto_hash(r, sm.subarray(32), n + 32)
|
||||||
|
reduce(r)
|
||||||
|
scalarbase(p, r)
|
||||||
|
pack(sm, p)
|
||||||
|
|
||||||
|
for (i = 32; i < 64; i++) sm[i] = sk[i]
|
||||||
|
crypto_hash(h, sm, n + 64)
|
||||||
|
reduce(h)
|
||||||
|
|
||||||
|
for (i = 0; i < 64; i++) x[i] = 0
|
||||||
|
for (i = 0; i < 32; i++) x[i] = r[i]
|
||||||
|
for (i = 0; i < 32; i++) {
|
||||||
|
for (j = 0; j < 32; j++) {
|
||||||
|
x[i + j] += h[i] * d[j]
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
modL(sm.subarray(32), x)
|
||||||
|
return smlen
|
||||||
|
}
|
||||||
|
|
||||||
|
function crypto_sign_detached (sig, m, sk) {
|
||||||
|
var sm = new Uint8Array(m.length + crypto_sign_BYTES)
|
||||||
|
crypto_sign(sm, m, sk)
|
||||||
|
for (let i = 0; i < crypto_sign_BYTES; i++) sig[i] = sm[i]
|
||||||
|
}
|
||||||
|
|
||||||
|
function unpackneg (r, p) {
|
||||||
|
var t = gf(), chk = gf(), num = gf(),
|
||||||
|
den = gf(), den2 = gf(), den4 = gf(),
|
||||||
|
den6 = gf()
|
||||||
|
|
||||||
|
set25519(r[2], gf1)
|
||||||
|
unpack25519(r[1], p)
|
||||||
|
S(num, r[1])
|
||||||
|
M(den, num, D)
|
||||||
|
Z(num, num, r[2])
|
||||||
|
A(den, r[2], den)
|
||||||
|
|
||||||
|
S(den2, den)
|
||||||
|
S(den4, den2)
|
||||||
|
M(den6, den4, den2)
|
||||||
|
M(t, den6, num)
|
||||||
|
M(t, t, den)
|
||||||
|
|
||||||
|
pow2523(t, t)
|
||||||
|
M(t, t, num)
|
||||||
|
M(t, t, den)
|
||||||
|
M(t, t, den)
|
||||||
|
M(r[0], t, den)
|
||||||
|
|
||||||
|
S(chk, r[0])
|
||||||
|
M(chk, chk, den)
|
||||||
|
if (!neq25519(chk, num)) M(r[0], r[0], I)
|
||||||
|
|
||||||
|
S(chk, r[0])
|
||||||
|
M(chk, chk, den)
|
||||||
|
if (!neq25519(chk, num)) return false
|
||||||
|
|
||||||
|
if (par25519(r[0]) === (p[31] >> 7)) {
|
||||||
|
Z(r[0], gf(), r[0])
|
||||||
|
}
|
||||||
|
|
||||||
|
M(r[3], r[0], r[1])
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
|
||||||
|
/* eslint-disable no-unused-vars */
|
||||||
|
function crypto_sign_open (msg, sm, pk) {
|
||||||
|
check(msg, sm.length - crypto_sign_BYTES)
|
||||||
|
check(sm, crypto_sign_BYTES)
|
||||||
|
check(pk, crypto_sign_PUBLICKEYBYTES)
|
||||||
|
var n = sm.length
|
||||||
|
var m = new Uint8Array(sm.length)
|
||||||
|
|
||||||
|
var i, mlen
|
||||||
|
var t = new Uint8Array(32), h = new Uint8Array(64)
|
||||||
|
var p = [gf(), gf(), gf(), gf()],
|
||||||
|
q = [gf(), gf(), gf(), gf()]
|
||||||
|
|
||||||
|
mlen = -1
|
||||||
|
if (n < 64) return false
|
||||||
|
|
||||||
|
if (!unpackneg(q, pk)) return false
|
||||||
|
|
||||||
|
for (i = 0; i < n; i++) m[i] = sm[i]
|
||||||
|
for (i = 0; i < 32; i++) m[i + 32] = pk[i]
|
||||||
|
crypto_hash(h, m, n)
|
||||||
|
reduce(h)
|
||||||
|
scalarmult(p, q, h)
|
||||||
|
|
||||||
|
scalarbase(q, sm.subarray(32))
|
||||||
|
add(p, q)
|
||||||
|
pack(t, p)
|
||||||
|
|
||||||
|
n -= 64
|
||||||
|
if (!crypto_verify_32(sm, 0, t, 0)) {
|
||||||
|
for (i = 0; i < n; i++) m[i] = 0
|
||||||
|
return false
|
||||||
|
// throw new Error('crypto_sign_open failed')
|
||||||
|
}
|
||||||
|
|
||||||
|
for (i = 0; i < n; i++) msg[i] = sm[i + 64]
|
||||||
|
mlen = n
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
/* eslint-enable no-unused-vars */
|
||||||
|
|
||||||
|
function crypto_sign_verify_detached (sig, m, pk) {
|
||||||
|
check(sig, crypto_sign_BYTES)
|
||||||
|
var sm = new Uint8Array(m.length + crypto_sign_BYTES)
|
||||||
|
var i = 0
|
||||||
|
for (i = 0; i < crypto_sign_BYTES; i++) sm[i] = sig[i]
|
||||||
|
for (i = 0; i < m.length; i++) sm[i + crypto_sign_BYTES] = m[i]
|
||||||
|
return crypto_sign_open(m, sm, pk)
|
||||||
|
}
|
||||||
|
|
||||||
|
function par25519 (a) {
|
||||||
|
var d = new Uint8Array(32)
|
||||||
|
pack25519(d, a)
|
||||||
|
return d[0] & 1
|
||||||
|
}
|
||||||
|
|
||||||
|
function neq25519 (a, b) {
|
||||||
|
var c = new Uint8Array(32), d = new Uint8Array(32)
|
||||||
|
pack25519(c, a)
|
||||||
|
pack25519(d, b)
|
||||||
|
return crypto_verify_32(c, 0, d, 0)
|
||||||
|
}
|
||||||
|
|
||||||
|
function ed25519_mul_l (p, q) {
|
||||||
|
scalarmult(p, q, L)
|
||||||
|
}
|
||||||
|
|
||||||
|
function ed25519_is_on_main_subgroup (p) {
|
||||||
|
var pl = [gf(), gf(), gf(), gf()]
|
||||||
|
|
||||||
|
ed25519_mul_l(pl, p)
|
||||||
|
|
||||||
|
var zero = 0
|
||||||
|
for (let i = 0; i < 16; i++) {
|
||||||
|
zero |= (pl[0][i] & 0xffff)
|
||||||
|
}
|
||||||
|
|
||||||
|
return zero === 0
|
||||||
|
}
|
||||||
|
|
||||||
|
function crypto_sign_ed25519_pk_to_curve25519 (x25519_pk, ed25519_pk) {
|
||||||
|
check(x25519_pk, crypto_sign_PUBLICKEYBYTES)
|
||||||
|
check(ed25519_pk, crypto_sign_ed25519_PUBLICKEYBYTES)
|
||||||
|
|
||||||
|
var a = [gf(), gf(), gf(), gf()]
|
||||||
|
var x = gf([1])
|
||||||
|
var one_minus_y = gf([1])
|
||||||
|
|
||||||
|
assert(
|
||||||
|
isSmallOrder(ed25519_pk) &&
|
||||||
|
unpackneg(a, ed25519_pk) &&
|
||||||
|
ed25519_is_on_main_subgroup(a), 'Cannot convert key: bad point')
|
||||||
|
|
||||||
|
for (let i = 0; i < a.length; i++) {
|
||||||
|
pack25519(x25519_pk, a[i])
|
||||||
|
}
|
||||||
|
|
||||||
|
Z(one_minus_y, one_minus_y, a[1])
|
||||||
|
A(x, x, a[1])
|
||||||
|
inv25519(one_minus_y, one_minus_y)
|
||||||
|
M(x, x, one_minus_y)
|
||||||
|
pack25519(x25519_pk, x)
|
||||||
|
|
||||||
|
return 0
|
||||||
|
}
|
||||||
|
|
||||||
|
function isSmallOrder (s) {
|
||||||
|
Uint8Array.from([])
|
||||||
|
|
||||||
|
var bad_points = [
|
||||||
|
// 0 (order 4)
|
||||||
|
Uint8Array.from([0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||||
|
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||||
|
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00]),
|
||||||
|
|
||||||
|
// 1 (order 1)
|
||||||
|
Uint8Array.from([0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||||
|
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||||
|
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00]),
|
||||||
|
|
||||||
|
// 2707385501144840649318225287225658788936804267575313519463743609750303402022(order 8)
|
||||||
|
Uint8Array.from([0x26, 0xe8, 0x95, 0x8f, 0xc2, 0xb2, 0x27, 0xb0, 0x45, 0xc3,
|
||||||
|
0xf4, 0x89, 0xf2, 0xef, 0x98, 0xf0, 0xd5, 0xdf, 0xac, 0x05, 0xd3,
|
||||||
|
0xc6, 0x33, 0x39, 0xb1, 0x38, 0x02, 0x88, 0x6d, 0x53, 0xfc, 0x05]),
|
||||||
|
|
||||||
|
// 55188659117513257062467267217118295137698188065244968500265048394206261417927 (order 8)
|
||||||
|
Uint8Array.from([0xc7, 0x17, 0x6a, 0x70, 0x3d, 0x4d, 0xd8, 0x4f, 0xba, 0x3c,
|
||||||
|
0x0b, 0x76, 0x0d, 0x10, 0x67, 0x0f, 0x2a, 0x20, 0x53, 0xfa, 0x2c,
|
||||||
|
0x39, 0xcc, 0xc6, 0x4e, 0xc7, 0xfd, 0x77, 0x92, 0xac, 0x03, 0x7a]),
|
||||||
|
|
||||||
|
// p-1 (order 2)
|
||||||
|
Uint8Array.from([0xec, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
|
||||||
|
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
|
||||||
|
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x7f]),
|
||||||
|
|
||||||
|
// p (=0 order 4)
|
||||||
|
Uint8Array.from([0xed, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
|
||||||
|
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
|
||||||
|
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x7f]),
|
||||||
|
|
||||||
|
// p + 1 (=1 order 1)
|
||||||
|
Uint8Array.from([0xee, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
|
||||||
|
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
|
||||||
|
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x7f])
|
||||||
|
]
|
||||||
|
|
||||||
|
var c = new Uint8Array(7)
|
||||||
|
var j
|
||||||
|
|
||||||
|
check(bad_points, 7)
|
||||||
|
for (let i = 0; i < bad_points.length; i++) {
|
||||||
|
for (j = 0; j < 31; j++) {
|
||||||
|
c[i] |= s[j] ^ bad_points[i][j]
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
for (let i = 0; i < bad_points.length; i++) {
|
||||||
|
c[i] |= (s[j] & 0x7f) ^ bad_points[i][j]
|
||||||
|
}
|
||||||
|
|
||||||
|
var k = 0
|
||||||
|
for (let i = 0; i < bad_points.length; i++) {
|
||||||
|
k |= (c[i] - 1)
|
||||||
|
}
|
||||||
|
|
||||||
|
return ((k >> 8) & 1) === 0
|
||||||
|
}
|
||||||
|
|
||||||
|
function crypto_sign_ed25519_sk_to_pk (pk, sk) {
|
||||||
|
check(pk, crypto_sign_ed25519_PUBLICKEYBYTES)
|
||||||
|
pk.set(sk.subarray(crypto_sign_ed25519_SEEDBYTES))
|
||||||
|
return pk
|
||||||
|
}
|
||||||
|
|
||||||
|
function crypto_sign_ed25519_sk_to_curve25519 (curveSk, edSk) {
|
||||||
|
assert(curveSk && curveSk.byteLength === crypto_scalarmult_BYTES, "curveSk must be 'crypto_sign_SECRETKEYBYTES' long")
|
||||||
|
assert(edSk && edSk.byteLength === crypto_sign_ed25519_SECRETKEYBYTES, "edSk must be 'crypto_sign_ed25519_SECRETKEYBYTES' long")
|
||||||
|
|
||||||
|
var h = new Uint8Array(crypto_hash_sha512_BYTES)
|
||||||
|
crypto_hash(h, edSk, 32)
|
||||||
|
|
||||||
|
h[0] &= 248
|
||||||
|
h[31] &= 127
|
||||||
|
h[31] |= 64
|
||||||
|
|
||||||
|
curveSk.set(h.subarray(0, crypto_scalarmult_BYTES))
|
||||||
|
h.fill(0)
|
||||||
|
return curveSk
|
||||||
|
}
|
||||||
|
|
||||||
|
function check (buf, len, arg = 'Argument') {
|
||||||
|
if (!buf || (len && buf.length < len)) throw new Error(arg + ' must be a buffer' + (len ? ' of length ' + len : ''))
|
||||||
|
}
|
@ -1,17 +1,22 @@
|
|||||||
var xsalsa20 = require('xsalsa20')
|
/* eslint-disable camelcase */
|
||||||
|
const xsalsa20 = require('xsalsa20')
|
||||||
|
|
||||||
|
if (new Uint16Array([1])[0] !== 1) throw new Error('Big endian architecture is not supported.')
|
||||||
|
|
||||||
exports.crypto_stream_KEYBYTES = 32
|
exports.crypto_stream_KEYBYTES = 32
|
||||||
exports.crypto_stream_NONCEBYTES = 24
|
exports.crypto_stream_NONCEBYTES = 24
|
||||||
exports.crypto_stream_PRIMITIVE = 'xsalsa20'
|
exports.crypto_stream_PRIMITIVE = 'xsalsa20'
|
||||||
|
exports.crypto_stream_xsalsa20_MESSAGEBYTES_MAX = Number.MAX_SAFE_INTEGER
|
||||||
|
|
||||||
exports.crypto_stream = function (out, nonce, key) {
|
exports.crypto_stream = function (c, nonce, key) {
|
||||||
out.fill(0)
|
c.fill(0)
|
||||||
exports.crypto_stream_xor(out, out, nonce, key)
|
exports.crypto_stream_xor(c, c, nonce, key)
|
||||||
}
|
}
|
||||||
|
|
||||||
exports.crypto_stream_xor = function (out, inp, nonce, key) {
|
exports.crypto_stream_xor = function (c, m, nonce, key) {
|
||||||
var xor = xsalsa20(nonce, key)
|
const xor = xsalsa20(nonce, key)
|
||||||
xor.update(inp, out)
|
|
||||||
|
xor.update(m, c)
|
||||||
xor.final()
|
xor.final()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
84
crypto_stream_chacha20.js
Normal file
84
crypto_stream_chacha20.js
Normal file
@ -0,0 +1,84 @@
|
|||||||
|
const assert = require('nanoassert')
|
||||||
|
const Chacha20 = require('chacha20-universal')
|
||||||
|
|
||||||
|
if (new Uint16Array([1])[0] !== 1) throw new Error('Big endian architecture is not supported.')
|
||||||
|
|
||||||
|
exports.crypto_stream_chacha20_KEYBYTES = 32
|
||||||
|
exports.crypto_stream_chacha20_NONCEBYTES = 8
|
||||||
|
exports.crypto_stream_chacha20_MESSAGEBYTES_MAX = Number.MAX_SAFE_INTEGER
|
||||||
|
|
||||||
|
exports.crypto_stream_chacha20_ietf_KEYBYTES = 32
|
||||||
|
exports.crypto_stream_chacha20_ietf_NONCEBYTES = 12
|
||||||
|
exports.crypto_stream_chacha20_ietf_MESSAGEBYTES_MAX = 2 ** 32
|
||||||
|
|
||||||
|
exports.crypto_stream_chacha20 = function (c, n, k) {
|
||||||
|
c.fill(0)
|
||||||
|
exports.crypto_stream_chacha20_xor(c, c, n, k)
|
||||||
|
}
|
||||||
|
|
||||||
|
exports.crypto_stream_chacha20_xor = function (c, m, n, k) {
|
||||||
|
assert(n.byteLength === exports.crypto_stream_chacha20_NONCEBYTES,
|
||||||
|
'n should be crypto_stream_chacha20_NONCEBYTES')
|
||||||
|
assert(k.byteLength === exports.crypto_stream_chacha20_KEYBYTES,
|
||||||
|
'k should be crypto_stream_chacha20_KEYBYTES')
|
||||||
|
|
||||||
|
const xor = new Chacha20(n, k)
|
||||||
|
xor.update(c, m)
|
||||||
|
xor.final()
|
||||||
|
}
|
||||||
|
|
||||||
|
exports.crypto_stream_chacha20_xor_ic = function (c, m, n, ic, k) {
|
||||||
|
assert(n.byteLength === exports.crypto_stream_chacha20_NONCEBYTES,
|
||||||
|
'n should be crypto_stream_chacha20_NONCEBYTES')
|
||||||
|
assert(k.byteLength === exports.crypto_stream_chacha20_KEYBYTES,
|
||||||
|
'k should be crypto_stream_chacha20_KEYBYTES')
|
||||||
|
|
||||||
|
const xor = new Chacha20(n, k, ic)
|
||||||
|
xor.update(c, m)
|
||||||
|
xor.final()
|
||||||
|
}
|
||||||
|
|
||||||
|
exports.crypto_stream_chacha20_xor_instance = function (n, k) {
|
||||||
|
assert(n.byteLength === exports.crypto_stream_chacha20_NONCEBYTES,
|
||||||
|
'n should be crypto_stream_chacha20_NONCEBYTES')
|
||||||
|
assert(k.byteLength === exports.crypto_stream_chacha20_KEYBYTES,
|
||||||
|
'k should be crypto_stream_chacha20_KEYBYTES')
|
||||||
|
|
||||||
|
return new Chacha20(n, k)
|
||||||
|
}
|
||||||
|
|
||||||
|
exports.crypto_stream_chacha20_ietf = function (c, n, k) {
|
||||||
|
c.fill(0)
|
||||||
|
exports.crypto_stream_chacha20_ietf_xor(c, c, n, k)
|
||||||
|
}
|
||||||
|
|
||||||
|
exports.crypto_stream_chacha20_ietf_xor = function (c, m, n, k) {
|
||||||
|
assert(n.byteLength === exports.crypto_stream_chacha20_ietf_NONCEBYTES,
|
||||||
|
'n should be crypto_stream_chacha20_ietf_NONCEBYTES')
|
||||||
|
assert(k.byteLength === exports.crypto_stream_chacha20_ietf_KEYBYTES,
|
||||||
|
'k should be crypto_stream_chacha20_ietf_KEYBYTES')
|
||||||
|
|
||||||
|
const xor = new Chacha20(n, k)
|
||||||
|
xor.update(c, m)
|
||||||
|
xor.final()
|
||||||
|
}
|
||||||
|
|
||||||
|
exports.crypto_stream_chacha20_ietf_xor_ic = function (c, m, n, ic, k) {
|
||||||
|
assert(n.byteLength === exports.crypto_stream_chacha20_ietf_NONCEBYTES,
|
||||||
|
'n should be crypto_stream_chacha20_ietf_NONCEBYTES')
|
||||||
|
assert(k.byteLength === exports.crypto_stream_chacha20_ietf_KEYBYTES,
|
||||||
|
'k should be crypto_stream_chacha20_ietf_KEYBYTES')
|
||||||
|
|
||||||
|
const xor = new Chacha20(n, k, ic)
|
||||||
|
xor.update(c, m)
|
||||||
|
xor.final()
|
||||||
|
}
|
||||||
|
|
||||||
|
exports.crypto_stream_chacha20_ietf_xor_instance = function (n, k) {
|
||||||
|
assert(n.byteLength === exports.crypto_stream_chacha20_ietf_NONCEBYTES,
|
||||||
|
'n should be crypto_stream_chacha20_ietf_NONCEBYTES')
|
||||||
|
assert(k.byteLength === exports.crypto_stream_chacha20_ietf_KEYBYTES,
|
||||||
|
'k should be crypto_stream_chacha20_ietf_KEYBYTES')
|
||||||
|
|
||||||
|
return new Chacha20(n, k)
|
||||||
|
}
|
29
crypto_verify.js
Normal file
29
crypto_verify.js
Normal file
@ -0,0 +1,29 @@
|
|||||||
|
/* eslint-disable camelcase */
|
||||||
|
module.exports = {
|
||||||
|
crypto_verify_16,
|
||||||
|
crypto_verify_32,
|
||||||
|
crypto_verify_64
|
||||||
|
}
|
||||||
|
|
||||||
|
function vn (x, xi, y, yi, n) {
|
||||||
|
var d = 0
|
||||||
|
for (let i = 0; i < n; i++) d |= x[xi + i] ^ y[yi + i]
|
||||||
|
return (1 & ((d - 1) >>> 8)) - 1
|
||||||
|
}
|
||||||
|
|
||||||
|
// Make non enumerable as this is an internal function
|
||||||
|
Object.defineProperty(module.exports, 'vn', {
|
||||||
|
value: vn
|
||||||
|
})
|
||||||
|
|
||||||
|
function crypto_verify_16 (x, xi, y, yi) {
|
||||||
|
return vn(x, xi, y, yi, 16) === 0
|
||||||
|
}
|
||||||
|
|
||||||
|
function crypto_verify_32 (x, xi, y, yi) {
|
||||||
|
return vn(x, xi, y, yi, 32) === 0
|
||||||
|
}
|
||||||
|
|
||||||
|
function crypto_verify_64 (x, xi, y, yi) {
|
||||||
|
return vn(x, xi, y, yi, 64) === 0
|
||||||
|
}
|
12
example.js
12
example.js
@ -1,19 +1,19 @@
|
|||||||
var sodium = require('./')
|
const sodium = require('./')
|
||||||
|
|
||||||
var key = new Buffer(sodium.crypto_secretbox_KEYBYTES)
|
const key = Buffer.alloc(sodium.crypto_secretbox_KEYBYTES)
|
||||||
var nonce = new Buffer(sodium.crypto_secretbox_NONCEBYTES)
|
const nonce = Buffer.alloc(sodium.crypto_secretbox_NONCEBYTES)
|
||||||
|
|
||||||
sodium.randombytes_buf(key)
|
sodium.randombytes_buf(key)
|
||||||
sodium.randombytes_buf(nonce)
|
sodium.randombytes_buf(nonce)
|
||||||
|
|
||||||
var message = new Buffer('Hello, World!')
|
const message = Buffer.from('Hello, World!')
|
||||||
var cipher = new Buffer(message.length + sodium.crypto_secretbox_MACBYTES)
|
const cipher = Buffer.alloc(message.length + sodium.crypto_secretbox_MACBYTES)
|
||||||
|
|
||||||
sodium.crypto_secretbox_easy(cipher, message, nonce, key)
|
sodium.crypto_secretbox_easy(cipher, message, nonce, key)
|
||||||
|
|
||||||
console.log('Encrypted:', cipher)
|
console.log('Encrypted:', cipher)
|
||||||
|
|
||||||
var plainText = new Buffer(cipher.length - sodium.crypto_secretbox_MACBYTES)
|
const plainText = Buffer.alloc(cipher.length - sodium.crypto_secretbox_MACBYTES)
|
||||||
|
|
||||||
sodium.crypto_secretbox_open_easy(plainText, cipher, nonce, key)
|
sodium.crypto_secretbox_open_easy(plainText, cipher, nonce, key)
|
||||||
|
|
||||||
|
31
helpers.js
Normal file
31
helpers.js
Normal file
@ -0,0 +1,31 @@
|
|||||||
|
/* eslint-disable camelcase */
|
||||||
|
const assert = require('nanoassert')
|
||||||
|
const { vn } = require('./crypto_verify')
|
||||||
|
|
||||||
|
function sodium_increment (n) {
|
||||||
|
const nlen = n.byteLength
|
||||||
|
var c = 1
|
||||||
|
for (var i = 0; i < nlen; i++) {
|
||||||
|
c += n[i]
|
||||||
|
n[i] = c
|
||||||
|
c >>= 8
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
function sodium_memcmp (a, b) {
|
||||||
|
assert(a.byteLength === b.byteLength, 'buffers must be the same size')
|
||||||
|
|
||||||
|
return vn(a, 0, b, 0, a.byteLength) === 0
|
||||||
|
}
|
||||||
|
|
||||||
|
function sodium_is_zero (arr) {
|
||||||
|
var d = 0
|
||||||
|
for (let i = 0; i < arr.length; i++) d |= arr[i]
|
||||||
|
return d === 0
|
||||||
|
}
|
||||||
|
|
||||||
|
module.exports = {
|
||||||
|
sodium_increment,
|
||||||
|
sodium_memcmp,
|
||||||
|
sodium_is_zero
|
||||||
|
}
|
483
internal/ed25519.js
Normal file
483
internal/ed25519.js
Normal file
@ -0,0 +1,483 @@
|
|||||||
|
if (new Uint16Array([1])[0] !== 1) throw new Error('Big endian architecture is not supported.')
|
||||||
|
|
||||||
|
var gf = function(init) {
|
||||||
|
var i, r = new Float64Array(16);
|
||||||
|
if (init) for (i = 0; i < init.length; i++) r[i] = init[i];
|
||||||
|
return r;
|
||||||
|
}
|
||||||
|
|
||||||
|
var _0 = new Uint8Array(16);
|
||||||
|
var _9 = new Uint8Array(32); _9[0] = 9;
|
||||||
|
|
||||||
|
var gf0 = gf(),
|
||||||
|
gf1 = gf([1]),
|
||||||
|
_121665 = gf([0xdb41, 1]),
|
||||||
|
D = gf([0x78a3, 0x1359, 0x4dca, 0x75eb, 0xd8ab, 0x4141, 0x0a4d, 0x0070, 0xe898, 0x7779, 0x4079, 0x8cc7, 0xfe73, 0x2b6f, 0x6cee, 0x5203]),
|
||||||
|
D2 = gf([0xf159, 0x26b2, 0x9b94, 0xebd6, 0xb156, 0x8283, 0x149a, 0x00e0, 0xd130, 0xeef3, 0x80f2, 0x198e, 0xfce7, 0x56df, 0xd9dc, 0x2406]),
|
||||||
|
X = gf([0xd51a, 0x8f25, 0x2d60, 0xc956, 0xa7b2, 0x9525, 0xc760, 0x692c, 0xdc5c, 0xfdd6, 0xe231, 0xc0a4, 0x53fe, 0xcd6e, 0x36d3, 0x2169]),
|
||||||
|
Y = gf([0x6658, 0x6666, 0x6666, 0x6666, 0x6666, 0x6666, 0x6666, 0x6666, 0x6666, 0x6666, 0x6666, 0x6666, 0x6666, 0x6666, 0x6666, 0x6666]),
|
||||||
|
I = gf([0xa0b0, 0x4a0e, 0x1b27, 0xc4ee, 0xe478, 0xad2f, 0x1806, 0x2f43, 0xd7a7, 0x3dfb, 0x0099, 0x2b4d, 0xdf0b, 0x4fc1, 0x2480, 0x2b83]);
|
||||||
|
|
||||||
|
function A(o, a, b) {
|
||||||
|
for (var i = 0; i < 16; i++) o[i] = a[i] + b[i];
|
||||||
|
}
|
||||||
|
|
||||||
|
function Z(o, a, b) {
|
||||||
|
for (var i = 0; i < 16; i++) o[i] = a[i] - b[i];
|
||||||
|
}
|
||||||
|
|
||||||
|
function M(o, a, b) {
|
||||||
|
var v, c,
|
||||||
|
t0 = 0, t1 = 0, t2 = 0, t3 = 0, t4 = 0, t5 = 0, t6 = 0, t7 = 0,
|
||||||
|
t8 = 0, t9 = 0, t10 = 0, t11 = 0, t12 = 0, t13 = 0, t14 = 0, t15 = 0,
|
||||||
|
t16 = 0, t17 = 0, t18 = 0, t19 = 0, t20 = 0, t21 = 0, t22 = 0, t23 = 0,
|
||||||
|
t24 = 0, t25 = 0, t26 = 0, t27 = 0, t28 = 0, t29 = 0, t30 = 0,
|
||||||
|
b0 = b[0],
|
||||||
|
b1 = b[1],
|
||||||
|
b2 = b[2],
|
||||||
|
b3 = b[3],
|
||||||
|
b4 = b[4],
|
||||||
|
b5 = b[5],
|
||||||
|
b6 = b[6],
|
||||||
|
b7 = b[7],
|
||||||
|
b8 = b[8],
|
||||||
|
b9 = b[9],
|
||||||
|
b10 = b[10],
|
||||||
|
b11 = b[11],
|
||||||
|
b12 = b[12],
|
||||||
|
b13 = b[13],
|
||||||
|
b14 = b[14],
|
||||||
|
b15 = b[15];
|
||||||
|
|
||||||
|
v = a[0];
|
||||||
|
t0 += v * b0;
|
||||||
|
t1 += v * b1;
|
||||||
|
t2 += v * b2;
|
||||||
|
t3 += v * b3;
|
||||||
|
t4 += v * b4;
|
||||||
|
t5 += v * b5;
|
||||||
|
t6 += v * b6;
|
||||||
|
t7 += v * b7;
|
||||||
|
t8 += v * b8;
|
||||||
|
t9 += v * b9;
|
||||||
|
t10 += v * b10;
|
||||||
|
t11 += v * b11;
|
||||||
|
t12 += v * b12;
|
||||||
|
t13 += v * b13;
|
||||||
|
t14 += v * b14;
|
||||||
|
t15 += v * b15;
|
||||||
|
v = a[1];
|
||||||
|
t1 += v * b0;
|
||||||
|
t2 += v * b1;
|
||||||
|
t3 += v * b2;
|
||||||
|
t4 += v * b3;
|
||||||
|
t5 += v * b4;
|
||||||
|
t6 += v * b5;
|
||||||
|
t7 += v * b6;
|
||||||
|
t8 += v * b7;
|
||||||
|
t9 += v * b8;
|
||||||
|
t10 += v * b9;
|
||||||
|
t11 += v * b10;
|
||||||
|
t12 += v * b11;
|
||||||
|
t13 += v * b12;
|
||||||
|
t14 += v * b13;
|
||||||
|
t15 += v * b14;
|
||||||
|
t16 += v * b15;
|
||||||
|
v = a[2];
|
||||||
|
t2 += v * b0;
|
||||||
|
t3 += v * b1;
|
||||||
|
t4 += v * b2;
|
||||||
|
t5 += v * b3;
|
||||||
|
t6 += v * b4;
|
||||||
|
t7 += v * b5;
|
||||||
|
t8 += v * b6;
|
||||||
|
t9 += v * b7;
|
||||||
|
t10 += v * b8;
|
||||||
|
t11 += v * b9;
|
||||||
|
t12 += v * b10;
|
||||||
|
t13 += v * b11;
|
||||||
|
t14 += v * b12;
|
||||||
|
t15 += v * b13;
|
||||||
|
t16 += v * b14;
|
||||||
|
t17 += v * b15;
|
||||||
|
v = a[3];
|
||||||
|
t3 += v * b0;
|
||||||
|
t4 += v * b1;
|
||||||
|
t5 += v * b2;
|
||||||
|
t6 += v * b3;
|
||||||
|
t7 += v * b4;
|
||||||
|
t8 += v * b5;
|
||||||
|
t9 += v * b6;
|
||||||
|
t10 += v * b7;
|
||||||
|
t11 += v * b8;
|
||||||
|
t12 += v * b9;
|
||||||
|
t13 += v * b10;
|
||||||
|
t14 += v * b11;
|
||||||
|
t15 += v * b12;
|
||||||
|
t16 += v * b13;
|
||||||
|
t17 += v * b14;
|
||||||
|
t18 += v * b15;
|
||||||
|
v = a[4];
|
||||||
|
t4 += v * b0;
|
||||||
|
t5 += v * b1;
|
||||||
|
t6 += v * b2;
|
||||||
|
t7 += v * b3;
|
||||||
|
t8 += v * b4;
|
||||||
|
t9 += v * b5;
|
||||||
|
t10 += v * b6;
|
||||||
|
t11 += v * b7;
|
||||||
|
t12 += v * b8;
|
||||||
|
t13 += v * b9;
|
||||||
|
t14 += v * b10;
|
||||||
|
t15 += v * b11;
|
||||||
|
t16 += v * b12;
|
||||||
|
t17 += v * b13;
|
||||||
|
t18 += v * b14;
|
||||||
|
t19 += v * b15;
|
||||||
|
v = a[5];
|
||||||
|
t5 += v * b0;
|
||||||
|
t6 += v * b1;
|
||||||
|
t7 += v * b2;
|
||||||
|
t8 += v * b3;
|
||||||
|
t9 += v * b4;
|
||||||
|
t10 += v * b5;
|
||||||
|
t11 += v * b6;
|
||||||
|
t12 += v * b7;
|
||||||
|
t13 += v * b8;
|
||||||
|
t14 += v * b9;
|
||||||
|
t15 += v * b10;
|
||||||
|
t16 += v * b11;
|
||||||
|
t17 += v * b12;
|
||||||
|
t18 += v * b13;
|
||||||
|
t19 += v * b14;
|
||||||
|
t20 += v * b15;
|
||||||
|
v = a[6];
|
||||||
|
t6 += v * b0;
|
||||||
|
t7 += v * b1;
|
||||||
|
t8 += v * b2;
|
||||||
|
t9 += v * b3;
|
||||||
|
t10 += v * b4;
|
||||||
|
t11 += v * b5;
|
||||||
|
t12 += v * b6;
|
||||||
|
t13 += v * b7;
|
||||||
|
t14 += v * b8;
|
||||||
|
t15 += v * b9;
|
||||||
|
t16 += v * b10;
|
||||||
|
t17 += v * b11;
|
||||||
|
t18 += v * b12;
|
||||||
|
t19 += v * b13;
|
||||||
|
t20 += v * b14;
|
||||||
|
t21 += v * b15;
|
||||||
|
v = a[7];
|
||||||
|
t7 += v * b0;
|
||||||
|
t8 += v * b1;
|
||||||
|
t9 += v * b2;
|
||||||
|
t10 += v * b3;
|
||||||
|
t11 += v * b4;
|
||||||
|
t12 += v * b5;
|
||||||
|
t13 += v * b6;
|
||||||
|
t14 += v * b7;
|
||||||
|
t15 += v * b8;
|
||||||
|
t16 += v * b9;
|
||||||
|
t17 += v * b10;
|
||||||
|
t18 += v * b11;
|
||||||
|
t19 += v * b12;
|
||||||
|
t20 += v * b13;
|
||||||
|
t21 += v * b14;
|
||||||
|
t22 += v * b15;
|
||||||
|
v = a[8];
|
||||||
|
t8 += v * b0;
|
||||||
|
t9 += v * b1;
|
||||||
|
t10 += v * b2;
|
||||||
|
t11 += v * b3;
|
||||||
|
t12 += v * b4;
|
||||||
|
t13 += v * b5;
|
||||||
|
t14 += v * b6;
|
||||||
|
t15 += v * b7;
|
||||||
|
t16 += v * b8;
|
||||||
|
t17 += v * b9;
|
||||||
|
t18 += v * b10;
|
||||||
|
t19 += v * b11;
|
||||||
|
t20 += v * b12;
|
||||||
|
t21 += v * b13;
|
||||||
|
t22 += v * b14;
|
||||||
|
t23 += v * b15;
|
||||||
|
v = a[9];
|
||||||
|
t9 += v * b0;
|
||||||
|
t10 += v * b1;
|
||||||
|
t11 += v * b2;
|
||||||
|
t12 += v * b3;
|
||||||
|
t13 += v * b4;
|
||||||
|
t14 += v * b5;
|
||||||
|
t15 += v * b6;
|
||||||
|
t16 += v * b7;
|
||||||
|
t17 += v * b8;
|
||||||
|
t18 += v * b9;
|
||||||
|
t19 += v * b10;
|
||||||
|
t20 += v * b11;
|
||||||
|
t21 += v * b12;
|
||||||
|
t22 += v * b13;
|
||||||
|
t23 += v * b14;
|
||||||
|
t24 += v * b15;
|
||||||
|
v = a[10];
|
||||||
|
t10 += v * b0;
|
||||||
|
t11 += v * b1;
|
||||||
|
t12 += v * b2;
|
||||||
|
t13 += v * b3;
|
||||||
|
t14 += v * b4;
|
||||||
|
t15 += v * b5;
|
||||||
|
t16 += v * b6;
|
||||||
|
t17 += v * b7;
|
||||||
|
t18 += v * b8;
|
||||||
|
t19 += v * b9;
|
||||||
|
t20 += v * b10;
|
||||||
|
t21 += v * b11;
|
||||||
|
t22 += v * b12;
|
||||||
|
t23 += v * b13;
|
||||||
|
t24 += v * b14;
|
||||||
|
t25 += v * b15;
|
||||||
|
v = a[11];
|
||||||
|
t11 += v * b0;
|
||||||
|
t12 += v * b1;
|
||||||
|
t13 += v * b2;
|
||||||
|
t14 += v * b3;
|
||||||
|
t15 += v * b4;
|
||||||
|
t16 += v * b5;
|
||||||
|
t17 += v * b6;
|
||||||
|
t18 += v * b7;
|
||||||
|
t19 += v * b8;
|
||||||
|
t20 += v * b9;
|
||||||
|
t21 += v * b10;
|
||||||
|
t22 += v * b11;
|
||||||
|
t23 += v * b12;
|
||||||
|
t24 += v * b13;
|
||||||
|
t25 += v * b14;
|
||||||
|
t26 += v * b15;
|
||||||
|
v = a[12];
|
||||||
|
t12 += v * b0;
|
||||||
|
t13 += v * b1;
|
||||||
|
t14 += v * b2;
|
||||||
|
t15 += v * b3;
|
||||||
|
t16 += v * b4;
|
||||||
|
t17 += v * b5;
|
||||||
|
t18 += v * b6;
|
||||||
|
t19 += v * b7;
|
||||||
|
t20 += v * b8;
|
||||||
|
t21 += v * b9;
|
||||||
|
t22 += v * b10;
|
||||||
|
t23 += v * b11;
|
||||||
|
t24 += v * b12;
|
||||||
|
t25 += v * b13;
|
||||||
|
t26 += v * b14;
|
||||||
|
t27 += v * b15;
|
||||||
|
v = a[13];
|
||||||
|
t13 += v * b0;
|
||||||
|
t14 += v * b1;
|
||||||
|
t15 += v * b2;
|
||||||
|
t16 += v * b3;
|
||||||
|
t17 += v * b4;
|
||||||
|
t18 += v * b5;
|
||||||
|
t19 += v * b6;
|
||||||
|
t20 += v * b7;
|
||||||
|
t21 += v * b8;
|
||||||
|
t22 += v * b9;
|
||||||
|
t23 += v * b10;
|
||||||
|
t24 += v * b11;
|
||||||
|
t25 += v * b12;
|
||||||
|
t26 += v * b13;
|
||||||
|
t27 += v * b14;
|
||||||
|
t28 += v * b15;
|
||||||
|
v = a[14];
|
||||||
|
t14 += v * b0;
|
||||||
|
t15 += v * b1;
|
||||||
|
t16 += v * b2;
|
||||||
|
t17 += v * b3;
|
||||||
|
t18 += v * b4;
|
||||||
|
t19 += v * b5;
|
||||||
|
t20 += v * b6;
|
||||||
|
t21 += v * b7;
|
||||||
|
t22 += v * b8;
|
||||||
|
t23 += v * b9;
|
||||||
|
t24 += v * b10;
|
||||||
|
t25 += v * b11;
|
||||||
|
t26 += v * b12;
|
||||||
|
t27 += v * b13;
|
||||||
|
t28 += v * b14;
|
||||||
|
t29 += v * b15;
|
||||||
|
v = a[15];
|
||||||
|
t15 += v * b0;
|
||||||
|
t16 += v * b1;
|
||||||
|
t17 += v * b2;
|
||||||
|
t18 += v * b3;
|
||||||
|
t19 += v * b4;
|
||||||
|
t20 += v * b5;
|
||||||
|
t21 += v * b6;
|
||||||
|
t22 += v * b7;
|
||||||
|
t23 += v * b8;
|
||||||
|
t24 += v * b9;
|
||||||
|
t25 += v * b10;
|
||||||
|
t26 += v * b11;
|
||||||
|
t27 += v * b12;
|
||||||
|
t28 += v * b13;
|
||||||
|
t29 += v * b14;
|
||||||
|
t30 += v * b15;
|
||||||
|
|
||||||
|
t0 += 38 * t16;
|
||||||
|
t1 += 38 * t17;
|
||||||
|
t2 += 38 * t18;
|
||||||
|
t3 += 38 * t19;
|
||||||
|
t4 += 38 * t20;
|
||||||
|
t5 += 38 * t21;
|
||||||
|
t6 += 38 * t22;
|
||||||
|
t7 += 38 * t23;
|
||||||
|
t8 += 38 * t24;
|
||||||
|
t9 += 38 * t25;
|
||||||
|
t10 += 38 * t26;
|
||||||
|
t11 += 38 * t27;
|
||||||
|
t12 += 38 * t28;
|
||||||
|
t13 += 38 * t29;
|
||||||
|
t14 += 38 * t30;
|
||||||
|
// t15 left as is
|
||||||
|
|
||||||
|
// first car
|
||||||
|
c = 1;
|
||||||
|
v = t0 + c + 65535; c = Math.floor(v / 65536); t0 = v - c * 65536;
|
||||||
|
v = t1 + c + 65535; c = Math.floor(v / 65536); t1 = v - c * 65536;
|
||||||
|
v = t2 + c + 65535; c = Math.floor(v / 65536); t2 = v - c * 65536;
|
||||||
|
v = t3 + c + 65535; c = Math.floor(v / 65536); t3 = v - c * 65536;
|
||||||
|
v = t4 + c + 65535; c = Math.floor(v / 65536); t4 = v - c * 65536;
|
||||||
|
v = t5 + c + 65535; c = Math.floor(v / 65536); t5 = v - c * 65536;
|
||||||
|
v = t6 + c + 65535; c = Math.floor(v / 65536); t6 = v - c * 65536;
|
||||||
|
v = t7 + c + 65535; c = Math.floor(v / 65536); t7 = v - c * 65536;
|
||||||
|
v = t8 + c + 65535; c = Math.floor(v / 65536); t8 = v - c * 65536;
|
||||||
|
v = t9 + c + 65535; c = Math.floor(v / 65536); t9 = v - c * 65536;
|
||||||
|
v = t10 + c + 65535; c = Math.floor(v / 65536); t10 = v - c * 65536;
|
||||||
|
v = t11 + c + 65535; c = Math.floor(v / 65536); t11 = v - c * 65536;
|
||||||
|
v = t12 + c + 65535; c = Math.floor(v / 65536); t12 = v - c * 65536;
|
||||||
|
v = t13 + c + 65535; c = Math.floor(v / 65536); t13 = v - c * 65536;
|
||||||
|
v = t14 + c + 65535; c = Math.floor(v / 65536); t14 = v - c * 65536;
|
||||||
|
v = t15 + c + 65535; c = Math.floor(v / 65536); t15 = v - c * 65536;
|
||||||
|
t0 += c-1 + 37 * (c-1);
|
||||||
|
|
||||||
|
// second car
|
||||||
|
c = 1;
|
||||||
|
v = t0 + c + 65535; c = Math.floor(v / 65536); t0 = v - c * 65536;
|
||||||
|
v = t1 + c + 65535; c = Math.floor(v / 65536); t1 = v - c * 65536;
|
||||||
|
v = t2 + c + 65535; c = Math.floor(v / 65536); t2 = v - c * 65536;
|
||||||
|
v = t3 + c + 65535; c = Math.floor(v / 65536); t3 = v - c * 65536;
|
||||||
|
v = t4 + c + 65535; c = Math.floor(v / 65536); t4 = v - c * 65536;
|
||||||
|
v = t5 + c + 65535; c = Math.floor(v / 65536); t5 = v - c * 65536;
|
||||||
|
v = t6 + c + 65535; c = Math.floor(v / 65536); t6 = v - c * 65536;
|
||||||
|
v = t7 + c + 65535; c = Math.floor(v / 65536); t7 = v - c * 65536;
|
||||||
|
v = t8 + c + 65535; c = Math.floor(v / 65536); t8 = v - c * 65536;
|
||||||
|
v = t9 + c + 65535; c = Math.floor(v / 65536); t9 = v - c * 65536;
|
||||||
|
v = t10 + c + 65535; c = Math.floor(v / 65536); t10 = v - c * 65536;
|
||||||
|
v = t11 + c + 65535; c = Math.floor(v / 65536); t11 = v - c * 65536;
|
||||||
|
v = t12 + c + 65535; c = Math.floor(v / 65536); t12 = v - c * 65536;
|
||||||
|
v = t13 + c + 65535; c = Math.floor(v / 65536); t13 = v - c * 65536;
|
||||||
|
v = t14 + c + 65535; c = Math.floor(v / 65536); t14 = v - c * 65536;
|
||||||
|
v = t15 + c + 65535; c = Math.floor(v / 65536); t15 = v - c * 65536;
|
||||||
|
t0 += c-1 + 37 * (c-1);
|
||||||
|
|
||||||
|
o[ 0] = t0;
|
||||||
|
o[ 1] = t1;
|
||||||
|
o[ 2] = t2;
|
||||||
|
o[ 3] = t3;
|
||||||
|
o[ 4] = t4;
|
||||||
|
o[ 5] = t5;
|
||||||
|
o[ 6] = t6;
|
||||||
|
o[ 7] = t7;
|
||||||
|
o[ 8] = t8;
|
||||||
|
o[ 9] = t9;
|
||||||
|
o[10] = t10;
|
||||||
|
o[11] = t11;
|
||||||
|
o[12] = t12;
|
||||||
|
o[13] = t13;
|
||||||
|
o[14] = t14;
|
||||||
|
o[15] = t15;
|
||||||
|
}
|
||||||
|
|
||||||
|
function S(o, a) {
|
||||||
|
M(o, a, a);
|
||||||
|
}
|
||||||
|
|
||||||
|
function sel25519(p, q, b) {
|
||||||
|
var t, c = ~(b-1);
|
||||||
|
for (var i = 0; i < 16; i++) {
|
||||||
|
t = c & (p[i] ^ q[i]);
|
||||||
|
p[i] ^= t;
|
||||||
|
q[i] ^= t;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
function pack25519(o, n) {
|
||||||
|
var i, j, b;
|
||||||
|
var m = gf(), t = gf();
|
||||||
|
for (i = 0; i < 16; i++) t[i] = n[i];
|
||||||
|
car25519(t);
|
||||||
|
car25519(t);
|
||||||
|
car25519(t);
|
||||||
|
for (j = 0; j < 2; j++) {
|
||||||
|
m[0] = t[0] - 0xffed;
|
||||||
|
for (i = 1; i < 15; i++) {
|
||||||
|
m[i] = t[i] - 0xffff - ((m[i-1]>>16) & 1);
|
||||||
|
m[i-1] &= 0xffff;
|
||||||
|
}
|
||||||
|
m[15] = t[15] - 0x7fff - ((m[14]>>16) & 1);
|
||||||
|
b = (m[15]>>16) & 1;
|
||||||
|
m[14] &= 0xffff;
|
||||||
|
sel25519(t, m, 1-b);
|
||||||
|
}
|
||||||
|
for (i = 0; i < 16; i++) {
|
||||||
|
o[2*i] = t[i] & 0xff;
|
||||||
|
o[2*i+1] = t[i]>>8;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
function unpack25519(o, n) {
|
||||||
|
var i;
|
||||||
|
for (i = 0; i < 16; i++) o[i] = n[2*i] + (n[2*i+1] << 8);
|
||||||
|
o[15] &= 0x7fff;
|
||||||
|
}
|
||||||
|
|
||||||
|
function inv25519(o, i) {
|
||||||
|
var c = gf();
|
||||||
|
var a;
|
||||||
|
for (a = 0; a < 16; a++) c[a] = i[a];
|
||||||
|
for (a = 253; a >= 0; a--) {
|
||||||
|
S(c, c);
|
||||||
|
if(a !== 2 && a !== 4) M(c, c, i);
|
||||||
|
}
|
||||||
|
for (a = 0; a < 16; a++) o[a] = c[a];
|
||||||
|
}
|
||||||
|
|
||||||
|
function car25519(o) {
|
||||||
|
var i, v, c = 1;
|
||||||
|
for (i = 0; i < 16; i++) {
|
||||||
|
v = o[i] + c + 65535;
|
||||||
|
c = Math.floor(v / 65536);
|
||||||
|
o[i] = v - c * 65536;
|
||||||
|
}
|
||||||
|
o[0] += c-1 + 37 * (c-1);
|
||||||
|
}
|
||||||
|
|
||||||
|
module.exports = {
|
||||||
|
gf,
|
||||||
|
A,
|
||||||
|
Z,
|
||||||
|
M,
|
||||||
|
S,
|
||||||
|
sel25519,
|
||||||
|
pack25519,
|
||||||
|
unpack25519,
|
||||||
|
inv25519,
|
||||||
|
gf0,
|
||||||
|
gf1,
|
||||||
|
_9,
|
||||||
|
_121665,
|
||||||
|
D,
|
||||||
|
D2,
|
||||||
|
X,
|
||||||
|
Y,
|
||||||
|
I
|
||||||
|
}
|
128
internal/hchacha20.js
Normal file
128
internal/hchacha20.js
Normal file
@ -0,0 +1,128 @@
|
|||||||
|
/* eslint-disable camelcase */
|
||||||
|
const { sodium_malloc } = require('../memory')
|
||||||
|
const assert = require('nanoassert')
|
||||||
|
|
||||||
|
if (new Uint16Array([1])[0] !== 1) throw new Error('Big endian architecture is not supported.')
|
||||||
|
|
||||||
|
const crypto_core_hchacha20_OUTPUTBYTES = 32
|
||||||
|
const crypto_core_hchacha20_INPUTBYTES = 16
|
||||||
|
const crypto_core_hchacha20_KEYBYTES = 32
|
||||||
|
const crypto_core_hchacha20_CONSTBYTES = 16
|
||||||
|
|
||||||
|
function ROTL32 (x, b) {
|
||||||
|
x &= 0xFFFFFFFF
|
||||||
|
b &= 0xFFFFFFFF
|
||||||
|
return (x << b) | (x >>> (32 - b))
|
||||||
|
}
|
||||||
|
|
||||||
|
function LOAD32_LE (src, offset) {
|
||||||
|
assert(src instanceof Uint8Array, 'src not byte array')
|
||||||
|
let w = src[offset]
|
||||||
|
w |= src[offset + 1] << 8
|
||||||
|
w |= src[offset + 2] << 16
|
||||||
|
w |= src[offset + 3] << 24
|
||||||
|
return w
|
||||||
|
}
|
||||||
|
|
||||||
|
function STORE32_LE (dest, int, offset) {
|
||||||
|
assert(dest instanceof Uint8Array, 'dest not byte array')
|
||||||
|
var mul = 1
|
||||||
|
var i = 0
|
||||||
|
dest[offset] = int & 0xFF // grab bottom byte
|
||||||
|
while (++i < 4 && (mul *= 0x100)) {
|
||||||
|
dest[offset + i] = (int / mul) & 0xFF
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
function QUARTERROUND (l, A, B, C, D) {
|
||||||
|
l[A] += l[B]
|
||||||
|
l[D] = ROTL32(l[D] ^ l[A], 16)
|
||||||
|
l[C] += l[D]
|
||||||
|
l[B] = ROTL32(l[B] ^ l[C], 12)
|
||||||
|
l[A] += l[B]
|
||||||
|
l[D] = ROTL32(l[D] ^ l[A], 8)
|
||||||
|
l[C] += l[D]
|
||||||
|
l[B] = ROTL32(l[B] ^ l[C], 7)
|
||||||
|
}
|
||||||
|
|
||||||
|
function crypto_core_hchacha20 (out, _in, k, c) {
|
||||||
|
assert(out instanceof Uint8Array && out.length === 32, 'out is not an array of 32 bytes')
|
||||||
|
assert(k instanceof Uint8Array && k.length === 32, 'k is not an array of 32 bytes')
|
||||||
|
assert(c === null || (c instanceof Uint8Array && c.length === 16), 'c is not null or an array of 16 bytes')
|
||||||
|
|
||||||
|
let i = 0
|
||||||
|
const x = new Uint32Array(16)
|
||||||
|
if (!c) {
|
||||||
|
x[0] = 0x61707865
|
||||||
|
x[1] = 0x3320646E
|
||||||
|
x[2] = 0x79622D32
|
||||||
|
x[3] = 0x6B206574
|
||||||
|
} else {
|
||||||
|
x[0] = LOAD32_LE(c, 0)
|
||||||
|
x[1] = LOAD32_LE(c, 4)
|
||||||
|
x[2] = LOAD32_LE(c, 8)
|
||||||
|
x[3] = LOAD32_LE(c, 12)
|
||||||
|
}
|
||||||
|
x[4] = LOAD32_LE(k, 0)
|
||||||
|
x[5] = LOAD32_LE(k, 4)
|
||||||
|
x[6] = LOAD32_LE(k, 8)
|
||||||
|
x[7] = LOAD32_LE(k, 12)
|
||||||
|
x[8] = LOAD32_LE(k, 16)
|
||||||
|
x[9] = LOAD32_LE(k, 20)
|
||||||
|
x[10] = LOAD32_LE(k, 24)
|
||||||
|
x[11] = LOAD32_LE(k, 28)
|
||||||
|
x[12] = LOAD32_LE(_in, 0)
|
||||||
|
x[13] = LOAD32_LE(_in, 4)
|
||||||
|
x[14] = LOAD32_LE(_in, 8)
|
||||||
|
x[15] = LOAD32_LE(_in, 12)
|
||||||
|
|
||||||
|
for (i = 0; i < 10; i++) {
|
||||||
|
QUARTERROUND(x, 0, 4, 8, 12)
|
||||||
|
QUARTERROUND(x, 1, 5, 9, 13)
|
||||||
|
QUARTERROUND(x, 2, 6, 10, 14)
|
||||||
|
QUARTERROUND(x, 3, 7, 11, 15)
|
||||||
|
QUARTERROUND(x, 0, 5, 10, 15)
|
||||||
|
QUARTERROUND(x, 1, 6, 11, 12)
|
||||||
|
QUARTERROUND(x, 2, 7, 8, 13)
|
||||||
|
QUARTERROUND(x, 3, 4, 9, 14)
|
||||||
|
}
|
||||||
|
|
||||||
|
STORE32_LE(out, x[0], 0)
|
||||||
|
STORE32_LE(out, x[1], 4)
|
||||||
|
STORE32_LE(out, x[2], 8)
|
||||||
|
STORE32_LE(out, x[3], 12)
|
||||||
|
STORE32_LE(out, x[12], 16)
|
||||||
|
STORE32_LE(out, x[13], 20)
|
||||||
|
STORE32_LE(out, x[14], 24)
|
||||||
|
STORE32_LE(out, x[15], 28)
|
||||||
|
|
||||||
|
return 0
|
||||||
|
}
|
||||||
|
|
||||||
|
function crypto_core_hchacha20_outputbytes () {
|
||||||
|
return crypto_core_hchacha20_OUTPUTBYTES
|
||||||
|
}
|
||||||
|
|
||||||
|
function crypto_core_hchacha20_inputbytes () {
|
||||||
|
return crypto_core_hchacha20_INPUTBYTES
|
||||||
|
}
|
||||||
|
|
||||||
|
function crypto_core_hchacha20_keybytes () {
|
||||||
|
return crypto_core_hchacha20_KEYBYTES
|
||||||
|
}
|
||||||
|
|
||||||
|
function crypto_core_hchacha20_constbytes () {
|
||||||
|
return crypto_core_hchacha20_CONSTBYTES
|
||||||
|
}
|
||||||
|
|
||||||
|
module.exports = {
|
||||||
|
crypto_core_hchacha20_INPUTBYTES,
|
||||||
|
LOAD32_LE,
|
||||||
|
STORE32_LE,
|
||||||
|
QUARTERROUND,
|
||||||
|
crypto_core_hchacha20,
|
||||||
|
crypto_core_hchacha20_outputbytes,
|
||||||
|
crypto_core_hchacha20_inputbytes,
|
||||||
|
crypto_core_hchacha20_keybytes,
|
||||||
|
crypto_core_hchacha20_constbytes
|
||||||
|
}
|
360
internal/poly1305.js
Normal file
360
internal/poly1305.js
Normal file
@ -0,0 +1,360 @@
|
|||||||
|
/*
|
||||||
|
* Port of Andrew Moon's Poly1305-donna-16. Public domain.
|
||||||
|
* https://github.com/floodyberry/poly1305-donna
|
||||||
|
*/
|
||||||
|
|
||||||
|
if (new Uint16Array([1])[0] !== 1) throw new Error('Big endian architecture is not supported.')
|
||||||
|
|
||||||
|
var poly1305 = function(key) {
|
||||||
|
this.buffer = new Uint8Array(16);
|
||||||
|
this.r = new Uint16Array(10);
|
||||||
|
this.h = new Uint16Array(10);
|
||||||
|
this.pad = new Uint16Array(8);
|
||||||
|
this.leftover = 0;
|
||||||
|
this.fin = 0;
|
||||||
|
|
||||||
|
var t0, t1, t2, t3, t4, t5, t6, t7;
|
||||||
|
|
||||||
|
t0 = key[ 0] & 0xff | (key[ 1] & 0xff) << 8; this.r[0] = ( t0 ) & 0x1fff;
|
||||||
|
t1 = key[ 2] & 0xff | (key[ 3] & 0xff) << 8; this.r[1] = ((t0 >>> 13) | (t1 << 3)) & 0x1fff;
|
||||||
|
t2 = key[ 4] & 0xff | (key[ 5] & 0xff) << 8; this.r[2] = ((t1 >>> 10) | (t2 << 6)) & 0x1f03;
|
||||||
|
t3 = key[ 6] & 0xff | (key[ 7] & 0xff) << 8; this.r[3] = ((t2 >>> 7) | (t3 << 9)) & 0x1fff;
|
||||||
|
t4 = key[ 8] & 0xff | (key[ 9] & 0xff) << 8; this.r[4] = ((t3 >>> 4) | (t4 << 12)) & 0x00ff;
|
||||||
|
this.r[5] = ((t4 >>> 1)) & 0x1ffe;
|
||||||
|
t5 = key[10] & 0xff | (key[11] & 0xff) << 8; this.r[6] = ((t4 >>> 14) | (t5 << 2)) & 0x1fff;
|
||||||
|
t6 = key[12] & 0xff | (key[13] & 0xff) << 8; this.r[7] = ((t5 >>> 11) | (t6 << 5)) & 0x1f81;
|
||||||
|
t7 = key[14] & 0xff | (key[15] & 0xff) << 8; this.r[8] = ((t6 >>> 8) | (t7 << 8)) & 0x1fff;
|
||||||
|
this.r[9] = ((t7 >>> 5)) & 0x007f;
|
||||||
|
|
||||||
|
this.pad[0] = key[16] & 0xff | (key[17] & 0xff) << 8;
|
||||||
|
this.pad[1] = key[18] & 0xff | (key[19] & 0xff) << 8;
|
||||||
|
this.pad[2] = key[20] & 0xff | (key[21] & 0xff) << 8;
|
||||||
|
this.pad[3] = key[22] & 0xff | (key[23] & 0xff) << 8;
|
||||||
|
this.pad[4] = key[24] & 0xff | (key[25] & 0xff) << 8;
|
||||||
|
this.pad[5] = key[26] & 0xff | (key[27] & 0xff) << 8;
|
||||||
|
this.pad[6] = key[28] & 0xff | (key[29] & 0xff) << 8;
|
||||||
|
this.pad[7] = key[30] & 0xff | (key[31] & 0xff) << 8;
|
||||||
|
};
|
||||||
|
|
||||||
|
poly1305.prototype.blocks = function(m, mpos, bytes) {
|
||||||
|
var hibit = this.fin ? 0 : (1 << 11);
|
||||||
|
var t0, t1, t2, t3, t4, t5, t6, t7, c;
|
||||||
|
var d0, d1, d2, d3, d4, d5, d6, d7, d8, d9;
|
||||||
|
|
||||||
|
var h0 = this.h[0],
|
||||||
|
h1 = this.h[1],
|
||||||
|
h2 = this.h[2],
|
||||||
|
h3 = this.h[3],
|
||||||
|
h4 = this.h[4],
|
||||||
|
h5 = this.h[5],
|
||||||
|
h6 = this.h[6],
|
||||||
|
h7 = this.h[7],
|
||||||
|
h8 = this.h[8],
|
||||||
|
h9 = this.h[9];
|
||||||
|
|
||||||
|
var r0 = this.r[0],
|
||||||
|
r1 = this.r[1],
|
||||||
|
r2 = this.r[2],
|
||||||
|
r3 = this.r[3],
|
||||||
|
r4 = this.r[4],
|
||||||
|
r5 = this.r[5],
|
||||||
|
r6 = this.r[6],
|
||||||
|
r7 = this.r[7],
|
||||||
|
r8 = this.r[8],
|
||||||
|
r9 = this.r[9];
|
||||||
|
|
||||||
|
while (bytes >= 16) {
|
||||||
|
t0 = m[mpos+ 0] & 0xff | (m[mpos+ 1] & 0xff) << 8; h0 += ( t0 ) & 0x1fff;
|
||||||
|
t1 = m[mpos+ 2] & 0xff | (m[mpos+ 3] & 0xff) << 8; h1 += ((t0 >>> 13) | (t1 << 3)) & 0x1fff;
|
||||||
|
t2 = m[mpos+ 4] & 0xff | (m[mpos+ 5] & 0xff) << 8; h2 += ((t1 >>> 10) | (t2 << 6)) & 0x1fff;
|
||||||
|
t3 = m[mpos+ 6] & 0xff | (m[mpos+ 7] & 0xff) << 8; h3 += ((t2 >>> 7) | (t3 << 9)) & 0x1fff;
|
||||||
|
t4 = m[mpos+ 8] & 0xff | (m[mpos+ 9] & 0xff) << 8; h4 += ((t3 >>> 4) | (t4 << 12)) & 0x1fff;
|
||||||
|
h5 += ((t4 >>> 1)) & 0x1fff;
|
||||||
|
t5 = m[mpos+10] & 0xff | (m[mpos+11] & 0xff) << 8; h6 += ((t4 >>> 14) | (t5 << 2)) & 0x1fff;
|
||||||
|
t6 = m[mpos+12] & 0xff | (m[mpos+13] & 0xff) << 8; h7 += ((t5 >>> 11) | (t6 << 5)) & 0x1fff;
|
||||||
|
t7 = m[mpos+14] & 0xff | (m[mpos+15] & 0xff) << 8; h8 += ((t6 >>> 8) | (t7 << 8)) & 0x1fff;
|
||||||
|
h9 += ((t7 >>> 5)) | hibit;
|
||||||
|
|
||||||
|
c = 0;
|
||||||
|
|
||||||
|
d0 = c;
|
||||||
|
d0 += h0 * r0;
|
||||||
|
d0 += h1 * (5 * r9);
|
||||||
|
d0 += h2 * (5 * r8);
|
||||||
|
d0 += h3 * (5 * r7);
|
||||||
|
d0 += h4 * (5 * r6);
|
||||||
|
c = (d0 >>> 13); d0 &= 0x1fff;
|
||||||
|
d0 += h5 * (5 * r5);
|
||||||
|
d0 += h6 * (5 * r4);
|
||||||
|
d0 += h7 * (5 * r3);
|
||||||
|
d0 += h8 * (5 * r2);
|
||||||
|
d0 += h9 * (5 * r1);
|
||||||
|
c += (d0 >>> 13); d0 &= 0x1fff;
|
||||||
|
|
||||||
|
d1 = c;
|
||||||
|
d1 += h0 * r1;
|
||||||
|
d1 += h1 * r0;
|
||||||
|
d1 += h2 * (5 * r9);
|
||||||
|
d1 += h3 * (5 * r8);
|
||||||
|
d1 += h4 * (5 * r7);
|
||||||
|
c = (d1 >>> 13); d1 &= 0x1fff;
|
||||||
|
d1 += h5 * (5 * r6);
|
||||||
|
d1 += h6 * (5 * r5);
|
||||||
|
d1 += h7 * (5 * r4);
|
||||||
|
d1 += h8 * (5 * r3);
|
||||||
|
d1 += h9 * (5 * r2);
|
||||||
|
c += (d1 >>> 13); d1 &= 0x1fff;
|
||||||
|
|
||||||
|
d2 = c;
|
||||||
|
d2 += h0 * r2;
|
||||||
|
d2 += h1 * r1;
|
||||||
|
d2 += h2 * r0;
|
||||||
|
d2 += h3 * (5 * r9);
|
||||||
|
d2 += h4 * (5 * r8);
|
||||||
|
c = (d2 >>> 13); d2 &= 0x1fff;
|
||||||
|
d2 += h5 * (5 * r7);
|
||||||
|
d2 += h6 * (5 * r6);
|
||||||
|
d2 += h7 * (5 * r5);
|
||||||
|
d2 += h8 * (5 * r4);
|
||||||
|
d2 += h9 * (5 * r3);
|
||||||
|
c += (d2 >>> 13); d2 &= 0x1fff;
|
||||||
|
|
||||||
|
d3 = c;
|
||||||
|
d3 += h0 * r3;
|
||||||
|
d3 += h1 * r2;
|
||||||
|
d3 += h2 * r1;
|
||||||
|
d3 += h3 * r0;
|
||||||
|
d3 += h4 * (5 * r9);
|
||||||
|
c = (d3 >>> 13); d3 &= 0x1fff;
|
||||||
|
d3 += h5 * (5 * r8);
|
||||||
|
d3 += h6 * (5 * r7);
|
||||||
|
d3 += h7 * (5 * r6);
|
||||||
|
d3 += h8 * (5 * r5);
|
||||||
|
d3 += h9 * (5 * r4);
|
||||||
|
c += (d3 >>> 13); d3 &= 0x1fff;
|
||||||
|
|
||||||
|
d4 = c;
|
||||||
|
d4 += h0 * r4;
|
||||||
|
d4 += h1 * r3;
|
||||||
|
d4 += h2 * r2;
|
||||||
|
d4 += h3 * r1;
|
||||||
|
d4 += h4 * r0;
|
||||||
|
c = (d4 >>> 13); d4 &= 0x1fff;
|
||||||
|
d4 += h5 * (5 * r9);
|
||||||
|
d4 += h6 * (5 * r8);
|
||||||
|
d4 += h7 * (5 * r7);
|
||||||
|
d4 += h8 * (5 * r6);
|
||||||
|
d4 += h9 * (5 * r5);
|
||||||
|
c += (d4 >>> 13); d4 &= 0x1fff;
|
||||||
|
|
||||||
|
d5 = c;
|
||||||
|
d5 += h0 * r5;
|
||||||
|
d5 += h1 * r4;
|
||||||
|
d5 += h2 * r3;
|
||||||
|
d5 += h3 * r2;
|
||||||
|
d5 += h4 * r1;
|
||||||
|
c = (d5 >>> 13); d5 &= 0x1fff;
|
||||||
|
d5 += h5 * r0;
|
||||||
|
d5 += h6 * (5 * r9);
|
||||||
|
d5 += h7 * (5 * r8);
|
||||||
|
d5 += h8 * (5 * r7);
|
||||||
|
d5 += h9 * (5 * r6);
|
||||||
|
c += (d5 >>> 13); d5 &= 0x1fff;
|
||||||
|
|
||||||
|
d6 = c;
|
||||||
|
d6 += h0 * r6;
|
||||||
|
d6 += h1 * r5;
|
||||||
|
d6 += h2 * r4;
|
||||||
|
d6 += h3 * r3;
|
||||||
|
d6 += h4 * r2;
|
||||||
|
c = (d6 >>> 13); d6 &= 0x1fff;
|
||||||
|
d6 += h5 * r1;
|
||||||
|
d6 += h6 * r0;
|
||||||
|
d6 += h7 * (5 * r9);
|
||||||
|
d6 += h8 * (5 * r8);
|
||||||
|
d6 += h9 * (5 * r7);
|
||||||
|
c += (d6 >>> 13); d6 &= 0x1fff;
|
||||||
|
|
||||||
|
d7 = c;
|
||||||
|
d7 += h0 * r7;
|
||||||
|
d7 += h1 * r6;
|
||||||
|
d7 += h2 * r5;
|
||||||
|
d7 += h3 * r4;
|
||||||
|
d7 += h4 * r3;
|
||||||
|
c = (d7 >>> 13); d7 &= 0x1fff;
|
||||||
|
d7 += h5 * r2;
|
||||||
|
d7 += h6 * r1;
|
||||||
|
d7 += h7 * r0;
|
||||||
|
d7 += h8 * (5 * r9);
|
||||||
|
d7 += h9 * (5 * r8);
|
||||||
|
c += (d7 >>> 13); d7 &= 0x1fff;
|
||||||
|
|
||||||
|
d8 = c;
|
||||||
|
d8 += h0 * r8;
|
||||||
|
d8 += h1 * r7;
|
||||||
|
d8 += h2 * r6;
|
||||||
|
d8 += h3 * r5;
|
||||||
|
d8 += h4 * r4;
|
||||||
|
c = (d8 >>> 13); d8 &= 0x1fff;
|
||||||
|
d8 += h5 * r3;
|
||||||
|
d8 += h6 * r2;
|
||||||
|
d8 += h7 * r1;
|
||||||
|
d8 += h8 * r0;
|
||||||
|
d8 += h9 * (5 * r9);
|
||||||
|
c += (d8 >>> 13); d8 &= 0x1fff;
|
||||||
|
|
||||||
|
d9 = c;
|
||||||
|
d9 += h0 * r9;
|
||||||
|
d9 += h1 * r8;
|
||||||
|
d9 += h2 * r7;
|
||||||
|
d9 += h3 * r6;
|
||||||
|
d9 += h4 * r5;
|
||||||
|
c = (d9 >>> 13); d9 &= 0x1fff;
|
||||||
|
d9 += h5 * r4;
|
||||||
|
d9 += h6 * r3;
|
||||||
|
d9 += h7 * r2;
|
||||||
|
d9 += h8 * r1;
|
||||||
|
d9 += h9 * r0;
|
||||||
|
c += (d9 >>> 13); d9 &= 0x1fff;
|
||||||
|
|
||||||
|
c = (((c << 2) + c)) | 0;
|
||||||
|
c = (c + d0) | 0;
|
||||||
|
d0 = c & 0x1fff;
|
||||||
|
c = (c >>> 13);
|
||||||
|
d1 += c;
|
||||||
|
|
||||||
|
h0 = d0;
|
||||||
|
h1 = d1;
|
||||||
|
h2 = d2;
|
||||||
|
h3 = d3;
|
||||||
|
h4 = d4;
|
||||||
|
h5 = d5;
|
||||||
|
h6 = d6;
|
||||||
|
h7 = d7;
|
||||||
|
h8 = d8;
|
||||||
|
h9 = d9;
|
||||||
|
|
||||||
|
mpos += 16;
|
||||||
|
bytes -= 16;
|
||||||
|
}
|
||||||
|
this.h[0] = h0;
|
||||||
|
this.h[1] = h1;
|
||||||
|
this.h[2] = h2;
|
||||||
|
this.h[3] = h3;
|
||||||
|
this.h[4] = h4;
|
||||||
|
this.h[5] = h5;
|
||||||
|
this.h[6] = h6;
|
||||||
|
this.h[7] = h7;
|
||||||
|
this.h[8] = h8;
|
||||||
|
this.h[9] = h9;
|
||||||
|
};
|
||||||
|
|
||||||
|
poly1305.prototype.finish = function(mac, macpos) {
|
||||||
|
var g = new Uint16Array(10);
|
||||||
|
var c, mask, f, i;
|
||||||
|
|
||||||
|
if (this.leftover) {
|
||||||
|
i = this.leftover;
|
||||||
|
this.buffer[i++] = 1;
|
||||||
|
for (; i < 16; i++) this.buffer[i] = 0;
|
||||||
|
this.fin = 1;
|
||||||
|
this.blocks(this.buffer, 0, 16);
|
||||||
|
}
|
||||||
|
|
||||||
|
c = this.h[1] >>> 13;
|
||||||
|
this.h[1] &= 0x1fff;
|
||||||
|
for (i = 2; i < 10; i++) {
|
||||||
|
this.h[i] += c;
|
||||||
|
c = this.h[i] >>> 13;
|
||||||
|
this.h[i] &= 0x1fff;
|
||||||
|
}
|
||||||
|
this.h[0] += (c * 5);
|
||||||
|
c = this.h[0] >>> 13;
|
||||||
|
this.h[0] &= 0x1fff;
|
||||||
|
this.h[1] += c;
|
||||||
|
c = this.h[1] >>> 13;
|
||||||
|
this.h[1] &= 0x1fff;
|
||||||
|
this.h[2] += c;
|
||||||
|
|
||||||
|
g[0] = this.h[0] + 5;
|
||||||
|
c = g[0] >>> 13;
|
||||||
|
g[0] &= 0x1fff;
|
||||||
|
for (i = 1; i < 10; i++) {
|
||||||
|
g[i] = this.h[i] + c;
|
||||||
|
c = g[i] >>> 13;
|
||||||
|
g[i] &= 0x1fff;
|
||||||
|
}
|
||||||
|
g[9] -= (1 << 13);
|
||||||
|
|
||||||
|
mask = (c ^ 1) - 1;
|
||||||
|
for (i = 0; i < 10; i++) g[i] &= mask;
|
||||||
|
mask = ~mask;
|
||||||
|
for (i = 0; i < 10; i++) this.h[i] = (this.h[i] & mask) | g[i];
|
||||||
|
|
||||||
|
this.h[0] = ((this.h[0] ) | (this.h[1] << 13) ) & 0xffff;
|
||||||
|
this.h[1] = ((this.h[1] >>> 3) | (this.h[2] << 10) ) & 0xffff;
|
||||||
|
this.h[2] = ((this.h[2] >>> 6) | (this.h[3] << 7) ) & 0xffff;
|
||||||
|
this.h[3] = ((this.h[3] >>> 9) | (this.h[4] << 4) ) & 0xffff;
|
||||||
|
this.h[4] = ((this.h[4] >>> 12) | (this.h[5] << 1) | (this.h[6] << 14)) & 0xffff;
|
||||||
|
this.h[5] = ((this.h[6] >>> 2) | (this.h[7] << 11) ) & 0xffff;
|
||||||
|
this.h[6] = ((this.h[7] >>> 5) | (this.h[8] << 8) ) & 0xffff;
|
||||||
|
this.h[7] = ((this.h[8] >>> 8) | (this.h[9] << 5) ) & 0xffff;
|
||||||
|
|
||||||
|
f = this.h[0] + this.pad[0];
|
||||||
|
this.h[0] = f & 0xffff;
|
||||||
|
for (i = 1; i < 8; i++) {
|
||||||
|
f = (((this.h[i] + this.pad[i]) | 0) + (f >>> 16)) | 0;
|
||||||
|
this.h[i] = f & 0xffff;
|
||||||
|
}
|
||||||
|
|
||||||
|
mac[macpos+ 0] = (this.h[0] >>> 0) & 0xff;
|
||||||
|
mac[macpos+ 1] = (this.h[0] >>> 8) & 0xff;
|
||||||
|
mac[macpos+ 2] = (this.h[1] >>> 0) & 0xff;
|
||||||
|
mac[macpos+ 3] = (this.h[1] >>> 8) & 0xff;
|
||||||
|
mac[macpos+ 4] = (this.h[2] >>> 0) & 0xff;
|
||||||
|
mac[macpos+ 5] = (this.h[2] >>> 8) & 0xff;
|
||||||
|
mac[macpos+ 6] = (this.h[3] >>> 0) & 0xff;
|
||||||
|
mac[macpos+ 7] = (this.h[3] >>> 8) & 0xff;
|
||||||
|
mac[macpos+ 8] = (this.h[4] >>> 0) & 0xff;
|
||||||
|
mac[macpos+ 9] = (this.h[4] >>> 8) & 0xff;
|
||||||
|
mac[macpos+10] = (this.h[5] >>> 0) & 0xff;
|
||||||
|
mac[macpos+11] = (this.h[5] >>> 8) & 0xff;
|
||||||
|
mac[macpos+12] = (this.h[6] >>> 0) & 0xff;
|
||||||
|
mac[macpos+13] = (this.h[6] >>> 8) & 0xff;
|
||||||
|
mac[macpos+14] = (this.h[7] >>> 0) & 0xff;
|
||||||
|
mac[macpos+15] = (this.h[7] >>> 8) & 0xff;
|
||||||
|
};
|
||||||
|
|
||||||
|
poly1305.prototype.update = function(m, mpos, bytes) {
|
||||||
|
var i, want;
|
||||||
|
|
||||||
|
if (this.leftover) {
|
||||||
|
want = (16 - this.leftover);
|
||||||
|
if (want > bytes)
|
||||||
|
want = bytes;
|
||||||
|
for (i = 0; i < want; i++)
|
||||||
|
this.buffer[this.leftover + i] = m[mpos+i];
|
||||||
|
bytes -= want;
|
||||||
|
mpos += want;
|
||||||
|
this.leftover += want;
|
||||||
|
if (this.leftover < 16)
|
||||||
|
return;
|
||||||
|
this.blocks(this.buffer, 0, 16);
|
||||||
|
this.leftover = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (bytes >= 16) {
|
||||||
|
want = bytes - (bytes % 16);
|
||||||
|
this.blocks(m, mpos, want);
|
||||||
|
mpos += want;
|
||||||
|
bytes -= want;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (bytes) {
|
||||||
|
for (i = 0; i < bytes; i++)
|
||||||
|
this.buffer[this.leftover + i] = m[mpos+i];
|
||||||
|
this.leftover += bytes;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
module.exports = poly1305
|
30
memory.js
Normal file
30
memory.js
Normal file
@ -0,0 +1,30 @@
|
|||||||
|
/* eslint-disable camelcase */
|
||||||
|
|
||||||
|
function sodium_malloc (n) {
|
||||||
|
return new Uint8Array(n)
|
||||||
|
}
|
||||||
|
|
||||||
|
function sodium_free (n) {
|
||||||
|
sodium_memzero(n)
|
||||||
|
loadSink().port1.postMessage(n.buffer, [n.buffer])
|
||||||
|
}
|
||||||
|
|
||||||
|
function sodium_memzero (arr) {
|
||||||
|
arr.fill(0)
|
||||||
|
}
|
||||||
|
|
||||||
|
var sink
|
||||||
|
|
||||||
|
function loadSink () {
|
||||||
|
if (sink) return sink
|
||||||
|
var MessageChannel = globalThis.MessageChannel
|
||||||
|
if (MessageChannel == null) ({ MessageChannel } = require('worker' + '_threads'))
|
||||||
|
sink = new MessageChannel()
|
||||||
|
return sink
|
||||||
|
}
|
||||||
|
|
||||||
|
module.exports = {
|
||||||
|
sodium_malloc,
|
||||||
|
sodium_free,
|
||||||
|
sodium_memzero
|
||||||
|
}
|
44
package.json
44
package.json
@ -1,32 +1,52 @@
|
|||||||
{
|
{
|
||||||
"name": "sodium-javascript",
|
"name": "sodium-javascript",
|
||||||
"version": "0.5.2",
|
"version": "0.8.0",
|
||||||
"description": "WIP - a pure javascript version of sodium-native",
|
"description": "WIP - a pure javascript version of sodium-native",
|
||||||
"main": "index.js",
|
"main": "index.js",
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"blake2b": "^2.1.1",
|
"blake2b": "^2.1.1",
|
||||||
"nanoassert": "^1.0.0",
|
"chacha20-universal": "^1.0.4",
|
||||||
|
"nanoassert": "^2.0.0",
|
||||||
|
"sha256-universal": "^1.1.0",
|
||||||
|
"sha512-universal": "^1.1.0",
|
||||||
"siphash24": "^1.0.1",
|
"siphash24": "^1.0.1",
|
||||||
"xsalsa20": "^1.0.0"
|
"xsalsa20": "^1.0.0"
|
||||||
},
|
},
|
||||||
"devDependencies": {
|
"devDependencies": {
|
||||||
"browser-run": "^4.0.2",
|
"brittle": "^3.2.1",
|
||||||
"browserify": "^14.1.0",
|
"browserify": "^16.5.1",
|
||||||
"sodium-test": "^0.7.0"
|
"standard": "^15.0.1"
|
||||||
|
},
|
||||||
|
"standard": {
|
||||||
|
"ignore": [
|
||||||
|
"/internal/**/*.js",
|
||||||
|
"/test/fixtures/*.js"
|
||||||
|
],
|
||||||
|
"rules": {
|
||||||
|
"camelcase": "off"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"browser": {
|
||||||
|
"crypto": false,
|
||||||
|
"worker_threads": false
|
||||||
},
|
},
|
||||||
"scripts": {
|
"scripts": {
|
||||||
"browser": "browserify test.js | browser-run",
|
"pretest": "standard",
|
||||||
"browser-manual": "browserify test.js | browser-run -p 1234",
|
"test": "brittle test/*.js",
|
||||||
"test": "node test.js"
|
"test-browser": "browserify test.js | tape-run"
|
||||||
},
|
},
|
||||||
"repository": {
|
"repository": {
|
||||||
"type": "git",
|
"type": "git",
|
||||||
"url": "https://github.com/mafintosh/sodium-javascript.git"
|
"url": "git+https://github.com/sodium-friends/sodium-javascript.git"
|
||||||
},
|
},
|
||||||
"author": "Mathias Buus (@mafintosh)",
|
"contributors": [
|
||||||
|
"Christophe Diederichs <chm-diederichs@hyperdivision.dk>",
|
||||||
|
"Emil Bay <github@tixz.dk> (http://bayes.dk)",
|
||||||
|
"Mathias Buus <mathiasbuus@gmail.com> (https://mafinto.sh)"
|
||||||
|
],
|
||||||
"license": "MIT",
|
"license": "MIT",
|
||||||
"bugs": {
|
"bugs": {
|
||||||
"url": "https://github.com/mafintosh/sodium-javascript/issues"
|
"url": "https://github.com/sodium-friends/sodium-javascript/issues"
|
||||||
},
|
},
|
||||||
"homepage": "https://github.com/mafintosh/sodium-javascript"
|
"homepage": "https://github.com/sodium-friends/sodium-javascript#readme"
|
||||||
}
|
}
|
||||||
|
@ -1,40 +1,40 @@
|
|||||||
var assert = require('nanoassert')
|
var assert = require('nanoassert')
|
||||||
|
|
||||||
var randombytes = (function () {
|
var randombytes = (function () {
|
||||||
var QUOTA = 65536 // limit for QuotaExceededException
|
var QUOTA = 65536 // limit for QuotaExceededException
|
||||||
var crypto = typeof global !== 'undefined' ? crypto = (global.crypto || global.msCrypto) : null
|
var crypto = globalThis.crypto || globalThis.msCrypto
|
||||||
|
|
||||||
function browserBytes (out, n) {
|
function browserBytes (out, n) {
|
||||||
for (var i = 0; i < n; i += QUOTA) {
|
for (let i = 0; i < n; i += QUOTA) {
|
||||||
crypto.getRandomValues(out.subarray(i, i + Math.min(n - i, QUOTA)))
|
crypto.getRandomValues(new Uint8Array(out.buffer, i + out.byteOffset, Math.min(n - i, QUOTA)))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
function nodeBytes (out, n) {
|
function nodeBytes (out, n) {
|
||||||
out.set(crypto.randomBytes(n))
|
new Uint8Array(out.buffer, out.byteOffset, n).set(crypto.randomBytes(n))
|
||||||
}
|
}
|
||||||
|
|
||||||
function noImpl () {
|
function noImpl () {
|
||||||
throw new Error('No secure random number generator available')
|
throw new Error('No secure random number generator available')
|
||||||
}
|
}
|
||||||
|
|
||||||
if (crypto && crypto.getRandomValues) {
|
if (crypto && crypto.getRandomValues) return browserBytes
|
||||||
return browserBytes
|
|
||||||
} else if (typeof require !== 'undefined') {
|
if (require != null) {
|
||||||
// Node.js.
|
// Node.js. Bust Browserify
|
||||||
crypto = require('cry' + 'pto');
|
crypto = require('cry' + 'pto')
|
||||||
if (crypto && crypto.randomBytes) {
|
if (crypto && crypto.randomBytes) return nodeBytes
|
||||||
return nodeBytes
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return noImpl
|
return noImpl
|
||||||
})()
|
})()
|
||||||
|
|
||||||
|
// Make non enumerable as this is an internal function
|
||||||
Object.defineProperty(module.exports, 'randombytes', {
|
Object.defineProperty(module.exports, 'randombytes', {
|
||||||
value: randombytes
|
value: randombytes
|
||||||
})
|
})
|
||||||
|
|
||||||
module.exports.randombytes_buf = function (out) {
|
module.exports.randombytes_buf = function (out) {
|
||||||
assert(out, 'out must be given')
|
assert(out, 'out must be given')
|
||||||
randombytes(out, out.length)
|
randombytes(out, out.byteLength)
|
||||||
}
|
}
|
||||||
|
3
test.js
3
test.js
@ -1,3 +0,0 @@
|
|||||||
require('sodium-test')(require('.'))
|
|
||||||
|
|
||||||
if (typeof window !== 'undefined') window.close()
|
|
285
test/crypto_aead_chacha20poly1305_ietf.js
Normal file
285
test/crypto_aead_chacha20poly1305_ietf.js
Normal file
@ -0,0 +1,285 @@
|
|||||||
|
/* eslint-disable camelcase */
|
||||||
|
const test = require('brittle')
|
||||||
|
const b4a = require('b4a')
|
||||||
|
const sodium = require('..')
|
||||||
|
|
||||||
|
test('constants', function (t) {
|
||||||
|
t.is(typeof sodium.crypto_aead_chacha20poly1305_ietf_ABYTES, 'number')
|
||||||
|
t.is(typeof sodium.crypto_aead_chacha20poly1305_ietf_KEYBYTES, 'number')
|
||||||
|
t.is(typeof sodium.crypto_aead_chacha20poly1305_ietf_NPUBBYTES, 'number')
|
||||||
|
t.is(typeof sodium.crypto_aead_chacha20poly1305_ietf_NSECBYTES, 'number')
|
||||||
|
t.is(sodium.crypto_aead_chacha20poly1305_ietf_NSECBYTES, 0)
|
||||||
|
t.is(typeof sodium.crypto_aead_chacha20poly1305_ietf_MESSAGEBYTES_MAX, 'number')
|
||||||
|
t.is(sodium.crypto_aead_chacha20poly1305_ietf_MESSAGEBYTES_MAX, Number.MAX_SAFE_INTEGER) // to make sure, see note in binding.cc
|
||||||
|
})
|
||||||
|
|
||||||
|
test('ported from libsodium', function (t) {
|
||||||
|
const mlen = 114
|
||||||
|
const adlen = 12
|
||||||
|
const clen = mlen + sodium.crypto_aead_chacha20poly1305_ietf_ABYTES
|
||||||
|
|
||||||
|
const firstkey = b4a.from([
|
||||||
|
0x80, 0x81, 0x82, 0x83, 0x84, 0x85, 0x86, 0x87,
|
||||||
|
0x88, 0x89, 0x8a, 0x8b, 0x8c, 0x8d, 0x8e, 0x8f,
|
||||||
|
0x90, 0x91, 0x92, 0x93, 0x94, 0x95, 0x96, 0x97,
|
||||||
|
0x98, 0x99, 0x9a, 0x9b, 0x9c, 0x9d, 0x9e, 0x9f
|
||||||
|
])
|
||||||
|
|
||||||
|
const message = b4a.from('Ladies and Gentlemen of the class of \'99: If I could offer you only one tip for the future, sunscreen would be it.')
|
||||||
|
|
||||||
|
const m = sodium.sodium_malloc(mlen)
|
||||||
|
const nonce = b4a.from([
|
||||||
|
0x07, 0x00, 0x00, 0x00, 0x40, 0x41, 0x42, 0x43,
|
||||||
|
0x44, 0x45, 0x46, 0x47
|
||||||
|
])
|
||||||
|
t.is(nonce.length, sodium.crypto_aead_chacha20poly1305_ietf_NPUBBYTES)
|
||||||
|
|
||||||
|
const ad = b4a.from([
|
||||||
|
0x50, 0x51, 0x52, 0x53, 0xc0, 0xc1, 0xc2, 0xc3,
|
||||||
|
0xc4, 0xc5, 0xc6, 0xc7
|
||||||
|
])
|
||||||
|
t.is(ad.length, adlen)
|
||||||
|
|
||||||
|
const c = sodium.sodium_malloc(clen)
|
||||||
|
const detachedc = sodium.sodium_malloc(mlen)
|
||||||
|
|
||||||
|
const mac = sodium.sodium_malloc(sodium.crypto_aead_chacha20poly1305_ietf_ABYTES)
|
||||||
|
|
||||||
|
const m2 = sodium.sodium_malloc(mlen)
|
||||||
|
|
||||||
|
let foundclen = 0
|
||||||
|
let foundmaclen = 0
|
||||||
|
let m2len = 0
|
||||||
|
|
||||||
|
let i = 0
|
||||||
|
|
||||||
|
t.is(message.length, mlen)
|
||||||
|
b4a.copy(message, m)
|
||||||
|
|
||||||
|
foundclen = sodium.crypto_aead_chacha20poly1305_ietf_encrypt(c, m, ad, null, nonce, firstkey)
|
||||||
|
t.is(foundclen, mlen + sodium.crypto_aead_chacha20poly1305_ietf_ABYTES)
|
||||||
|
|
||||||
|
const exp1 = new Uint8Array([
|
||||||
|
0xd3, 0x1a, 0x8d, 0x34, 0x64, 0x8e, 0x60, 0xdb, 0x7b, 0x86, 0xaf, 0xbc,
|
||||||
|
0x53, 0xef, 0x7e, 0xc2, 0xa4, 0xad, 0xed, 0x51, 0x29, 0x6e, 0x08, 0xfe,
|
||||||
|
0xa9, 0xe2, 0xb5, 0xa7, 0x36, 0xee, 0x62, 0xd6, 0x3d, 0xbe, 0xa4, 0x5e,
|
||||||
|
0x8c, 0xa9, 0x67, 0x12, 0x82, 0xfa, 0xfb, 0x69, 0xda, 0x92, 0x72, 0x8b,
|
||||||
|
0x1a, 0x71, 0xde, 0x0a, 0x9e, 0x06, 0x0b, 0x29, 0x05, 0xd6, 0xa5, 0xb6,
|
||||||
|
0x7e, 0xcd, 0x3b, 0x36, 0x92, 0xdd, 0xbd, 0x7f, 0x2d, 0x77, 0x8b, 0x8c,
|
||||||
|
0x98, 0x03, 0xae, 0xe3, 0x28, 0x09, 0x1b, 0x58, 0xfa, 0xb3, 0x24, 0xe4,
|
||||||
|
0xfa, 0xd6, 0x75, 0x94, 0x55, 0x85, 0x80, 0x8b, 0x48, 0x31, 0xd7, 0xbc,
|
||||||
|
0x3f, 0xf4, 0xde, 0xf0, 0x8e, 0x4b, 0x7a, 0x9d, 0xe5, 0x76, 0xd2, 0x65,
|
||||||
|
0x86, 0xce, 0xc6, 0x4b, 0x61, 0x16, 0x1a, 0xe1, 0x0b, 0x59, 0x4f, 0x09,
|
||||||
|
0xe2, 0x6a, 0x7e, 0x90, 0x2e, 0xcb, 0xd0, 0x60, 0x06, 0x91
|
||||||
|
])
|
||||||
|
|
||||||
|
t.alike(c, exp1)
|
||||||
|
|
||||||
|
foundmaclen = sodium.crypto_aead_chacha20poly1305_ietf_encrypt_detached(detachedc, mac, m, ad, null, nonce, firstkey)
|
||||||
|
|
||||||
|
t.is(foundmaclen, sodium.crypto_aead_chacha20poly1305_ietf_ABYTES)
|
||||||
|
const exp0 = c.slice(0, mlen)
|
||||||
|
|
||||||
|
t.alike(detachedc, exp0)
|
||||||
|
|
||||||
|
m2len = sodium.crypto_aead_chacha20poly1305_ietf_decrypt(m2, null, c, ad, nonce, firstkey)
|
||||||
|
t.is(m2len, mlen)
|
||||||
|
|
||||||
|
t.alike(m, m2)
|
||||||
|
|
||||||
|
m2.fill(0)
|
||||||
|
sodium.crypto_aead_chacha20poly1305_ietf_decrypt_detached(m2, null, c.slice(0, mlen), mac, ad, nonce, firstkey)
|
||||||
|
|
||||||
|
t.alike(m, m2)
|
||||||
|
|
||||||
|
for (i = 0; i < clen; i++) {
|
||||||
|
c[i] ^= (i + 1)
|
||||||
|
t.exception.all(_ => sodium.crypto_aead_chacha20poly1305_ietf_decrypt(m2, null, c, ad, nonce, firstkey))
|
||||||
|
if (b4a.equals(m, m2)) t.fail()
|
||||||
|
c[i] ^= (i + 1)
|
||||||
|
}
|
||||||
|
|
||||||
|
foundclen = sodium.crypto_aead_chacha20poly1305_ietf_encrypt(c, m, null, null, nonce, firstkey)
|
||||||
|
t.is(foundclen, clen)
|
||||||
|
|
||||||
|
const exp2 = new Uint8Array([
|
||||||
|
0xd3, 0x1a, 0x8d, 0x34, 0x64, 0x8e, 0x60, 0xdb, 0x7b, 0x86, 0xaf, 0xbc,
|
||||||
|
0x53, 0xef, 0x7e, 0xc2, 0xa4, 0xad, 0xed, 0x51, 0x29, 0x6e, 0x08, 0xfe,
|
||||||
|
0xa9, 0xe2, 0xb5, 0xa7, 0x36, 0xee, 0x62, 0xd6, 0x3d, 0xbe, 0xa4, 0x5e,
|
||||||
|
0x8c, 0xa9, 0x67, 0x12, 0x82, 0xfa, 0xfb, 0x69, 0xda, 0x92, 0x72, 0x8b,
|
||||||
|
0x1a, 0x71, 0xde, 0x0a, 0x9e, 0x06, 0x0b, 0x29, 0x05, 0xd6, 0xa5, 0xb6,
|
||||||
|
0x7e, 0xcd, 0x3b, 0x36, 0x92, 0xdd, 0xbd, 0x7f, 0x2d, 0x77, 0x8b, 0x8c,
|
||||||
|
0x98, 0x03, 0xae, 0xe3, 0x28, 0x09, 0x1b, 0x58, 0xfa, 0xb3, 0x24, 0xe4,
|
||||||
|
0xfa, 0xd6, 0x75, 0x94, 0x55, 0x85, 0x80, 0x8b, 0x48, 0x31, 0xd7, 0xbc,
|
||||||
|
0x3f, 0xf4, 0xde, 0xf0, 0x8e, 0x4b, 0x7a, 0x9d, 0xe5, 0x76, 0xd2, 0x65,
|
||||||
|
0x86, 0xce, 0xc6, 0x4b, 0x61, 0x16, 0x6a, 0x23, 0xa4, 0x68, 0x1f, 0xd5,
|
||||||
|
0x94, 0x56, 0xae, 0xa1, 0xd2, 0x9f, 0x82, 0x47, 0x72, 0x16
|
||||||
|
])
|
||||||
|
|
||||||
|
t.alike(c, exp2)
|
||||||
|
|
||||||
|
m2len = sodium.crypto_aead_chacha20poly1305_ietf_decrypt(m2, null, c, null, nonce, firstkey)
|
||||||
|
t.is(m2len, mlen)
|
||||||
|
|
||||||
|
t.alike(m2, m)
|
||||||
|
|
||||||
|
b4a.copy(m, c)
|
||||||
|
|
||||||
|
foundclen = sodium.crypto_aead_chacha20poly1305_ietf_encrypt(c, c.slice(0, mlen), null, null, nonce, firstkey)
|
||||||
|
|
||||||
|
t.is(foundclen, clen, 'clen is properly set (adlen=0)')
|
||||||
|
|
||||||
|
const exp3 = new Uint8Array([
|
||||||
|
0xd3, 0x1a, 0x8d, 0x34, 0x64, 0x8e, 0x60, 0xdb, 0x7b, 0x86, 0xaf, 0xbc,
|
||||||
|
0x53, 0xef, 0x7e, 0xc2, 0xa4, 0xad, 0xed, 0x51, 0x29, 0x6e, 0x08, 0xfe,
|
||||||
|
0xa9, 0xe2, 0xb5, 0xa7, 0x36, 0xee, 0x62, 0xd6, 0x3d, 0xbe, 0xa4, 0x5e,
|
||||||
|
0x8c, 0xa9, 0x67, 0x12, 0x82, 0xfa, 0xfb, 0x69, 0xda, 0x92, 0x72, 0x8b,
|
||||||
|
0x1a, 0x71, 0xde, 0x0a, 0x9e, 0x06, 0x0b, 0x29, 0x05, 0xd6, 0xa5, 0xb6,
|
||||||
|
0x7e, 0xcd, 0x3b, 0x36, 0x92, 0xdd, 0xbd, 0x7f, 0x2d, 0x77, 0x8b, 0x8c,
|
||||||
|
0x98, 0x03, 0xae, 0xe3, 0x28, 0x09, 0x1b, 0x58, 0xfa, 0xb3, 0x24, 0xe4,
|
||||||
|
0xfa, 0xd6, 0x75, 0x94, 0x55, 0x85, 0x80, 0x8b, 0x48, 0x31, 0xd7, 0xbc,
|
||||||
|
0x3f, 0xf4, 0xde, 0xf0, 0x8e, 0x4b, 0x7a, 0x9d, 0xe5, 0x76, 0xd2, 0x65,
|
||||||
|
0x86, 0xce, 0xc6, 0x4b, 0x61, 0x16, 0x6a, 0x23, 0xa4, 0x68, 0x1f, 0xd5,
|
||||||
|
0x94, 0x56, 0xae, 0xa1, 0xd2, 0x9f, 0x82, 0x47, 0x72, 0x16
|
||||||
|
])
|
||||||
|
|
||||||
|
t.alike(c, exp3)
|
||||||
|
|
||||||
|
const decrypted = sodium.sodium_malloc(c.byteLength - sodium.crypto_aead_chacha20poly1305_ietf_ABYTES)
|
||||||
|
m2len = sodium.crypto_aead_chacha20poly1305_ietf_decrypt(decrypted, null, c, null, nonce, firstkey)
|
||||||
|
t.is(m2len, mlen, 'm2len is properly set (adlen=0)')
|
||||||
|
|
||||||
|
t.alike(m, decrypted, 'm == c (adlen=0)')
|
||||||
|
})
|
||||||
|
|
||||||
|
test.skip('keygen', function (t) {
|
||||||
|
const key1 = sodium.sodium_malloc(sodium.crypto_aead_chacha20poly1305_ietf_KEYBYTES)
|
||||||
|
const key2 = sodium.sodium_malloc(sodium.crypto_aead_chacha20poly1305_ietf_KEYBYTES)
|
||||||
|
|
||||||
|
sodium.crypto_aead_chacha20poly1305_ietf_keygen(key1)
|
||||||
|
sodium.crypto_aead_chacha20poly1305_ietf_keygen(key2)
|
||||||
|
|
||||||
|
t.unlike(key1, key2)
|
||||||
|
})
|
||||||
|
|
||||||
|
test.skip('different keys', function (t) {
|
||||||
|
const m = b4a.from('Ladies and Gentlemen of the class of \'99: If I could offer you only one tip for the future, sunscreen would be it.')
|
||||||
|
|
||||||
|
const key1 = sodium.sodium_malloc(sodium.crypto_aead_chacha20poly1305_ietf_KEYBYTES)
|
||||||
|
const key2 = sodium.sodium_malloc(sodium.crypto_aead_chacha20poly1305_ietf_KEYBYTES)
|
||||||
|
sodium.crypto_aead_chacha20poly1305_ietf_keygen(key1)
|
||||||
|
sodium.crypto_aead_chacha20poly1305_ietf_keygen(key2)
|
||||||
|
|
||||||
|
const nonce = sodium.sodium_malloc(sodium.crypto_aead_chacha20poly1305_ietf_NPUBBYTES)
|
||||||
|
sodium.randombytes_buf(nonce)
|
||||||
|
|
||||||
|
const clen = m.byteLength + sodium.crypto_aead_chacha20poly1305_ietf_ABYTES
|
||||||
|
const c1 = sodium.sodium_malloc(clen)
|
||||||
|
const c2 = sodium.sodium_malloc(clen)
|
||||||
|
|
||||||
|
const m1 = sodium.sodium_malloc(m.byteLength)
|
||||||
|
const m2 = sodium.sodium_malloc(m.byteLength)
|
||||||
|
|
||||||
|
t.is(sodium.crypto_aead_chacha20poly1305_ietf_encrypt(c1, m, null, null, nonce, key1), clen)
|
||||||
|
t.absent(c1.equals(c2))
|
||||||
|
t.absent(c1.equals(m))
|
||||||
|
t.is(sodium.crypto_aead_chacha20poly1305_ietf_encrypt(c2, m, null, null, nonce, key2), clen)
|
||||||
|
t.absent(c1.equals(c2))
|
||||||
|
t.absent(c2.equals(m))
|
||||||
|
|
||||||
|
t.exception.all(_ => sodium.crypto_aead_chacha20poly1305_ietf_decrypt(m1, null, c1, null, nonce, key2))
|
||||||
|
t.exception.all(_ => sodium.crypto_aead_chacha20poly1305_ietf_decrypt(m2, null, c2, null, nonce, key1))
|
||||||
|
|
||||||
|
t.is(sodium.crypto_aead_chacha20poly1305_ietf_decrypt(m1, null, c1, null, nonce, key1), m.byteLength)
|
||||||
|
t.ok(m.equals(m1))
|
||||||
|
t.is(sodium.crypto_aead_chacha20poly1305_ietf_decrypt(m2, null, c2, null, nonce, key2), m.byteLength)
|
||||||
|
t.ok(m.equals(m2))
|
||||||
|
})
|
||||||
|
|
||||||
|
test.skip('different nonce', function (t) {
|
||||||
|
const m = b4a.from('Ladies and Gentlemen of the class of \'99: If I could offer you only one tip for the future, sunscreen would be it.')
|
||||||
|
|
||||||
|
const key = sodium.sodium_malloc(sodium.crypto_aead_chacha20poly1305_ietf_KEYBYTES)
|
||||||
|
sodium.crypto_aead_chacha20poly1305_ietf_keygen(key)
|
||||||
|
|
||||||
|
const n1 = sodium.sodium_malloc(sodium.crypto_aead_chacha20poly1305_ietf_NPUBBYTES)
|
||||||
|
const n2 = sodium.sodium_malloc(sodium.crypto_aead_chacha20poly1305_ietf_NPUBBYTES)
|
||||||
|
sodium.randombytes_buf(n1)
|
||||||
|
sodium.randombytes_buf(n2)
|
||||||
|
|
||||||
|
const clen = m.byteLength + sodium.crypto_aead_chacha20poly1305_ietf_ABYTES
|
||||||
|
const c1 = sodium.sodium_malloc(clen)
|
||||||
|
const c2 = sodium.sodium_malloc(clen)
|
||||||
|
|
||||||
|
const m1 = sodium.sodium_malloc(m.byteLength)
|
||||||
|
const m2 = sodium.sodium_malloc(m.byteLength)
|
||||||
|
|
||||||
|
t.is(sodium.crypto_aead_chacha20poly1305_ietf_encrypt(c1, m, null, null, n1, key), clen)
|
||||||
|
t.absent(c1.equals(c2))
|
||||||
|
t.absent(c1.equals(m))
|
||||||
|
t.is(sodium.crypto_aead_chacha20poly1305_ietf_encrypt(c2, m, null, null, n2, key), clen)
|
||||||
|
t.absent(c1.equals(c2))
|
||||||
|
t.absent(c2.equals(m))
|
||||||
|
|
||||||
|
t.exception.all(_ => sodium.crypto_aead_chacha20poly1305_ietf_decrypt(m1, null, c1, null, n2, key))
|
||||||
|
t.exception.all(_ => sodium.crypto_aead_chacha20poly1305_ietf_decrypt(m2, null, c2, null, n1, key))
|
||||||
|
|
||||||
|
t.is(sodium.crypto_aead_chacha20poly1305_ietf_decrypt(m1, null, c1, null, n1, key), m.byteLength)
|
||||||
|
t.ok(m.equals(m1))
|
||||||
|
t.is(sodium.crypto_aead_chacha20poly1305_ietf_decrypt(m2, null, c2, null, n2, key), m.byteLength)
|
||||||
|
t.ok(m.equals(m2))
|
||||||
|
})
|
||||||
|
|
||||||
|
test.skip('detached -> non-detached', function (t) {
|
||||||
|
const m = b4a.from('Ladies and Gentlemen of the class of \'99: If I could offer you only one tip for the future, sunscreen would be it.')
|
||||||
|
m.secure = true
|
||||||
|
|
||||||
|
const key = sodium.sodium_malloc(sodium.crypto_aead_chacha20poly1305_ietf_KEYBYTES)
|
||||||
|
sodium.crypto_aead_chacha20poly1305_ietf_keygen(key)
|
||||||
|
|
||||||
|
const nonce = sodium.sodium_malloc(sodium.crypto_aead_chacha20poly1305_ietf_NPUBBYTES)
|
||||||
|
sodium.randombytes_buf(nonce)
|
||||||
|
|
||||||
|
const mac = sodium.sodium_malloc(sodium.crypto_aead_chacha20poly1305_ietf_ABYTES)
|
||||||
|
const clen = m.byteLength
|
||||||
|
const c = sodium.sodium_malloc(clen)
|
||||||
|
|
||||||
|
t.is(sodium.crypto_aead_chacha20poly1305_ietf_encrypt_detached(c, mac, m, null, null, nonce, key), mac.byteLength)
|
||||||
|
|
||||||
|
const m1 = sodium.sodium_malloc(m.byteLength)
|
||||||
|
t.is(sodium.crypto_aead_chacha20poly1305_ietf_decrypt(m1, null, b4a.concat([c, mac]), null, nonce, key), m.byteLength)
|
||||||
|
|
||||||
|
t.alike(m, m1)
|
||||||
|
})
|
||||||
|
|
||||||
|
test.skip('non-detached -> detached', function (t) {
|
||||||
|
const m = b4a.from('Ladies and Gentlemen of the class of \'99: If I could offer you only one tip for the future, sunscreen would be it.')
|
||||||
|
m.secure = true
|
||||||
|
|
||||||
|
const key = sodium.sodium_malloc(sodium.crypto_aead_chacha20poly1305_ietf_KEYBYTES)
|
||||||
|
sodium.crypto_aead_chacha20poly1305_ietf_keygen(key)
|
||||||
|
|
||||||
|
const nonce = sodium.sodium_malloc(sodium.crypto_aead_chacha20poly1305_ietf_NPUBBYTES)
|
||||||
|
sodium.randombytes_buf(nonce)
|
||||||
|
|
||||||
|
const clen = m.byteLength + sodium.crypto_aead_chacha20poly1305_ietf_ABYTES
|
||||||
|
const c = sodium.sodium_malloc(clen)
|
||||||
|
|
||||||
|
t.is(sodium.crypto_aead_chacha20poly1305_ietf_encrypt(c, m, null, null, nonce, key), c.byteLength)
|
||||||
|
|
||||||
|
const m1 = sodium.sodium_malloc(m.byteLength)
|
||||||
|
const csub = c.subarray(0, clen - sodium.crypto_aead_chacha20poly1305_ietf_ABYTES)
|
||||||
|
const macsub = c.subarray(csub.byteLength)
|
||||||
|
sodium.crypto_aead_chacha20poly1305_ietf_decrypt_detached(m1, null, csub, macsub, null, nonce, key)
|
||||||
|
|
||||||
|
t.alike(m, m1)
|
||||||
|
})
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Need to test in-place encryption
|
||||||
|
* detach can talk to non detach
|
||||||
|
* encrypt - decrypt
|
||||||
|
* different nonce
|
||||||
|
* different key
|
||||||
|
* return values
|
||||||
|
*/
|
219
test/crypto_auth.js
Normal file
219
test/crypto_auth.js
Normal file
@ -0,0 +1,219 @@
|
|||||||
|
/* eslint-disable camelcase */
|
||||||
|
const test = require('brittle')
|
||||||
|
const sodium = require('..')
|
||||||
|
|
||||||
|
test('crypto_auth', function (t) {
|
||||||
|
const key = Buffer.alloc(sodium.crypto_auth_KEYBYTES)
|
||||||
|
sodium.randombytes_buf(key)
|
||||||
|
|
||||||
|
const mac = Buffer.alloc(sodium.crypto_auth_BYTES)
|
||||||
|
const value = Buffer.from('Hej, Verden')
|
||||||
|
|
||||||
|
sodium.crypto_auth(mac, value, key)
|
||||||
|
|
||||||
|
t.not(mac, Buffer.alloc(mac.length), 'mac not blank')
|
||||||
|
t.absent(sodium.crypto_auth_verify(Buffer.alloc(mac.length), value, key), 'does not verify')
|
||||||
|
t.ok(sodium.crypto_auth_verify(mac, value, key), 'verifies')
|
||||||
|
})
|
||||||
|
|
||||||
|
test('crypto_auth #1', t => {
|
||||||
|
// "Test Case 2" from RFC 4231
|
||||||
|
const key = stringToArray('Jefe', 32)
|
||||||
|
const c = stringToArray('what do ya want for nothing?')
|
||||||
|
const c1 = stringToArray('wwhat do ya want for nothing')
|
||||||
|
|
||||||
|
const a = new Uint8Array(sodium.crypto_auth_BYTES)
|
||||||
|
|
||||||
|
const exp = [
|
||||||
|
new Uint8Array([
|
||||||
|
0x16, 0x4b, 0x7a, 0x7b, 0xfc, 0xf8, 0x19, 0xe2,
|
||||||
|
0xe3, 0x95, 0xfb, 0xe7, 0x3b, 0x56, 0xe0, 0xa3,
|
||||||
|
0x87, 0xbd, 0x64, 0x22, 0x2e, 0x83, 0x1f, 0xd6,
|
||||||
|
0x10, 0x27, 0x0c, 0xd7, 0xea, 0x25, 0x05, 0x54
|
||||||
|
]),
|
||||||
|
new Uint8Array([
|
||||||
|
0x7b, 0x9d, 0x83, 0x38, 0xeb, 0x1e, 0x3d, 0xdd,
|
||||||
|
0xba, 0x8a, 0x9a, 0x35, 0x08, 0xd0, 0x34, 0xa1,
|
||||||
|
0xec, 0xbe, 0x75, 0x11, 0x37, 0xfa, 0x1b, 0xcb,
|
||||||
|
0xa0, 0xf9, 0x2a, 0x3e, 0x6d, 0xfc, 0x79, 0x80
|
||||||
|
]),
|
||||||
|
new Uint8Array([
|
||||||
|
0xb9, 0xd1, 0x4c, 0x51, 0xa6, 0xd4, 0xdd, 0x41,
|
||||||
|
0x60, 0x4e, 0xb0, 0x6c, 0x9c, 0x24, 0x0f, 0x1f,
|
||||||
|
0x64, 0xf1, 0x43, 0xb5, 0xcf, 0xde, 0xa3, 0x71,
|
||||||
|
0x29, 0xb2, 0x8b, 0xb7, 0x5d, 0x13, 0x71, 0xd3
|
||||||
|
])
|
||||||
|
]
|
||||||
|
|
||||||
|
sodium.crypto_auth(a, c, key)
|
||||||
|
t.alike(a, exp[0])
|
||||||
|
t.ok(sodium.crypto_auth_verify(exp[0], c, key))
|
||||||
|
|
||||||
|
a.fill(0)
|
||||||
|
sodium.crypto_auth(a, c1, key)
|
||||||
|
t.alike(a, exp[1])
|
||||||
|
t.ok(sodium.crypto_auth_verify(exp[1], c1, key))
|
||||||
|
|
||||||
|
// Empty message tests
|
||||||
|
a.fill(0)
|
||||||
|
sodium.crypto_auth(a, new Uint8Array(0), key)
|
||||||
|
t.alike(a, exp[2])
|
||||||
|
t.ok(sodium.crypto_auth_verify(exp[2], new Uint8Array(0), key))
|
||||||
|
t.end()
|
||||||
|
})
|
||||||
|
|
||||||
|
test('crypto_auth', function (t) {
|
||||||
|
const key = stringToArray('Jefe', 32)
|
||||||
|
const c = stringToArray('what do ya want for nothing?')
|
||||||
|
const a = new Uint8Array(sodium.crypto_auth_BYTES)
|
||||||
|
const expected = new Uint8Array([
|
||||||
|
0x16, 0x4b, 0x7a, 0x7b, 0xfc, 0xf8, 0x19, 0xe2, 0xe3, 0x95, 0xfb, 0xe7,
|
||||||
|
0x3b, 0x56, 0xe0, 0xa3, 0x87, 0xbd, 0x64, 0x22, 0x2e, 0x83, 0x1f, 0xd6,
|
||||||
|
0x10, 0x27, 0x0c, 0xd7, 0xea, 0x25, 0x05, 0x54
|
||||||
|
])
|
||||||
|
|
||||||
|
sodium.crypto_auth(a, c, key)
|
||||||
|
|
||||||
|
t.alike(a, expected)
|
||||||
|
t.ok(sodium.crypto_auth_verify(a, c, key))
|
||||||
|
|
||||||
|
c[Math.floor(Math.random() * c.length)] += 1
|
||||||
|
t.absent(sodium.crypto_auth_verify(a, c, key))
|
||||||
|
|
||||||
|
t.end()
|
||||||
|
})
|
||||||
|
|
||||||
|
test('wrong keylength', t => {
|
||||||
|
const a = new Uint8Array(32)
|
||||||
|
const c = new Uint8Array(0)
|
||||||
|
|
||||||
|
for (let i = 0; i < 128; i++) {
|
||||||
|
if (i === 32) continue
|
||||||
|
const k = new Uint8Array(i)
|
||||||
|
try {
|
||||||
|
sodium.crypto_auth(a, c, k)
|
||||||
|
t.fail('failed on test #' + i)
|
||||||
|
} catch (e) {
|
||||||
|
try {
|
||||||
|
sodium.crypto_auth_verify(a, c, k)
|
||||||
|
t.fail('failed on test #' + i)
|
||||||
|
} catch (e) {
|
||||||
|
try {
|
||||||
|
sodium.crypto_auth_verify(k, c, a)
|
||||||
|
t.fail('failed on test #' + i)
|
||||||
|
} catch {}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
t.pass('should not accept bad input length')
|
||||||
|
t.end()
|
||||||
|
})
|
||||||
|
|
||||||
|
test('crypto_auth constants', t => {
|
||||||
|
t.is(sodium.crypto_auth_BYTES, 32)
|
||||||
|
t.is(sodium.crypto_auth_KEYBYTES, 32)
|
||||||
|
t.end()
|
||||||
|
})
|
||||||
|
|
||||||
|
test('rfc4231 test case #6', t => {
|
||||||
|
const keys = [
|
||||||
|
new Uint8Array([
|
||||||
|
0x0b, 0x0b, 0x0b, 0x0b, 0x0b, 0x0b, 0x0b, 0x0b,
|
||||||
|
0x0b, 0x0b, 0x0b, 0x0b, 0x0b, 0x0b, 0x0b, 0x0b,
|
||||||
|
0x0b, 0x0b, 0x0b, 0x0b, 0x00, 0x00, 0x00, 0x00,
|
||||||
|
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
|
||||||
|
]),
|
||||||
|
new Uint8Array([
|
||||||
|
0x4a, 0x65, 0x66, 0x65, 0x00, 0x00, 0x00, 0x00,
|
||||||
|
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||||
|
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||||
|
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
|
||||||
|
]),
|
||||||
|
new Uint8Array([
|
||||||
|
0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa,
|
||||||
|
0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa,
|
||||||
|
0xaa, 0xaa, 0xaa, 0xaa, 0x00, 0x00, 0x00, 0x00,
|
||||||
|
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
|
||||||
|
]),
|
||||||
|
new Uint8Array([
|
||||||
|
0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08,
|
||||||
|
0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f, 0x10,
|
||||||
|
0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17, 0x18,
|
||||||
|
0x19, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
|
||||||
|
])
|
||||||
|
]
|
||||||
|
|
||||||
|
const data = [
|
||||||
|
new Uint8Array([
|
||||||
|
0x48, 0x69, 0x20, 0x54, 0x68, 0x65, 0x72, 0x65
|
||||||
|
]),
|
||||||
|
new Uint8Array([
|
||||||
|
0x77, 0x68, 0x61, 0x74, 0x20, 0x64, 0x6f, 0x20,
|
||||||
|
0x79, 0x61, 0x20, 0x77, 0x61, 0x6e, 0x74, 0x20,
|
||||||
|
0x66, 0x6f, 0x72, 0x20, 0x6e, 0x6f, 0x74, 0x68,
|
||||||
|
0x69, 0x6e, 0x67, 0x3f
|
||||||
|
]),
|
||||||
|
new Uint8Array([
|
||||||
|
0xdd, 0xdd, 0xdd, 0xdd, 0xdd, 0xdd, 0xdd, 0xdd,
|
||||||
|
0xdd, 0xdd, 0xdd, 0xdd, 0xdd, 0xdd, 0xdd, 0xdd,
|
||||||
|
0xdd, 0xdd, 0xdd, 0xdd, 0xdd, 0xdd, 0xdd, 0xdd,
|
||||||
|
0xdd, 0xdd, 0xdd, 0xdd, 0xdd, 0xdd, 0xdd, 0xdd,
|
||||||
|
0xdd, 0xdd, 0xdd, 0xdd, 0xdd, 0xdd, 0xdd, 0xdd,
|
||||||
|
0xdd, 0xdd, 0xdd, 0xdd, 0xdd, 0xdd, 0xdd, 0xdd,
|
||||||
|
0xdd, 0xdd
|
||||||
|
]),
|
||||||
|
new Uint8Array([
|
||||||
|
0xcd, 0xcd, 0xcd, 0xcd, 0xcd, 0xcd, 0xcd, 0xcd,
|
||||||
|
0xcd, 0xcd, 0xcd, 0xcd, 0xcd, 0xcd, 0xcd, 0xcd,
|
||||||
|
0xcd, 0xcd, 0xcd, 0xcd, 0xcd, 0xcd, 0xcd, 0xcd,
|
||||||
|
0xcd, 0xcd, 0xcd, 0xcd, 0xcd, 0xcd, 0xcd, 0xcd,
|
||||||
|
0xcd, 0xcd, 0xcd, 0xcd, 0xcd, 0xcd, 0xcd, 0xcd,
|
||||||
|
0xcd, 0xcd, 0xcd, 0xcd, 0xcd, 0xcd, 0xcd, 0xcd,
|
||||||
|
0xcd, 0xcd
|
||||||
|
])
|
||||||
|
]
|
||||||
|
|
||||||
|
const exp = [
|
||||||
|
new Uint8Array([
|
||||||
|
0x87, 0xaa, 0x7c, 0xde, 0xa5, 0xef, 0x61, 0x9d,
|
||||||
|
0x4f, 0xf0, 0xb4, 0x24, 0x1a, 0x1d, 0x6c, 0xb0,
|
||||||
|
0x23, 0x79, 0xf4, 0xe2, 0xce, 0x4e, 0xc2, 0x78,
|
||||||
|
0x7a, 0xd0, 0xb3, 0x05, 0x45, 0xe1, 0x7c, 0xde
|
||||||
|
]),
|
||||||
|
new Uint8Array([
|
||||||
|
0x16, 0x4b, 0x7a, 0x7b, 0xfc, 0xf8, 0x19, 0xe2,
|
||||||
|
0xe3, 0x95, 0xfb, 0xe7, 0x3b, 0x56, 0xe0, 0xa3,
|
||||||
|
0x87, 0xbd, 0x64, 0x22, 0x2e, 0x83, 0x1f, 0xd6,
|
||||||
|
0x10, 0x27, 0x0c, 0xd7, 0xea, 0x25, 0x05, 0x54
|
||||||
|
]),
|
||||||
|
new Uint8Array([
|
||||||
|
0xfa, 0x73, 0xb0, 0x08, 0x9d, 0x56, 0xa2, 0x84,
|
||||||
|
0xef, 0xb0, 0xf0, 0x75, 0x6c, 0x89, 0x0b, 0xe9,
|
||||||
|
0xb1, 0xb5, 0xdb, 0xdd, 0x8e, 0xe8, 0x1a, 0x36,
|
||||||
|
0x55, 0xf8, 0x3e, 0x33, 0xb2, 0x27, 0x9d, 0x39
|
||||||
|
]),
|
||||||
|
new Uint8Array([
|
||||||
|
0xb0, 0xba, 0x46, 0x56, 0x37, 0x45, 0x8c, 0x69,
|
||||||
|
0x90, 0xe5, 0xa8, 0xc5, 0xf6, 0x1d, 0x4a, 0xf7,
|
||||||
|
0xe5, 0x76, 0xd9, 0x7f, 0xf9, 0x4b, 0x87, 0x2d,
|
||||||
|
0xe7, 0x6f, 0x80, 0x50, 0x36, 0x1e, 0xe3, 0xdb
|
||||||
|
])
|
||||||
|
]
|
||||||
|
|
||||||
|
const a = new Uint8Array(sodium.crypto_auth_BYTES)
|
||||||
|
|
||||||
|
for (let i = 0; i < keys.length; i++) {
|
||||||
|
sodium.crypto_auth(a, data[i], keys[i])
|
||||||
|
t.alike(a, exp[i])
|
||||||
|
t.ok(sodium.crypto_auth_verify(exp[i], data[i], keys[i]))
|
||||||
|
}
|
||||||
|
|
||||||
|
t.end()
|
||||||
|
})
|
||||||
|
|
||||||
|
function stringToArray (s, size = s.length) {
|
||||||
|
const array = new Uint8Array(size)
|
||||||
|
array.set(s.split('').map((c) => c.charCodeAt(0)))
|
||||||
|
return array
|
||||||
|
}
|
305
test/crypto_box.js
Normal file
305
test/crypto_box.js
Normal file
@ -0,0 +1,305 @@
|
|||||||
|
/* eslint-disable camelcase */
|
||||||
|
const test = require('brittle')
|
||||||
|
const sodium = require('..')
|
||||||
|
|
||||||
|
test('crypto_box_seed_keypair', function (t) {
|
||||||
|
const pk = Buffer.alloc(sodium.crypto_box_PUBLICKEYBYTES)
|
||||||
|
const sk = Buffer.alloc(sodium.crypto_box_SECRETKEYBYTES)
|
||||||
|
const seed = Buffer.alloc(sodium.crypto_box_SEEDBYTES, 'lo')
|
||||||
|
|
||||||
|
t.exception.all(function () {
|
||||||
|
sodium.crypto_box_seed_keypair()
|
||||||
|
}, 'should validate input')
|
||||||
|
|
||||||
|
t.exception.all(function () {
|
||||||
|
sodium.crypto_box_seed_keypair(Buffer.alloc(0), Buffer.alloc(0), Buffer.alloc(0))
|
||||||
|
}, 'should validate input length')
|
||||||
|
|
||||||
|
sodium.crypto_box_seed_keypair(pk, sk, seed)
|
||||||
|
|
||||||
|
const eSk = '8661a95d21b134adc02881022ad86d37f32a230d537b525b997bce27aa745afc'
|
||||||
|
const ePk = '425c5ba523e70411c77300bb48dd846562e6c1fcf0142d81d2567d650ce76c3b'
|
||||||
|
|
||||||
|
t.alike(pk.toString('hex'), ePk, 'seeded public key')
|
||||||
|
t.alike(sk.toString('hex'), eSk, 'seeded secret key')
|
||||||
|
})
|
||||||
|
|
||||||
|
test('crypto_box_keypair', function (t) {
|
||||||
|
const pk = Buffer.alloc(sodium.crypto_box_PUBLICKEYBYTES)
|
||||||
|
const sk = Buffer.alloc(sodium.crypto_box_SECRETKEYBYTES)
|
||||||
|
|
||||||
|
sodium.crypto_box_keypair(pk, sk)
|
||||||
|
|
||||||
|
t.not(pk, Buffer.alloc(pk.length), 'made public key')
|
||||||
|
t.not(sk, Buffer.alloc(sk.length), 'made secret key')
|
||||||
|
|
||||||
|
t.exception.all(function () {
|
||||||
|
sodium.crypto_box_keypair()
|
||||||
|
}, 'should validate input')
|
||||||
|
|
||||||
|
t.exception.all(function () {
|
||||||
|
sodium.crypto_box_keypair(Buffer.alloc(0), Buffer.alloc(0))
|
||||||
|
}, 'should validate input length')
|
||||||
|
})
|
||||||
|
|
||||||
|
test('crypto_box_detached', function (t) {
|
||||||
|
const pk = Buffer.alloc(sodium.crypto_box_PUBLICKEYBYTES)
|
||||||
|
const sk = Buffer.alloc(sodium.crypto_box_SECRETKEYBYTES)
|
||||||
|
const nonce = Buffer.alloc(sodium.crypto_box_NONCEBYTES)
|
||||||
|
|
||||||
|
sodium.crypto_box_keypair(pk, sk)
|
||||||
|
|
||||||
|
const message = Buffer.from('Hello, World!')
|
||||||
|
const mac = Buffer.alloc(sodium.crypto_box_MACBYTES)
|
||||||
|
const cipher = Buffer.alloc(message.length)
|
||||||
|
|
||||||
|
sodium.crypto_box_detached(cipher, mac, message, nonce, pk, sk)
|
||||||
|
|
||||||
|
t.not(cipher, Buffer.alloc(cipher.length), 'not blank')
|
||||||
|
|
||||||
|
const plain = Buffer.alloc(cipher.length)
|
||||||
|
t.absent(sodium.crypto_box_open_detached(plain, cipher, Buffer.alloc(mac.length), nonce, pk, sk), 'does not decrypt')
|
||||||
|
t.ok(sodium.crypto_box_open_detached(plain, cipher, mac, nonce, pk, sk), 'decrypts')
|
||||||
|
t.alike(plain, message, 'same message')
|
||||||
|
})
|
||||||
|
|
||||||
|
test('crypto_box_easy', function (t) {
|
||||||
|
const pk = Buffer.alloc(sodium.crypto_box_PUBLICKEYBYTES)
|
||||||
|
const sk = Buffer.alloc(sodium.crypto_box_SECRETKEYBYTES)
|
||||||
|
const nonce = Buffer.alloc(sodium.crypto_box_NONCEBYTES)
|
||||||
|
|
||||||
|
sodium.crypto_box_keypair(pk, sk)
|
||||||
|
|
||||||
|
const message = Buffer.from('Hello, World!')
|
||||||
|
const cipher = Buffer.alloc(message.length + sodium.crypto_box_MACBYTES)
|
||||||
|
|
||||||
|
sodium.crypto_box_easy(cipher, message, nonce, pk, sk)
|
||||||
|
|
||||||
|
t.not(cipher, Buffer.alloc(cipher.length), 'not blank')
|
||||||
|
|
||||||
|
const plain = Buffer.alloc(cipher.length - sodium.crypto_box_MACBYTES)
|
||||||
|
t.absent(sodium.crypto_box_open_easy(plain, Buffer.alloc(cipher.length), nonce, pk, sk), 'does not decrypt')
|
||||||
|
t.ok(sodium.crypto_box_open_easy(plain, cipher, nonce, pk, sk), 'decrypts')
|
||||||
|
t.alike(plain, message, 'same message')
|
||||||
|
})
|
||||||
|
|
||||||
|
test('crypto_box_seal', function (t) {
|
||||||
|
const pk = Buffer.alloc(sodium.crypto_box_PUBLICKEYBYTES)
|
||||||
|
const sk = Buffer.alloc(sodium.crypto_box_SECRETKEYBYTES)
|
||||||
|
|
||||||
|
sodium.crypto_box_keypair(pk, sk)
|
||||||
|
|
||||||
|
const pk2 = Buffer.alloc(sodium.crypto_box_PUBLICKEYBYTES)
|
||||||
|
const sk2 = Buffer.alloc(sodium.crypto_box_SECRETKEYBYTES)
|
||||||
|
|
||||||
|
sodium.crypto_box_keypair(pk2, sk2)
|
||||||
|
|
||||||
|
const message = Buffer.from('Hello, sealed World!')
|
||||||
|
const cipher = Buffer.alloc(message.length + sodium.crypto_box_SEALBYTES)
|
||||||
|
|
||||||
|
sodium.crypto_box_seal(cipher, message, pk)
|
||||||
|
t.not(cipher, message, 'did not encrypt!')
|
||||||
|
|
||||||
|
t.not(cipher, Buffer.alloc(cipher.length), 'not blank')
|
||||||
|
|
||||||
|
const plain = Buffer.alloc(cipher.length - sodium.crypto_box_SEALBYTES)
|
||||||
|
t.absent(sodium.crypto_box_seal_open(plain, cipher, pk2, sk2), 'does not decrypt')
|
||||||
|
t.ok(sodium.crypto_box_seal_open(plain, cipher, pk, sk), 'decrypts')
|
||||||
|
t.alike(plain, message, 'same message')
|
||||||
|
})
|
||||||
|
|
||||||
|
test('crypto_box_seal/crypto_box_seal_open self-decrypt', function (t) {
|
||||||
|
const pubKey = Buffer.alloc(sodium.crypto_box_PUBLICKEYBYTES)
|
||||||
|
const secret = Buffer.alloc(sodium.crypto_box_SECRETKEYBYTES)
|
||||||
|
|
||||||
|
sodium.crypto_box_keypair(pubKey, secret)
|
||||||
|
|
||||||
|
const msg = Buffer.from('hello world')
|
||||||
|
const cipher = Buffer.alloc(sodium.crypto_box_SEALBYTES + msg.length)
|
||||||
|
sodium.crypto_box_seal(cipher, msg, pubKey)
|
||||||
|
|
||||||
|
const out = Buffer.alloc(cipher.length - sodium.crypto_box_SEALBYTES)
|
||||||
|
sodium.crypto_box_seal_open(out, cipher, pubKey, secret)
|
||||||
|
t.alike(out.toString(), msg.toString())
|
||||||
|
t.end()
|
||||||
|
})
|
||||||
|
|
||||||
|
test('crypto_box_seal_open cross-decrypt', function (t) {
|
||||||
|
const pubKey = Buffer.from(
|
||||||
|
'e0bb844ae3f48bb04323c8dfe7c34cf86608db2e2112f927953060c80506287f', 'hex')
|
||||||
|
const secret = Buffer.from(
|
||||||
|
'036a9de1ecc9d152cf39fed1b3e15bf761ae39a299031adc011cc9809041abfa', 'hex')
|
||||||
|
const cipher = Buffer.from(
|
||||||
|
'249912e916ad8bcf96a3f9b750da2703' +
|
||||||
|
'2eccdf83b5cff0d6a59a8bbe0bcd5823' +
|
||||||
|
'5de9fbca55bd5416c754e5e0e0fe2f0c' +
|
||||||
|
'4e50df0cb302f1c4378f80', 'hex')
|
||||||
|
|
||||||
|
const out = Buffer.alloc(cipher.length - sodium.crypto_box_SEALBYTES)
|
||||||
|
sodium.crypto_box_seal_open(out, cipher, pubKey, secret)
|
||||||
|
t.alike(out.toString(), 'hello world')
|
||||||
|
t.end()
|
||||||
|
})
|
||||||
|
|
||||||
|
test('crypto_box_seed_keypair', function (t) {
|
||||||
|
const seed = Buffer.from([
|
||||||
|
0x77, 0x07, 0x6d, 0x0a, 0x73, 0x18, 0xa5,
|
||||||
|
0x7d, 0x3c, 0x16, 0xc1, 0x72, 0x51, 0xb2,
|
||||||
|
0x66, 0x45, 0xdf, 0x4c, 0x2f, 0x87, 0xeb,
|
||||||
|
0xc0, 0x99, 0x2a, 0xb1, 0x77, 0xfb, 0xa5,
|
||||||
|
0x1d, 0xb9, 0x2c, 0x2a
|
||||||
|
])
|
||||||
|
|
||||||
|
const expPk = Buffer.from([
|
||||||
|
0xed, 0x77, 0x49, 0xb4, 0xd9, 0x89, 0xf6, 0x95,
|
||||||
|
0x7f, 0x3b, 0xfd, 0xe6, 0xc5, 0x67, 0x67, 0xe9,
|
||||||
|
0x88, 0xe2, 0x1c, 0x9f, 0x87, 0x84, 0xd9, 0x1d,
|
||||||
|
0x61, 0x00, 0x11, 0xcd, 0x55, 0x3f, 0x9b, 0x06
|
||||||
|
])
|
||||||
|
|
||||||
|
const expSk = Buffer.from([
|
||||||
|
0xac, 0xcd, 0x44, 0xeb, 0x8e, 0x93, 0x31, 0x9c,
|
||||||
|
0x05, 0x70, 0xbc, 0x11, 0x00, 0x5c, 0x0e, 0x01,
|
||||||
|
0x89, 0xd3, 0x4f, 0xf0, 0x2f, 0x6c, 0x17, 0x77,
|
||||||
|
0x34, 0x11, 0xad, 0x19, 0x12, 0x93, 0xc9, 0x8f
|
||||||
|
])
|
||||||
|
|
||||||
|
const sk = Buffer.alloc(32)
|
||||||
|
const pk = Buffer.alloc(32)
|
||||||
|
|
||||||
|
sodium.crypto_box_seed_keypair(pk, sk, seed)
|
||||||
|
|
||||||
|
t.alike(pk, expPk)
|
||||||
|
t.alike(sk, expSk)
|
||||||
|
|
||||||
|
t.end()
|
||||||
|
})
|
||||||
|
|
||||||
|
test('crypto_box_easy', (t) => {
|
||||||
|
const alicesk = new Uint8Array([
|
||||||
|
0x77, 0x07, 0x6d, 0x0a, 0x73, 0x18, 0xa5, 0x7d, 0x3c, 0x16, 0xc1, 0x72,
|
||||||
|
0x51, 0xb2, 0x66, 0x45, 0xdf, 0x4c, 0x2f, 0x87, 0xeb, 0xc0, 0x99, 0x2a,
|
||||||
|
0xb1, 0x77, 0xfb, 0xa5, 0x1d, 0xb9, 0x2c, 0x2a
|
||||||
|
])
|
||||||
|
const bobpk = new Uint8Array([
|
||||||
|
0xde, 0x9e, 0xdb, 0x7d, 0x7b, 0x7d, 0xc1, 0xb4, 0xd3, 0x5b, 0x61, 0xc2,
|
||||||
|
0xec, 0xe4, 0x35, 0x37, 0x3f, 0x83, 0x43, 0xc8, 0x5b, 0x78, 0x67, 0x4d,
|
||||||
|
0xad, 0xfc, 0x7e, 0x14, 0x6f, 0x88, 0x2b, 0x4f
|
||||||
|
])
|
||||||
|
const nonce = new Uint8Array([
|
||||||
|
0x69, 0x69, 0x6e, 0xe9, 0x55, 0xb6, 0x2b, 0x73, 0xcd, 0x62, 0xbd, 0xa8,
|
||||||
|
0x75, 0xfc, 0x73, 0xd6, 0x82, 0x19, 0xe0, 0x03, 0x6b, 0x7a, 0x0b, 0x37
|
||||||
|
])
|
||||||
|
const m = new Uint8Array([
|
||||||
|
0xbe, 0x07, 0x5f, 0xc5, 0x3c, 0x81, 0xf2, 0xd5, 0xcf, 0x14, 0x13, 0x16,
|
||||||
|
0xeb, 0xeb, 0x0c, 0x7b, 0x52, 0x28, 0xc5, 0x2a, 0x4c, 0x62, 0xcb, 0xd4,
|
||||||
|
0x4b, 0x66, 0x84, 0x9b, 0x64, 0x24, 0x4f, 0xfc, 0xe5, 0xec, 0xba, 0xaf,
|
||||||
|
0x33, 0xbd, 0x75, 0x1a, 0x1a, 0xc7, 0x28, 0xd4, 0x5e, 0x6c, 0x61, 0x29,
|
||||||
|
0x6c, 0xdc, 0x3c, 0x01, 0x23, 0x35, 0x61, 0xf4, 0x1d, 0xb6, 0x6c, 0xce,
|
||||||
|
0x31, 0x4a, 0xdb, 0x31, 0x0e, 0x3b, 0xe8, 0x25, 0x0c, 0x46, 0xf0, 0x6d,
|
||||||
|
0xce, 0xea, 0x3a, 0x7f, 0xa1, 0x34, 0x80, 0x57, 0xe2, 0xf6, 0x55, 0x6a,
|
||||||
|
0xd6, 0xb1, 0x31, 0x8a, 0x02, 0x4a, 0x83, 0x8f, 0x21, 0xaf, 0x1f, 0xde,
|
||||||
|
0x04, 0x89, 0x77, 0xeb, 0x48, 0xf5, 0x9f, 0xfd, 0x49, 0x24, 0xca, 0x1c,
|
||||||
|
0x60, 0x90, 0x2e, 0x52, 0xf0, 0xa0, 0x89, 0xbc, 0x76, 0x89, 0x70, 0x40,
|
||||||
|
0xe0, 0x82, 0xf9, 0x37, 0x76, 0x38, 0x48, 0x64, 0x5e, 0x07, 0x05
|
||||||
|
])
|
||||||
|
|
||||||
|
const c = new Uint8Array(147)
|
||||||
|
sodium.crypto_box_easy(c, m, nonce, bobpk, alicesk)
|
||||||
|
|
||||||
|
const expected1 = new Uint8Array([
|
||||||
|
0xf3, 0xff, 0xc7, 0x70, 0x3f, 0x94, 0x00, 0xe5, 0x2a, 0x7d, 0xfb, 0x4b,
|
||||||
|
0x3d, 0x33, 0x05, 0xd9, 0x8e, 0x99, 0x3b, 0x9f, 0x48, 0x68, 0x12, 0x73,
|
||||||
|
0xc2, 0x96, 0x50, 0xba, 0x32, 0xfc, 0x76, 0xce, 0x48, 0x33, 0x2e, 0xa7,
|
||||||
|
0x16, 0x4d, 0x96, 0xa4, 0x47, 0x6f, 0xb8, 0xc5, 0x31, 0xa1, 0x18, 0x6a,
|
||||||
|
0xc0, 0xdf, 0xc1, 0x7c, 0x98, 0xdc, 0xe8, 0x7b, 0x4d, 0xa7, 0xf0, 0x11,
|
||||||
|
0xec, 0x48, 0xc9, 0x72, 0x71, 0xd2, 0xc2, 0x0f, 0x9b, 0x92, 0x8f, 0xe2,
|
||||||
|
0x27, 0x0d, 0x6f, 0xb8, 0x63, 0xd5, 0x17, 0x38, 0xb4, 0x8e, 0xee, 0xe3,
|
||||||
|
0x14, 0xa7, 0xcc, 0x8a, 0xb9, 0x32, 0x16, 0x45, 0x48, 0xe5, 0x26, 0xae,
|
||||||
|
0x90, 0x22, 0x43, 0x68, 0x51, 0x7a, 0xcf, 0xea, 0xbd, 0x6b, 0xb3, 0x73,
|
||||||
|
0x2b, 0xc0, 0xe9, 0xda, 0x99, 0x83, 0x2b, 0x61, 0xca, 0x01, 0xb6, 0xde,
|
||||||
|
0x56, 0x24, 0x4a, 0x9e, 0x88, 0xd5, 0xf9, 0xb3, 0x79, 0x73, 0xf6, 0x22,
|
||||||
|
0xa4, 0x3d, 0x14, 0xa6, 0x59, 0x9b, 0x1f, 0x65, 0x4c, 0xb4, 0x5a, 0x74,
|
||||||
|
0xe3, 0x55, 0xa5
|
||||||
|
])
|
||||||
|
|
||||||
|
t.alike(c, expected1, 'encrypts correctly')
|
||||||
|
|
||||||
|
// This test isn't found upstream, but it seems necessary to have at least
|
||||||
|
// one crypto_box_open_easy() working since the next test diverges.
|
||||||
|
const o = new Uint8Array(131)
|
||||||
|
t.ok(sodium.crypto_box_open_easy(o, expected1, nonce, bobpk, alicesk))
|
||||||
|
t.alike(o, m, 'decrypts correctly')
|
||||||
|
|
||||||
|
const guardPage = new Uint8Array(0)
|
||||||
|
|
||||||
|
t.execution(() => sodium.crypto_box_easy(
|
||||||
|
c.subarray(0, sodium.crypto_box_MACBYTES),
|
||||||
|
guardPage,
|
||||||
|
nonce,
|
||||||
|
bobpk,
|
||||||
|
alicesk
|
||||||
|
))
|
||||||
|
|
||||||
|
const expected2 = new Uint8Array([
|
||||||
|
0x25, 0x39, 0x12, 0x1d, 0x8e, 0x23, 0x4e, 0x65, 0x2d, 0x65, 0x1f, 0xa4,
|
||||||
|
0xc8, 0xcf, 0xf8, 0x80, 0x8e
|
||||||
|
])
|
||||||
|
|
||||||
|
t.alike(c.subarray(0, expected2.length), expected2)
|
||||||
|
|
||||||
|
t.ok(sodium.crypto_box_open_easy(
|
||||||
|
new Uint8Array(0),
|
||||||
|
c.subarray(0, sodium.crypto_box_MACBYTES),
|
||||||
|
nonce,
|
||||||
|
bobpk,
|
||||||
|
alicesk
|
||||||
|
))
|
||||||
|
|
||||||
|
c[Math.floor(Math.random() * sodium.crypto_box_MACBYTES)] += 1
|
||||||
|
|
||||||
|
t.absent(sodium.crypto_box_open_easy(new Uint8Array(0), c.subarray(0, sodium.crypto_box_MACBYTES), nonce, bobpk, alicesk))
|
||||||
|
|
||||||
|
t.end()
|
||||||
|
})
|
||||||
|
|
||||||
|
/* eslint-disable camelcase */
|
||||||
|
test('crypto_box_easy2', t => {
|
||||||
|
const alicepk = new Uint8Array(sodium.crypto_box_PUBLICKEYBYTES)
|
||||||
|
const alicesk = new Uint8Array(sodium.crypto_box_SECRETKEYBYTES)
|
||||||
|
const bobpk = new Uint8Array(sodium.crypto_box_PUBLICKEYBYTES)
|
||||||
|
const bobsk = new Uint8Array(sodium.crypto_box_SECRETKEYBYTES)
|
||||||
|
const nonce = new Uint8Array(sodium.crypto_box_NONCEBYTES)
|
||||||
|
const m_size = 7 + Math.floor(Math.random() * 1000)
|
||||||
|
const m = new Uint8Array(m_size)
|
||||||
|
const m2 = new Uint8Array(m_size)
|
||||||
|
const c = new Uint8Array(sodium.crypto_box_MACBYTES + m_size)
|
||||||
|
|
||||||
|
sodium.crypto_box_keypair(alicepk, alicesk)
|
||||||
|
sodium.crypto_box_keypair(bobpk, bobsk)
|
||||||
|
|
||||||
|
const mlen = Math.floor(Math.random() * m_size) + 1
|
||||||
|
sodium.randombytes_buf(m.subarray(0, mlen))
|
||||||
|
sodium.randombytes_buf(nonce.subarray(0, sodium.crypto_box_NONCEBYTES))
|
||||||
|
|
||||||
|
t.execution(() => sodium.crypto_box_easy(c.subarray(0, mlen + sodium.crypto_box_MACBYTES), m.subarray(0, mlen), nonce, bobpk, alicesk))
|
||||||
|
|
||||||
|
t.ok(sodium.crypto_box_open_easy(m2.subarray(0, mlen), c.subarray(0, mlen + sodium.crypto_box_MACBYTES), nonce, alicepk, bobsk))
|
||||||
|
t.alike(m.subarray(0, mlen), m2.subarray(0, mlen))
|
||||||
|
|
||||||
|
for (let i = sodium.crypto_box_MACBYTES; i < mlen + sodium.crypto_box_MACBYTES - 1; i++) {
|
||||||
|
if (sodium.crypto_box_open_easy(m2.subarray(0, i - sodium.crypto_box_MACBYTES), c.subarray(0, i), nonce, alicepk, bobsk)) {
|
||||||
|
t.fail('short open() should fail.')
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
c.set(m.subarray(0, mlen))
|
||||||
|
t.execution(() => sodium.crypto_box_easy(c.subarray(0, mlen + sodium.crypto_box_MACBYTES), c.subarray(0, mlen), nonce, bobpk, alicesk))
|
||||||
|
|
||||||
|
t.unlike(m.subarray(0, mlen), c.subarray(0, mlen))
|
||||||
|
t.unlike(m.subarray(0, mlen), c.subarray(sodium.crypto_box_MACBYTES, sodium.crypto_box_MACBYTES + mlen))
|
||||||
|
|
||||||
|
t.ok(sodium.crypto_box_open_easy(c.subarray(0, mlen), c.subarray(0, mlen + sodium.crypto_box_MACBYTES), nonce, alicepk, bobsk))
|
||||||
|
|
||||||
|
t.end()
|
||||||
|
})
|
133
test/crypto_generichash.js
Normal file
133
test/crypto_generichash.js
Normal file
@ -0,0 +1,133 @@
|
|||||||
|
/* eslint-disable camelcase */
|
||||||
|
const test = require('brittle')
|
||||||
|
const sodium = require('..')
|
||||||
|
|
||||||
|
test('crypto_generichash', function (t) {
|
||||||
|
const buf = Buffer.from('Hello, World!')
|
||||||
|
|
||||||
|
const out = Buffer.alloc(sodium.crypto_generichash_BYTES)
|
||||||
|
sodium.crypto_generichash(out, buf)
|
||||||
|
|
||||||
|
t.alike(out.toString('hex'), '511bc81dde11180838c562c82bb35f3223f46061ebde4a955c27b3f489cf1e03', 'hashed buffer')
|
||||||
|
|
||||||
|
const min = Buffer.alloc(sodium.crypto_generichash_BYTES_MIN)
|
||||||
|
sodium.crypto_generichash(min, buf)
|
||||||
|
|
||||||
|
t.alike(min.toString('hex'), '3895c59e4aeb0903396b5be3fbec69fe', 'hashed buffer min')
|
||||||
|
|
||||||
|
const max = Buffer.alloc(sodium.crypto_generichash_BYTES_MAX)
|
||||||
|
sodium.crypto_generichash(max, buf)
|
||||||
|
|
||||||
|
const res = '7dfdb888af71eae0e6a6b751e8e3413d767ef4fa52a7993daa9ef097f7aa3d949199c113caa37c94f80cf3b22f7d9d6e4f5def4ff927830cffe4857c34be3d89'
|
||||||
|
t.alike(max.toString('hex'), res, 'hashed buffer max')
|
||||||
|
})
|
||||||
|
|
||||||
|
test('crypto_generichash with key', function (t) {
|
||||||
|
const buf = Buffer.from('Hello, World!')
|
||||||
|
const key = Buffer.alloc(sodium.crypto_generichash_KEYBYTES)
|
||||||
|
|
||||||
|
key.fill('lo')
|
||||||
|
|
||||||
|
const out = Buffer.alloc(sodium.crypto_generichash_BYTES)
|
||||||
|
sodium.crypto_generichash(out, buf, key)
|
||||||
|
|
||||||
|
t.alike(out.toString('hex'), 'f4113fe33d43c24c54627d40efa1a78838d4a6d689fd6e83c213848904fffa8c', 'hashed buffer')
|
||||||
|
|
||||||
|
const min = Buffer.alloc(sodium.crypto_generichash_BYTES_MIN)
|
||||||
|
sodium.crypto_generichash(min, buf, key)
|
||||||
|
|
||||||
|
t.alike(min.toString('hex'), 'c8226257b0d1c3dcf4bbc3ef79574689', 'hashed buffer min')
|
||||||
|
|
||||||
|
const max = Buffer.alloc(sodium.crypto_generichash_BYTES_MAX)
|
||||||
|
sodium.crypto_generichash(max, buf, key)
|
||||||
|
|
||||||
|
const res = '763eda46f4c6c61abb4310eb8a488950e9e0667b2fca03c463dc7489e94f065b7af6063fe86b0441c3eb9052800121d55730412abb2cbe0761b1d66f9b047c1c'
|
||||||
|
t.alike(max.toString('hex'), res, 'hashed buffer max')
|
||||||
|
})
|
||||||
|
|
||||||
|
test.skip('crypto_generichash_state', function (t) {
|
||||||
|
const state = Buffer.alloc(sodium.crypto_generichash_STATEBYTES)
|
||||||
|
sodium.crypto_generichash_init(state, null, sodium.crypto_generichash_BYTES)
|
||||||
|
|
||||||
|
const buf = Buffer.from('Hej, Verden')
|
||||||
|
|
||||||
|
for (let i = 0; i < 10; i++) sodium.crypto_generichash_update(state, buf)
|
||||||
|
|
||||||
|
const out = Buffer.alloc(sodium.crypto_generichash_BYTES)
|
||||||
|
sodium.crypto_generichash_final(state, out)
|
||||||
|
|
||||||
|
t.alike(out.toString('hex'), 'cbc20f347f5dfe37dc13231cbf7eaa4ec48e585ec055a96839b213f62bd8ce00', 'streaming hash')
|
||||||
|
})
|
||||||
|
|
||||||
|
test.skip('crypto_generichash state with key', function (t) {
|
||||||
|
const key = Buffer.alloc(sodium.crypto_generichash_KEYBYTES)
|
||||||
|
key.fill('lo')
|
||||||
|
|
||||||
|
const state = Buffer.alloc(sodium.crypto_generichash_STATEBYTES)
|
||||||
|
sodium.crypto_generichash_init(state, key, sodium.crypto_generichash_BYTES)
|
||||||
|
|
||||||
|
const buf = Buffer.from('Hej, Verden')
|
||||||
|
|
||||||
|
for (let i = 0; i < 10; i++) sodium.crypto_generichash_update(state, buf)
|
||||||
|
|
||||||
|
const out = Buffer.alloc(sodium.crypto_generichash_BYTES)
|
||||||
|
sodium.crypto_generichash_final(state, out)
|
||||||
|
|
||||||
|
t.alike(out.toString('hex'), '405f14acbeeb30396b8030f78e6a84bab0acf08cb1376aa200a500f669f675dc', 'streaming keyed hash')
|
||||||
|
})
|
||||||
|
|
||||||
|
test.skip('crypto_generichash state with hash length', function (t) {
|
||||||
|
const state = Buffer.alloc(sodium.crypto_generichash_STATEBYTES)
|
||||||
|
sodium.crypto_generichash_init(state, null, sodium.crypto_generichash_BYTES_MIN)
|
||||||
|
|
||||||
|
const buf = Buffer.from('Hej, Verden')
|
||||||
|
|
||||||
|
for (let i = 0; i < 10; i++) sodium.crypto_generichash_update(state, buf)
|
||||||
|
|
||||||
|
const out = Buffer.alloc(sodium.crypto_generichash_BYTES_MIN)
|
||||||
|
sodium.crypto_generichash_final(state, out)
|
||||||
|
|
||||||
|
t.alike(out.toString('hex'), 'decacdcc3c61948c79d9f8dee5b6aa99', 'streaming short hash')
|
||||||
|
})
|
||||||
|
|
||||||
|
test.skip('crypto_generichash state with key and hash length', function (t) {
|
||||||
|
const key = Buffer.alloc(sodium.crypto_generichash_KEYBYTES)
|
||||||
|
key.fill('lo')
|
||||||
|
|
||||||
|
const state = Buffer.alloc(sodium.crypto_generichash_STATEBYTES)
|
||||||
|
sodium.crypto_generichash_init(state, key, sodium.crypto_generichash_BYTES_MIN)
|
||||||
|
|
||||||
|
const buf = Buffer.from('Hej, Verden')
|
||||||
|
|
||||||
|
for (let i = 0; i < 10; i++) sodium.crypto_generichash_update(state, buf)
|
||||||
|
|
||||||
|
const out = Buffer.alloc(sodium.crypto_generichash_BYTES_MIN)
|
||||||
|
sodium.crypto_generichash_final(state, out)
|
||||||
|
|
||||||
|
t.alike(out.toString('hex'), 'fb43f0ab6872cbfd39ec4f8a1bc6fb37', 'streaming short keyed hash')
|
||||||
|
})
|
||||||
|
|
||||||
|
test('crypto_generichash_batch', function (t) {
|
||||||
|
const buf = Buffer.from('Hej, Verden')
|
||||||
|
const batch = []
|
||||||
|
for (let i = 0; i < 10; i++) batch.push(buf)
|
||||||
|
|
||||||
|
const out = Buffer.alloc(sodium.crypto_generichash_BYTES)
|
||||||
|
sodium.crypto_generichash_batch(out, batch)
|
||||||
|
|
||||||
|
t.alike(out.toString('hex'), 'cbc20f347f5dfe37dc13231cbf7eaa4ec48e585ec055a96839b213f62bd8ce00', 'batch hash')
|
||||||
|
})
|
||||||
|
|
||||||
|
test('crypto_generichash_batch with key', function (t) {
|
||||||
|
const key = Buffer.alloc(sodium.crypto_generichash_KEYBYTES)
|
||||||
|
key.fill('lo')
|
||||||
|
|
||||||
|
const buf = Buffer.from('Hej, Verden')
|
||||||
|
const batch = []
|
||||||
|
for (let i = 0; i < 10; i++) batch.push(buf)
|
||||||
|
|
||||||
|
const out = Buffer.alloc(sodium.crypto_generichash_BYTES)
|
||||||
|
sodium.crypto_generichash_batch(out, batch, key)
|
||||||
|
|
||||||
|
t.alike(out.toString('hex'), '405f14acbeeb30396b8030f78e6a84bab0acf08cb1376aa200a500f669f675dc', 'batch keyed hash')
|
||||||
|
})
|
17
test/crypto_hash.js
Normal file
17
test/crypto_hash.js
Normal file
@ -0,0 +1,17 @@
|
|||||||
|
/* eslint-disable camelcase */
|
||||||
|
const test = require('brittle')
|
||||||
|
const sodium = require('..')
|
||||||
|
|
||||||
|
test('crypto_hash', function (t) {
|
||||||
|
const out = Buffer.alloc(sodium.crypto_hash_BYTES)
|
||||||
|
const inp = Buffer.from('Hej, Verden!')
|
||||||
|
|
||||||
|
t.exception.all(function () {
|
||||||
|
sodium.crypto_hash(Buffer.alloc(0), inp)
|
||||||
|
}, 'throws on bad input')
|
||||||
|
|
||||||
|
sodium.crypto_hash(out, inp)
|
||||||
|
|
||||||
|
const result = 'bcf8e6d11dec2da6e93abb99a73c8e9c387886a5f84fbca5e25af85af26ee39161b7e0c9f9cf547f2aef40523f1aab80e26ec3c630db43ce78adc8c058dc5d16'
|
||||||
|
t.alike(out.toString('hex'), result, 'hashed the string')
|
||||||
|
})
|
32
test/crypto_hash_sha256.js
Normal file
32
test/crypto_hash_sha256.js
Normal file
@ -0,0 +1,32 @@
|
|||||||
|
/* eslint-disable camelcase */
|
||||||
|
const test = require('brittle')
|
||||||
|
const sodium = require('..')
|
||||||
|
|
||||||
|
test('crypto_hash_sha256', function (t) {
|
||||||
|
const out = Buffer.alloc(sodium.crypto_hash_sha256_BYTES)
|
||||||
|
const inp = Buffer.from('Hej, Verden!')
|
||||||
|
|
||||||
|
t.exception.all(function () {
|
||||||
|
sodium.crypto_hash(Buffer.alloc(0), inp)
|
||||||
|
}, 'throws on bad input')
|
||||||
|
|
||||||
|
sodium.crypto_hash_sha256(out, inp)
|
||||||
|
|
||||||
|
const result = 'f0704b1e832b05d01223952fb2512181af4f843ce7bb6b443afd5ea028010e6c'
|
||||||
|
t.alike(out.toString('hex'), result, 'hashed the string')
|
||||||
|
})
|
||||||
|
|
||||||
|
test.skip('crypto_hash_sha256_state', function (t) {
|
||||||
|
const state = Buffer.alloc(sodium.crypto_hash_sha256_STATEBYTES)
|
||||||
|
sodium.crypto_hash_sha256_init(state)
|
||||||
|
|
||||||
|
const buf = Buffer.from('Hej, Verden!')
|
||||||
|
|
||||||
|
for (let i = 0; i < 10; i++) sodium.crypto_hash_sha256_update(state, buf)
|
||||||
|
|
||||||
|
const out = Buffer.alloc(sodium.crypto_hash_sha256_BYTES)
|
||||||
|
sodium.crypto_hash_sha256_final(state, out)
|
||||||
|
|
||||||
|
const result = '14207db33c6ac7d39ca5fe0e74432fa7a2ed15caf7f6ab5ef68d24017a899974'
|
||||||
|
t.alike(out.toString('hex'), result, 'hashed the string')
|
||||||
|
})
|
32
test/crypto_hash_sha512.js
Normal file
32
test/crypto_hash_sha512.js
Normal file
@ -0,0 +1,32 @@
|
|||||||
|
/* eslint-disable camelcase */
|
||||||
|
const test = require('brittle')
|
||||||
|
const sodium = require('..')
|
||||||
|
|
||||||
|
test('crypto_hash_sha512', function (t) {
|
||||||
|
const out = Buffer.alloc(sodium.crypto_hash_sha512_BYTES)
|
||||||
|
const inp = Buffer.from('Hej, Verden!')
|
||||||
|
|
||||||
|
t.exception.all(function () {
|
||||||
|
sodium.crypto_hash(Buffer.alloc(0), inp)
|
||||||
|
}, 'throws on bad input')
|
||||||
|
|
||||||
|
sodium.crypto_hash_sha512(out, inp)
|
||||||
|
|
||||||
|
const result = 'bcf8e6d11dec2da6e93abb99a73c8e9c387886a5f84fbca5e25af85af26ee39161b7e0c9f9cf547f2aef40523f1aab80e26ec3c630db43ce78adc8c058dc5d16'
|
||||||
|
t.alike(out.toString('hex'), result, 'hashed the string')
|
||||||
|
})
|
||||||
|
|
||||||
|
test.skip('crypto_hash_sha512_state', function (t) {
|
||||||
|
const state = Buffer.alloc(sodium.crypto_hash_sha512_STATEBYTES)
|
||||||
|
sodium.crypto_hash_sha512_init(state)
|
||||||
|
|
||||||
|
const buf = Buffer.from('Hej, Verden!')
|
||||||
|
|
||||||
|
for (let i = 0; i < 10; i++) sodium.crypto_hash_sha512_update(state, buf)
|
||||||
|
|
||||||
|
const out = Buffer.alloc(sodium.crypto_hash_sha512_BYTES)
|
||||||
|
sodium.crypto_hash_sha512_final(state, out)
|
||||||
|
|
||||||
|
const result = 'a0a9b965c23be41fa8c344f483da39bedcf88b7f25cdc0bc9ea335fa264dc3db51f08c1d0f5f6f0ffb08a1d8643e2a1cd0ea8f03408ca03711c751d61787a229'
|
||||||
|
t.alike(out.toString('hex'), result, 'hashed the string')
|
||||||
|
})
|
71
test/crypto_kdf.js
Normal file
71
test/crypto_kdf.js
Normal file
@ -0,0 +1,71 @@
|
|||||||
|
/* eslint-disable camelcase */
|
||||||
|
const test = require('brittle')
|
||||||
|
const sodium = require('..')
|
||||||
|
|
||||||
|
test('crypto_kdf_keygen', function (t) {
|
||||||
|
const key = Buffer.alloc(sodium.crypto_kdf_KEYBYTES)
|
||||||
|
|
||||||
|
t.exception.all(function () {
|
||||||
|
sodium.crypto_kdf_keygen(Buffer.alloc(1))
|
||||||
|
})
|
||||||
|
|
||||||
|
sodium.crypto_kdf_keygen(key)
|
||||||
|
|
||||||
|
t.not(key, Buffer.alloc(key.length))
|
||||||
|
})
|
||||||
|
|
||||||
|
test('crypto_kdf_derive_from_key', function (t) {
|
||||||
|
const key = Buffer.alloc(sodium.crypto_kdf_KEYBYTES)
|
||||||
|
|
||||||
|
sodium.crypto_kdf_keygen(key)
|
||||||
|
|
||||||
|
const subkey = Buffer.alloc(sodium.crypto_kdf_BYTES_MIN)
|
||||||
|
|
||||||
|
sodium.crypto_kdf_derive_from_key(subkey, 0, Buffer.from('context_'), key)
|
||||||
|
t.not(subkey, Buffer.alloc(subkey.length))
|
||||||
|
|
||||||
|
const subkey2 = Buffer.alloc(sodium.crypto_kdf_BYTES_MIN)
|
||||||
|
|
||||||
|
sodium.crypto_kdf_derive_from_key(subkey2, 1, Buffer.from('context_'), key)
|
||||||
|
t.not(subkey, subkey2)
|
||||||
|
|
||||||
|
sodium.crypto_kdf_derive_from_key(subkey2, 0, Buffer.from('context_'), key)
|
||||||
|
t.alike(subkey, subkey2)
|
||||||
|
})
|
||||||
|
|
||||||
|
test('test vectors', function (assert) {
|
||||||
|
const fixtures = require('./fixtures/crypto_kdf.json')
|
||||||
|
|
||||||
|
for (let i = 0; i < fixtures.length; i++) {
|
||||||
|
const key = Buffer.from(fixtures[i].key, 'hex')
|
||||||
|
const subkeyLen = fixtures[i].subkey_len
|
||||||
|
const id = fixtures[i].id
|
||||||
|
const context = Buffer.from(fixtures[i].context, 'hex')
|
||||||
|
|
||||||
|
const shouldError = fixtures[i].error
|
||||||
|
|
||||||
|
const actual = Buffer.alloc(subkeyLen)
|
||||||
|
|
||||||
|
try {
|
||||||
|
sodium.crypto_kdf_derive_from_key(actual, id, context, key)
|
||||||
|
const expected = Buffer.from(fixtures[i].subkey, 'hex')
|
||||||
|
if (Buffer.compare(actual, expected) !== 0) {
|
||||||
|
assert.fail('Failed on fixture #' + i)
|
||||||
|
}
|
||||||
|
} catch (ex) {
|
||||||
|
if (shouldError === false) assert.fail('Failed on fixture #' + i)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
assert.pass('Passed all fixtures')
|
||||||
|
assert.end()
|
||||||
|
})
|
||||||
|
|
||||||
|
test('constants', function (t) {
|
||||||
|
t.ok(sodium.crypto_kdf_PRIMITIVE)
|
||||||
|
t.ok(sodium.crypto_kdf_BYTES_MAX > 0)
|
||||||
|
t.ok(sodium.crypto_kdf_BYTES_MIN <= sodium.crypto_kdf_BYTES_MAX)
|
||||||
|
t.ok(sodium.crypto_kdf_CONTEXTBYTES > 0)
|
||||||
|
t.ok(sodium.crypto_kdf_KEYBYTES >= 16)
|
||||||
|
t.end()
|
||||||
|
})
|
265
test/crypto_kx.js
Normal file
265
test/crypto_kx.js
Normal file
@ -0,0 +1,265 @@
|
|||||||
|
/* eslint-disable camelcase */
|
||||||
|
const test = require('brittle')
|
||||||
|
const sodium = require('..')
|
||||||
|
|
||||||
|
test('crypto_kx_seed_keypair', function (t) {
|
||||||
|
const pk = Buffer.alloc(sodium.crypto_kx_PUBLICKEYBYTES)
|
||||||
|
const sk = Buffer.alloc(sodium.crypto_kx_SECRETKEYBYTES)
|
||||||
|
const seed = Buffer.alloc(sodium.crypto_kx_SEEDBYTES, 'lo')
|
||||||
|
|
||||||
|
t.exception.all(function () {
|
||||||
|
sodium.crypto_kx_seed_keypair()
|
||||||
|
}, 'should validate input')
|
||||||
|
|
||||||
|
t.exception.all(function () {
|
||||||
|
sodium.crypto_kx_seed_keypair(Buffer.alloc(0), Buffer.alloc(0), Buffer.alloc(0))
|
||||||
|
}, 'should validate input length')
|
||||||
|
|
||||||
|
sodium.crypto_kx_seed_keypair(pk, sk, seed)
|
||||||
|
|
||||||
|
const eSk = '768475983073421d5b1676c4aabb24fdf17c3a5f19e6e9e9cdefbfeb45ceb153'
|
||||||
|
const ePk = '0cd703bbd6b1d46dc431a1fc4f1f7724c64b1d4c471e8c17de4966c9e15bf85e'
|
||||||
|
|
||||||
|
t.alike(pk.toString('hex'), ePk, 'seeded public key')
|
||||||
|
t.alike(sk.toString('hex'), eSk, 'seeded secret key')
|
||||||
|
})
|
||||||
|
|
||||||
|
test('crypto_kx_keypair', function (t) {
|
||||||
|
const pk = Buffer.alloc(sodium.crypto_kx_PUBLICKEYBYTES)
|
||||||
|
const sk = Buffer.alloc(sodium.crypto_kx_SECRETKEYBYTES)
|
||||||
|
|
||||||
|
sodium.crypto_kx_keypair(pk, sk)
|
||||||
|
|
||||||
|
t.not(pk, Buffer.alloc(pk.length), 'made public key')
|
||||||
|
t.not(sk, Buffer.alloc(sk.length), 'made secret key')
|
||||||
|
|
||||||
|
t.exception.all(function () {
|
||||||
|
sodium.crypto_kx_keypair()
|
||||||
|
}, 'should validate input')
|
||||||
|
|
||||||
|
t.exception.all(function () {
|
||||||
|
sodium.crypto_kx_keypair(Buffer.alloc(0), Buffer.alloc(0))
|
||||||
|
}, 'should validate input length')
|
||||||
|
})
|
||||||
|
|
||||||
|
test.skip('crypto_kx_client_session_keys', function (t) {
|
||||||
|
const clientPk = Buffer.alloc(sodium.crypto_kx_PUBLICKEYBYTES)
|
||||||
|
const clientSk = Buffer.alloc(sodium.crypto_kx_SECRETKEYBYTES)
|
||||||
|
const serverPk = Buffer.alloc(sodium.crypto_kx_PUBLICKEYBYTES)
|
||||||
|
const serverSk = Buffer.alloc(sodium.crypto_kx_SECRETKEYBYTES)
|
||||||
|
|
||||||
|
const serverRx = Buffer.alloc(sodium.crypto_kx_SESSIONKEYBYTES)
|
||||||
|
const serverTx = Buffer.alloc(sodium.crypto_kx_SESSIONKEYBYTES)
|
||||||
|
|
||||||
|
const clientRx = Buffer.alloc(sodium.crypto_kx_SESSIONKEYBYTES)
|
||||||
|
const clientTx = Buffer.alloc(sodium.crypto_kx_SESSIONKEYBYTES)
|
||||||
|
|
||||||
|
sodium.crypto_kx_keypair(serverPk, serverSk)
|
||||||
|
sodium.crypto_kx_keypair(clientPk, clientSk)
|
||||||
|
|
||||||
|
t.exception.all(function () {
|
||||||
|
sodium.crypto_kx_client_session_keys()
|
||||||
|
}, 'should validate')
|
||||||
|
|
||||||
|
t.exception.all(function () {
|
||||||
|
sodium.crypto_kx_server_session_keys()
|
||||||
|
}, 'should validate')
|
||||||
|
|
||||||
|
sodium.crypto_kx_client_session_keys(clientRx, clientTx, clientPk, clientSk, serverPk)
|
||||||
|
sodium.crypto_kx_server_session_keys(serverRx, serverTx, serverPk, serverSk, clientPk)
|
||||||
|
|
||||||
|
t.alike(clientRx, serverTx)
|
||||||
|
t.alike(clientTx, serverRx)
|
||||||
|
})
|
||||||
|
|
||||||
|
test.skip('crypto_kx_client_session_keys one NULL', function (t) {
|
||||||
|
const clientPk = Buffer.alloc(sodium.crypto_kx_PUBLICKEYBYTES)
|
||||||
|
const clientSk = Buffer.alloc(sodium.crypto_kx_SECRETKEYBYTES)
|
||||||
|
const serverPk = Buffer.alloc(sodium.crypto_kx_PUBLICKEYBYTES)
|
||||||
|
const serverSk = Buffer.alloc(sodium.crypto_kx_SECRETKEYBYTES)
|
||||||
|
|
||||||
|
const serverRx = Buffer.alloc(sodium.crypto_kx_SESSIONKEYBYTES)
|
||||||
|
const serverTx = Buffer.alloc(sodium.crypto_kx_SESSIONKEYBYTES)
|
||||||
|
|
||||||
|
const clientRx = Buffer.alloc(sodium.crypto_kx_SESSIONKEYBYTES)
|
||||||
|
const clientTx = Buffer.alloc(sodium.crypto_kx_SESSIONKEYBYTES)
|
||||||
|
|
||||||
|
sodium.crypto_kx_keypair(serverPk, serverSk)
|
||||||
|
sodium.crypto_kx_keypair(clientPk, clientSk)
|
||||||
|
|
||||||
|
t.exception.all(function () {
|
||||||
|
sodium.crypto_kx_client_session_keys()
|
||||||
|
}, 'should validate')
|
||||||
|
|
||||||
|
t.exception.all(function () {
|
||||||
|
sodium.crypto_kx_server_session_keys()
|
||||||
|
}, 'should validate')
|
||||||
|
|
||||||
|
t.exception(function () {
|
||||||
|
sodium.crypto_kx_server_session_keys(null, null, clientPk, clientSk, serverPk)
|
||||||
|
}, 'should validate')
|
||||||
|
|
||||||
|
t.exception(function () {
|
||||||
|
sodium.crypto_kx_client_session_keys(null, null, clientPk, clientSk, serverPk)
|
||||||
|
}, 'should validate')
|
||||||
|
|
||||||
|
sodium.crypto_kx_client_session_keys(clientRx, null, clientPk, clientSk, serverPk)
|
||||||
|
sodium.crypto_kx_server_session_keys(null, serverTx, serverPk, serverSk, clientPk)
|
||||||
|
|
||||||
|
t.alike(clientRx, serverTx)
|
||||||
|
|
||||||
|
sodium.crypto_kx_client_session_keys(null, clientTx, clientPk, clientSk, serverPk)
|
||||||
|
sodium.crypto_kx_server_session_keys(serverRx, null, serverPk, serverSk, clientPk)
|
||||||
|
t.alike(clientTx, serverRx)
|
||||||
|
})
|
||||||
|
|
||||||
|
test('crypto_kx constants', function (t) {
|
||||||
|
t.alike(typeof sodium.crypto_kx_SESSIONKEYBYTES, 'number')
|
||||||
|
t.alike(typeof sodium.crypto_kx_PUBLICKEYBYTES, 'number')
|
||||||
|
t.alike(typeof sodium.crypto_kx_SECRETKEYBYTES, 'number')
|
||||||
|
t.alike(typeof sodium.crypto_kx_SEEDBYTES, 'number')
|
||||||
|
t.alike(typeof sodium.crypto_kx_PRIMITIVE, 'string')
|
||||||
|
|
||||||
|
t.is(sodium.crypto_kx_SEEDBYTES, 32)
|
||||||
|
t.is(sodium.crypto_kx_PUBLICKEYBYTES, 32)
|
||||||
|
t.is(sodium.crypto_kx_SESSIONKEYBYTES, 32)
|
||||||
|
t.is(sodium.crypto_kx_SECRETKEYBYTES, 32)
|
||||||
|
|
||||||
|
t.end()
|
||||||
|
})
|
||||||
|
|
||||||
|
/* eslint-disable camelcase */
|
||||||
|
test.skip('libsodium', function (t) {
|
||||||
|
const small_order_p = new Uint8Array([
|
||||||
|
0xe0, 0xeb, 0x7a, 0x7c, 0x3b, 0x41, 0xb8, 0xae, 0x16, 0x56, 0xe3,
|
||||||
|
0xfa, 0xf1, 0x9f, 0xc4, 0x6a, 0xda, 0x09, 0x8d, 0xeb, 0x9c, 0x32,
|
||||||
|
0xb1, 0xfd, 0x86, 0x62, 0x05, 0x16, 0x5f, 0x49, 0xb8, 0x00
|
||||||
|
])
|
||||||
|
|
||||||
|
const seed = new Uint8Array(sodium.crypto_kx_SEEDBYTES)
|
||||||
|
const client_pk = new Uint8Array(sodium.crypto_kx_PUBLICKEYBYTES)
|
||||||
|
const client_sk = new Uint8Array(sodium.crypto_kx_SECRETKEYBYTES)
|
||||||
|
const client_rx = new Uint8Array(sodium.crypto_kx_SESSIONKEYBYTES)
|
||||||
|
const client_tx = new Uint8Array(sodium.crypto_kx_SESSIONKEYBYTES)
|
||||||
|
const server_pk = new Uint8Array(sodium.crypto_kx_PUBLICKEYBYTES)
|
||||||
|
const server_sk = new Uint8Array(sodium.crypto_kx_SECRETKEYBYTES)
|
||||||
|
const server_rx = new Uint8Array(sodium.crypto_kx_SESSIONKEYBYTES)
|
||||||
|
const server_tx = new Uint8Array(sodium.crypto_kx_SESSIONKEYBYTES)
|
||||||
|
|
||||||
|
for (let i = 0; i < sodium.crypto_kx_SEEDBYTES; i++) {
|
||||||
|
seed[i] = i
|
||||||
|
}
|
||||||
|
|
||||||
|
sodium.crypto_kx_seed_keypair(client_pk, client_sk, seed)
|
||||||
|
|
||||||
|
const exp1 = new Uint8Array([
|
||||||
|
0x0e, 0x02, 0x16, 0x22, 0x3f, 0x14, 0x71, 0x43, 0xd3, 0x26, 0x15,
|
||||||
|
0xa9, 0x11, 0x89, 0xc2, 0x88, 0xc1, 0x72, 0x8c, 0xba, 0x3c, 0xc5,
|
||||||
|
0xf9, 0xf6, 0x21, 0xb1, 0x02, 0x6e, 0x03, 0xd8, 0x31, 0x29
|
||||||
|
])
|
||||||
|
|
||||||
|
const exp2 = new Uint8Array([
|
||||||
|
0xcb, 0x2f, 0x51, 0x60, 0xfc, 0x1f, 0x7e, 0x05, 0xa5, 0x5e, 0xf4,
|
||||||
|
0x9d, 0x34, 0x0b, 0x48, 0xda, 0x2e, 0x5a, 0x78, 0x09, 0x9d, 0x53,
|
||||||
|
0x39, 0x33, 0x51, 0xcd, 0x57, 0x9d, 0xd4, 0x25, 0x03, 0xd6
|
||||||
|
])
|
||||||
|
|
||||||
|
t.alike(client_pk, exp1, 'client_pk')
|
||||||
|
t.alike(client_sk, exp2, 'client_pk')
|
||||||
|
|
||||||
|
sodium.crypto_kx_keypair(server_pk, server_sk)
|
||||||
|
|
||||||
|
t.exception(() => {
|
||||||
|
sodium.crypto_kx_client_session_keys(client_rx, client_tx, client_pk, client_sk, small_order_p)
|
||||||
|
})
|
||||||
|
|
||||||
|
t.execution(() => {
|
||||||
|
sodium.crypto_kx_client_session_keys(client_rx, client_tx, client_pk, client_sk, server_pk)
|
||||||
|
})
|
||||||
|
|
||||||
|
t.exception(() => sodium.crypto_kx_server_session_keys(server_rx, server_tx, server_pk, server_sk, small_order_p))
|
||||||
|
t.execution(() => {
|
||||||
|
sodium.crypto_kx_server_session_keys(server_rx, server_tx, server_pk, server_sk, client_pk)
|
||||||
|
})
|
||||||
|
|
||||||
|
t.alike(server_rx, client_tx)
|
||||||
|
t.alike(server_tx, client_rx)
|
||||||
|
|
||||||
|
sodium.sodium_increment(client_pk)
|
||||||
|
|
||||||
|
t.execution(() => {
|
||||||
|
sodium.crypto_kx_server_session_keys(server_rx, server_tx, server_pk, server_sk, client_pk)
|
||||||
|
})
|
||||||
|
|
||||||
|
t.unlike(server_rx, client_tx)
|
||||||
|
t.unlike(server_tx, client_rx)
|
||||||
|
|
||||||
|
sodium.crypto_kx_keypair(client_pk, client_sk)
|
||||||
|
|
||||||
|
t.execution(() => {
|
||||||
|
sodium.crypto_kx_server_session_keys(server_rx, server_tx, server_pk, server_sk, client_pk)
|
||||||
|
})
|
||||||
|
|
||||||
|
t.unlike(server_rx, client_tx)
|
||||||
|
t.unlike(server_tx, client_rx)
|
||||||
|
|
||||||
|
sodium.crypto_kx_seed_keypair(client_pk, client_sk, seed)
|
||||||
|
sodium.sodium_increment(seed)
|
||||||
|
|
||||||
|
sodium.crypto_kx_seed_keypair(server_pk, server_sk, seed)
|
||||||
|
t.execution(() => {
|
||||||
|
sodium.crypto_kx_server_session_keys(server_rx, server_tx, server_pk, server_sk, client_pk)
|
||||||
|
})
|
||||||
|
|
||||||
|
const exp3 = new Uint8Array([
|
||||||
|
0x62, 0xc8, 0xf4, 0xfa, 0x81, 0x80, 0x0a, 0xbd, 0x05, 0x77, 0xd9,
|
||||||
|
0x99, 0x18, 0xd1, 0x29, 0xb6, 0x5d, 0xeb, 0x78, 0x9a, 0xf8, 0xc8,
|
||||||
|
0x35, 0x1f, 0x39, 0x1f, 0xeb, 0x0c, 0xbf, 0x23, 0x86, 0x04
|
||||||
|
])
|
||||||
|
|
||||||
|
const exp4 = new Uint8Array([
|
||||||
|
0x74, 0x95, 0x19, 0xc6, 0x80, 0x59, 0xbc, 0xe6, 0x9f, 0x7c, 0xfc,
|
||||||
|
0xc7, 0xb3, 0x87, 0xa3, 0xde, 0x1a, 0x1e, 0x82, 0x37, 0xd1, 0x10,
|
||||||
|
0x99, 0x13, 0x23, 0xbf, 0x62, 0x87, 0x01, 0x15, 0x73, 0x1a
|
||||||
|
])
|
||||||
|
|
||||||
|
t.alike(server_rx, exp3)
|
||||||
|
t.alike(server_tx, exp4)
|
||||||
|
|
||||||
|
t.execution(() => {
|
||||||
|
sodium.crypto_kx_client_session_keys(client_rx, client_tx, client_pk, client_sk, server_pk)
|
||||||
|
})
|
||||||
|
|
||||||
|
const exp5 = new Uint8Array([
|
||||||
|
0x74, 0x95, 0x19, 0xc6, 0x80, 0x59, 0xbc, 0xe6, 0x9f, 0x7c, 0xfc,
|
||||||
|
0xc7, 0xb3, 0x87, 0xa3, 0xde, 0x1a, 0x1e, 0x82, 0x37, 0xd1, 0x10,
|
||||||
|
0x99, 0x13, 0x23, 0xbf, 0x62, 0x87, 0x01, 0x15, 0x73, 0x1a
|
||||||
|
])
|
||||||
|
|
||||||
|
const exp6 = new Uint8Array([
|
||||||
|
0x62, 0xc8, 0xf4, 0xfa, 0x81, 0x80, 0x0a, 0xbd, 0x05, 0x77, 0xd9,
|
||||||
|
0x99, 0x18, 0xd1, 0x29, 0xb6, 0x5d, 0xeb, 0x78, 0x9a, 0xf8, 0xc8,
|
||||||
|
0x35, 0x1f, 0x39, 0x1f, 0xeb, 0x0c, 0xbf, 0x23, 0x86, 0x04
|
||||||
|
])
|
||||||
|
|
||||||
|
t.alike(client_rx, exp5)
|
||||||
|
t.alike(client_tx, exp6)
|
||||||
|
|
||||||
|
sodium.randombytes_buf(client_rx)
|
||||||
|
sodium.randombytes_buf(client_tx)
|
||||||
|
sodium.randombytes_buf(server_rx)
|
||||||
|
sodium.randombytes_buf(server_tx)
|
||||||
|
|
||||||
|
t.execution(() => sodium.crypto_kx_client_session_keys(client_rx, null,
|
||||||
|
client_pk, client_sk, server_pk))
|
||||||
|
t.execution(() => sodium.crypto_kx_client_session_keys(null, client_tx,
|
||||||
|
client_pk, client_sk, server_pk))
|
||||||
|
t.execution(() => sodium.crypto_kx_server_session_keys(server_rx, null,
|
||||||
|
server_pk, server_sk, client_pk))
|
||||||
|
t.execution(() => sodium.crypto_kx_server_session_keys(null, server_tx,
|
||||||
|
server_pk, server_sk, client_pk))
|
||||||
|
|
||||||
|
t.alike(client_rx, client_tx)
|
||||||
|
t.alike(client_tx, server_rx)
|
||||||
|
t.alike(server_rx, server_tx)
|
||||||
|
})
|
37
test/crypto_onetimeauth.js
Normal file
37
test/crypto_onetimeauth.js
Normal file
@ -0,0 +1,37 @@
|
|||||||
|
/* eslint-disable camelcase */
|
||||||
|
const test = require('brittle')
|
||||||
|
const sodium = require('..')
|
||||||
|
|
||||||
|
test('crypto_onetimeauth', function (t) {
|
||||||
|
const key = Buffer.alloc(sodium.crypto_onetimeauth_KEYBYTES)
|
||||||
|
const mac = Buffer.alloc(sodium.crypto_onetimeauth_BYTES)
|
||||||
|
const value = Buffer.from('Hello, World!')
|
||||||
|
|
||||||
|
sodium.randombytes_buf(key)
|
||||||
|
sodium.crypto_onetimeauth(mac, value, key)
|
||||||
|
|
||||||
|
t.not(mac, Buffer.alloc(mac.length), 'not blank')
|
||||||
|
t.absent(sodium.crypto_onetimeauth_verify(Buffer.alloc(mac.length), value, key), 'does not verify')
|
||||||
|
t.ok(sodium.crypto_onetimeauth_verify(mac, value, key), 'verifies')
|
||||||
|
})
|
||||||
|
|
||||||
|
test.skip('crypto_onetimeauth_state', function (t) {
|
||||||
|
const key = Buffer.alloc(sodium.crypto_onetimeauth_KEYBYTES, 'lo')
|
||||||
|
const state = Buffer.alloc(sodium.crypto_onetimeauth_STATEBYTES)
|
||||||
|
|
||||||
|
t.exception.all(function () {
|
||||||
|
sodium.crypto_onetimeauth_init(state)
|
||||||
|
}, 'key required')
|
||||||
|
|
||||||
|
key[0] = 42
|
||||||
|
|
||||||
|
sodium.crypto_onetimeauth_init(state, key)
|
||||||
|
const value = Buffer.from('Hello, World!')
|
||||||
|
|
||||||
|
for (let i = 0; i < 10; i++) sodium.crypto_onetimeauth_update(state, value)
|
||||||
|
|
||||||
|
const mac = Buffer.alloc(sodium.crypto_onetimeauth_BYTES)
|
||||||
|
sodium.crypto_onetimeauth_final(state, mac)
|
||||||
|
|
||||||
|
t.alike(mac.toString('hex'), 'ac35df70e6b95051e015de11a6cbf4ab', 'streaming mac')
|
||||||
|
})
|
39
test/crypto_scalarmult.js
Normal file
39
test/crypto_scalarmult.js
Normal file
@ -0,0 +1,39 @@
|
|||||||
|
/* eslint-disable camelcase */
|
||||||
|
const test = require('brittle')
|
||||||
|
const sodium = require('..')
|
||||||
|
|
||||||
|
test('crypto_scalarmult_base', function (t) {
|
||||||
|
const keys = keyPair()
|
||||||
|
|
||||||
|
t.not(keys.secretKey, Buffer.alloc(keys.secretKey.length), 'secret key not blank')
|
||||||
|
t.not(keys.publicKey, Buffer.alloc(keys.publicKey.length), 'public key not blank')
|
||||||
|
})
|
||||||
|
|
||||||
|
test('crypto_scalarmult', function (t) {
|
||||||
|
const peer1 = keyPair()
|
||||||
|
const peer2 = keyPair()
|
||||||
|
|
||||||
|
t.not(peer1.secretKey, peer2.secretKey, 'diff secret keys')
|
||||||
|
t.not(peer1.publicKey, peer2.publicKey, 'diff public keys')
|
||||||
|
|
||||||
|
const shared1 = Buffer.alloc(sodium.crypto_scalarmult_BYTES)
|
||||||
|
const shared2 = Buffer.alloc(sodium.crypto_scalarmult_BYTES)
|
||||||
|
|
||||||
|
sodium.crypto_scalarmult(shared1, peer1.secretKey, peer2.publicKey)
|
||||||
|
sodium.crypto_scalarmult(shared2, peer2.secretKey, peer1.publicKey)
|
||||||
|
|
||||||
|
t.alike(shared1, shared2, 'same shared secret')
|
||||||
|
})
|
||||||
|
|
||||||
|
function keyPair () {
|
||||||
|
const secretKey = Buffer.alloc(sodium.crypto_scalarmult_SCALARBYTES)
|
||||||
|
sodium.randombytes_buf(secretKey)
|
||||||
|
|
||||||
|
const publicKey = Buffer.alloc(sodium.crypto_scalarmult_BYTES)
|
||||||
|
sodium.crypto_scalarmult_base(publicKey, secretKey)
|
||||||
|
|
||||||
|
return {
|
||||||
|
publicKey,
|
||||||
|
secretKey
|
||||||
|
}
|
||||||
|
}
|
72
test/crypto_secretbox.js
Normal file
72
test/crypto_secretbox.js
Normal file
@ -0,0 +1,72 @@
|
|||||||
|
/* eslint-disable camelcase */
|
||||||
|
const test = require('brittle')
|
||||||
|
const sodium = require('..')
|
||||||
|
|
||||||
|
test('crypto_secretbox_easy', function (t) {
|
||||||
|
const message = Buffer.from('Hej, Verden!')
|
||||||
|
const output = Buffer.alloc(message.length + sodium.crypto_secretbox_MACBYTES)
|
||||||
|
|
||||||
|
const key = Buffer.alloc(sodium.crypto_secretbox_KEYBYTES)
|
||||||
|
sodium.randombytes_buf(key)
|
||||||
|
|
||||||
|
const nonce = Buffer.alloc(sodium.crypto_secretbox_NONCEBYTES)
|
||||||
|
sodium.randombytes_buf(nonce)
|
||||||
|
|
||||||
|
t.exception.all(function () {
|
||||||
|
sodium.crypto_secretbox_easy(Buffer.alloc(0), message, nonce, key)
|
||||||
|
}, 'throws if output is too small')
|
||||||
|
|
||||||
|
t.exception.all(function () {
|
||||||
|
sodium.crypto_secretbox_easy(Buffer.alloc(message.length), message, nonce, key)
|
||||||
|
}, 'throws if output is too small')
|
||||||
|
|
||||||
|
sodium.crypto_secretbox_easy(output, message, nonce, key)
|
||||||
|
t.not(output, Buffer.alloc(output.length))
|
||||||
|
|
||||||
|
const result = Buffer.alloc(output.length - sodium.crypto_secretbox_MACBYTES)
|
||||||
|
t.absent(sodium.crypto_secretbox_open_easy(result, output, Buffer.alloc(sodium.crypto_secretbox_NONCEBYTES), key), 'could not decrypt')
|
||||||
|
t.ok(sodium.crypto_secretbox_open_easy(result, output, nonce, key), 'could decrypt')
|
||||||
|
|
||||||
|
t.alike(result, message, 'decrypted message is correct')
|
||||||
|
})
|
||||||
|
|
||||||
|
test('crypto_secretbox_easy overwrite buffer', function (t) {
|
||||||
|
const output = Buffer.alloc(Buffer.byteLength('Hej, Verden!') + sodium.crypto_secretbox_MACBYTES)
|
||||||
|
output.write('Hej, Verden!', sodium.crypto_secretbox_MACBYTES)
|
||||||
|
|
||||||
|
const key = Buffer.alloc(sodium.crypto_secretbox_KEYBYTES)
|
||||||
|
sodium.randombytes_buf(key)
|
||||||
|
|
||||||
|
const nonce = Buffer.alloc(sodium.crypto_secretbox_NONCEBYTES)
|
||||||
|
sodium.randombytes_buf(nonce)
|
||||||
|
|
||||||
|
sodium.crypto_secretbox_easy(output, output.slice(sodium.crypto_secretbox_MACBYTES), nonce, key)
|
||||||
|
t.not(output, Buffer.alloc(output.length))
|
||||||
|
|
||||||
|
t.ok(sodium.crypto_secretbox_open_easy(output.slice(sodium.crypto_secretbox_MACBYTES), output, nonce, key), 'could decrypt')
|
||||||
|
t.alike(output.slice(sodium.crypto_secretbox_MACBYTES), Buffer.from('Hej, Verden!'), 'decrypted message is correct')
|
||||||
|
})
|
||||||
|
|
||||||
|
test('crypto_secretbox_detached', function (t) {
|
||||||
|
const message = Buffer.from('Hej, Verden!')
|
||||||
|
const output = Buffer.alloc(message.length)
|
||||||
|
const mac = Buffer.alloc(sodium.crypto_secretbox_MACBYTES)
|
||||||
|
|
||||||
|
const key = Buffer.alloc(sodium.crypto_secretbox_KEYBYTES)
|
||||||
|
sodium.randombytes_buf(key)
|
||||||
|
|
||||||
|
const nonce = Buffer.alloc(sodium.crypto_secretbox_NONCEBYTES)
|
||||||
|
sodium.randombytes_buf(nonce)
|
||||||
|
|
||||||
|
sodium.crypto_secretbox_detached(output, mac, message, nonce, key)
|
||||||
|
|
||||||
|
t.not(mac, Buffer.alloc(mac.length), 'mac not blank')
|
||||||
|
t.not(output, Buffer.alloc(output.length), 'output not blank')
|
||||||
|
|
||||||
|
const result = Buffer.alloc(output.length)
|
||||||
|
|
||||||
|
t.absent(sodium.crypto_secretbox_open_detached(result, output, mac, nonce, Buffer.alloc(key.length)), 'could not decrypt')
|
||||||
|
t.ok(sodium.crypto_secretbox_open_detached(result, output, mac, nonce, key), 'could decrypt')
|
||||||
|
|
||||||
|
t.alike(result, message, 'decrypted message is correct')
|
||||||
|
})
|
148
test/crypto_secretstream.js
Normal file
148
test/crypto_secretstream.js
Normal file
@ -0,0 +1,148 @@
|
|||||||
|
/* eslint-disable camelcase */
|
||||||
|
const test = require('brittle')
|
||||||
|
const sodium = require('..')
|
||||||
|
|
||||||
|
test('constants', function (t) {
|
||||||
|
t.alike(typeof sodium.crypto_secretstream_xchacha20poly1305_ABYTES, 'number', 'crypto_secretstream_xchacha20poly1305_ABYTES is number')
|
||||||
|
t.alike(typeof sodium.crypto_secretstream_xchacha20poly1305_HEADERBYTES, 'number', 'crypto_secretstream_xchacha20poly1305_HEADERBYTES is number')
|
||||||
|
t.alike(typeof sodium.crypto_secretstream_xchacha20poly1305_KEYBYTES, 'number', 'crypto_secretstream_xchacha20poly1305_KEYBYTES is number')
|
||||||
|
t.alike(typeof sodium.crypto_secretstream_xchacha20poly1305_MESSAGEBYTES_MAX, 'bigint', 'crypto_secretstream_xchacha20poly1305_MESSAGEBYTES_MAX is number')
|
||||||
|
|
||||||
|
t.ok(typeof sodium.crypto_secretstream_xchacha20poly1305_TAG_MESSAGE === 'number', 'crypto_secretstream_xchacha20poly1305_TAG_MESSAGE is Buffer')
|
||||||
|
t.ok(typeof sodium.crypto_secretstream_xchacha20poly1305_TAG_PUSH === 'number', 'crypto_secretstream_xchacha20poly1305_TAG_PUSH is Buffer')
|
||||||
|
t.ok(typeof sodium.crypto_secretstream_xchacha20poly1305_TAG_REKEY === 'number', 'crypto_secretstream_xchacha20poly1305_TAG_REKEY is Buffer')
|
||||||
|
t.ok(typeof sodium.crypto_secretstream_xchacha20poly1305_TAG_FINAL === 'number', 'crypto_secretstream_xchacha20poly1305_TAG_FINAL is Buffer')
|
||||||
|
})
|
||||||
|
|
||||||
|
test.skip('crypto_secretstream', function (t) {
|
||||||
|
const state = Buffer.alloc(sodium.crypto_secretstream_xchacha20poly1305_STATEBYTES)
|
||||||
|
|
||||||
|
const header = Buffer.alloc(sodium.crypto_secretstream_xchacha20poly1305_HEADERBYTES)
|
||||||
|
const ad = Buffer.alloc(Math.floor(Math.random() * 100))
|
||||||
|
sodium.randombytes_buf(ad)
|
||||||
|
|
||||||
|
const m1 = Buffer.alloc(Math.floor(Math.random() * 1000))
|
||||||
|
sodium.randombytes_buf(m1)
|
||||||
|
|
||||||
|
const m2 = Buffer.alloc(Math.floor(Math.random() * 1000))
|
||||||
|
sodium.randombytes_buf(m2)
|
||||||
|
|
||||||
|
const m3 = Buffer.alloc(Math.floor(Math.random() * 1000))
|
||||||
|
sodium.randombytes_buf(m3)
|
||||||
|
|
||||||
|
const m4 = Buffer.alloc(Math.floor(Math.random() * 1000))
|
||||||
|
sodium.randombytes_buf(m4)
|
||||||
|
|
||||||
|
const m1_ = Buffer.from(m1)
|
||||||
|
const m2_ = Buffer.from(m2)
|
||||||
|
const m3_ = Buffer.from(m3)
|
||||||
|
const m4_ = Buffer.from(m4)
|
||||||
|
|
||||||
|
const c1 = Buffer.alloc(m1.length + sodium.crypto_secretstream_xchacha20poly1305_ABYTES)
|
||||||
|
const c2 = Buffer.alloc(m2.length + sodium.crypto_secretstream_xchacha20poly1305_ABYTES)
|
||||||
|
const c3 = Buffer.alloc(m3.length + sodium.crypto_secretstream_xchacha20poly1305_ABYTES)
|
||||||
|
const c4 = Buffer.alloc(m4.length + sodium.crypto_secretstream_xchacha20poly1305_ABYTES)
|
||||||
|
|
||||||
|
const key = Buffer.alloc(sodium.crypto_secretstream_xchacha20poly1305_KEYBYTES)
|
||||||
|
let ret
|
||||||
|
const tag = Buffer.alloc(sodium.crypto_secretstream_xchacha20poly1305_TAGBYTES, 0xdb)
|
||||||
|
|
||||||
|
sodium.crypto_secretstream_xchacha20poly1305_keygen(key)
|
||||||
|
|
||||||
|
sodium.crypto_secretstream_xchacha20poly1305_init_push(state, header, key)
|
||||||
|
t.unlike(header.toString('hex'), '000000000000000000000000000000000000000000000000')
|
||||||
|
ret = sodium.crypto_secretstream_xchacha20poly1305_push(state, c1, m1, null, sodium.crypto_secretstream_xchacha20poly1305_TAG_MESSAGE)
|
||||||
|
t.alike(ret, m1.length + sodium.crypto_secretstream_xchacha20poly1305_ABYTES)
|
||||||
|
ret = sodium.crypto_secretstream_xchacha20poly1305_push(state, c2, m2, ad.slice(0, 0), sodium.crypto_secretstream_xchacha20poly1305_TAG_MESSAGE)
|
||||||
|
t.alike(ret, m2.length + sodium.crypto_secretstream_xchacha20poly1305_ABYTES)
|
||||||
|
ret = sodium.crypto_secretstream_xchacha20poly1305_push(state, c3, m3, ad, sodium.crypto_secretstream_xchacha20poly1305_TAG_MESSAGE)
|
||||||
|
t.alike(ret, m3.length + sodium.crypto_secretstream_xchacha20poly1305_ABYTES)
|
||||||
|
ret = sodium.crypto_secretstream_xchacha20poly1305_push(state, c4, m4, null, sodium.crypto_secretstream_xchacha20poly1305_TAG_FINAL)
|
||||||
|
t.alike(ret, m4.length + sodium.crypto_secretstream_xchacha20poly1305_ABYTES)
|
||||||
|
|
||||||
|
sodium.crypto_secretstream_xchacha20poly1305_init_pull(state, header, key)
|
||||||
|
m1.fill(0)
|
||||||
|
tag.fill(0xdb)
|
||||||
|
ret = sodium.crypto_secretstream_xchacha20poly1305_pull(state, m1, tag, c1, null)
|
||||||
|
t.alike(ret, c1.length - sodium.crypto_secretstream_xchacha20poly1305_ABYTES)
|
||||||
|
t.alike(tag[0], sodium.crypto_secretstream_xchacha20poly1305_TAG_MESSAGE)
|
||||||
|
t.ok(m1.equals(m1_))
|
||||||
|
|
||||||
|
m2.fill(0)
|
||||||
|
tag.fill(0xdb)
|
||||||
|
ret = sodium.crypto_secretstream_xchacha20poly1305_pull(state, m2, tag, c2, null)
|
||||||
|
t.alike(ret, c2.length - sodium.crypto_secretstream_xchacha20poly1305_ABYTES)
|
||||||
|
t.alike(tag[0], sodium.crypto_secretstream_xchacha20poly1305_TAG_MESSAGE)
|
||||||
|
t.ok(m2.equals(m2_))
|
||||||
|
|
||||||
|
if (ad.length > 0) {
|
||||||
|
t.exception.all(function () {
|
||||||
|
sodium.crypto_secretstream_xchacha20poly1305_pull(state, m3, tag, c3, null)
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
m3.fill(0)
|
||||||
|
tag.fill(0xdb)
|
||||||
|
ret = sodium.crypto_secretstream_xchacha20poly1305_pull(state, m3, tag, c3, ad)
|
||||||
|
t.alike(ret, c3.length - sodium.crypto_secretstream_xchacha20poly1305_ABYTES)
|
||||||
|
t.alike(tag[0], sodium.crypto_secretstream_xchacha20poly1305_TAG_MESSAGE)
|
||||||
|
t.ok(m3.equals(m3_))
|
||||||
|
|
||||||
|
m4.fill(0)
|
||||||
|
tag.fill(0xdb)
|
||||||
|
ret = sodium.crypto_secretstream_xchacha20poly1305_pull(state, m4, tag, c4, null)
|
||||||
|
t.alike(ret, c4.length - sodium.crypto_secretstream_xchacha20poly1305_ABYTES)
|
||||||
|
t.alike(tag[0], sodium.crypto_secretstream_xchacha20poly1305_TAG_FINAL)
|
||||||
|
t.ok(m4.equals(m4_))
|
||||||
|
|
||||||
|
t.exception.all(function () {
|
||||||
|
sodium.crypto_secretstream_xchacha20poly1305_pull(state, m4, tag, c4, null)
|
||||||
|
}, 'previous with FINAL tag')
|
||||||
|
|
||||||
|
t.exception.all(function () {
|
||||||
|
sodium.crypto_secretstream_xchacha20poly1305_pull(state, m2, tag, c2, null)
|
||||||
|
}, 'previous with without tag')
|
||||||
|
|
||||||
|
t.exception.all(function () {
|
||||||
|
sodium.crypto_secretstream_xchacha20poly1305_pull(state, m2, tag, c2.slice(0, Math.random() * sodium.crypto_secretstream_xchacha20poly1305_ABYTES | 0), null) // fixme
|
||||||
|
}, 'short ciphertext')
|
||||||
|
|
||||||
|
t.exception.all(function () {
|
||||||
|
sodium.crypto_secretstream_xchacha20poly1305_pull(state, m2, tag, c2.slice(0, sodium.crypto_secretstream_xchacha20poly1305_ABYTES), null)
|
||||||
|
}, 'empty ciphertext')
|
||||||
|
|
||||||
|
/* without explicit rekeying */
|
||||||
|
|
||||||
|
sodium.crypto_secretstream_xchacha20poly1305_init_push(state, header, key)
|
||||||
|
sodium.crypto_secretstream_xchacha20poly1305_push(state, c1, m1, null, sodium.crypto_secretstream_xchacha20poly1305_TAG_REKEY)
|
||||||
|
sodium.crypto_secretstream_xchacha20poly1305_push(state, c2, m2, null, sodium.crypto_secretstream_xchacha20poly1305_TAG_MESSAGE)
|
||||||
|
|
||||||
|
sodium.crypto_secretstream_xchacha20poly1305_init_pull(state, header, key)
|
||||||
|
tag.fill(0xdb)
|
||||||
|
sodium.crypto_secretstream_xchacha20poly1305_pull(state, m1, tag, c1, null)
|
||||||
|
t.alike(tag[0], sodium.crypto_secretstream_xchacha20poly1305_TAG_REKEY)
|
||||||
|
tag.fill(0xdb)
|
||||||
|
sodium.crypto_secretstream_xchacha20poly1305_pull(state, m2, tag, c2, null)
|
||||||
|
t.alike(tag[0], sodium.crypto_secretstream_xchacha20poly1305_TAG_MESSAGE)
|
||||||
|
|
||||||
|
/* with explicit rekeying */
|
||||||
|
|
||||||
|
sodium.crypto_secretstream_xchacha20poly1305_init_push(state, header, key)
|
||||||
|
sodium.crypto_secretstream_xchacha20poly1305_push(state, c1, m1, null, sodium.crypto_secretstream_xchacha20poly1305_TAG_MESSAGE)
|
||||||
|
sodium.crypto_secretstream_xchacha20poly1305_rekey(state)
|
||||||
|
sodium.crypto_secretstream_xchacha20poly1305_push(state, c2, m2, null, sodium.crypto_secretstream_xchacha20poly1305_TAG_MESSAGE)
|
||||||
|
|
||||||
|
sodium.crypto_secretstream_xchacha20poly1305_init_pull(state, header, key)
|
||||||
|
tag.fill(0xdb)
|
||||||
|
sodium.crypto_secretstream_xchacha20poly1305_pull(state, m1, tag, c1, null)
|
||||||
|
t.alike(tag[0], sodium.crypto_secretstream_xchacha20poly1305_TAG_MESSAGE)
|
||||||
|
|
||||||
|
t.exception.all(function () {
|
||||||
|
sodium.crypto_secretstream_xchacha20poly1305_pull(state, m2, tag, c2, null)
|
||||||
|
})
|
||||||
|
|
||||||
|
sodium.crypto_secretstream_xchacha20poly1305_rekey(state)
|
||||||
|
tag.fill(0xdb)
|
||||||
|
sodium.crypto_secretstream_xchacha20poly1305_pull(state, m2, tag, c2, null)
|
||||||
|
t.alike(tag[0], sodium.crypto_secretstream_xchacha20poly1305_TAG_MESSAGE)
|
||||||
|
})
|
214
test/crypto_shorthash.js
Normal file
214
test/crypto_shorthash.js
Normal file
@ -0,0 +1,214 @@
|
|||||||
|
/* eslint-disable camelcase */
|
||||||
|
const test = require('brittle')
|
||||||
|
const sodium = require('..')
|
||||||
|
|
||||||
|
const vectors = [ // generated from https://github.com/jedisct1/siphash-js/blob/master/test/index.js
|
||||||
|
['aON1dHrq90SbG8Hx', 'v7LyiwuCrB7EgAibPve6Yg2gLmggxE6j7ocR37EudrH_P9XX2rQK', [147, 73, 50, 63, 71, 98, 203, 42]],
|
||||||
|
['YOT4AG5F7ONRW5na', '4Ks1pPO_2wGYR-gfJShqUO-FirA9c5cF4oKwvStp2Ix5hHUg2klPofVJ8TZoBdFfgTh8', [138, 27, 129, 27, 185, 163, 160, 153]],
|
||||||
|
['63UlqXfSckA3Dv8S', 'bMQudI8yVdDx5ScGQCMQy4K_QXYCq1w1eC', [6, 78, 44, 167, 186, 29, 113, 244]],
|
||||||
|
['P3hpmZEuwfDO_uZ-', 'Wh8yRitk__n4MsETCTRFrB4bjWRtPjUZVLPnywlvv5nTMA2C71', [241, 171, 151, 44, 166, 163, 156, 234]],
|
||||||
|
['d9oTrpd-a_Na4b6w', 'f-NT', [182, 147, 203, 88, 65, 57, 119, 203]],
|
||||||
|
['fe88HBnyyEiuIJ8G', 'KSWP9sFkhSdGsha0Fmd5raCf_eA5gnV1', [218, 10, 3, 10, 16, 50, 241, 229]],
|
||||||
|
['o6LxtnACG0RGQ3z-', 'k8zMl', [16, 158, 19, 145, 214, 142, 177, 55]],
|
||||||
|
['AHGkoQQ6xdf90MD9', 'HC9bz8XUYkan0jxYSaj0vP-cs324Y4PrnAXutwKBgIko5oOOOViJSjLD2m8WenV8HdF78J', [157, 186, 255, 238, 165, 21, 187, 163]],
|
||||||
|
['TlVmpfbZMFkeuENo', '5is', [166, 36, 114, 58, 101, 106, 79, 30]],
|
||||||
|
['iBLscVfsPM1xrSFJ', 'J-aH-', [14, 91, 64, 158, 190, 247, 72, 26]],
|
||||||
|
['hUehErdKolgd0erH', 'DhS94w_07-vaAXo_msv8Fk57slIHnuxy3iv4Yymh5k', [45, 207, 192, 24, 158, 243, 93, 68]],
|
||||||
|
['B-aq-09jmO0z_PUD', '1p2IMG4A1NMyWsfUS02VK8fOEhn', [161, 224, 65, 80, 91, 44, 131, 177]],
|
||||||
|
['fyNYE8SMJvYrDgao', 'HWCtQs19BHZcH', [122, 114, 254, 14, 124, 226, 23, 173]],
|
||||||
|
['5vQHK_yJlJez45N5', '8YJwfpxwbH9h-N27i-uTUUK2Vt', [142, 216, 87, 77, 16, 17, 8, 199]],
|
||||||
|
['q7Oo0g9DDjLJ_pyV', 'jQFAHtrTUDaCaSIcis5h2j4fyOJpJGfdZBMTO5GOAAB4AwZtutDenNZ', [230, 111, 182, 25, 233, 231, 14, 141]],
|
||||||
|
['IUle6P8g2uyX_8ms', 'hOKGFGrsAux60CQmbOjQd-EzQBKUjLbDUhhtsKt3ZY4', [64, 247, 102, 236, 211, 145, 4, 152]],
|
||||||
|
['-bZa23onpInwqNWG', 'DNbtZuulH9', [247, 2, 142, 172, 208, 100, 60, 127]],
|
||||||
|
['1xjmLXTmVJwse8M-', 'j1_Hh', [197, 81, 6, 184, 57, 173, 83, 126]],
|
||||||
|
['Ey7hygEVd8RxZdtX', 'GNRDNJDu00L', [137, 196, 184, 4, 146, 27, 188, 191]],
|
||||||
|
['weTzikz4EGUbhSgC', 'g1SXT7b4Zz6q2tQykV1tZS', [105, 39, 69, 220, 198, 210, 96, 240]],
|
||||||
|
['OjSaplYVoQPDXG7S', 'QCk4v3D9s6R471p0xa--Vv00vzIaMpJ1S48Qnz6uzhmtke99HmWcY9vapyjdWVS', [183, 208, 142, 194, 95, 247, 239, 122]],
|
||||||
|
['4g2ZB-SA-HlqJT7D', 'N5Ht5QIk6KziyTE4-q5eNkqGdQgg8fxkr4w-ARqRgdaZd3XpbePGGb4jPFo3', [127, 245, 152, 248, 155, 148, 212, 127]],
|
||||||
|
['CXOF2EKm5CDPYpNC', 'xkY0T8bPF4JFq6Mu0K5YtFp7KfOni', [124, 172, 24, 66, 198, 236, 234, 226]],
|
||||||
|
['ID4UzFBiztXW--b0', 'qyICNMPaivgDmX', [46, 95, 156, 18, 186, 88, 188, 122]],
|
||||||
|
['TaGesMDe_0UNGzcp', 'nlNv', [103, 245, 211, 70, 87, 104, 0, 17]],
|
||||||
|
['lMDS8Vcs-8aCV9hJ', 'KW44Qk', [69, 47, 130, 50, 196, 101, 206, 62]],
|
||||||
|
['BmQCaB-c777zvFsc', 'o-tr2zQVbtrmkH4rCCAXoXFt8KwAWo4YFpK', [123, 168, 235, 94, 113, 233, 190, 213]],
|
||||||
|
['OQlCpJOLmsouyme1', 'aRk9nyHhXlad-TpIemD2VTRiHVlzSysY7uKof9ApR5DejFjT-Bmdzl_z', [89, 201, 222, 238, 50, 99, 249, 215]],
|
||||||
|
['t6Wl3FKDhr9FAMzz', 'BLu17bk_iQtpGv1N4A', [80, 7, 121, 129, 115, 84, 153, 140]],
|
||||||
|
['XU5km7La0ujNVvlV', 'OUEAH4yu6SXQ4I8zjn07NuB_AudmoewXc39HqgN8rc', [220, 180, 100, 142, 210, 176, 72, 108]],
|
||||||
|
['zDKBNpM2cdf0HwkK', 'dEqgpqTRc', [221, 42, 57, 242, 197, 147, 27, 81]],
|
||||||
|
['yZGrKEShM0z7Vvns', 'sgUtgxRQpMl_o6iuZqomKhJxaSBCD_NBHa2lqX3cWfq8byu', [211, 179, 114, 59, 129, 223, 168, 65]],
|
||||||
|
['4-wM8GXg1a7hyerE', 'djJ3-b2', [157, 165, 254, 119, 109, 239, 114, 115]],
|
||||||
|
['jD3Y4PgdExHU2JaY', 'uQC59dKTf3unOGu-Lg9IgmC8MTSg-BcH-', [249, 179, 174, 181, 118, 232, 40, 255]],
|
||||||
|
['dZhRW8ubIZovieQg', 'GCbxph1HICSKgHLafk_8TRjGdZa7jnJOu', [73, 24, 76, 226, 201, 86, 43, 223]],
|
||||||
|
['P9hudzT3H87QzC9E', 'Vfeo26fUa3sLk6BNM', [31, 150, 174, 223, 224, 214, 127, 107]],
|
||||||
|
['ocfdt04Np8Bs5hn9', 'dQiaUqksbXOWmBPt2kBn0ARiVkr3r4mBwypQq', [203, 253, 155, 6, 148, 92, 81, 212]],
|
||||||
|
['UuQ68x330IdojsLI', 'pb6-OdmVdQ1gLP8E1szvlf0T6aOQp-EQHPW-tAKQ8Xj', [23, 158, 11, 26, 216, 251, 17, 229]],
|
||||||
|
['T4ec6Q68QKiuIARL', 'BeLjFIoODtDg5vLMLBN1Sae', [250, 103, 43, 65, 80, 229, 66, 116]],
|
||||||
|
['xmZBUpwjJwnXZAp6', 'WS2F3Nzg2s7TqVIygm8W1tQyNc6DFy', [186, 206, 177, 250, 182, 139, 138, 19]],
|
||||||
|
['4qB6m0d_ryzb3w6q', '2Nr1sd1phWDB9gnuYOLUsjvX9jxntScWyRlX3Nj_xs8MV10LGgSgfRBKVGnO', [97, 101, 207, 79, 55, 205, 142, 253]],
|
||||||
|
['SmVONU3BEODnkbdM', 'G4WIU3UrBqbN6_nccFrIyx_TdXx-W80YzWw', [33, 147, 134, 20, 73, 169, 2, 107]],
|
||||||
|
['zseM9_-0y7B9URxM', 'us8B1DmHxOF10ue3jm2VfoJ250h364zRd2U8VIm2Lbkf3OWprSUpLF4ePjdj5aS', [80, 47, 98, 151, 139, 175, 78, 166]],
|
||||||
|
['WY_sEWLFAybHSwX4', 'vLJyXNkHCYGHWsvhXcU2sWYzgFYlWF7A_ZjFg8kJ4wwuJ', [132, 67, 168, 204, 90, 10, 169, 235]],
|
||||||
|
['maWrEov1bBjSq2Zn', 'sCP9zPakZ_wZ8hcQu-G6nN', [136, 204, 107, 221, 66, 198, 31, 201]],
|
||||||
|
['tXInZHO-x4AWxKTp', 'JQUM_O-E4-YI6dhxo', [36, 245, 166, 183, 31, 222, 192, 96]],
|
||||||
|
['OqaQt_b1hvU-atC3', 'X7Ou8cKo17xHlq_5gwM56GZrCSJBReeA60pDj2hUer6', [169, 107, 175, 79, 116, 24, 153, 93]],
|
||||||
|
['nHdnXHGmGknC8FfC', 'cRupnAESNmU', [18, 200, 205, 81, 7, 32, 8, 213]],
|
||||||
|
['59n9lAJdrxIz3joe', 'WBPr', [75, 153, 152, 122, 242, 233, 165, 255]],
|
||||||
|
['q-PAAgkE9z2xed85', 'AFOQD_H7MO3q3cxLa7TOUd89kpH03SpjpqmzY6AX16-uZFYcZZBb8D', [45, 4, 101, 133, 174, 99, 42, 4]],
|
||||||
|
['tBzStZxn2ZqlQfBf', 'nZdIaI7-bdqqh6aU7w4HfDCByX-x4_3q9Jf', [253, 49, 199, 224, 50, 253, 75, 144]],
|
||||||
|
['rH8Nn75LyYC0hjVG', 'IrDPpL-dkoh6VTy7pOtKKdAD9dLwUnE-', [76, 2, 97, 127, 190, 74, 74, 5]],
|
||||||
|
['F-pI7AhpS1V-48eT', 'Ao7hV41P08Zq4C1szyOVN7K1iWW8z', [121, 76, 85, 13, 162, 105, 174, 114]],
|
||||||
|
['Khje_RmXXmJ3CAb1', 'TvMx3ISTfIQ', [237, 102, 92, 182, 242, 45, 27, 178]],
|
||||||
|
['G1KRzk-KMqCk-kbD', 'imHZWdBz01lGR3m1zuO74berNn68uFZR3kcoWEaMhVjJ1g', [165, 3, 34, 126, 199, 101, 203, 184]],
|
||||||
|
['wJhnTtBLcy_1rZay', 'qbZ6oK0a4eWf2ud1sEnKLeguOmYsbG4aOTdlMdrf', [226, 169, 14, 147, 180, 88, 90, 132]],
|
||||||
|
['vVl9fhjkwASu2WXe', '8-CjQylw18IKWgAL2mMxo', [30, 193, 202, 34, 74, 172, 72, 42]],
|
||||||
|
['m2Qx2Dtbvwv3qjNJ', 'WrIqIIsHqbgm3Qfg03QvaVG9G6fz2zxjnfNZUVuX8XUtjz4LQuj3VZNh', [237, 163, 64, 58, 187, 234, 117, 106]],
|
||||||
|
['5R1maUgHiPQ0ZoaD', 'SZJ6uMXnMuLll2xOfHcy_DE', [209, 26, 182, 131, 19, 180, 5, 55]],
|
||||||
|
['dDBufcmObAK1dKYw', 'ayjd0F5mqWsVF0MtUNJYo8S8GhuCsMCnEU6k3H9z0f8', [126, 244, 206, 245, 56, 4, 39, 63]],
|
||||||
|
['o_YPVOjQ7Xw0G9OD', 'UPF-HW1hJukwdVvhCl7IZJzy7a', [30, 211, 48, 214, 88, 189, 59, 33]],
|
||||||
|
['oule-vFYlFJfsXU3', '8ORL7DUv28-yVfUw_cJ3imWP-iXrQRmzZRp0jtspwW_qm-rXmc1aBsbvbAut8', [66, 62, 243, 87, 153, 23, 230, 113]],
|
||||||
|
['kEPlQxhC27GQcJeb', 'wL-dAWvwZapITZZvgW46', [153, 83, 52, 252, 33, 23, 48, 216]],
|
||||||
|
['GFilE6NpBPWE25uB', 'RzoQCcd5NVeDbd2cx', [144, 101, 221, 104, 142, 244, 87, 216]],
|
||||||
|
['sENqlFHs0NvkY28u', 'Gm2ojB-BJBdL', [75, 226, 42, 7, 94, 14, 215, 52]],
|
||||||
|
['mxiOr15qouOEhzHS', 'SChjLg6SXpEb9', [174, 64, 56, 79, 211, 158, 21, 229]],
|
||||||
|
['pFL_Sbx5RW0fuPHO', 'hdb8HqaxEN99N4V1STTpnR4kr9F-lONwKp2TcOCopBFnDrjITz3jHPM4WKIYyw59US', [108, 66, 228, 165, 111, 142, 78, 201]],
|
||||||
|
['sMgAXpCtVqeFm14R', 'dNPnh6shnGYEZuN0id', [101, 147, 101, 20, 126, 33, 84, 255]],
|
||||||
|
['nTu9mRGqYc1SOPk7', 'ogL8VEqgoMkh6YNgTzvF4f87wHvmRhzncGPunN2ZJ5p3qUqZeJ3', [253, 16, 23, 144, 34, 207, 28, 82]],
|
||||||
|
['d5jDH8Ppk82zj_vd', '5sfq9Q_0P0H', [197, 245, 4, 89, 247, 26, 240, 77]],
|
||||||
|
['bEEUPVwdHlYwYL6o', 'AGoiVTE9foWm2MZqsn3dfS1XQiQW0QJwLXi6oXR2L9nMnPCPG_oF', [186, 203, 217, 87, 4, 177, 20, 242]],
|
||||||
|
['JbKhWuTfRMWb4hFD', 'NTNhYIahQ769TsCDwFyfOYZ8x6np58jg9hMAHFH-BMv7hBwESi596D4aDuyPabFGbqcG', [60, 79, 166, 97, 146, 213, 223, 59]],
|
||||||
|
['hvCtw1q_GJUBFW_X', 'uL5zgFM9WUTyO25dzVCmSVOxbpV70ZPurKK-CPUAmP', [127, 4, 233, 105, 7, 183, 123, 61]],
|
||||||
|
['hWxh0P6EXlm4yYKA', 'NUgrOoTOfqaB6JDZj', [96, 255, 249, 149, 117, 178, 189, 183]],
|
||||||
|
['TLHDMak8qeH3ABaV', 'HW-7PPunyMCinXt8QjQUuJUzZZQs1-T9ADR-6y', [46, 167, 85, 216, 34, 240, 131, 74]],
|
||||||
|
['uE4OfzzqHVDH8lbd', '8KCUyGtkcG-T8gA3lpplC13LsnFZ', [18, 9, 33, 96, 47, 132, 243, 76]],
|
||||||
|
['ocjA0Quge9vdCDbH', 'tLlU03I9CDBbP1Pnl6KM3MW34TNzuuZYv0u-uU-l7RtFF0OmGoySyg_yc7vWswGkz', [124, 174, 227, 126, 197, 91, 232, 11]],
|
||||||
|
['TDVmxGeyDULfxyrz', 'A57Y0_L6K4TTzQx1-Yr1E6fVAZi31RyipeK0Q4uqwXXfRLo4tz2a5PSqN3-bdQ4f2', [53, 212, 137, 227, 12, 85, 50, 251]],
|
||||||
|
['8OhqW3sA7s1vqEDr', 'jlFquRWvL07TyLjW9ZNk81gxkvs4u1WLkNhOQVLOjFjw3iecMjun5Yk0xcruo', [147, 130, 134, 67, 235, 29, 115, 34]],
|
||||||
|
['9kPcY6rfhPzSzEGn', 'nS1kAxpsghzJJXiCzhNycDk2_EJ_yIT97fV2kxXTtfZ9p0', [178, 109, 176, 237, 184, 79, 209, 89]],
|
||||||
|
['AJJ_yoEL8WyEtA1U', 'vFNErhfCk1TZiTFMA6J8D', [26, 63, 142, 247, 30, 50, 167, 102]],
|
||||||
|
['PBr4drRAJTaWv5Um', '5quc8Vd2rHVNk2NoDxk3TL', [150, 113, 209, 153, 101, 74, 42, 2]],
|
||||||
|
['MnODoRJI2FgZrvLs', 'gqJ_7HnrfiqYkenyvhe53SB1vTBgMiMB3kxF5', [205, 11, 216, 157, 130, 39, 60, 161]],
|
||||||
|
['iSxQPJpp_s0ws-4b', 'K-J', [46, 78, 209, 241, 112, 90, 91, 181]],
|
||||||
|
['ZMm2tCGDJ04A3I_6', 'gw-wcFYO1G2KEqJagWAic2l2d1FoTVXVT', [22, 60, 166, 216, 76, 146, 36, 22]],
|
||||||
|
['Hxf6qsSIV6blPdB1', 'GTWOerCQdUMkL6it6hEEPKBcOe_9f_B618ivjeM3BKfjzRQ8rvcGjUUJnsljerca6', [122, 74, 100, 36, 79, 173, 4, 91]],
|
||||||
|
['U5gXdMrRYUdxuDjK', 'siy9CxY2BbhazTqBWwFrtBLh', [79, 92, 248, 231, 189, 215, 27, 51]],
|
||||||
|
['YJiK_B-TENJsVnd_', 'Ohyz8XU06XWewcgTX-PffLVdatU3UFl6CYe', [22, 147, 91, 237, 188, 184, 70, 223]],
|
||||||
|
['J7wVNfLdkCCtndH5', '1Vw163YqXwP8cPXIy5dSkcIoClBep7gWb0qGJzHM8h_hzk2GFtZyLKk', [123, 221, 220, 145, 75, 144, 103, 74]],
|
||||||
|
['elId3b7ZyOg6HVif', 'N89kQR7VMUgF4DyWhpTo_ZW2lERbNqFa1RdXjaUctO1FdevDAZaA', [39, 244, 17, 57, 240, 193, 34, 112]],
|
||||||
|
['ydBueYO29jaUsEVU', 'HMcnfvYjjz8Uf8bUhxXlAYHcyO7x5NHE_gc3bcWSMWJD2JdryrUBBdYj1', [252, 15, 32, 244, 143, 126, 130, 34]],
|
||||||
|
['fVprx-PzTSx6CUcX', 'Q', [253, 22, 240, 135, 62, 55, 219, 1]],
|
||||||
|
['9ORMwecQjlob9aTT', '2cpq2XTWPk5sVLlN4OR5y6X_rTRFNUURgrwnWDg76u927cYud6PS-17UTgd3TO9g3K4', [15, 124, 108, 136, 56, 254, 85, 250]],
|
||||||
|
['-V3BEGXuTWtFOMv4', '8l6qcZXfG9iSywi1IgwJ_PkZh0Bg2iR1cbGps_sWPdKXbIvDDX-3IeTTg', [111, 8, 18, 99, 6, 72, 56, 232]],
|
||||||
|
['Cbvx4_KdboiNHs6P', 'nzUo0UnqKn05adw5g0jtBN703bUgb8UxywfC93I7KN', [85, 17, 95, 157, 77, 25, 206, 45]],
|
||||||
|
['SDPzfgeqkvmi62JH', 'Z6kJuDD-8FSz1VwOuPeoSJ6X-4hpib563UjYxtFcB4SvhQr-Hstg5OhMi4iZZ', [153, 35, 172, 58, 141, 180, 95, 97]],
|
||||||
|
['mBJlhP6D3M2raEjD', 'ogtg66jr2KLCFO2RvodOXw0mt4XS6BOnLhBI_gDV0', [85, 231, 198, 97, 240, 108, 230, 150]],
|
||||||
|
['Sz-mxKc7KGM7SDaf', 'ecQ-7-3VddOdMSeKUbZE1t6Aa67pYGXjQeOckq1l50GkvfomFr', [18, 241, 24, 133, 142, 74, 218, 178]],
|
||||||
|
['_5ck5scojT4oyJEq', '43oLkeixGHShTMUhtI', [35, 190, 107, 33, 2, 165, 11, 34]],
|
||||||
|
['48ulC82W4qv49InN', '8HQyT55TtmGahy6w', [2, 70, 28, 124, 164, 101, 100, 185]],
|
||||||
|
['-exgd5coAHqBu3ga', 'vRfqYthbUNh', [48, 188, 141, 96, 138, 114, 132, 143]],
|
||||||
|
['hJEBugObOX06pplH', 'oYYZ-v', [153, 112, 89, 5, 46, 138, 209, 254]],
|
||||||
|
['eSDsC63oTtVfi_F7', 'BVmyPas409CmRHiRRiTPjJL87KgJefuDK6lEh5isghLl7l3a4Xmxa', [21, 198, 30, 251, 173, 36, 165, 82]],
|
||||||
|
['KZtUPWMUr469RWL8', 'F9K6TUd6j7Dm25rAS7cqOKDtSnnxj0hYKVTMFQ6CfA5218gPeZo', [203, 233, 183, 39, 57, 54, 60, 173]],
|
||||||
|
['0TeBxGk-V7RPSZML', 'kmL1fKqHwAoxI1b_ap8I9fGZMmcx3gIMiglxLLPFWOoDNUGe', [193, 7, 13, 148, 71, 231, 166, 135]],
|
||||||
|
['PWYY82PNqwshPHiv', 'Ya4LyHqxIxK8GaND9FIzqugleh-QELha_ntbRJixl6hZI5m3RfdrcntjiPJ', [27, 177, 64, 55, 129, 165, 132, 108]],
|
||||||
|
['PtCub86vGwNj1tcv', 'qR08eqAeNrrUYDl18C-wttqMDk', [66, 134, 247, 100, 38, 3, 7, 125]],
|
||||||
|
['3eqQxzhNdv2kJqy5', '0wxAd9NT-Z8xFzomFwgMqMVbaUg', [36, 191, 165, 105, 211, 159, 155, 13]],
|
||||||
|
['MgEjpTNPFFwes6Sm', '7SCVGNJYZhtnbiLZAE5TrsL5K1X', [208, 79, 201, 49, 48, 3, 227, 199]],
|
||||||
|
['vSofRAYxXUU1qjhl', 'HATE-YsASxySRkK5aJR4yV0mxx1YAuEgM5tUqyJDc7cLL', [61, 205, 183, 24, 68, 135, 7, 74]],
|
||||||
|
['kIUe96sZ6LV464T_', 'rjwrCOQAzLFbIM_3M7KfDQ1A6r3nkebk-dgqORG0Uy-n89_apYNLVTbdr3yuzXKOTfkRh', [83, 214, 143, 126, 145, 218, 225, 186]],
|
||||||
|
['8wao85IcCu1mC-Rc', 'AdVncBX6wkLXqMQPol3tNDPd5HJ', [161, 223, 243, 36, 219, 75, 215, 63]],
|
||||||
|
['NRVNeO5wysG3DRuU', 'Mr8vhiVPo5GpI6sho4R09k8D-vFgcghF3-kF', [246, 119, 57, 225, 254, 189, 182, 180]],
|
||||||
|
['VHJZOECxfyxVyufk', 'TMB3UMDEIs-vj_9aDBNDzT6HkHcwQQhr4EnG6A1AD9JkHENVAAQnS7s', [117, 85, 69, 116, 56, 27, 123, 62]],
|
||||||
|
['TUfnTd3pmaJzSdD4', 'VoRGCJgaGEhPSGRl0EPKWIzN7CRpD49CiyjC7y_4xRpppMNlR4v', [3, 116, 140, 4, 113, 208, 78, 186]],
|
||||||
|
['-I1YgwmWxehyB6kv', 'IplQLxea3JGywQn3XMNWrqVbE', [137, 251, 109, 201, 11, 101, 132, 97]],
|
||||||
|
['4ic5nM5lbfMOXDRR', 'TfVtpOoAQt1IxL0qJtAQoCJJThyxncIagOvKSpxjD7RDmh7YQBHWPkuv5lpSzpN', [192, 203, 84, 99, 85, 184, 122, 44]],
|
||||||
|
['NYOq6hIu2C-aZPhE', 'QQa0EWIHXqbrkq3nBeXt6yEj12z', [40, 199, 197, 21, 82, 53, 100, 58]],
|
||||||
|
['nC93tajnfzk6bMtM', 'p9gbEB4nMHXDqmOC413rI4Z', [200, 140, 102, 143, 89, 170, 219, 32]],
|
||||||
|
['ZCCkYIbGOzXa5GRO', '2f9VGQeb4AtW6SwPjAGxxjyHNw3-MZj2BfxttNLxM0Tv_rpXO8TUH4YASb', [0, 174, 100, 194, 149, 35, 81, 12]],
|
||||||
|
['oapO2W6hces4Pfkc', 'oEyf5eqpM-N7LBp3C5vejvO7M87OzT4MHdwJz', [140, 195, 199, 20, 207, 60, 104, 240]],
|
||||||
|
['__daPiDXrnPpS7eO', '1_tnhApr6nZbWIEPja0jAJ6LbTvD6oAEvPyrLYQ', [255, 244, 76, 119, 124, 124, 146, 214]],
|
||||||
|
['5iIExqPt5W-ZpudD', 'jNbLiDmQdN5X7HEOfgnAi5A7s1pGXwP41hX1Z', [149, 68, 125, 203, 174, 150, 66, 31]],
|
||||||
|
['gD_J-R8tOb977BtL', 'f7A81Qbh8gQhfRpOmtz5-ZJqBxiQJ6myBhGfqK7BVaGBL_W2MvfB', [106, 38, 140, 196, 141, 190, 232, 110]],
|
||||||
|
['ZxHO4JJ8p45jTUXU', 'fs4Oy8mPZS6919SZ7gDyKIILDkXnPt8SsXkfBd-Mnm4wO6alw-veQD9', [209, 53, 104, 100, 102, 136, 84, 134]],
|
||||||
|
['2bVzT0moojGNQgIX', 'nuyb-AgYY-rsmhtdav3LC7meSPy1dCosjSw0YAvgP', [1, 201, 247, 25, 104, 147, 148, 252]],
|
||||||
|
['FicyyNT0BRua05i9', 'TG4leSS_mcrZ_L68GKFdxc4-McFCCtdG7QpbPu_MolD5luE6n3dKlPzb9MvfvkiZKi', [136, 150, 66, 224, 178, 235, 114, 238]],
|
||||||
|
['g5Qaf7mQAIxuHR0O', 'A6u5gtb1yMSiGlWVt3exYsRS', [169, 20, 115, 32, 43, 71, 21, 193]],
|
||||||
|
['aOACI6GP6u4WFyxp', '1eEx55L3E9MZga7l1WzpnKfI', [177, 26, 15, 27, 217, 101, 69, 195]],
|
||||||
|
['Rr2jLg-asIQrlaRJ', 'rgALEbs', [163, 103, 250, 90, 4, 46, 69, 32]],
|
||||||
|
['p8qW0oYzj5zi55s5', 'V1ZCoK73ifwcnzPjQEN7Q79MtZCskcpqiE3gfbqYPYRmy-q0lPxopkZZp2lNWKkpL_q5z', [29, 121, 240, 174, 51, 38, 238, 123]],
|
||||||
|
['wA0cNUJOhIMpiopE', 'U2RE2L2zZysyOTcsj5_JosVDaMRtUxkRWVCeBH0AeodMvYGBcHizhxc2QM89', [40, 230, 148, 164, 7, 168, 3, 46]],
|
||||||
|
['zBCN1w4ypWCEfpwC', 'VRcTwONsyRQIy2ymVniMmry', [184, 177, 56, 54, 152, 189, 120, 222]],
|
||||||
|
['i8cumEDwOxSXT0gL', 'ifKav', [53, 190, 193, 228, 179, 41, 246, 171]],
|
||||||
|
['g3EswbaCSNMsegzm', 'rTFnEuEDlwBB0Dw_q3-FUSaTCEjWe0pOPZDIWD35Us08Qa-nulc57YjDoGphUfBamq', [157, 64, 119, 179, 60, 147, 48, 17]],
|
||||||
|
['iYsckWoQTk5ap8YO', 'wIyTqa43-_GiZlHJ8UXcD_tnqKikH5DZUWxdQ1xjYMyzCr2JvKKRBm8BbcDl_Q8p', [96, 237, 170, 183, 48, 45, 116, 106]],
|
||||||
|
['Iyk5MoAjoWq4n8bG', 'IV2N5MC6kvk95ykEzb3jj0A7Sv0jjif45SR1avc0bRWot2aW', [99, 23, 149, 225, 242, 204, 47, 7]],
|
||||||
|
['NfzdRXCegRRsHHYj', '5uLBPbyFQqiv', [136, 45, 110, 192, 36, 204, 171, 218]],
|
||||||
|
['YiJTXegVwaNDtlpl', 'DbwKoF3CI5kd2JRKwfyuLpeGd6sFhqI0t43C2ph', [188, 126, 147, 191, 9, 114, 107, 60]],
|
||||||
|
['ZuUlFM-yEzZ9XHKj', 'errecd71', [158, 231, 84, 47, 149, 227, 92, 111]],
|
||||||
|
['EtEXELa6V_NSjvEh', 'yrTjrRuW8mJc3utw2JUH7iIW-J5vF3t9GC1-ZvRmO8UXNsG8-I3Iqgtinzoabqqbs1yvR', [186, 52, 144, 215, 104, 246, 174, 71]],
|
||||||
|
['q2uA_VwMnaBtAgTx', 'uJOymuDgBBS9Ec56JRGmKYsMHoGLCKA5wzwhtYf-g8-IT7UsAX1JHFGSV0EF', [176, 65, 188, 134, 212, 6, 97, 186]],
|
||||||
|
['4RmqR10QiIZDDKNO', 'oWY0Aj2CDCWuEFhdNHq2RFcGJD0sSRxK5K', [114, 28, 238, 228, 122, 40, 82, 13]],
|
||||||
|
['a9DfUPCLyQ_yrNIa', '5G-6AVe7CBJl-NuuUN_7TN', [95, 206, 124, 185, 194, 207, 227, 111]],
|
||||||
|
['8oB5yG87C2v5j0_4', '1S-aiUNRJ2c', [123, 42, 242, 79, 90, 36, 208, 81]],
|
||||||
|
['ZA2ZT22NXwD_UvTM', 'UpV3pLYniWPm-PnWUAbBNeO4V-zuuw6IZQ1ZprLsC_LjGdSJP7rZCnoPz', [189, 209, 102, 128, 246, 141, 212, 109]],
|
||||||
|
['ycz6aiuQFGKxZVsM', 'fBuJp4_A_hiq--4uBhxjXfT3nRaYEJ8azW2_FKooXdSVRv2Y03VoWzPzG', [241, 127, 162, 199, 73, 10, 75, 24]],
|
||||||
|
['eAmt0pClMyL8Sk69', 'JFzXjfJhEMUCYEDrBKRM9OFFK0PSX', [176, 167, 43, 60, 16, 69, 194, 2]],
|
||||||
|
['CTFnU2nwy9s1_kBj', 'hEHqR0idFTzbvG193aLYj6y2DFPi2UKQut_A--43PdN1XF', [6, 84, 156, 248, 125, 55, 230, 121]],
|
||||||
|
['CAhom0f872WEDXP6', 'dmX', [203, 98, 175, 172, 19, 3, 244, 177]],
|
||||||
|
['aON1dHrq90SbG8Hx', 'v7LyiwuCrB7EgAibPve6Yg2gLmggxE6j7ocR37EudrH_P9XX2rQK', [147, 73, 50, 63, 71, 98, 203, 42]]
|
||||||
|
]
|
||||||
|
|
||||||
|
test('crypto_shorthash', function (t) {
|
||||||
|
const out = Buffer.alloc(sodium.crypto_shorthash_BYTES)
|
||||||
|
const inp = Buffer.from('Hej, Verden!')
|
||||||
|
const key = Buffer.alloc(sodium.crypto_shorthash_KEYBYTES)
|
||||||
|
|
||||||
|
t.exception.all(function () {
|
||||||
|
sodium.crypto_shorthash(Buffer.alloc(0), inp)
|
||||||
|
}, 'throws on bad input')
|
||||||
|
|
||||||
|
sodium.crypto_shorthash(out, inp, key)
|
||||||
|
|
||||||
|
const result = '6a29984f782e684e'
|
||||||
|
t.alike(out.toString('hex'), result, 'hashed the string')
|
||||||
|
})
|
||||||
|
|
||||||
|
test('constants', function (assert) {
|
||||||
|
assert.ok(sodium.crypto_shorthash_PRIMITIVE)
|
||||||
|
assert.ok(sodium.crypto_shorthash_KEYBYTES > 0)
|
||||||
|
assert.ok(sodium.crypto_shorthash_BYTES > 0)
|
||||||
|
assert.end()
|
||||||
|
})
|
||||||
|
|
||||||
|
test('crypto_shorthash fixtures', function (assert) {
|
||||||
|
run(assert)
|
||||||
|
})
|
||||||
|
|
||||||
|
test('crypto_shorthash fixtures (wasm)', function (assert) {
|
||||||
|
if (!sodium.crypto_shorthash_WASM_SUPPORTED) {
|
||||||
|
assert.pass('wasm not supported')
|
||||||
|
assert.end()
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
assert.ok(sodium.crypto_shorthash_WASM_LOADED)
|
||||||
|
run(assert)
|
||||||
|
})
|
||||||
|
|
||||||
|
function run (assert) {
|
||||||
|
for (let i = 0; i < vectors.length; i++) {
|
||||||
|
const v = vectors[i]
|
||||||
|
const key = Buffer.from(v[0])
|
||||||
|
const message = Buffer.from(v[1])
|
||||||
|
const expected = Buffer.from(v[2])
|
||||||
|
const out = Buffer.alloc(sodium.crypto_shorthash_BYTES)
|
||||||
|
|
||||||
|
sodium.crypto_shorthash(out, message, key)
|
||||||
|
if (Buffer.compare(out, expected) !== 0) {
|
||||||
|
assert.fail('Failed on fixture #' + i)
|
||||||
|
assert.end()
|
||||||
|
return
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
assert.pass('Passed all fixtures')
|
||||||
|
assert.end()
|
||||||
|
}
|
334
test/crypto_sign.js
Normal file
334
test/crypto_sign.js
Normal file
@ -0,0 +1,334 @@
|
|||||||
|
/* eslint-disable camelcase */
|
||||||
|
const test = require('brittle')
|
||||||
|
const sodium = require('..')
|
||||||
|
const fixtures = require('./fixtures/crypto_sign.json')
|
||||||
|
|
||||||
|
test('crypto_sign_ed25519_sk_to_pk', function (t) {
|
||||||
|
const pk = Buffer.alloc(sodium.crypto_sign_PUBLICKEYBYTES)
|
||||||
|
const pke = Buffer.alloc(sodium.crypto_sign_PUBLICKEYBYTES)
|
||||||
|
const sk = Buffer.alloc(sodium.crypto_sign_SECRETKEYBYTES)
|
||||||
|
|
||||||
|
sodium.crypto_sign_keypair(pk, sk)
|
||||||
|
sodium.crypto_sign_ed25519_sk_to_pk(pke, sk)
|
||||||
|
|
||||||
|
t.ok(pk.equals(pke))
|
||||||
|
})
|
||||||
|
|
||||||
|
test('crypto_sign_seed_keypair', function (t) {
|
||||||
|
const pk = Buffer.alloc(sodium.crypto_sign_PUBLICKEYBYTES)
|
||||||
|
const sk = Buffer.alloc(sodium.crypto_sign_SECRETKEYBYTES)
|
||||||
|
const seed = Buffer.alloc(sodium.crypto_sign_SEEDBYTES, 'lo')
|
||||||
|
|
||||||
|
t.exception.all(function () {
|
||||||
|
sodium.crypto_sign_seed_keypair()
|
||||||
|
}, 'should validate input')
|
||||||
|
|
||||||
|
t.exception.all(function () {
|
||||||
|
sodium.crypto_sign_seed_keypair(Buffer.alloc(0), Buffer.alloc(0), Buffer.alloc(0))
|
||||||
|
}, 'should validate input length')
|
||||||
|
|
||||||
|
sodium.crypto_sign_seed_keypair(pk, sk, seed)
|
||||||
|
|
||||||
|
const eSk = '6c6f6c6f6c6f6c6f6c6f6c6f6c6f6c6f6c6f6c6f6c6f6c6f6c6f6c6f6c6f6c6f41eb5b4dba29b19e391d9a4d1a4a879b27958ff3734e10cfbf1f46d68f4d3038'
|
||||||
|
const ePk = '41eb5b4dba29b19e391d9a4d1a4a879b27958ff3734e10cfbf1f46d68f4d3038'
|
||||||
|
|
||||||
|
t.alike(pk.toString('hex'), ePk, 'seeded public key')
|
||||||
|
t.alike(sk.toString('hex'), eSk, 'seeded secret key')
|
||||||
|
})
|
||||||
|
|
||||||
|
test('crypto_sign_keypair', function (t) {
|
||||||
|
const pk = Buffer.alloc(sodium.crypto_sign_PUBLICKEYBYTES)
|
||||||
|
const sk = Buffer.alloc(sodium.crypto_sign_SECRETKEYBYTES)
|
||||||
|
|
||||||
|
sodium.crypto_sign_keypair(pk, sk)
|
||||||
|
|
||||||
|
t.not(pk, Buffer.alloc(pk.length), 'made public key')
|
||||||
|
t.not(sk, Buffer.alloc(sk.length), 'made secret key')
|
||||||
|
|
||||||
|
t.exception.all(function () {
|
||||||
|
sodium.crypto_sign_keypair()
|
||||||
|
}, 'should validate input')
|
||||||
|
|
||||||
|
t.exception.all(function () {
|
||||||
|
sodium.crypto_sign_keypair(Buffer.alloc(0), Buffer.alloc(0))
|
||||||
|
}, 'should validate input length')
|
||||||
|
})
|
||||||
|
|
||||||
|
test('crypto_sign', function (t) {
|
||||||
|
const pk = Buffer.alloc(sodium.crypto_sign_PUBLICKEYBYTES)
|
||||||
|
const sk = Buffer.alloc(sodium.crypto_sign_SECRETKEYBYTES)
|
||||||
|
|
||||||
|
sodium.crypto_sign_keypair(pk, sk)
|
||||||
|
|
||||||
|
const message = Buffer.from('Hello, World!')
|
||||||
|
const signedMessage = Buffer.alloc(message.length + sodium.crypto_sign_BYTES)
|
||||||
|
|
||||||
|
sodium.crypto_sign(signedMessage, message, sk)
|
||||||
|
|
||||||
|
t.alike(signedMessage.slice(-message.length), message, 'contains message')
|
||||||
|
|
||||||
|
const output = Buffer.alloc(message.length)
|
||||||
|
|
||||||
|
t.absent(sodium.crypto_sign_open(output, Buffer.alloc(signedMessage.length), pk), 'was not signed')
|
||||||
|
t.ok(sodium.crypto_sign_open(output, signedMessage, pk), 'was signed')
|
||||||
|
|
||||||
|
t.alike(output, message, 'same message')
|
||||||
|
})
|
||||||
|
|
||||||
|
test('crypto_sign_detached', function (t) {
|
||||||
|
const pk = Buffer.alloc(sodium.crypto_sign_PUBLICKEYBYTES)
|
||||||
|
const sk = Buffer.alloc(sodium.crypto_sign_SECRETKEYBYTES)
|
||||||
|
|
||||||
|
sodium.crypto_sign_keypair(pk, sk)
|
||||||
|
|
||||||
|
const message = Buffer.from('Hello, World!')
|
||||||
|
const signature = Buffer.alloc(sodium.crypto_sign_BYTES)
|
||||||
|
|
||||||
|
sodium.crypto_sign_detached(signature, message, sk)
|
||||||
|
|
||||||
|
t.absent(sodium.crypto_sign_verify_detached(Buffer.concat([Buffer.alloc(1), signature]), message, pk), 'was not signed')
|
||||||
|
t.ok(sodium.crypto_sign_verify_detached(signature, message, pk), 'was signed')
|
||||||
|
})
|
||||||
|
|
||||||
|
test('crypto_sign_open fixtures', function (t) {
|
||||||
|
for (let i = 0; i < fixtures.length; i++) {
|
||||||
|
const publicKey = new Uint8Array(fixtures[i][1])
|
||||||
|
const message = new Uint8Array(fixtures[i][3])
|
||||||
|
const signed = new Uint8Array([].concat(fixtures[i][2], fixtures[i][3]))
|
||||||
|
|
||||||
|
if (!sodium.crypto_sign_open(message, signed, publicKey)) {
|
||||||
|
t.fail('Failed on fixture #' + i)
|
||||||
|
t.end()
|
||||||
|
return
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
t.pass('Passed all fixtures')
|
||||||
|
t.end()
|
||||||
|
})
|
||||||
|
|
||||||
|
test('crypto_sign fixtures', function (t) {
|
||||||
|
const fixtures = require('./fixtures/crypto_sign.json')
|
||||||
|
|
||||||
|
for (let i = 0; i < fixtures.length; i++) {
|
||||||
|
const secretKey = new Uint8Array([].concat(fixtures[i][0], fixtures[i][1]))
|
||||||
|
const message = new Uint8Array(fixtures[i][3])
|
||||||
|
|
||||||
|
const expected = new Uint8Array([].concat(fixtures[i][2], fixtures[i][3]))
|
||||||
|
const actual = new Uint8Array(sodium.crypto_sign_BYTES + message.length)
|
||||||
|
|
||||||
|
sodium.crypto_sign(actual, message, secretKey)
|
||||||
|
|
||||||
|
if (Buffer.compare(actual, expected) !== 0) {
|
||||||
|
t.fail('Failed on fixture #' + i)
|
||||||
|
t.end()
|
||||||
|
return
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
t.pass('Passed all fixtures')
|
||||||
|
t.end()
|
||||||
|
})
|
||||||
|
|
||||||
|
test('crypto_sign_verify_detached fixtures', function (t) {
|
||||||
|
const fixtures = require('./fixtures/crypto_sign.json')
|
||||||
|
|
||||||
|
for (let i = 0; i < fixtures.length; i++) {
|
||||||
|
const publicKey = new Uint8Array(fixtures[i][1])
|
||||||
|
const message = new Uint8Array(fixtures[i][3])
|
||||||
|
const signature = new Uint8Array(fixtures[i][2])
|
||||||
|
|
||||||
|
if (!sodium.crypto_sign_verify_detached(signature, message, publicKey)) {
|
||||||
|
t.fail('Failed on fixture #' + i)
|
||||||
|
t.end()
|
||||||
|
return
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
t.pass('Passed all fixtures')
|
||||||
|
t.end()
|
||||||
|
})
|
||||||
|
|
||||||
|
test('crypto_sign_detached fixtures', function (t) {
|
||||||
|
const fixtures = require('./fixtures/crypto_sign.json')
|
||||||
|
|
||||||
|
for (let i = 0; i < fixtures.length; i++) {
|
||||||
|
const secretKey = new Uint8Array([].concat(fixtures[i][0], fixtures[i][1]))
|
||||||
|
const message = new Uint8Array(fixtures[i][3])
|
||||||
|
|
||||||
|
const expected = new Uint8Array(fixtures[i][2])
|
||||||
|
const actual = new Uint8Array(sodium.crypto_sign_BYTES)
|
||||||
|
|
||||||
|
sodium.crypto_sign_detached(actual, message, secretKey)
|
||||||
|
|
||||||
|
if (Buffer.compare(actual, expected) !== 0) {
|
||||||
|
t.fail('Failed on fixture #' + i)
|
||||||
|
t.end()
|
||||||
|
return
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
t.pass('Passed all fixtures')
|
||||||
|
t.end()
|
||||||
|
})
|
||||||
|
|
||||||
|
/* eslint-disable camelcase */
|
||||||
|
test('libsodium', function (t) {
|
||||||
|
const sig = new Uint8Array(sodium.crypto_sign_BYTES)
|
||||||
|
const sm = new Uint8Array(1024 + sodium.crypto_sign_BYTES)
|
||||||
|
const skpk = new Uint8Array(sodium.crypto_sign_SECRETKEYBYTES)
|
||||||
|
const pk = new Uint8Array(sodium.crypto_sign_PUBLICKEYBYTES)
|
||||||
|
const sk = new Uint8Array(sodium.crypto_sign_SECRETKEYBYTES)
|
||||||
|
|
||||||
|
let smlen
|
||||||
|
let i
|
||||||
|
let test
|
||||||
|
|
||||||
|
sig.fill(0)
|
||||||
|
|
||||||
|
let pass = true
|
||||||
|
for (i = 0; i < fixtures.length; i++) {
|
||||||
|
test = parseTest(fixtures[i])
|
||||||
|
|
||||||
|
skpk.set(test.sk)
|
||||||
|
skpk.set(test.pk, sodium.crypto_sign_SEEDBYTES)
|
||||||
|
|
||||||
|
smlen = sodium.crypto_sign_BYTES + test.m.byteLength
|
||||||
|
|
||||||
|
sodium.crypto_sign(sm.subarray(0, test.m.byteLength + sodium.crypto_sign_BYTES), test.m, skpk)
|
||||||
|
pass &= Buffer.compare(test.sig, sm.subarray(0, 64)) === 0
|
||||||
|
pass &= sodium.crypto_sign_open(test.m, sm.subarray(0, smlen), test.pk)
|
||||||
|
|
||||||
|
sodium.crypto_sign_detached(sig, test.m, skpk)
|
||||||
|
|
||||||
|
pass &= sig.byteLength !== 0 && sig.byteLength <= sodium.crypto_sign_BYTES
|
||||||
|
pass &= Buffer.compare(test.sig, sig) === 0
|
||||||
|
pass &= sodium.crypto_sign_verify_detached(sig, test.m.subarray(0, i), test.pk)
|
||||||
|
|
||||||
|
if (!pass) t.fail('failed on fixture #' + i)
|
||||||
|
}
|
||||||
|
t.pass('passed all fixtures')
|
||||||
|
|
||||||
|
for (let j = 1; j < 8; j++) {
|
||||||
|
sig[63] ^= (j << 5)
|
||||||
|
|
||||||
|
t.absent(sodium.crypto_sign_verify_detached(sig, test.m.subarray(0, i), test.pk))
|
||||||
|
|
||||||
|
sig[63] ^= (j << 5)
|
||||||
|
}
|
||||||
|
|
||||||
|
pk.fill(0)
|
||||||
|
t.absent(sodium.crypto_sign_verify_detached(sig, test.m.subarray(0, i), pk))
|
||||||
|
|
||||||
|
sig.subarray(0, 32).fill(0xff)
|
||||||
|
sig[0] = 0xdb
|
||||||
|
|
||||||
|
t.absent(sodium.crypto_sign_verify_detached(sig, test.m.subarray(0, i), pk))
|
||||||
|
sodium.crypto_sign_detached(sig, test.m.subarray(0, i), skpk)
|
||||||
|
|
||||||
|
hex2bin(pk, '3eee494fb9eac773144e34b0c755affaf33ea782c0722e5ea8b150e61209ab36')
|
||||||
|
t.absent(sodium.crypto_sign_verify_detached(sig, test.m.subarray(0, i), pk))
|
||||||
|
|
||||||
|
hex2bin(pk, '0200000000000000000000000000000000000000000000000000000000000000')
|
||||||
|
t.absent(sodium.crypto_sign_verify_detached(sig, test.m.subarray(0, i), pk))
|
||||||
|
|
||||||
|
hex2bin(pk, '0500000000000000000000000000000000000000000000000000000000000000')
|
||||||
|
t.absent(sodium.crypto_sign_verify_detached(sig, test.m.subarray(0, i), pk))
|
||||||
|
|
||||||
|
const keypair_seed = new Uint8Array([
|
||||||
|
0x42, 0x11, 0x51, 0xa4, 0x59, 0xfa, 0xea, 0xde, 0x3d, 0x24, 0x71,
|
||||||
|
0x15, 0xf9, 0x4a, 0xed, 0xae, 0x42, 0x31, 0x81, 0x24, 0x09, 0x5a,
|
||||||
|
0xfa, 0xbe, 0x4d, 0x14, 0x51, 0xa5, 0x59, 0xfa, 0xed, 0xee
|
||||||
|
])
|
||||||
|
|
||||||
|
t.execution(() => sodium.crypto_sign_seed_keypair(pk, sk, keypair_seed))
|
||||||
|
t.execution(() => sodium.crypto_sign_keypair(pk, sk))
|
||||||
|
|
||||||
|
t.ok(sodium.crypto_sign_BYTES > 0)
|
||||||
|
t.ok(sodium.crypto_sign_SEEDBYTES > 0)
|
||||||
|
t.ok(sodium.crypto_sign_PUBLICKEYBYTES > 0)
|
||||||
|
t.ok(sodium.crypto_sign_SECRETKEYBYTES > 0)
|
||||||
|
t.is(sodium.crypto_sign_BYTES, 64)
|
||||||
|
t.is(sodium.crypto_sign_SEEDBYTES, 32)
|
||||||
|
t.is(sodium.crypto_sign_PUBLICKEYBYTES, 32)
|
||||||
|
t.is(sodium.crypto_sign_SECRETKEYBYTES, 64)
|
||||||
|
|
||||||
|
t.end()
|
||||||
|
})
|
||||||
|
|
||||||
|
test('ed25519 convert', function (t) {
|
||||||
|
const keypair_seed = new Uint8Array([
|
||||||
|
0x42, 0x11, 0x51, 0xa4, 0x59, 0xfa, 0xea, 0xde, 0x3d, 0x24, 0x71,
|
||||||
|
0x15, 0xf9, 0x4a, 0xed, 0xae, 0x42, 0x31, 0x81, 0x24, 0x09, 0x5a,
|
||||||
|
0xfa, 0xbe, 0x4d, 0x14, 0x51, 0xa5, 0x59, 0xfa, 0xed, 0xee
|
||||||
|
])
|
||||||
|
|
||||||
|
const ed25519_pk = new Uint8Array(sodium.crypto_sign_PUBLICKEYBYTES)
|
||||||
|
const ed25519_skpk = new Uint8Array(sodium.crypto_sign_SECRETKEYBYTES)
|
||||||
|
const curve25519_pk = new Uint8Array(sodium.crypto_scalarmult_BYTES)
|
||||||
|
const curve25519_pk2 = new Uint8Array(sodium.crypto_scalarmult_BYTES)
|
||||||
|
const curve25519_sk = new Uint8Array(sodium.crypto_scalarmult_BYTES)
|
||||||
|
|
||||||
|
t.ok(sodium.crypto_sign_SEEDBYTES <= sodium.crypto_hash_sha512_BYTES)
|
||||||
|
|
||||||
|
sodium.crypto_sign_seed_keypair(ed25519_pk, ed25519_skpk, keypair_seed)
|
||||||
|
sodium.crypto_sign_ed25519_pk_to_curve25519(curve25519_pk, ed25519_pk)
|
||||||
|
sodium.crypto_sign_ed25519_sk_to_curve25519(curve25519_sk, ed25519_skpk)
|
||||||
|
|
||||||
|
const expected_pk = new Uint8Array([
|
||||||
|
0xf1, 0x81, 0x4f, 0x0e, 0x8f, 0xf1, 0x04, 0x3d, 0x8a, 0x44, 0xd2, 0x5b,
|
||||||
|
0xab, 0xff, 0x3c, 0xed, 0xca, 0xe6, 0xc2, 0x2c, 0x3e, 0xda, 0xa4, 0x8f,
|
||||||
|
0x85, 0x7a, 0xe7, 0x0d, 0xe2, 0xba, 0xae, 0x50
|
||||||
|
])
|
||||||
|
|
||||||
|
const expected_sk = new Uint8Array([
|
||||||
|
0x80, 0x52, 0x03, 0x03, 0x76, 0xd4, 0x71, 0x12, 0xbe, 0x7f, 0x73, 0xed,
|
||||||
|
0x7a, 0x01, 0x92, 0x93, 0xdd, 0x12, 0xad, 0x91, 0x0b, 0x65, 0x44, 0x55,
|
||||||
|
0x79, 0x8b, 0x46, 0x67, 0xd7, 0x3d, 0xe1, 0x66
|
||||||
|
])
|
||||||
|
|
||||||
|
t.alike(curve25519_pk, expected_pk)
|
||||||
|
t.alike(curve25519_sk, expected_sk)
|
||||||
|
|
||||||
|
for (let i = 0; i < 500; i++) {
|
||||||
|
sodium.crypto_sign_keypair(ed25519_pk, ed25519_skpk)
|
||||||
|
sodium.crypto_sign_ed25519_pk_to_curve25519(curve25519_pk, ed25519_pk)
|
||||||
|
|
||||||
|
sodium.crypto_sign_ed25519_sk_to_curve25519(curve25519_sk, ed25519_skpk)
|
||||||
|
sodium.crypto_scalarmult_base(curve25519_pk2, curve25519_sk)
|
||||||
|
if (Buffer.compare(curve25519_pk, curve25519_pk2) !== 0) t.fail()
|
||||||
|
}
|
||||||
|
t.pass('passed all cases')
|
||||||
|
|
||||||
|
ed25519_pk.fill(0)
|
||||||
|
t.exception(() => {
|
||||||
|
sodium.crypto_sign_ed25519_pk_to_curve25519(curve25519_pk, ed25519_pk)
|
||||||
|
})
|
||||||
|
|
||||||
|
t.exception(() => {
|
||||||
|
ed25519_pk[0] = 2
|
||||||
|
sodium.crypto_sign_ed25519_pk_to_curve25519(curve25519_pk, ed25519_pk)
|
||||||
|
})
|
||||||
|
|
||||||
|
t.exception(() => {
|
||||||
|
ed25519_pk[0] = 5
|
||||||
|
sodium.crypto_sign_ed25519_pk_to_curve25519(curve25519_pk, ed25519_pk)
|
||||||
|
})
|
||||||
|
|
||||||
|
t.end()
|
||||||
|
})
|
||||||
|
|
||||||
|
function parseTest (t) {
|
||||||
|
return {
|
||||||
|
sk: new Uint8Array(t[0]),
|
||||||
|
pk: new Uint8Array(t[1]),
|
||||||
|
sig: new Uint8Array(t[2]),
|
||||||
|
m: new Uint8Array(t[3])
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
function hex2bin (buf, hex) {
|
||||||
|
for (let i = 0; i < hex.length / 2; i++) {
|
||||||
|
buf[i] = Number('0x' + hex.slice(2 * i, 2 * i + 1))
|
||||||
|
}
|
||||||
|
}
|
213
test/crypto_stream.js
Normal file
213
test/crypto_stream.js
Normal file
@ -0,0 +1,213 @@
|
|||||||
|
/* eslint-disable camelcase */
|
||||||
|
const test = require('brittle')
|
||||||
|
const sodium = require('..')
|
||||||
|
|
||||||
|
test('crypto_stream', function (t) {
|
||||||
|
const buf = Buffer.alloc(50)
|
||||||
|
const nonce = random(sodium.crypto_stream_NONCEBYTES)
|
||||||
|
const key = random(sodium.crypto_stream_KEYBYTES)
|
||||||
|
|
||||||
|
sodium.crypto_stream(buf, nonce, key)
|
||||||
|
|
||||||
|
t.not(buf, Buffer.alloc(50), 'contains noise now')
|
||||||
|
const copy = Buffer.from(buf.toString('hex'), 'hex')
|
||||||
|
|
||||||
|
sodium.crypto_stream(buf, nonce, key)
|
||||||
|
t.alike(buf, copy, 'predictable from nonce, key')
|
||||||
|
})
|
||||||
|
|
||||||
|
test('crypto_stream_xor', function (t) {
|
||||||
|
const message = Buffer.from('Hello, World!')
|
||||||
|
const nonce = random(sodium.crypto_stream_NONCEBYTES)
|
||||||
|
const key = random(sodium.crypto_stream_KEYBYTES)
|
||||||
|
|
||||||
|
sodium.crypto_stream_xor(message, message, nonce, key)
|
||||||
|
|
||||||
|
t.not(message, Buffer.from('Hello, World!'), 'encrypted')
|
||||||
|
|
||||||
|
sodium.crypto_stream_xor(message, message, nonce, key)
|
||||||
|
|
||||||
|
t.alike(message, Buffer.from('Hello, World!'), 'decrypted')
|
||||||
|
})
|
||||||
|
|
||||||
|
test.skip('crypto_stream_xor state', function (t) {
|
||||||
|
const message = Buffer.from('Hello, world!')
|
||||||
|
const nonce = random(sodium.crypto_stream_NONCEBYTES)
|
||||||
|
const key = random(sodium.crypto_stream_KEYBYTES)
|
||||||
|
|
||||||
|
const out = Buffer.alloc(message.length)
|
||||||
|
|
||||||
|
const state = Buffer.alloc(sodium.crypto_stream_xor_STATEBYTES)
|
||||||
|
sodium.crypto_stream_xor_init(state, nonce, key)
|
||||||
|
|
||||||
|
for (let i = 0; i < message.length; i++) {
|
||||||
|
sodium.crypto_stream_xor_update(state, out.slice(i, i + 1), message.slice(i, i + 1))
|
||||||
|
}
|
||||||
|
|
||||||
|
sodium.crypto_stream_xor_final(state)
|
||||||
|
sodium.crypto_stream_xor(out, out, nonce, key)
|
||||||
|
t.alike(out, message, 'decrypted')
|
||||||
|
})
|
||||||
|
|
||||||
|
test.skip('crypto_stream_xor state with empty buffers', function (t) {
|
||||||
|
const message = Buffer.from('Hello, world!')
|
||||||
|
const nonce = random(sodium.crypto_stream_NONCEBYTES)
|
||||||
|
const key = random(sodium.crypto_stream_KEYBYTES)
|
||||||
|
|
||||||
|
const out = Buffer.alloc(message.length)
|
||||||
|
|
||||||
|
const state = Buffer.alloc(sodium.crypto_stream_xor_STATEBYTES)
|
||||||
|
sodium.crypto_stream_xor_init(state, nonce, key)
|
||||||
|
|
||||||
|
sodium.crypto_stream_xor_update(state, Buffer.alloc(0), Buffer.alloc(0))
|
||||||
|
|
||||||
|
for (let i = 0; i < message.length; i++) {
|
||||||
|
sodium.crypto_stream_xor_update(state, out.slice(i, i + 1), message.slice(i, i + 1))
|
||||||
|
sodium.crypto_stream_xor_update(state, Buffer.alloc(0), Buffer.alloc(0))
|
||||||
|
}
|
||||||
|
|
||||||
|
sodium.crypto_stream_xor_final(state)
|
||||||
|
sodium.crypto_stream_xor(out, out, nonce, key)
|
||||||
|
t.alike(out, message, 'decrypted')
|
||||||
|
})
|
||||||
|
|
||||||
|
test.skip('crypto_stream_xor state long stream', function (t) {
|
||||||
|
const nonce = random(sodium.crypto_stream_NONCEBYTES)
|
||||||
|
const key = random(sodium.crypto_stream_KEYBYTES)
|
||||||
|
|
||||||
|
const encState = Buffer.alloc(sodium.crypto_stream_xor_STATEBYTES)
|
||||||
|
const decState = Buffer.alloc(sodium.crypto_stream_xor_STATEBYTES)
|
||||||
|
|
||||||
|
sodium.crypto_stream_xor_init(encState, nonce, key)
|
||||||
|
sodium.crypto_stream_xor_init(decState, nonce, key)
|
||||||
|
const plain = []
|
||||||
|
const encrypted = []
|
||||||
|
const decrypted = []
|
||||||
|
|
||||||
|
for (let i = 0; i < 1000; i++) {
|
||||||
|
const next = random(61)
|
||||||
|
plain.push(next)
|
||||||
|
|
||||||
|
const enc = Buffer.alloc(61)
|
||||||
|
sodium.crypto_stream_xor_update(encState, enc, next)
|
||||||
|
encrypted.push(enc)
|
||||||
|
|
||||||
|
const dec = Buffer.alloc(61)
|
||||||
|
sodium.crypto_stream_xor_update(decState, dec, enc)
|
||||||
|
decrypted.push(dec)
|
||||||
|
}
|
||||||
|
|
||||||
|
const enc2 = Buffer.alloc(1000 * 61)
|
||||||
|
sodium.crypto_stream_xor(enc2, Buffer.concat(plain), nonce, key)
|
||||||
|
|
||||||
|
t.alike(Buffer.concat(encrypted), enc2, 'same as encrypting all at once')
|
||||||
|
t.alike(Buffer.concat(decrypted), Buffer.concat(plain), 'decrypts')
|
||||||
|
})
|
||||||
|
|
||||||
|
test.skip('crypto_stream_xor state long stream (random chunks)', function (t) {
|
||||||
|
const nonce = random(sodium.crypto_stream_NONCEBYTES)
|
||||||
|
const key = random(sodium.crypto_stream_KEYBYTES)
|
||||||
|
|
||||||
|
const encState = Buffer.alloc(sodium.crypto_stream_xor_STATEBYTES)
|
||||||
|
const decState = Buffer.alloc(sodium.crypto_stream_xor_STATEBYTES)
|
||||||
|
|
||||||
|
sodium.crypto_stream_xor_init(encState, nonce, key)
|
||||||
|
sodium.crypto_stream_xor_init(decState, nonce, key)
|
||||||
|
const plain = []
|
||||||
|
const encrypted = []
|
||||||
|
const decrypted = []
|
||||||
|
|
||||||
|
for (let i = 0; i < 10000; i++) {
|
||||||
|
const len = Math.floor(Math.random() * 256)
|
||||||
|
const next = random(len)
|
||||||
|
plain.push(next)
|
||||||
|
|
||||||
|
const enc = Buffer.alloc(len)
|
||||||
|
sodium.crypto_stream_xor_update(encState, enc, next)
|
||||||
|
encrypted.push(enc)
|
||||||
|
|
||||||
|
const dec = Buffer.alloc(len)
|
||||||
|
sodium.crypto_stream_xor_update(decState, dec, enc)
|
||||||
|
decrypted.push(dec)
|
||||||
|
}
|
||||||
|
|
||||||
|
const enc2 = Buffer.alloc(Buffer.concat(plain).length)
|
||||||
|
sodium.crypto_stream_xor(enc2, Buffer.concat(plain), nonce, key)
|
||||||
|
|
||||||
|
t.alike(Buffer.concat(encrypted), enc2, 'same as encrypting all at once')
|
||||||
|
t.alike(Buffer.concat(decrypted), Buffer.concat(plain), 'decrypts')
|
||||||
|
})
|
||||||
|
|
||||||
|
test.skip('crypto_stream_xor state long stream (random chunks) with empty buffers', function (t) {
|
||||||
|
const nonce = random(sodium.crypto_stream_NONCEBYTES)
|
||||||
|
const key = random(sodium.crypto_stream_KEYBYTES)
|
||||||
|
|
||||||
|
const encState = Buffer.alloc(sodium.crypto_stream_xor_STATEBYTES)
|
||||||
|
const decState = Buffer.alloc(sodium.crypto_stream_xor_STATEBYTES)
|
||||||
|
|
||||||
|
sodium.crypto_stream_xor_init(encState, nonce, key)
|
||||||
|
sodium.crypto_stream_xor_init(decState, nonce, key)
|
||||||
|
const plain = []
|
||||||
|
const encrypted = []
|
||||||
|
const decrypted = []
|
||||||
|
|
||||||
|
for (let i = 0; i < 10000; i++) {
|
||||||
|
const len = Math.floor(Math.random() * 256)
|
||||||
|
const next = random(len)
|
||||||
|
plain.push(next)
|
||||||
|
|
||||||
|
sodium.crypto_stream_xor_update(encState, Buffer.alloc(0), Buffer.alloc(0))
|
||||||
|
|
||||||
|
const enc = Buffer.alloc(len)
|
||||||
|
sodium.crypto_stream_xor_update(encState, enc, next)
|
||||||
|
encrypted.push(enc)
|
||||||
|
|
||||||
|
const dec = Buffer.alloc(len)
|
||||||
|
sodium.crypto_stream_xor_update(decState, dec, enc)
|
||||||
|
decrypted.push(dec)
|
||||||
|
sodium.crypto_stream_xor_update(decState, Buffer.alloc(0), Buffer.alloc(0))
|
||||||
|
}
|
||||||
|
|
||||||
|
const enc2 = Buffer.alloc(Buffer.concat(plain).length)
|
||||||
|
sodium.crypto_stream_xor(enc2, Buffer.concat(plain), nonce, key)
|
||||||
|
|
||||||
|
t.alike(Buffer.concat(encrypted), enc2, 'same as encrypting all at once')
|
||||||
|
t.alike(Buffer.concat(decrypted), Buffer.concat(plain), 'decrypts')
|
||||||
|
})
|
||||||
|
|
||||||
|
test.skip('crypto_stream_xor state after GC', function (t) {
|
||||||
|
const message = Buffer.from('Hello, world!')
|
||||||
|
let nonce = random(sodium.crypto_stream_NONCEBYTES)
|
||||||
|
let key = random(sodium.crypto_stream_KEYBYTES)
|
||||||
|
|
||||||
|
const out = Buffer.alloc(message.length)
|
||||||
|
|
||||||
|
const state = Buffer.alloc(sodium.crypto_stream_xor_STATEBYTES)
|
||||||
|
sodium.crypto_stream_xor_init(state, nonce, key)
|
||||||
|
|
||||||
|
const nonceCopy = Buffer.from(nonce.toString('hex'), 'hex')
|
||||||
|
const keyCopy = Buffer.from(key.toString('hex'), 'hex')
|
||||||
|
nonce = null
|
||||||
|
key = null
|
||||||
|
|
||||||
|
forceGC()
|
||||||
|
|
||||||
|
for (let i = 0; i < message.length; i++) {
|
||||||
|
sodium.crypto_stream_xor_update(state, out.slice(i, i + 1), message.slice(i, i + 1))
|
||||||
|
}
|
||||||
|
|
||||||
|
sodium.crypto_stream_xor_final(state)
|
||||||
|
sodium.crypto_stream_xor(out, out, nonceCopy, keyCopy)
|
||||||
|
t.alike(out, message, 'decrypted')
|
||||||
|
})
|
||||||
|
|
||||||
|
function random (n) {
|
||||||
|
const buf = Buffer.alloc(n)
|
||||||
|
sodium.randombytes_buf(buf)
|
||||||
|
return buf
|
||||||
|
}
|
||||||
|
|
||||||
|
function forceGC () {
|
||||||
|
require('v8').setFlagsFromString('--expose-gc')
|
||||||
|
require('vm').runInNewContext('gc')()
|
||||||
|
}
|
284
test/crypto_stream_chacha20.js
Normal file
284
test/crypto_stream_chacha20.js
Normal file
@ -0,0 +1,284 @@
|
|||||||
|
/* eslint-disable camelcase */
|
||||||
|
const test = require('brittle')
|
||||||
|
const sodium = require('..')
|
||||||
|
|
||||||
|
const tests = [
|
||||||
|
['0000000000000000000000000000000000000000000000000000000000000000', '0000000000000000', '76b8e0ada0f13d90405d6ae55386bd28bdd219b8a08ded1aa836efcc8b770dc7da41597c5157488d7724e03fb8d84a376a43b8f41518a11cc387b669b2ee65869f07e7be5551387a98ba977c732d080dcb0f29a048e3656912c6533e32ee7aed29b721769ce64e43d57133b074d839d531ed1f28510afb45ace10a1f4b794d6f2d09a0e663266ce1ae7ed1081968a0758e718e997bd362c6b0c34634a9a0b35d'],
|
||||||
|
['0000000000000000000000000000000000000000000000000000000000000001', '0000000000000000', '4540f05a9f1fb296d7736e7b208e3c96eb4fe1834688d2604f450952ed432d41bbe2a0b6ea7566d2a5d1e7e20d42af2c53d792b1c43fea817e9ad275ae5469633aeb5224ecf849929b9d828db1ced4dd832025e8018b8160b82284f3c949aa5a8eca00bbb4a73bdad192b5c42f73f2fd4e273644c8b36125a64addeb006c13a096d68b9ff7b57e7090f880392effd5b297a83bbaf2fbe8cf5d4618965e3dc776'],
|
||||||
|
['0000000000000000000000000000000000000000000000000000000000000000', '0000000000000001', 'de9cba7bf3d69ef5e786dc63973f653a0b49e015adbff7134fcb7df137821031e85a050278a7084527214f73efc7fa5b5277062eb7a0433e445f41e31afab757283547e3d3d30ee0371c1e6025ff4c91b794a291cf7568d48ff84b37329e2730b12738a072a2b2c7169e326fe4893a7b2421bb910b79599a7ce4fbaee86be427c5ee0e8225eb6f48231fd504939d59eac8bd106cc138779b893c54da8758f62a'],
|
||||||
|
['0000000000000000000000000000000000000000000000000000000000000000', '0100000000000000', 'ef3fdfd6c61578fbf5cf35bd3dd33b8009631634d21e42ac33960bd138e50d32111e4caf237ee53ca8ad6426194a88545ddc497a0b466e7d6bbdb0041b2f586b5305e5e44aff19b235936144675efbe4409eb7e8e5f1430f5f5836aeb49bb5328b017c4b9dc11f8a03863fa803dc71d5726b2b6b31aa32708afe5af1d6b690584d58792b271e5fdb92c486051c48b79a4d48a109bb2d0477956e74c25e93c3c2'],
|
||||||
|
['000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f', '0001020304050607', 'f798a189f195e66982105ffb640bb7757f579da31602fc93ec01ac56f85ac3c134a4547b733b46413042c9440049176905d3be59ea1c53f15916155c2be8241a38008b9a26bc35941e2444177c8ade6689de95264986d95889fb60e84629c9bd9a5acb1cc118be563eb9b3a4a472f82e09a7e778492b562ef7130e88dfe031c79db9d4f7c7a899151b9a475032b63fc385245fe054e3dd5a97a5f576fe064025']
|
||||||
|
]
|
||||||
|
|
||||||
|
const vectors = [
|
||||||
|
'f7010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101',
|
||||||
|
'f798a189040404040404040404040404040404040404040404040404040404040404040404040404040404040404040404040404040404040404040404040404040404040404040404040404040404040404040404040404040404040404040404040404040404040404040404040404040404040404040404040404040404040404040404040404040404040404040404040404040404040404040404040404',
|
||||||
|
'f798a189f195e6070707070707070707070707070707070707070707070707070707070707070707070707070707070707070707070707070707070707070707070707070707070707070707070707070707070707070707070707070707070707070707070707070707070707070707070707070707070707070707070707070707070707070707070707070707070707070707070707070707070707070707',
|
||||||
|
'f798a189f195e66982100a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0a',
|
||||||
|
'f798a189f195e66982105ffb640d0d0d0d0d0d0d0d0d0d0d0d0d0d0d0d0d0d0d0d0d0d0d0d0d0d0d0d0d0d0d0d0d0d0d0d0d0d0d0d0d0d0d0d0d0d0d0d0d0d0d0d0d0d0d0d0d0d0d0d0d0d0d0d0d0d0d0d0d0d0d0d0d0d0d0d0d0d0d0d0d0d0d0d0d0d0d0d0d0d0d0d0d0d0d0d0d0d0d0d0d0d0d0d0d0d0d0d0d0d0d0d0d0d0d0d0d0d0d0d0d0d0d0d0d0d0d0d0d0d0d0d0d0d0d0d0d0d0d0d0d0d0d0d0d0d0d',
|
||||||
|
'f798a189f195e66982105ffb640bb775101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010',
|
||||||
|
'f798a189f195e66982105ffb640bb7757f579d131313131313131313131313131313131313131313131313131313131313131313131313131313131313131313131313131313131313131313131313131313131313131313131313131313131313131313131313131313131313131313131313131313131313131313131313131313131313131313131313131313131313131313131313131313131313131313',
|
||||||
|
'f798a189f195e66982105ffb640bb7757f579da31602161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616',
|
||||||
|
'f798a189f195e66982105ffb640bb7757f579da31602fc93ec191919191919191919191919191919191919191919191919191919191919191919191919191919191919191919191919191919191919191919191919191919191919191919191919191919191919191919191919191919191919191919191919191919191919191919191919191919191919191919191919191919191919191919191919191919',
|
||||||
|
'f798a189f195e66982105ffb640bb7757f579da31602fc93ec01ac561c1c1c1c1c1c1c1c1c1c1c1c1c1c1c1c1c1c1c1c1c1c1c1c1c1c1c1c1c1c1c1c1c1c1c1c1c1c1c1c1c1c1c1c1c1c1c1c1c1c1c1c1c1c1c1c1c1c1c1c1c1c1c1c1c1c1c1c1c1c1c1c1c1c1c1c1c1c1c1c1c1c1c1c1c1c1c1c1c1c1c1c1c1c1c1c1c1c1c1c1c1c1c1c1c1c1c1c1c1c1c1c1c1c1c1c1c1c1c1c1c1c1c1c1c1c1c1c1c1c1c1c',
|
||||||
|
'f798a189f195e66982105ffb640bb7757f579da31602fc93ec01ac56f85ac31f1f1f1f1f1f1f1f1f1f1f1f1f1f1f1f1f1f1f1f1f1f1f1f1f1f1f1f1f1f1f1f1f1f1f1f1f1f1f1f1f1f1f1f1f1f1f1f1f1f1f1f1f1f1f1f1f1f1f1f1f1f1f1f1f1f1f1f1f1f1f1f1f1f1f1f1f1f1f1f1f1f1f1f1f1f1f1f1f1f1f1f1f1f1f1f1f1f1f1f1f1f1f1f1f1f1f1f1f1f1f1f1f1f1f1f1f1f1f1f1f1f1f1f1f1f1f1f1f',
|
||||||
|
'f798a189f195e66982105ffb640bb7757f579da31602fc93ec01ac56f85ac3c134a4222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222',
|
||||||
|
'f798a189f195e66982105ffb640bb7757f579da31602fc93ec01ac56f85ac3c134a4547b73252525252525252525252525252525252525252525252525252525252525252525252525252525252525252525252525252525252525252525252525252525252525252525252525252525252525252525252525252525252525252525252525252525252525252525252525252525252525252525252525252525',
|
||||||
|
'f798a189f195e66982105ffb640bb7757f579da31602fc93ec01ac56f85ac3c134a4547b733b4641282828282828282828282828282828282828282828282828282828282828282828282828282828282828282828282828282828282828282828282828282828282828282828282828282828282828282828282828282828282828282828282828282828282828282828282828282828282828282828282828',
|
||||||
|
'f798a189f195e66982105ffb640bb7757f579da31602fc93ec01ac56f85ac3c134a4547b733b46413042c92b2b2b2b2b2b2b2b2b2b2b2b2b2b2b2b2b2b2b2b2b2b2b2b2b2b2b2b2b2b2b2b2b2b2b2b2b2b2b2b2b2b2b2b2b2b2b2b2b2b2b2b2b2b2b2b2b2b2b2b2b2b2b2b2b2b2b2b2b2b2b2b2b2b2b2b2b2b2b2b2b2b2b2b2b2b2b2b2b2b2b2b2b2b2b2b2b2b2b2b2b2b2b2b2b2b2b2b2b2b2b2b2b2b2b2b2b',
|
||||||
|
'f798a189f195e66982105ffb640bb7757f579da31602fc93ec01ac56f85ac3c134a4547b733b46413042c94400492e2e2e2e2e2e2e2e2e2e2e2e2e2e2e2e2e2e2e2e2e2e2e2e2e2e2e2e2e2e2e2e2e2e2e2e2e2e2e2e2e2e2e2e2e2e2e2e2e2e2e2e2e2e2e2e2e2e2e2e2e2e2e2e2e2e2e2e2e2e2e2e2e2e2e2e2e2e2e2e2e2e2e2e2e2e2e2e2e2e2e2e2e2e2e2e2e2e2e2e2e2e2e2e2e2e2e2e2e2e2e2e2e2e',
|
||||||
|
'f798a189f195e66982105ffb640bb7757f579da31602fc93ec01ac56f85ac3c134a4547b733b46413042c9440049176905313131313131313131313131313131313131313131313131313131313131313131313131313131313131313131313131313131313131313131313131313131313131313131313131313131313131313131313131313131313131313131313131313131313131313131313131313131',
|
||||||
|
'f798a189f195e66982105ffb640bb7757f579da31602fc93ec01ac56f85ac3c134a4547b733b46413042c9440049176905d3be59343434343434343434343434343434343434343434343434343434343434343434343434343434343434343434343434343434343434343434343434343434343434343434343434343434343434343434343434343434343434343434343434343434343434343434343434',
|
||||||
|
'f798a189f195e66982105ffb640bb7757f579da31602fc93ec01ac56f85ac3c134a4547b733b46413042c9440049176905d3be59ea1c53373737373737373737373737373737373737373737373737373737373737373737373737373737373737373737373737373737373737373737373737373737373737373737373737373737373737373737373737373737373737373737373737373737373737373737',
|
||||||
|
'f798a189f195e66982105ffb640bb7757f579da31602fc93ec01ac56f85ac3c134a4547b733b46413042c9440049176905d3be59ea1c53f159163a3a3a3a3a3a3a3a3a3a3a3a3a3a3a3a3a3a3a3a3a3a3a3a3a3a3a3a3a3a3a3a3a3a3a3a3a3a3a3a3a3a3a3a3a3a3a3a3a3a3a3a3a3a3a3a3a3a3a3a3a3a3a3a3a3a3a3a3a3a3a3a3a3a3a3a3a3a3a3a3a3a3a3a3a3a3a3a3a3a3a3a3a3a3a3a3a3a3a3a3a3a',
|
||||||
|
'f798a189f195e66982105ffb640bb7757f579da31602fc93ec01ac56f85ac3c134a4547b733b46413042c9440049176905d3be59ea1c53f15916155c2b3d3d3d3d3d3d3d3d3d3d3d3d3d3d3d3d3d3d3d3d3d3d3d3d3d3d3d3d3d3d3d3d3d3d3d3d3d3d3d3d3d3d3d3d3d3d3d3d3d3d3d3d3d3d3d3d3d3d3d3d3d3d3d3d3d3d3d3d3d3d3d3d3d3d3d3d3d3d3d3d3d3d3d3d3d3d3d3d3d3d3d3d3d3d3d3d3d3d3d',
|
||||||
|
'f798a189f195e66982105ffb640bb7757f579da31602fc93ec01ac56f85ac3c134a4547b733b46413042c9440049176905d3be59ea1c53f15916155c2be8241a404040404040404040404040404040404040404040404040404040404040404040404040404040404040404040404040404040404040404040404040404040404040404040404040404040404040404040404040404040404040404040404040'
|
||||||
|
]
|
||||||
|
|
||||||
|
test('constants', function (t) {
|
||||||
|
t.ok(sodium.crypto_stream_chacha20_KEYBYTES > 0)
|
||||||
|
t.ok(sodium.crypto_stream_chacha20_NONCEBYTES > 0)
|
||||||
|
t.ok(sodium.crypto_stream_chacha20_MESSAGEBYTES_MAX > 0)
|
||||||
|
})
|
||||||
|
|
||||||
|
test('libsodium crypto_stream_chacha20', function (t) {
|
||||||
|
const key = Buffer.alloc(sodium.crypto_stream_chacha20_KEYBYTES)
|
||||||
|
const nonce = Buffer.alloc(sodium.crypto_stream_chacha20_NONCEBYTES)
|
||||||
|
|
||||||
|
const out = Buffer.alloc(160)
|
||||||
|
|
||||||
|
for (let i = 0; i < tests.length; i++) {
|
||||||
|
key.write(tests[i][0], 0, key.byteLength, 'hex')
|
||||||
|
nonce.write(tests[i][1], 0, nonce.byteLength, 'hex')
|
||||||
|
sodium.crypto_stream_chacha20(out, nonce, key)
|
||||||
|
t.alike(out, Buffer.from(tests[i][2], 'hex'))
|
||||||
|
for (let plen = 0; plen < out.byteLength; plen++) {
|
||||||
|
const part = Buffer.alloc(plen)
|
||||||
|
sodium.crypto_stream_chacha20_xor(part, out.subarray(0, plen), nonce, key)
|
||||||
|
if (part.every(b => b === 0) === false) return t.fail()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
for (let plen = 1, i = 0; plen < 66; plen += 3, i++) {
|
||||||
|
out.fill(plen & 0xff)
|
||||||
|
sodium.crypto_stream_chacha20(out.subarray(0, plen), nonce, key)
|
||||||
|
if (out.equals(Buffer.from(vectors[i], 'hex')) === false) return t.fail()
|
||||||
|
}
|
||||||
|
|
||||||
|
sodium.randombytes_buf(out)
|
||||||
|
sodium.crypto_stream_chacha20(out, nonce, key)
|
||||||
|
t.alike(out, Buffer.from('f798a189f195e66982105ffb640bb7757f579da31602fc93ec01ac56f85ac3c134a4547b733b46413042c9440049176905d3be59ea1c53f15916155c2be8241a38008b9a26bc35941e2444177c8ade6689de95264986d95889fb60e84629c9bd9a5acb1cc118be563eb9b3a4a472f82e09a7e778492b562ef7130e88dfe031c79db9d4f7c7a899151b9a475032b63fc385245fe054e3dd5a97a5f576fe064025', 'hex'))
|
||||||
|
|
||||||
|
t.execution(() => sodium.crypto_stream_chacha20(out.subarray(0, 0), nonce, key))
|
||||||
|
t.execution(() => sodium.crypto_stream_chacha20_xor(out.subarray(0, 0), Buffer.alloc(0), nonce, key))
|
||||||
|
t.execution(() => sodium.crypto_stream_chacha20_xor(out.subarray(0, 0), Buffer.alloc(0), nonce, key))
|
||||||
|
t.execution(() => sodium.crypto_stream_chacha20_xor_ic(out.subarray(0, 0), Buffer.alloc(0), nonce, 1, key))
|
||||||
|
|
||||||
|
out.fill(0x42)
|
||||||
|
sodium.crypto_stream_chacha20_xor(out, out, nonce, key)
|
||||||
|
t.alike(out, Buffer.from('b5dae3cbb3d7a42bc0521db92649f5373d15dfe15440bed1ae43ee14ba18818376e616393179040372008b06420b552b4791fc1ba85e11b31b54571e69aa66587a42c9d864fe77d65c6606553ec89c24cb9cd7640bc49b1acbb922aa046b8bffd818895e835afc147cfbf1e6e630ba6c4be5a53a0b69146cb5514cca9da27385dffb96b585eadb5759d8051270f47d81c7661da216a19f18d5e7b734bc440267', 'hex'))
|
||||||
|
|
||||||
|
sodium.crypto_stream_chacha20_xor_ic(out, out, nonce, 0, key)
|
||||||
|
t.alike(out, Buffer.from('42424242424242424242424242424242424242424242424242424242424242424242424242424242424242424242424242424242424242424242424242424242424242424242424242424242424242424242424242424242424242424242424242424242424242424242424242424242424242424242424242424242424242424242424242424242424242424242424242424242424242424242424242424242', 'hex'))
|
||||||
|
|
||||||
|
sodium.crypto_stream_chacha20_xor_ic(out, out, nonce, 1, key)
|
||||||
|
t.alike(out, Buffer.from('7a42c9d864fe77d65c6606553ec89c24cb9cd7640bc49b1acbb922aa046b8bffd818895e835afc147cfbf1e6e630ba6c4be5a53a0b69146cb5514cca9da27385dffb96b585eadb5759d8051270f47d81c7661da216a19f18d5e7b734bc440267918c466e1428f08745f37a99c77c7f2b1b244bd4162e8b86e4a8bf85358202954ced04b52fef7b3ba787744e715554285ecb0ed6e133c528d69d346abc0ce8b0', 'hex'))
|
||||||
|
})
|
||||||
|
|
||||||
|
test('crypto_stream_chacha20', function (t) {
|
||||||
|
const buf = Buffer.alloc(50)
|
||||||
|
const nonce = random(sodium.crypto_stream_chacha20_NONCEBYTES)
|
||||||
|
const key = random(sodium.crypto_stream_chacha20_KEYBYTES)
|
||||||
|
|
||||||
|
sodium.crypto_stream_chacha20(buf, nonce, key)
|
||||||
|
|
||||||
|
t.unlike(buf, Buffer.alloc(50), 'contains noise now')
|
||||||
|
const copy = Buffer.from(buf.toString('hex'), 'hex')
|
||||||
|
|
||||||
|
sodium.crypto_stream_chacha20(buf, nonce, key)
|
||||||
|
t.alike(buf, copy, 'predictable from nonce, key')
|
||||||
|
|
||||||
|
t.end()
|
||||||
|
})
|
||||||
|
|
||||||
|
test.skip('crypto_stream_chacha20_xor state', function (t) {
|
||||||
|
const message = Buffer.from('Hello, world!')
|
||||||
|
const nonce = random(sodium.crypto_stream_chacha20_NONCEBYTES)
|
||||||
|
const key = random(sodium.crypto_stream_chacha20_KEYBYTES)
|
||||||
|
|
||||||
|
const out = Buffer.alloc(message.length)
|
||||||
|
|
||||||
|
const state = Buffer.alloc(sodium.crypto_stream_chacha20_xor_STATEBYTES)
|
||||||
|
sodium.crypto_stream_chacha20_xor_init(state, nonce, key)
|
||||||
|
|
||||||
|
for (let i = 0; i < message.length; i++) {
|
||||||
|
sodium.crypto_stream_chacha20_xor_update(state, out.slice(i, i + 1), message.slice(i, i + 1))
|
||||||
|
}
|
||||||
|
|
||||||
|
sodium.crypto_stream_chacha20_xor_final(state)
|
||||||
|
sodium.crypto_stream_chacha20_xor(out, out, nonce, key)
|
||||||
|
t.alike(out, message, 'decrypted')
|
||||||
|
})
|
||||||
|
|
||||||
|
test.skip('crypto_stream_chacha20_xor state with empty buffers', function (t) {
|
||||||
|
const message = Buffer.from('Hello, world!')
|
||||||
|
const nonce = random(sodium.crypto_stream_chacha20_NONCEBYTES)
|
||||||
|
const key = random(sodium.crypto_stream_chacha20_KEYBYTES)
|
||||||
|
|
||||||
|
const out = Buffer.alloc(message.length)
|
||||||
|
|
||||||
|
const state = Buffer.alloc(sodium.crypto_stream_chacha20_xor_STATEBYTES)
|
||||||
|
sodium.crypto_stream_chacha20_xor_init(state, nonce, key)
|
||||||
|
|
||||||
|
sodium.crypto_stream_chacha20_xor_update(state, Buffer.alloc(0), Buffer.alloc(0))
|
||||||
|
|
||||||
|
for (let i = 0; i < message.length; i++) {
|
||||||
|
sodium.crypto_stream_chacha20_xor_update(state, out.slice(i, i + 1), message.slice(i, i + 1))
|
||||||
|
sodium.crypto_stream_chacha20_xor_update(state, Buffer.alloc(0), Buffer.alloc(0))
|
||||||
|
}
|
||||||
|
|
||||||
|
sodium.crypto_stream_chacha20_xor_final(state)
|
||||||
|
sodium.crypto_stream_chacha20_xor(out, out, nonce, key)
|
||||||
|
t.alike(out, message, 'decrypted')
|
||||||
|
})
|
||||||
|
|
||||||
|
test.skip('crypto_stream_chacha20_xor state long stream', function (t) {
|
||||||
|
const nonce = random(sodium.crypto_stream_chacha20_NONCEBYTES)
|
||||||
|
const key = random(sodium.crypto_stream_chacha20_KEYBYTES)
|
||||||
|
|
||||||
|
const encState = Buffer.alloc(sodium.crypto_stream_chacha20_xor_STATEBYTES)
|
||||||
|
const decState = Buffer.alloc(sodium.crypto_stream_chacha20_xor_STATEBYTES)
|
||||||
|
|
||||||
|
sodium.crypto_stream_chacha20_xor_init(encState, nonce, key)
|
||||||
|
sodium.crypto_stream_chacha20_xor_init(decState, nonce, key)
|
||||||
|
const plain = []
|
||||||
|
const encrypted = []
|
||||||
|
const decrypted = []
|
||||||
|
|
||||||
|
for (let i = 0; i < 1000; i++) {
|
||||||
|
const next = random(61)
|
||||||
|
plain.push(next)
|
||||||
|
|
||||||
|
const enc = Buffer.alloc(61)
|
||||||
|
sodium.crypto_stream_chacha20_xor_update(encState, enc, next)
|
||||||
|
encrypted.push(enc)
|
||||||
|
|
||||||
|
const dec = Buffer.alloc(61)
|
||||||
|
sodium.crypto_stream_chacha20_xor_update(decState, dec, enc)
|
||||||
|
decrypted.push(dec)
|
||||||
|
}
|
||||||
|
|
||||||
|
const enc2 = Buffer.alloc(1000 * 61)
|
||||||
|
sodium.crypto_stream_chacha20_xor(enc2, Buffer.concat(plain), nonce, key)
|
||||||
|
|
||||||
|
t.alike(Buffer.concat(encrypted), enc2, 'same as encrypting all at once')
|
||||||
|
t.alike(Buffer.concat(decrypted), Buffer.concat(plain), 'decrypts')
|
||||||
|
})
|
||||||
|
|
||||||
|
test.skip('crypto_stream_chacha20_xor state long stream (random chunks)', function (t) {
|
||||||
|
const nonce = random(sodium.crypto_stream_chacha20_NONCEBYTES)
|
||||||
|
const key = random(sodium.crypto_stream_chacha20_KEYBYTES)
|
||||||
|
|
||||||
|
const encState = Buffer.alloc(sodium.crypto_stream_chacha20_xor_STATEBYTES)
|
||||||
|
const decState = Buffer.alloc(sodium.crypto_stream_chacha20_xor_STATEBYTES)
|
||||||
|
|
||||||
|
sodium.crypto_stream_chacha20_xor_init(encState, nonce, key)
|
||||||
|
sodium.crypto_stream_chacha20_xor_init(decState, nonce, key)
|
||||||
|
const plain = []
|
||||||
|
const encrypted = []
|
||||||
|
const decrypted = []
|
||||||
|
|
||||||
|
for (let i = 0; i < 10000; i++) {
|
||||||
|
const len = Math.floor(Math.random() * 256)
|
||||||
|
const next = random(len)
|
||||||
|
plain.push(next)
|
||||||
|
|
||||||
|
const enc = Buffer.alloc(len)
|
||||||
|
sodium.crypto_stream_chacha20_xor_update(encState, enc, next)
|
||||||
|
encrypted.push(enc)
|
||||||
|
|
||||||
|
const dec = Buffer.alloc(len)
|
||||||
|
sodium.crypto_stream_chacha20_xor_update(decState, dec, enc)
|
||||||
|
decrypted.push(dec)
|
||||||
|
}
|
||||||
|
|
||||||
|
const enc2 = Buffer.alloc(Buffer.concat(plain).length)
|
||||||
|
sodium.crypto_stream_chacha20_xor(enc2, Buffer.concat(plain), nonce, key)
|
||||||
|
|
||||||
|
t.alike(Buffer.concat(encrypted), enc2, 'same as encrypting all at once')
|
||||||
|
t.alike(Buffer.concat(decrypted), Buffer.concat(plain), 'decrypts')
|
||||||
|
})
|
||||||
|
|
||||||
|
test.skip('crypto_stream_chacha20_xor state long stream (random chunks) with empty buffers', function (t) {
|
||||||
|
const nonce = random(sodium.crypto_stream_chacha20_NONCEBYTES)
|
||||||
|
const key = random(sodium.crypto_stream_chacha20_KEYBYTES)
|
||||||
|
|
||||||
|
const encState = Buffer.alloc(sodium.crypto_stream_chacha20_xor_STATEBYTES)
|
||||||
|
const decState = Buffer.alloc(sodium.crypto_stream_chacha20_xor_STATEBYTES)
|
||||||
|
|
||||||
|
sodium.crypto_stream_chacha20_xor_init(encState, nonce, key)
|
||||||
|
sodium.crypto_stream_chacha20_xor_init(decState, nonce, key)
|
||||||
|
const plain = []
|
||||||
|
const encrypted = []
|
||||||
|
const decrypted = []
|
||||||
|
|
||||||
|
for (let i = 0; i < 10000; i++) {
|
||||||
|
const len = Math.floor(Math.random() * 256)
|
||||||
|
const next = random(len)
|
||||||
|
plain.push(next)
|
||||||
|
|
||||||
|
sodium.crypto_stream_chacha20_xor_update(encState, Buffer.alloc(0), Buffer.alloc(0))
|
||||||
|
|
||||||
|
const enc = Buffer.alloc(len)
|
||||||
|
sodium.crypto_stream_chacha20_xor_update(encState, enc, next)
|
||||||
|
encrypted.push(enc)
|
||||||
|
|
||||||
|
const dec = Buffer.alloc(len)
|
||||||
|
sodium.crypto_stream_chacha20_xor_update(decState, dec, enc)
|
||||||
|
decrypted.push(dec)
|
||||||
|
sodium.crypto_stream_chacha20_xor_update(decState, Buffer.alloc(0), Buffer.alloc(0))
|
||||||
|
}
|
||||||
|
|
||||||
|
const enc2 = Buffer.alloc(Buffer.concat(plain).length)
|
||||||
|
sodium.crypto_stream_chacha20_xor(enc2, Buffer.concat(plain), nonce, key)
|
||||||
|
|
||||||
|
t.alike(Buffer.concat(encrypted), enc2, 'same as encrypting all at once')
|
||||||
|
t.alike(Buffer.concat(decrypted), Buffer.concat(plain), 'decrypts')
|
||||||
|
})
|
||||||
|
|
||||||
|
test.skip('crypto_stream_chacha20_xor state after GC', function (t) {
|
||||||
|
const message = Buffer.from('Hello, world!')
|
||||||
|
let nonce = random(sodium.crypto_stream_chacha20_NONCEBYTES)
|
||||||
|
let key = random(sodium.crypto_stream_chacha20_KEYBYTES)
|
||||||
|
|
||||||
|
const out = Buffer.alloc(message.length)
|
||||||
|
|
||||||
|
const state = Buffer.alloc(sodium.crypto_stream_chacha20_xor_STATEBYTES)
|
||||||
|
sodium.crypto_stream_chacha20_xor_init(state, nonce, key)
|
||||||
|
|
||||||
|
const nonceCopy = Buffer.from(nonce.toString('hex'), 'hex')
|
||||||
|
const keyCopy = Buffer.from(key.toString('hex'), 'hex')
|
||||||
|
nonce = null
|
||||||
|
key = null
|
||||||
|
|
||||||
|
forceGC()
|
||||||
|
|
||||||
|
for (let i = 0; i < message.length; i++) {
|
||||||
|
sodium.crypto_stream_chacha20_xor_update(state, out.slice(i, i + 1), message.slice(i, i + 1))
|
||||||
|
}
|
||||||
|
|
||||||
|
sodium.crypto_stream_chacha20_xor_final(state)
|
||||||
|
sodium.crypto_stream_chacha20_xor(out, out, nonceCopy, keyCopy)
|
||||||
|
t.alike(out, message, 'decrypted')
|
||||||
|
})
|
||||||
|
|
||||||
|
function random (n) {
|
||||||
|
const buf = Buffer.alloc(n)
|
||||||
|
sodium.randombytes_buf(buf)
|
||||||
|
return buf
|
||||||
|
}
|
||||||
|
|
||||||
|
function forceGC () {
|
||||||
|
require('v8').setFlagsFromString('--expose-gc')
|
||||||
|
require('vm').runInNewContext('gc')()
|
||||||
|
}
|
303
test/crypto_stream_chacha20_ietf.js
Normal file
303
test/crypto_stream_chacha20_ietf.js
Normal file
@ -0,0 +1,303 @@
|
|||||||
|
/* eslint-disable camelcase */
|
||||||
|
const test = require('brittle')
|
||||||
|
const sodium = require('..')
|
||||||
|
|
||||||
|
const tests = [
|
||||||
|
['0000000000000000000000000000000000000000000000000000000000000000', '000000000000000000000000', 0, '76b8e0ada0f13d90405d6ae55386bd28bdd219b8a08ded1aa836efcc8b770dc7da41597c5157488d7724e03fb8d84a376a43b8f41518a11cc387b669b2ee65869f07e7be5551387a98ba977c732d080dcb0f29a048e3656912c6533e32ee7aed29b721769ce64e43d57133b074d839d531ed1f28510afb45ace10a1f4b794d6f2d09a0e663266ce1ae7ed1081968a0758e718e997bd362c6b0c34634a9a0b35d'],
|
||||||
|
['0000000000000000000000000000000000000000000000000000000000000000', '000000000000000000000000', 1, '9f07e7be5551387a98ba977c732d080dcb0f29a048e3656912c6533e32ee7aed29b721769ce64e43d57133b074d839d531ed1f28510afb45ace10a1f4b794d6f2d09a0e663266ce1ae7ed1081968a0758e718e997bd362c6b0c34634a9a0b35d012737681f7b5d0f281e3afde458bc1e73d2d313c9cf94c05ff3716240a248f21320a058d7b3566bd520daaa3ed2bf0ac5b8b120fb852773c3639734b45c91a4'],
|
||||||
|
['0000000000000000000000000000000000000000000000000000000000000001', '000000000000000000000000', 1, '3aeb5224ecf849929b9d828db1ced4dd832025e8018b8160b82284f3c949aa5a8eca00bbb4a73bdad192b5c42f73f2fd4e273644c8b36125a64addeb006c13a096d68b9ff7b57e7090f880392effd5b297a83bbaf2fbe8cf5d4618965e3dc776cd430d9b4e7eda8a767fb0e860319aadb5fd96a855de1fbfc92cb0489190cfdd87da6dbf1f736a2d499941ca097e5170bd685578611323120cebf296181ed4f5'],
|
||||||
|
['00ff000000000000000000000000000000000000000000000000000000000000', '000000000000000000000000', 2, '72d54dfbf12ec44b362692df94137f328fea8da73990265ec1bbbea1ae9af0ca13b25aa26cb4a648cb9b9d1be65b2c0924a66c54d545ec1b7374f4872e99f096bf74dbd52cc4fc95ceb6097fe5e65358c9dbc0a5ecbf7894a132a9a54ae3e951f2e9f209aa9c3d9a877ac9dab62433d2961a17d103e455dfb7337c90f6857aad233065955a212b5c7a8eab4dc8a629e5b6b8ba914afd06de7177054b33d21c96'],
|
||||||
|
['0000000000000000000000000000000000000000000000000000000000000000', '000000000000000000000002', 0, 'c2c64d378cd536374ae204b9ef933fcd1a8b2288b3dfa49672ab765b54ee27c78a970e0e955c14f3a88e741b97c286f75f8fc299e8148362fa198a39531bed6d1a91288c874ec254f322c2a197340c55bb3e9b3998f7de2309486a0bb494abd20c9c5ef99c1370d61e77f408ac5514f49202bcc6828d45409d2d1416f8ae106b06ebd2541256264fa415bd54cb12e1d4449ed85299a1b7a249b75ff6c89b2e3f'],
|
||||||
|
['000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f', '000000090000004a00000000', 1, '10f1e7e4d13b5915500fdd1fa32071c4c7d1f4c733c068030422aa9ac3d46c4ed2826446079faa0914c2d705d98b02a2b5129cd1de164eb9cbd083e8a2503c4e0a88837739d7bf4ef8ccacb0ea2bb9d69d56c394aa351dfda5bf459f0a2e9fe8e721f89255f9c486bf21679c683d4f9c5cf2fa27865526005b06ca374c86af3bdcbfbdcb83be65862ed5c20eae5a43241d6a92da6dca9a156be25297f51c2718'],
|
||||||
|
['000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f', '000000090000004a00000000', 0xfeffffff, '75924bad7831b25662dbac54b46827990b6168ae990e7bd7e1fd2ad282bf23ef052c7d1a0a6c1ef862070943a0d4da24705fbc006dfb85e2af18c0a264d772a44c70fbedac9d6a6867ff6be0a32826507f2c784101583211c9e2453d4cc8b283d5e86682bd4bf511271b91dbd351415f5a009d1f78b64085a9a4341be7d42e2679d57e2747097f0129950e2c9e9ca1356022d45da252af71ac37f351a2e77911']
|
||||||
|
]
|
||||||
|
|
||||||
|
const vectors = [
|
||||||
|
'8a010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101',
|
||||||
|
'8adc91fd040404040404040404040404040404040404040404040404040404040404040404040404040404040404040404040404040404040404040404040404040404040404040404040404040404040404040404040404040404040404040404040404040404040404040404040404040404040404040404040404040404040404040404040404040404040404040404040404040404040404040404040404',
|
||||||
|
'8adc91fd9ff4f0070707070707070707070707070707070707070707070707070707070707070707070707070707070707070707070707070707070707070707070707070707070707070707070707070707070707070707070707070707070707070707070707070707070707070707070707070707070707070707070707070707070707070707070707070707070707070707070707070707070707070707',
|
||||||
|
'8adc91fd9ff4f0f51b0f0a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0a',
|
||||||
|
'8adc91fd9ff4f0f51b0fad50ff0d0d0d0d0d0d0d0d0d0d0d0d0d0d0d0d0d0d0d0d0d0d0d0d0d0d0d0d0d0d0d0d0d0d0d0d0d0d0d0d0d0d0d0d0d0d0d0d0d0d0d0d0d0d0d0d0d0d0d0d0d0d0d0d0d0d0d0d0d0d0d0d0d0d0d0d0d0d0d0d0d0d0d0d0d0d0d0d0d0d0d0d0d0d0d0d0d0d0d0d0d0d0d0d0d0d0d0d0d0d0d0d0d0d0d0d0d0d0d0d0d0d0d0d0d0d0d0d0d0d0d0d0d0d0d0d0d0d0d0d0d0d0d0d0d0d0d',
|
||||||
|
'8adc91fd9ff4f0f51b0fad50ff15d637101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010',
|
||||||
|
'8adc91fd9ff4f0f51b0fad50ff15d637e40efd131313131313131313131313131313131313131313131313131313131313131313131313131313131313131313131313131313131313131313131313131313131313131313131313131313131313131313131313131313131313131313131313131313131313131313131313131313131313131313131313131313131313131313131313131313131313131313',
|
||||||
|
'8adc91fd9ff4f0f51b0fad50ff15d637e40efda206cc161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616',
|
||||||
|
'8adc91fd9ff4f0f51b0fad50ff15d637e40efda206cc52c783191919191919191919191919191919191919191919191919191919191919191919191919191919191919191919191919191919191919191919191919191919191919191919191919191919191919191919191919191919191919191919191919191919191919191919191919191919191919191919191919191919191919191919191919191919',
|
||||||
|
'8adc91fd9ff4f0f51b0fad50ff15d637e40efda206cc52c783a742001c1c1c1c1c1c1c1c1c1c1c1c1c1c1c1c1c1c1c1c1c1c1c1c1c1c1c1c1c1c1c1c1c1c1c1c1c1c1c1c1c1c1c1c1c1c1c1c1c1c1c1c1c1c1c1c1c1c1c1c1c1c1c1c1c1c1c1c1c1c1c1c1c1c1c1c1c1c1c1c1c1c1c1c1c1c1c1c1c1c1c1c1c1c1c1c1c1c1c1c1c1c1c1c1c1c1c1c1c1c1c1c1c1c1c1c1c1c1c1c1c1c1c1c1c1c1c1c1c1c1c1c',
|
||||||
|
'8adc91fd9ff4f0f51b0fad50ff15d637e40efda206cc52c783a74200503c151f1f1f1f1f1f1f1f1f1f1f1f1f1f1f1f1f1f1f1f1f1f1f1f1f1f1f1f1f1f1f1f1f1f1f1f1f1f1f1f1f1f1f1f1f1f1f1f1f1f1f1f1f1f1f1f1f1f1f1f1f1f1f1f1f1f1f1f1f1f1f1f1f1f1f1f1f1f1f1f1f1f1f1f1f1f1f1f1f1f1f1f1f1f1f1f1f1f1f1f1f1f1f1f1f1f1f1f1f1f1f1f1f1f1f1f1f1f1f1f1f1f1f1f1f1f1f1f1f',
|
||||||
|
'8adc91fd9ff4f0f51b0fad50ff15d637e40efda206cc52c783a74200503c1582cd98222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222',
|
||||||
|
'8adc91fd9ff4f0f51b0fad50ff15d637e40efda206cc52c783a74200503c1582cd9833367d252525252525252525252525252525252525252525252525252525252525252525252525252525252525252525252525252525252525252525252525252525252525252525252525252525252525252525252525252525252525252525252525252525252525252525252525252525252525252525252525252525',
|
||||||
|
'8adc91fd9ff4f0f51b0fad50ff15d637e40efda206cc52c783a74200503c1582cd9833367d0a54d5282828282828282828282828282828282828282828282828282828282828282828282828282828282828282828282828282828282828282828282828282828282828282828282828282828282828282828282828282828282828282828282828282828282828282828282828282828282828282828282828',
|
||||||
|
'8adc91fd9ff4f0f51b0fad50ff15d637e40efda206cc52c783a74200503c1582cd9833367d0a54d57d3c9e2b2b2b2b2b2b2b2b2b2b2b2b2b2b2b2b2b2b2b2b2b2b2b2b2b2b2b2b2b2b2b2b2b2b2b2b2b2b2b2b2b2b2b2b2b2b2b2b2b2b2b2b2b2b2b2b2b2b2b2b2b2b2b2b2b2b2b2b2b2b2b2b2b2b2b2b2b2b2b2b2b2b2b2b2b2b2b2b2b2b2b2b2b2b2b2b2b2b2b2b2b2b2b2b2b2b2b2b2b2b2b2b2b2b2b2b2b',
|
||||||
|
'8adc91fd9ff4f0f51b0fad50ff15d637e40efda206cc52c783a74200503c1582cd9833367d0a54d57d3c9e998f492e2e2e2e2e2e2e2e2e2e2e2e2e2e2e2e2e2e2e2e2e2e2e2e2e2e2e2e2e2e2e2e2e2e2e2e2e2e2e2e2e2e2e2e2e2e2e2e2e2e2e2e2e2e2e2e2e2e2e2e2e2e2e2e2e2e2e2e2e2e2e2e2e2e2e2e2e2e2e2e2e2e2e2e2e2e2e2e2e2e2e2e2e2e2e2e2e2e2e2e2e2e2e2e2e2e2e2e2e2e2e2e2e2e',
|
||||||
|
'8adc91fd9ff4f0f51b0fad50ff15d637e40efda206cc52c783a74200503c1582cd9833367d0a54d57d3c9e998f490ee69c313131313131313131313131313131313131313131313131313131313131313131313131313131313131313131313131313131313131313131313131313131313131313131313131313131313131313131313131313131313131313131313131313131313131313131313131313131',
|
||||||
|
'8adc91fd9ff4f0f51b0fad50ff15d637e40efda206cc52c783a74200503c1582cd9833367d0a54d57d3c9e998f490ee69ca34c1f343434343434343434343434343434343434343434343434343434343434343434343434343434343434343434343434343434343434343434343434343434343434343434343434343434343434343434343434343434343434343434343434343434343434343434343434',
|
||||||
|
'8adc91fd9ff4f0f51b0fad50ff15d637e40efda206cc52c783a74200503c1582cd9833367d0a54d57d3c9e998f490ee69ca34c1ff9e939373737373737373737373737373737373737373737373737373737373737373737373737373737373737373737373737373737373737373737373737373737373737373737373737373737373737373737373737373737373737373737373737373737373737373737',
|
||||||
|
'8adc91fd9ff4f0f51b0fad50ff15d637e40efda206cc52c783a74200503c1582cd9833367d0a54d57d3c9e998f490ee69ca34c1ff9e939a755843a3a3a3a3a3a3a3a3a3a3a3a3a3a3a3a3a3a3a3a3a3a3a3a3a3a3a3a3a3a3a3a3a3a3a3a3a3a3a3a3a3a3a3a3a3a3a3a3a3a3a3a3a3a3a3a3a3a3a3a3a3a3a3a3a3a3a3a3a3a3a3a3a3a3a3a3a3a3a3a3a3a3a3a3a3a3a3a3a3a3a3a3a3a3a3a3a3a3a3a3a3a',
|
||||||
|
'8adc91fd9ff4f0f51b0fad50ff15d637e40efda206cc52c783a74200503c1582cd9833367d0a54d57d3c9e998f490ee69ca34c1ff9e939a75584c52d693d3d3d3d3d3d3d3d3d3d3d3d3d3d3d3d3d3d3d3d3d3d3d3d3d3d3d3d3d3d3d3d3d3d3d3d3d3d3d3d3d3d3d3d3d3d3d3d3d3d3d3d3d3d3d3d3d3d3d3d3d3d3d3d3d3d3d3d3d3d3d3d3d3d3d3d3d3d3d3d3d3d3d3d3d3d3d3d3d3d3d3d3d3d3d3d3d3d3d',
|
||||||
|
'8adc91fd9ff4f0f51b0fad50ff15d637e40efda206cc52c783a74200503c1582cd9833367d0a54d57d3c9e998f490ee69ca34c1ff9e939a75584c52d690a35d4404040404040404040404040404040404040404040404040404040404040404040404040404040404040404040404040404040404040404040404040404040404040404040404040404040404040404040404040404040404040404040404040'
|
||||||
|
]
|
||||||
|
|
||||||
|
test('constants', function (t) {
|
||||||
|
t.ok(sodium.crypto_stream_chacha20_ietf_KEYBYTES > 0)
|
||||||
|
t.ok(sodium.crypto_stream_chacha20_ietf_NONCEBYTES > 0)
|
||||||
|
t.ok(sodium.crypto_stream_chacha20_ietf_MESSAGEBYTES_MAX > 0)
|
||||||
|
})
|
||||||
|
|
||||||
|
test('libsodium crypto_stream_chacha20_ietf', function (t) {
|
||||||
|
const key = Buffer.alloc(sodium.crypto_stream_chacha20_ietf_KEYBYTES)
|
||||||
|
const nonce = Buffer.alloc(sodium.crypto_stream_chacha20_ietf_NONCEBYTES)
|
||||||
|
|
||||||
|
const out = Buffer.alloc(160)
|
||||||
|
|
||||||
|
for (let i = 0; i < tests.length; i++) {
|
||||||
|
key.write(tests[i][0], 0, key.byteLength, 'hex')
|
||||||
|
nonce.write(tests[i][1], 0, nonce.byteLength, 'hex')
|
||||||
|
out.fill(0)
|
||||||
|
sodium.crypto_stream_chacha20_ietf_xor_ic(out, out, nonce, tests[i][2], key)
|
||||||
|
t.alike(out, Buffer.from(tests[i][3], 'hex'), 'crypto_stream_chacha20_ietf_xor_ic vector ' + i)
|
||||||
|
for (let plen = 0; plen < out.byteLength; plen++) {
|
||||||
|
const part = Buffer.alloc(plen)
|
||||||
|
sodium.crypto_stream_chacha20_ietf_xor_ic(part, out.subarray(0, plen), nonce, tests[i][2], key)
|
||||||
|
if (part.every(b => b === 0) === false) return t.fail()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
for (let plen = 1, i = 0; plen < 66; plen += 3, i++) {
|
||||||
|
out.fill(plen & 0xff)
|
||||||
|
sodium.crypto_stream_chacha20_ietf(out.subarray(0, plen), nonce, key)
|
||||||
|
if (out.equals(Buffer.from(vectors[i], 'hex')) === false) return t.fail()
|
||||||
|
}
|
||||||
|
|
||||||
|
sodium.randombytes_buf(out)
|
||||||
|
sodium.crypto_stream_chacha20_ietf(out, nonce, key)
|
||||||
|
t.alike(out, Buffer.from('8adc91fd9ff4f0f51b0fad50ff15d637e40efda206cc52c783a74200503c1582cd9833367d0a54d57d3c9e998f490ee69ca34c1ff9e939a75584c52d690a35d410f1e7e4d13b5915500fdd1fa32071c4c7d1f4c733c068030422aa9ac3d46c4ed2826446079faa0914c2d705d98b02a2b5129cd1de164eb9cbd083e8a2503c4e0a88837739d7bf4ef8ccacb0ea2bb9d69d56c394aa351dfda5bf459f0a2e9fe8', 'hex'))
|
||||||
|
|
||||||
|
t.execution(() => sodium.crypto_stream_chacha20_ietf(out.subarray(0, 0), nonce, key))
|
||||||
|
t.execution(() => sodium.crypto_stream_chacha20_ietf_xor(out.subarray(0, 0), Buffer.alloc(0), nonce, key))
|
||||||
|
t.execution(() => sodium.crypto_stream_chacha20_ietf_xor(out.subarray(0, 0), Buffer.alloc(0), nonce, key))
|
||||||
|
t.execution(() => sodium.crypto_stream_chacha20_ietf_xor_ic(out.subarray(0, 0), Buffer.alloc(0), nonce, 1, key))
|
||||||
|
|
||||||
|
out.fill(0x42)
|
||||||
|
sodium.crypto_stream_chacha20_ietf_xor(out, out, nonce, key)
|
||||||
|
t.alike(out, Buffer.from('c89ed3bfddb6b2b7594def12bd579475a64cbfe0448e1085c1e50042127e57c08fda71743f4816973f7edcdbcd0b4ca4dee10e5dbbab7be517c6876f2b48779652b3a5a693791b57124d9f5de16233868593b68571822a414660e8d881962e0c90c0260445dde84b568095479bc940e0f750de939c540cfb8992c1aae0127e0c48cac1357b95fd0cba8eeef2a869fb94df1481d6e8775fbfe7fd07dd486cddaa', 'hex'))
|
||||||
|
|
||||||
|
sodium.crypto_stream_chacha20_ietf_xor_ic(out, out, nonce, 0, key)
|
||||||
|
t.alike(out, Buffer.from('42424242424242424242424242424242424242424242424242424242424242424242424242424242424242424242424242424242424242424242424242424242424242424242424242424242424242424242424242424242424242424242424242424242424242424242424242424242424242424242424242424242424242424242424242424242424242424242424242424242424242424242424242424242', 'hex'))
|
||||||
|
|
||||||
|
sodium.crypto_stream_chacha20_ietf_xor_ic(out, out, nonce, 1, key)
|
||||||
|
t.alike(out, Buffer.from('52b3a5a693791b57124d9f5de16233868593b68571822a414660e8d881962e0c90c0260445dde84b568095479bc940e0f750de939c540cfb8992c1aae0127e0c48cac1357b95fd0cba8eeef2a869fb94df1481d6e8775fbfe7fd07dd486cddaaa563bad017bb86c4fd6325de2a7f0dde1eb0b865c4176442194488750ec4ed799efdff89c1fc27c46c97804cec1801665f28d0982f88d85729a010d5b75e655a', 'hex'))
|
||||||
|
})
|
||||||
|
|
||||||
|
test('crypto_stream_chacha20_ietf', function (t) {
|
||||||
|
const buf = Buffer.alloc(50)
|
||||||
|
const nonce = random(sodium.crypto_stream_chacha20_ietf_NONCEBYTES)
|
||||||
|
const key = random(sodium.crypto_stream_chacha20_ietf_KEYBYTES)
|
||||||
|
|
||||||
|
sodium.crypto_stream_chacha20_ietf(buf, nonce, key)
|
||||||
|
|
||||||
|
t.unlike(buf, Buffer.alloc(50), 'contains noise now')
|
||||||
|
const copy = Buffer.from(buf.toString('hex'), 'hex')
|
||||||
|
|
||||||
|
sodium.crypto_stream_chacha20_ietf(buf, nonce, key)
|
||||||
|
t.alike(buf, copy, 'predictable from nonce, key')
|
||||||
|
|
||||||
|
t.end()
|
||||||
|
})
|
||||||
|
|
||||||
|
test('crypto_stream_chacha20_ietf_xor', function (t) {
|
||||||
|
const message = Buffer.from('Hello, World!')
|
||||||
|
const nonce = random(sodium.crypto_stream_chacha20_ietf_NONCEBYTES)
|
||||||
|
const key = random(sodium.crypto_stream_chacha20_ietf_KEYBYTES)
|
||||||
|
|
||||||
|
sodium.crypto_stream_chacha20_ietf_xor(message, message, nonce, key)
|
||||||
|
|
||||||
|
t.unlike(message, Buffer.from('Hello, World!'), 'encrypted')
|
||||||
|
|
||||||
|
sodium.crypto_stream_chacha20_ietf_xor(message, message, nonce, key)
|
||||||
|
|
||||||
|
t.alike(message, Buffer.from('Hello, World!'), 'decrypted')
|
||||||
|
|
||||||
|
t.end()
|
||||||
|
})
|
||||||
|
|
||||||
|
test.skip('crypto_stream_chacha20_ietf_xor state', function (t) {
|
||||||
|
const message = Buffer.from('Hello, world!')
|
||||||
|
const nonce = random(sodium.crypto_stream_chacha20_ietf_NONCEBYTES)
|
||||||
|
const key = random(sodium.crypto_stream_chacha20_ietf_KEYBYTES)
|
||||||
|
|
||||||
|
const out = Buffer.alloc(message.length)
|
||||||
|
|
||||||
|
const state = Buffer.alloc(sodium.crypto_stream_chacha20_ietf_xor_STATEBYTES)
|
||||||
|
sodium.crypto_stream_chacha20_ietf_xor_init(state, nonce, key)
|
||||||
|
|
||||||
|
for (let i = 0; i < message.length; i++) {
|
||||||
|
sodium.crypto_stream_chacha20_ietf_xor_update(state, out.slice(i, i + 1), message.slice(i, i + 1))
|
||||||
|
}
|
||||||
|
|
||||||
|
sodium.crypto_stream_chacha20_ietf_xor_final(state)
|
||||||
|
sodium.crypto_stream_chacha20_ietf_xor(out, out, nonce, key)
|
||||||
|
t.alike(out, message, 'decrypted')
|
||||||
|
})
|
||||||
|
|
||||||
|
test.skip('crypto_stream_chacha20_ietf_xor state with empty buffers', function (t) {
|
||||||
|
const message = Buffer.from('Hello, world!')
|
||||||
|
const nonce = random(sodium.crypto_stream_chacha20_ietf_NONCEBYTES)
|
||||||
|
const key = random(sodium.crypto_stream_chacha20_ietf_KEYBYTES)
|
||||||
|
|
||||||
|
const out = Buffer.alloc(message.length)
|
||||||
|
|
||||||
|
const state = Buffer.alloc(sodium.crypto_stream_chacha20_ietf_xor_STATEBYTES)
|
||||||
|
sodium.crypto_stream_chacha20_ietf_xor_init(state, nonce, key)
|
||||||
|
|
||||||
|
sodium.crypto_stream_chacha20_ietf_xor_update(state, Buffer.alloc(0), Buffer.alloc(0))
|
||||||
|
|
||||||
|
for (let i = 0; i < message.length; i++) {
|
||||||
|
sodium.crypto_stream_chacha20_ietf_xor_update(state, out.slice(i, i + 1), message.slice(i, i + 1))
|
||||||
|
sodium.crypto_stream_chacha20_ietf_xor_update(state, Buffer.alloc(0), Buffer.alloc(0))
|
||||||
|
}
|
||||||
|
|
||||||
|
sodium.crypto_stream_chacha20_ietf_xor_final(state)
|
||||||
|
sodium.crypto_stream_chacha20_ietf_xor(out, out, nonce, key)
|
||||||
|
t.alike(out, message, 'decrypted')
|
||||||
|
})
|
||||||
|
|
||||||
|
test.skip('crypto_stream_chacha20_ietf_xor state long stream', function (t) {
|
||||||
|
const nonce = random(sodium.crypto_stream_chacha20_ietf_NONCEBYTES)
|
||||||
|
const key = random(sodium.crypto_stream_chacha20_ietf_KEYBYTES)
|
||||||
|
|
||||||
|
const encState = Buffer.alloc(sodium.crypto_stream_chacha20_ietf_xor_STATEBYTES)
|
||||||
|
const decState = Buffer.alloc(sodium.crypto_stream_chacha20_ietf_xor_STATEBYTES)
|
||||||
|
|
||||||
|
sodium.crypto_stream_chacha20_ietf_xor_init(encState, nonce, key)
|
||||||
|
sodium.crypto_stream_chacha20_ietf_xor_init(decState, nonce, key)
|
||||||
|
const plain = []
|
||||||
|
const encrypted = []
|
||||||
|
const decrypted = []
|
||||||
|
|
||||||
|
for (let i = 0; i < 1000; i++) {
|
||||||
|
const next = random(61)
|
||||||
|
plain.push(next)
|
||||||
|
|
||||||
|
const enc = Buffer.alloc(61)
|
||||||
|
sodium.crypto_stream_chacha20_ietf_xor_update(encState, enc, next)
|
||||||
|
encrypted.push(enc)
|
||||||
|
|
||||||
|
const dec = Buffer.alloc(61)
|
||||||
|
sodium.crypto_stream_chacha20_ietf_xor_update(decState, dec, enc)
|
||||||
|
decrypted.push(dec)
|
||||||
|
}
|
||||||
|
|
||||||
|
const enc2 = Buffer.alloc(1000 * 61)
|
||||||
|
sodium.crypto_stream_chacha20_ietf_xor(enc2, Buffer.concat(plain), nonce, key)
|
||||||
|
|
||||||
|
t.alike(Buffer.concat(encrypted), enc2, 'same as encrypting all at once')
|
||||||
|
t.alike(Buffer.concat(decrypted), Buffer.concat(plain), 'decrypts')
|
||||||
|
})
|
||||||
|
|
||||||
|
test.skip('crypto_stream_chacha20_ietf_xor state long stream (random chunks)', function (t) {
|
||||||
|
const nonce = random(sodium.crypto_stream_chacha20_ietf_NONCEBYTES)
|
||||||
|
const key = random(sodium.crypto_stream_chacha20_ietf_KEYBYTES)
|
||||||
|
|
||||||
|
const encState = Buffer.alloc(sodium.crypto_stream_chacha20_ietf_xor_STATEBYTES)
|
||||||
|
const decState = Buffer.alloc(sodium.crypto_stream_chacha20_ietf_xor_STATEBYTES)
|
||||||
|
|
||||||
|
sodium.crypto_stream_chacha20_ietf_xor_init(encState, nonce, key)
|
||||||
|
sodium.crypto_stream_chacha20_ietf_xor_init(decState, nonce, key)
|
||||||
|
const plain = []
|
||||||
|
const encrypted = []
|
||||||
|
const decrypted = []
|
||||||
|
|
||||||
|
for (let i = 0; i < 10000; i++) {
|
||||||
|
const len = Math.floor(Math.random() * 256)
|
||||||
|
const next = random(len)
|
||||||
|
plain.push(next)
|
||||||
|
|
||||||
|
const enc = Buffer.alloc(len)
|
||||||
|
sodium.crypto_stream_chacha20_ietf_xor_update(encState, enc, next)
|
||||||
|
encrypted.push(enc)
|
||||||
|
|
||||||
|
const dec = Buffer.alloc(len)
|
||||||
|
sodium.crypto_stream_chacha20_ietf_xor_update(decState, dec, enc)
|
||||||
|
decrypted.push(dec)
|
||||||
|
}
|
||||||
|
|
||||||
|
const enc2 = Buffer.alloc(Buffer.concat(plain).length)
|
||||||
|
sodium.crypto_stream_chacha20_ietf_xor(enc2, Buffer.concat(plain), nonce, key)
|
||||||
|
|
||||||
|
t.alike(Buffer.concat(encrypted), enc2, 'same as encrypting all at once')
|
||||||
|
t.alike(Buffer.concat(decrypted), Buffer.concat(plain), 'decrypts')
|
||||||
|
})
|
||||||
|
|
||||||
|
test.skip('crypto_stream_chacha20_ietf_xor state long stream (random chunks) with empty buffers', function (t) {
|
||||||
|
const nonce = random(sodium.crypto_stream_chacha20_ietf_NONCEBYTES)
|
||||||
|
const key = random(sodium.crypto_stream_chacha20_ietf_KEYBYTES)
|
||||||
|
|
||||||
|
const encState = Buffer.alloc(sodium.crypto_stream_chacha20_ietf_xor_STATEBYTES)
|
||||||
|
const decState = Buffer.alloc(sodium.crypto_stream_chacha20_ietf_xor_STATEBYTES)
|
||||||
|
|
||||||
|
sodium.crypto_stream_chacha20_ietf_xor_init(encState, nonce, key)
|
||||||
|
sodium.crypto_stream_chacha20_ietf_xor_init(decState, nonce, key)
|
||||||
|
const plain = []
|
||||||
|
const encrypted = []
|
||||||
|
const decrypted = []
|
||||||
|
|
||||||
|
for (let i = 0; i < 10000; i++) {
|
||||||
|
const len = Math.floor(Math.random() * 256)
|
||||||
|
const next = random(len)
|
||||||
|
plain.push(next)
|
||||||
|
|
||||||
|
sodium.crypto_stream_chacha20_ietf_xor_update(encState, Buffer.alloc(0), Buffer.alloc(0))
|
||||||
|
|
||||||
|
const enc = Buffer.alloc(len)
|
||||||
|
sodium.crypto_stream_chacha20_ietf_xor_update(encState, enc, next)
|
||||||
|
encrypted.push(enc)
|
||||||
|
|
||||||
|
const dec = Buffer.alloc(len)
|
||||||
|
sodium.crypto_stream_chacha20_ietf_xor_update(decState, dec, enc)
|
||||||
|
decrypted.push(dec)
|
||||||
|
sodium.crypto_stream_chacha20_ietf_xor_update(decState, Buffer.alloc(0), Buffer.alloc(0))
|
||||||
|
}
|
||||||
|
|
||||||
|
const enc2 = Buffer.alloc(Buffer.concat(plain).length)
|
||||||
|
sodium.crypto_stream_chacha20_ietf_xor(enc2, Buffer.concat(plain), nonce, key)
|
||||||
|
|
||||||
|
t.alike(Buffer.concat(encrypted), enc2, 'same as encrypting all at once')
|
||||||
|
t.alike(Buffer.concat(decrypted), Buffer.concat(plain), 'decrypts')
|
||||||
|
})
|
||||||
|
|
||||||
|
test.skip('crypto_stream_chacha20_xor state after GC', function (t) {
|
||||||
|
const message = Buffer.from('Hello, world!')
|
||||||
|
let nonce = random(sodium.crypto_stream_chacha20_ietf_NONCEBYTES)
|
||||||
|
let key = random(sodium.crypto_stream_chacha20_ietf_KEYBYTES)
|
||||||
|
|
||||||
|
const out = Buffer.alloc(message.length)
|
||||||
|
|
||||||
|
const state = Buffer.alloc(sodium.crypto_stream_chacha20_ietf_xor_STATEBYTES)
|
||||||
|
sodium.crypto_stream_chacha20_ietf_xor_init(state, nonce, key)
|
||||||
|
|
||||||
|
const nonceCopy = Buffer.from(nonce.toString('hex'), 'hex')
|
||||||
|
const keyCopy = Buffer.from(key.toString('hex'), 'hex')
|
||||||
|
nonce = null
|
||||||
|
key = null
|
||||||
|
|
||||||
|
forceGC()
|
||||||
|
|
||||||
|
for (let i = 0; i < message.length; i++) {
|
||||||
|
sodium.crypto_stream_chacha20_ietf_xor_update(state, out.slice(i, i + 1), message.slice(i, i + 1))
|
||||||
|
}
|
||||||
|
|
||||||
|
sodium.crypto_stream_chacha20_ietf_xor_final(state)
|
||||||
|
sodium.crypto_stream_chacha20_ietf_xor(out, out, nonceCopy, keyCopy)
|
||||||
|
t.alike(out, message, 'decrypted')
|
||||||
|
})
|
||||||
|
|
||||||
|
function random (n) {
|
||||||
|
const buf = Buffer.alloc(n)
|
||||||
|
sodium.randombytes_buf(buf)
|
||||||
|
return buf
|
||||||
|
}
|
||||||
|
|
||||||
|
function forceGC () {
|
||||||
|
require('v8').setFlagsFromString('--expose-gc')
|
||||||
|
require('vm').runInNewContext('gc')()
|
||||||
|
}
|
78
test/fixtures/crypto_kdf.json
vendored
Normal file
78
test/fixtures/crypto_kdf.json
vendored
Normal file
@ -0,0 +1,78 @@
|
|||||||
|
[
|
||||||
|
{"error": false, "id":0, "context":"4b44462074657374", "key":"000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f", "subkey_len":64, "subkey":"a0c724404728c8bb95e5433eb6a9716171144d61efb23e74b873fcbeda51d8071b5d70aae12066dfc94ce943f145aa176c055040c3dd73b0a15e36254d450614"},
|
||||||
|
{"error": false, "id":1, "context":"4b44462074657374", "key":"000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f", "subkey_len":64, "subkey":"02507f144fa9bf19010bf7c70b235b4c2663cc00e074f929602a5e2c10a780757d2a3993d06debc378a90efdac196dd841817b977d67b786804f6d3cd585bab5"},
|
||||||
|
{"error": false, "id":2, "context":"4b44462074657374", "key":"000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f", "subkey_len":64, "subkey":"1944da61ff18dc2028c3578ac85be904931b83860896598f62468f1cb5471c6a344c945dbc62c9aaf70feb62472d17775ea5db6ed5494c68b7a9a59761f39614"},
|
||||||
|
{"error": false, "id":3, "context":"4b44462074657374", "key":"000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f", "subkey_len":64, "subkey":"131c0ca1633ed074986215b264f6e0474f362c52b029effc7b0f75977ee89cc95d85c3db87f7e399197a25411592beeeb7e5128a74646a460ecd6deb4994b71e"},
|
||||||
|
{"error": false, "id":4, "context":"4b44462074657374", "key":"000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f", "subkey_len":64, "subkey":"a7023a0bf9be245d078aed26bcde0465ff0cc0961196a5482a0ff4ff8b4015971e13611f50529cb408f5776b14a90e7c3dd9160a22211db64ff4b5c0b9953680"},
|
||||||
|
{"error": false, "id":5, "context":"4b44462074657374", "key":"000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f", "subkey_len":64, "subkey":"50f49313f3a05b2e565c13feedb44daa675cafd42c2b2cf9edbce9c949fbfc3f175dcb738671509ae2ea66fb85e552394d479afa7fa3affe8791744796b94176"},
|
||||||
|
{"error": false, "id":6, "context":"4b44462074657374", "key":"000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f", "subkey_len":64, "subkey":"13b58d6d69780089293862cd59a1a8a4ef79bb850e3f3ba41fb22446a7dd1dc4da4667d37b33bf1225dcf8173c4c349a5d911c5bd2db9c5905ed70c11e809e3b"},
|
||||||
|
{"error": false, "id":7, "context":"4b44462074657374", "key":"000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f", "subkey_len":64, "subkey":"15d44b4b44ffa006eeceeb508c98a970aaa573d65905687b9e15854dec6d49c612757e149f78268f727660dedf9abce22a9691feb20a01b0525f4b47a3cf19db"},
|
||||||
|
{"error": false, "id":8, "context":"4b44462074657374", "key":"000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f", "subkey_len":64, "subkey":"9aebba11c5428ae8225716369e30a48943be39159a899f804e9963ef78822e186c21fe95bb0b85e60ef03a6f58d0b9d06e91f79d0ab998450b8810c73ca935b4"},
|
||||||
|
{"error": false, "id":9, "context":"4b44462074657374", "key":"000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f", "subkey_len":64, "subkey":"70f9b83e463fb441e7a4c43275125cd5b19d8e2e4a5d179a39f5db10bbce745a199104563d308cf8d4c6b27bbb759ded232f5bdb7c367dd632a9677320dfe416"},
|
||||||
|
{"error": true, "id":0, "context":"4b44462074657374", "key":"000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f", "subkey_len":0, "subkey":null},
|
||||||
|
{"error": true, "id":1, "context":"4b44462074657374", "key":"000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f", "subkey_len":1, "subkey":null},
|
||||||
|
{"error": true, "id":2, "context":"4b44462074657374", "key":"000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f", "subkey_len":2, "subkey":null},
|
||||||
|
{"error": true, "id":3, "context":"4b44462074657374", "key":"000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f", "subkey_len":3, "subkey":null},
|
||||||
|
{"error": true, "id":4, "context":"4b44462074657374", "key":"000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f", "subkey_len":4, "subkey":null},
|
||||||
|
{"error": true, "id":5, "context":"4b44462074657374", "key":"000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f", "subkey_len":5, "subkey":null},
|
||||||
|
{"error": true, "id":6, "context":"4b44462074657374", "key":"000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f", "subkey_len":6, "subkey":null},
|
||||||
|
{"error": true, "id":7, "context":"4b44462074657374", "key":"000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f", "subkey_len":7, "subkey":null},
|
||||||
|
{"error": true, "id":8, "context":"4b44462074657374", "key":"000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f", "subkey_len":8, "subkey":null},
|
||||||
|
{"error": true, "id":9, "context":"4b44462074657374", "key":"000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f", "subkey_len":9, "subkey":null},
|
||||||
|
{"error": true, "id":10, "context":"4b44462074657374", "key":"000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f", "subkey_len":10, "subkey":null},
|
||||||
|
{"error": true, "id":11, "context":"4b44462074657374", "key":"000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f", "subkey_len":11, "subkey":null},
|
||||||
|
{"error": true, "id":12, "context":"4b44462074657374", "key":"000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f", "subkey_len":12, "subkey":null},
|
||||||
|
{"error": true, "id":13, "context":"4b44462074657374", "key":"000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f", "subkey_len":13, "subkey":null},
|
||||||
|
{"error": true, "id":14, "context":"4b44462074657374", "key":"000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f", "subkey_len":14, "subkey":null},
|
||||||
|
{"error": true, "id":15, "context":"4b44462074657374", "key":"000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f", "subkey_len":15, "subkey":null},
|
||||||
|
{"error": false, "id":16, "context":"4b44462074657374", "key":"000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f", "subkey_len":16, "subkey":"a529216624ef9161e4cf117272aafff2"},
|
||||||
|
{"error": false, "id":17, "context":"4b44462074657374", "key":"000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f", "subkey_len":17, "subkey":"068bd6940b80c6cc2530a68c31d9f4e323"},
|
||||||
|
{"error": false, "id":18, "context":"4b44462074657374", "key":"000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f", "subkey_len":18, "subkey":"0acf4f6c74a590c8a1c0997ec9a1a3f48b2a"},
|
||||||
|
{"error": false, "id":19, "context":"4b44462074657374", "key":"000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f", "subkey_len":19, "subkey":"ac17a37ce74c0efece75f9337de20795dbadcc"},
|
||||||
|
{"error": false, "id":20, "context":"4b44462074657374", "key":"000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f", "subkey_len":20, "subkey":"268214dc9477a2e3c1022829f934ab992a5a3d84"},
|
||||||
|
{"error": false, "id":21, "context":"4b44462074657374", "key":"000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f", "subkey_len":21, "subkey":"33b76197b4531665e494760909eda1cc570e7da9bb"},
|
||||||
|
{"error": false, "id":22, "context":"4b44462074657374", "key":"000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f", "subkey_len":22, "subkey":"3d4efbc569ca7f858ad4f49c56b820986a406e6eebbc"},
|
||||||
|
{"error": false, "id":23, "context":"4b44462074657374", "key":"000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f", "subkey_len":23, "subkey":"983fea27520f507c40231f9557908f07c095bdf4a4ce5d"},
|
||||||
|
{"error": false, "id":24, "context":"4b44462074657374", "key":"000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f", "subkey_len":24, "subkey":"94d678717625e011995c7355f2092267dee47bf0722dd380"},
|
||||||
|
{"error": false, "id":25, "context":"4b44462074657374", "key":"000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f", "subkey_len":25, "subkey":"198901896c4f51e74ffa8b2805415c6eaba5accfc85a6e6b34"},
|
||||||
|
{"error": false, "id":26, "context":"4b44462074657374", "key":"000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f", "subkey_len":26, "subkey":"4ffabb81d49021f85ef5d2a713ab02ae86bc2e7d1522f5e077fe"},
|
||||||
|
{"error": false, "id":27, "context":"4b44462074657374", "key":"000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f", "subkey_len":27, "subkey":"eebc3d55b3f4fc8b64d2474063254da7db98e7398dfdd510e28075"},
|
||||||
|
{"error": false, "id":28, "context":"4b44462074657374", "key":"000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f", "subkey_len":28, "subkey":"22c134b9d664e1bdb14dc309a936bf1512b19e4f5175642efb1a0df7"},
|
||||||
|
{"error": false, "id":29, "context":"4b44462074657374", "key":"000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f", "subkey_len":29, "subkey":"4b179762bfc8e27a9e575113faa76247b9c046d6f22d5a02e2910a299b"},
|
||||||
|
{"error": false, "id":30, "context":"4b44462074657374", "key":"000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f", "subkey_len":30, "subkey":"abc45eb2b031307b8822c7e59a43f4108850c34a7445936bc848422251c4"},
|
||||||
|
{"error": false, "id":31, "context":"4b44462074657374", "key":"000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f", "subkey_len":31, "subkey":"d6565bd3265b6373f4f6a6b6458e981006da5e9d532ce94ca4737e188995e9"},
|
||||||
|
{"error": false, "id":32, "context":"4b44462074657374", "key":"000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f", "subkey_len":32, "subkey":"154b291f11196737f8b7f491e4ca11764e0227d34f94295408a869f007aa8618"},
|
||||||
|
{"error": false, "id":33, "context":"4b44462074657374", "key":"000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f", "subkey_len":33, "subkey":"e9dd395570e09ebb523ffc6ba098a38b17bc4944f14bd3725bdd7edbd8bcff54fb"},
|
||||||
|
{"error": false, "id":34, "context":"4b44462074657374", "key":"000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f", "subkey_len":34, "subkey":"7248294d37159e85bacde68c7762a673794c91b811e05f4e3b9e3ecc82bfcf63a2cd"},
|
||||||
|
{"error": false, "id":35, "context":"4b44462074657374", "key":"000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f", "subkey_len":35, "subkey":"d060ee4d93f8de6d9ae60fca9596413455183a1f83c7a2381227cec8f7a217e4072f85"},
|
||||||
|
{"error": false, "id":36, "context":"4b44462074657374", "key":"000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f", "subkey_len":36, "subkey":"20790290347b9b0f413a954f40e52e270b3b45417e96c8733161672188701c08dd76cc3d"},
|
||||||
|
{"error": false, "id":37, "context":"4b44462074657374", "key":"000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f", "subkey_len":37, "subkey":"7674188112a1ab8d3926d468be8e51d788ce4144bb20ff842034e4d1ddab3929a4f1a13a74"},
|
||||||
|
{"error": false, "id":38, "context":"4b44462074657374", "key":"000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f", "subkey_len":38, "subkey":"a2ab1f980a47472d8a539f20410cc9bf143d941331ab2259ea73684c0608939c5b23e9cbcb3d"},
|
||||||
|
{"error": false, "id":39, "context":"4b44462074657374", "key":"000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f", "subkey_len":39, "subkey":"f4cfbe3050f15ebbaf8d2f3bf3a678c01fc21ee1f4be07d0744c7fbf4835ea9d9472a3d785c24c"},
|
||||||
|
{"error": false, "id":40, "context":"4b44462074657374", "key":"000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f", "subkey_len":40, "subkey":"66efa5dfe3efd4cc8ca25f2d622c97a20a192d7add965f26b002b7eb81aae4203c0e5f07fd945845"},
|
||||||
|
{"error": false, "id":41, "context":"4b44462074657374", "key":"000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f", "subkey_len":41, "subkey":"ad5d8031055c96dc9db10285206d7edc38d3af85736df8a3b5fdd30a318e80c28d9b26c95a60fa3e68"},
|
||||||
|
{"error": false, "id":42, "context":"4b44462074657374", "key":"000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f", "subkey_len":42, "subkey":"9107c8a57a2c9ca40158f33ca0bfb64c095d2f21ca98bb7138477599330a36cdfc2ae5751e370d0e024e"},
|
||||||
|
{"error": false, "id":43, "context":"4b44462074657374", "key":"000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f", "subkey_len":43, "subkey":"b0c190177358b955ebebc5e0b86ec91dde3b6f1982ea4d68ec5ec3bdd6527c362e5275600b263601c98452"},
|
||||||
|
{"error": false, "id":44, "context":"4b44462074657374", "key":"000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f", "subkey_len":44, "subkey":"31bfaaad4adde0f87d87372e398c42cb7befe065ab2957ebb91ef9dc534b410783899b2e1e84221286f3bab4"},
|
||||||
|
{"error": false, "id":45, "context":"4b44462074657374", "key":"000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f", "subkey_len":45, "subkey":"2258dd1f3e516cb8e3d1f6c45808573c365192f073698939721af8961a02a8bdd002a31fd239b9498663a01f27"},
|
||||||
|
{"error": false, "id":46, "context":"4b44462074657374", "key":"000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f", "subkey_len":46, "subkey":"7c7a88016610493bb44a9432a88b50f97e2e94383972ff95da826692d96c52d82f86899b3561ec9c95a8b1bf3213"},
|
||||||
|
{"error": false, "id":47, "context":"4b44462074657374", "key":"000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f", "subkey_len":47, "subkey":"3929dc7473be4c633be9e08801a8abd284dc0c6154c5c81a4c18259699dd86753c5e14fbd723be46ebb04f4ab3058c"},
|
||||||
|
{"error": false, "id":48, "context":"4b44462074657374", "key":"000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f", "subkey_len":48, "subkey":"30b720220015fa60daa69c83f9754d772b1b2dd12ab6baaa2f4edab458d4d251c1cddb8c4a554f3eb13969316b890fbd"},
|
||||||
|
{"error": false, "id":49, "context":"4b44462074657374", "key":"000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f", "subkey_len":49, "subkey":"33fa2412a5c3294d49e964419e96d043a2099a72b3351e3bed0f07e12255c95b509ea9bf2963a4c0fe9cc2314dbc44f673"},
|
||||||
|
{"error": false, "id":50, "context":"4b44462074657374", "key":"000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f", "subkey_len":50, "subkey":"ca891d2c82a6a8f833dc1a05f190bab6de221307eab1dd2c88341d4d2537a2fc0056b0d04d8104fd3fe89e1ea20877893e81"},
|
||||||
|
{"error": false, "id":51, "context":"4b44462074657374", "key":"000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f", "subkey_len":51, "subkey":"fd78ac89a64d03672ad99d663f2613d15277cda1636e334a1706b7211ff1f3a3b3d2e671e391c75e3d242c482ce7e1b8b427ed"},
|
||||||
|
{"error": false, "id":52, "context":"4b44462074657374", "key":"000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f", "subkey_len":52, "subkey":"36a6072743d3aafd3ee89344b9ef92cb58a2853ae92b20283520439fcb55afffd3d4b5e4e8c92a85d3cf74497bdcf68bbf1fcf93"},
|
||||||
|
{"error": false, "id":53, "context":"4b44462074657374", "key":"000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f", "subkey_len":53, "subkey":"a90afcfaffec1105ad05fdaa9473fb5daf1bf8fb376b7326db46ef4c120c553188c69131933371d409eb56d66d5adca618e1dac65b"},
|
||||||
|
{"error": false, "id":54, "context":"4b44462074657374", "key":"000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f", "subkey_len":54, "subkey":"9b990d1fcddbdb5e5c7a48a6a2a666e02e7d4d4a814ece40660d99e1c02d5f023c56ae82526fc6dc8c933d0add92fc376efcddd55a42"},
|
||||||
|
{"error": false, "id":55, "context":"4b44462074657374", "key":"000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f", "subkey_len":55, "subkey":"ec545dcf456d1b0907c07418a42bf2b3d668b4797ba6874bf0d563f5f429a820f02177dd4d05e639a06807c9619fee54ffe07712493543"},
|
||||||
|
{"error": false, "id":56, "context":"4b44462074657374", "key":"000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f", "subkey_len":56, "subkey":"b0106957626894586682a275f69ed4533e2f94334cc0430394b68d82679aca00dd579e712bdd2d7f5bbce9a050269739bd8427b75b06027f"},
|
||||||
|
{"error": false, "id":57, "context":"4b44462074657374", "key":"000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f", "subkey_len":57, "subkey":"05751bfeebb480c9bca0d25d8197e2673845f405d7fb9793e29169ac19956c525f6e637f3d5ea50597b04342afed4ca16f988b4f21a34f1902"},
|
||||||
|
{"error": false, "id":58, "context":"4b44462074657374", "key":"000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f", "subkey_len":58, "subkey":"7b4e4294d3f64085b5c09be73548f1f5cb5c6f04e57ce6cdd3077e2fb37640bf1ca0c6393b87d48a6b7e3e42628bd30fca132ded03ce51f71d9d"},
|
||||||
|
{"error": false, "id":59, "context":"4b44462074657374", "key":"000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f", "subkey_len":59, "subkey":"082d248862cbfd71a634769a4b1cf52a4af47ace5b9ea4d583ca52207efc7234a6d321788130cbdec122579ad03afe00bc68c9fb3f68dd0532a96f"},
|
||||||
|
{"error": false, "id":60, "context":"4b44462074657374", "key":"000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f", "subkey_len":60, "subkey":"a2b39b4428d981013e8a9c0e41b3eed504983fc18dc4b60332b1ab28b9705228147bdb95cc17889d5f0f9cfb7fd16f9d414b1a829346a8922e945b40"},
|
||||||
|
{"error": false, "id":61, "context":"4b44462074657374", "key":"000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f", "subkey_len":61, "subkey":"efbf0f8bda1b9ef24fe389f1cf0c0c8a08bca03fc95badabb79a487d8ce1351683f59183aa6229f880d69ad60114ac128f69b2be250109972ab1f3fc3b"},
|
||||||
|
{"error": false, "id":62, "context":"4b44462074657374", "key":"000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f", "subkey_len":62, "subkey":"dfe0ba2a6de25fa06b47375e9d9cf6c6fa1493a8a2a81c28d6e09bc161057b445659db76e92e349ff44f34a2a9e3bcaa6b84b21bae56f1499c170ab81af0"},
|
||||||
|
{"error": false, "id":63, "context":"4b44462074657374", "key":"000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f", "subkey_len":63, "subkey":"02f9cbdb10759314515b01379c474ad74a1b575137bd3949776dbcfc3e18060cb13ee1f6dcf86035768fc7be63e01de321cacbfade209900dd94273fd8e176"},
|
||||||
|
{"error": false, "id":64, "context":"4b44462074657374", "key":"000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f", "subkey_len":64, "subkey":"06ae14308eeeda62a00cb6d5edf18d1707029515db98f472bbf0617419301b1d4f4f2ab65849446be46f87e1d31c6c74283897b9976f70d8a16253ac927e0d9f"},
|
||||||
|
{"error": true, "id":65, "context":"4b44462074657374", "key":"000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f", "subkey_len":65, "subkey":null}
|
||||||
|
]
|
2050
test/fixtures/crypto_sign.json
vendored
Normal file
2050
test/fixtures/crypto_sign.json
vendored
Normal file
File diff suppressed because it is too large
Load Diff
1025
test/fixtures/crypto_tweak_ed25519_sign.js
vendored
Normal file
1025
test/fixtures/crypto_tweak_ed25519_sign.js
vendored
Normal file
File diff suppressed because it is too large
Load Diff
6
test/fixtures/mprotect_noaccess.js
vendored
Normal file
6
test/fixtures/mprotect_noaccess.js
vendored
Normal file
@ -0,0 +1,6 @@
|
|||||||
|
/* eslint-disable */
|
||||||
|
const sodium = require('../..')
|
||||||
|
const buf = sodium.sodium_malloc(1)
|
||||||
|
sodium.sodium_mprotect_noaccess(buf)
|
||||||
|
buf[0]
|
||||||
|
process.send('read')
|
8
test/fixtures/mprotect_readonly.js
vendored
Normal file
8
test/fixtures/mprotect_readonly.js
vendored
Normal file
@ -0,0 +1,8 @@
|
|||||||
|
/* eslint-disable */
|
||||||
|
const sodium = require('../..')
|
||||||
|
const buf = sodium.sodium_malloc(1)
|
||||||
|
sodium.sodium_mprotect_readonly(buf)
|
||||||
|
buf[0]
|
||||||
|
process.send('read')
|
||||||
|
buf[0] = 1
|
||||||
|
process.send('write')
|
11
test/fixtures/mprotect_readwrite.js
vendored
Normal file
11
test/fixtures/mprotect_readwrite.js
vendored
Normal file
@ -0,0 +1,11 @@
|
|||||||
|
/* eslint-disable */
|
||||||
|
const sodium = require('../..')
|
||||||
|
const buf = sodium.sodium_malloc(1)
|
||||||
|
sodium.sodium_mprotect_noaccess(buf)
|
||||||
|
sodium.sodium_mprotect_readwrite(buf)
|
||||||
|
buf[0]
|
||||||
|
process.send('read')
|
||||||
|
buf[0] = 1
|
||||||
|
process.send('write')
|
||||||
|
sodium.sodium_mprotect_readonly(buf)
|
||||||
|
process.send(buf[0] === 1 ? 'did_write' : 'did_not_write')
|
103
test/helpers.js
Normal file
103
test/helpers.js
Normal file
@ -0,0 +1,103 @@
|
|||||||
|
/* eslint-disable camelcase */
|
||||||
|
const test = require('brittle')
|
||||||
|
const sodium = require('..')
|
||||||
|
|
||||||
|
test('sodium_memcmp', function (t) {
|
||||||
|
const b1 = Buffer.from([0, 1, 2, 3])
|
||||||
|
const b2 = Buffer.from([3, 2, 1, 0])
|
||||||
|
|
||||||
|
t.exception.all(_ => sodium.sodium_memcmp(), 'no args')
|
||||||
|
t.exception.all(_ => sodium.sodium_memcmp(b1), 'arg mismatch')
|
||||||
|
t.exception.all(_ => sodium.sodium_memcmp(b1, b2.slice(1)), 'length mismatch')
|
||||||
|
t.ok(sodium.sodium_memcmp(Buffer.alloc(0), Buffer.alloc(0)))
|
||||||
|
t.ok(sodium.sodium_memcmp(Buffer.alloc(5), Buffer.alloc(5)))
|
||||||
|
t.ok(sodium.sodium_memcmp(b1, b1))
|
||||||
|
t.absent(sodium.sodium_memcmp(b2, b1))
|
||||||
|
t.absent(sodium.sodium_memcmp(b1, b2))
|
||||||
|
})
|
||||||
|
|
||||||
|
test.skip('sodium_compare', function (t) {
|
||||||
|
const one = Buffer.from([1])
|
||||||
|
const two = Buffer.from([2])
|
||||||
|
const three = Buffer.from([3])
|
||||||
|
|
||||||
|
t.is(sodium.sodium_compare(Buffer.alloc(0), Buffer.alloc(0)), 0)
|
||||||
|
t.is(sodium.sodium_compare(one, one), 0)
|
||||||
|
t.is(sodium.sodium_compare(two, two), 0)
|
||||||
|
t.is(sodium.sodium_compare(three, three), 0)
|
||||||
|
|
||||||
|
t.is(sodium.sodium_compare(one, two), -1)
|
||||||
|
t.is(sodium.sodium_compare(one, three), -1)
|
||||||
|
t.is(sodium.sodium_compare(two, one), 1)
|
||||||
|
t.is(sodium.sodium_compare(three, one), 1)
|
||||||
|
|
||||||
|
t.is(sodium.sodium_compare(two, three), -1)
|
||||||
|
t.is(sodium.sodium_compare(three, two), 1)
|
||||||
|
})
|
||||||
|
|
||||||
|
test.skip('sodium_add', function (t) {
|
||||||
|
const large = Buffer.alloc(32)
|
||||||
|
large[23] = 0b00000011
|
||||||
|
const largeLessOne = Buffer.alloc(32)
|
||||||
|
largeLessOne[23] = 0b00000001
|
||||||
|
|
||||||
|
const c = Buffer.from(large)
|
||||||
|
|
||||||
|
sodium.sodium_add(c, largeLessOne)
|
||||||
|
t.ok(large[23], 4)
|
||||||
|
|
||||||
|
const overflow = Buffer.alloc(56, 0xff)
|
||||||
|
const one = Buffer.alloc(56)
|
||||||
|
one[0] = 1
|
||||||
|
sodium.sodium_add(overflow, one)
|
||||||
|
|
||||||
|
t.ok(sodium.sodium_is_zero(overflow))
|
||||||
|
})
|
||||||
|
|
||||||
|
test.skip('sub', function (t) {
|
||||||
|
const large = Buffer.alloc(32)
|
||||||
|
large[23] = 0b00000011
|
||||||
|
const largeLessOne = Buffer.alloc(32)
|
||||||
|
largeLessOne[23] = 0b00000001
|
||||||
|
|
||||||
|
const c = Buffer.from(large)
|
||||||
|
|
||||||
|
sodium.sodium_sub(c, largeLessOne)
|
||||||
|
t.ok(large[23], 2)
|
||||||
|
|
||||||
|
const overflow = Buffer.alloc(56, 0x00)
|
||||||
|
const one = Buffer.alloc(56)
|
||||||
|
one[0] = 1
|
||||||
|
sodium.sodium_sub(overflow, one)
|
||||||
|
|
||||||
|
t.ok(sodium.sodium_memcmp(overflow, Buffer.alloc(56, 0xff)))
|
||||||
|
})
|
||||||
|
|
||||||
|
test('sodium_increment', function (t) {
|
||||||
|
const zero = Buffer.alloc(4)
|
||||||
|
sodium.sodium_increment(zero)
|
||||||
|
|
||||||
|
t.ok(zero[0], 1)
|
||||||
|
|
||||||
|
const overflow = Buffer.alloc(56, 0xff)
|
||||||
|
sodium.sodium_increment(overflow)
|
||||||
|
|
||||||
|
t.ok(sodium.sodium_is_zero(overflow))
|
||||||
|
})
|
||||||
|
|
||||||
|
test('sodium_is_zero', function (t) {
|
||||||
|
const buf = Buffer.from([0, 0, 0, 1])
|
||||||
|
|
||||||
|
t.exception.all(_ => sodium.sodium_is_zero(), 'no args')
|
||||||
|
t.exception.all(_ => sodium.sodium_is_zero(null), 'missing buf')
|
||||||
|
|
||||||
|
t.ok(sodium.sodium_is_zero(Buffer.alloc(0)), 'empty buffer')
|
||||||
|
t.ok(sodium.sodium_is_zero(buf.subarray(0, 0)), 'zero bytes')
|
||||||
|
t.ok(sodium.sodium_is_zero(buf.subarray(0, 1)), 'one byte')
|
||||||
|
t.ok(sodium.sodium_is_zero(buf.subarray(0, 2)), 'two bytes')
|
||||||
|
t.ok(sodium.sodium_is_zero(buf.subarray(0, 3)), '3 bytes')
|
||||||
|
t.absent(sodium.sodium_is_zero(buf), 'first non-zero byte')
|
||||||
|
t.ok(sodium.sodium_is_zero(buf.subarray(1, 2)), 'view')
|
||||||
|
t.ok(sodium.sodium_is_zero(buf.subarray(1, 2)), 'view')
|
||||||
|
t.absent(sodium.sodium_is_zero(buf.subarray(3)), 'view')
|
||||||
|
})
|
126
test/memory.js
Normal file
126
test/memory.js
Normal file
@ -0,0 +1,126 @@
|
|||||||
|
/* eslint-disable camelcase */
|
||||||
|
const test = require('brittle')
|
||||||
|
const sodium = require('..')
|
||||||
|
const fork = require('child_process').fork
|
||||||
|
|
||||||
|
test.skip('sodium_mprotect_noaccess', function (t) {
|
||||||
|
t.plan(1)
|
||||||
|
const p = fork(require.resolve('./fixtures/mprotect_noaccess'))
|
||||||
|
|
||||||
|
p.on('message', function () {
|
||||||
|
t.fail()
|
||||||
|
})
|
||||||
|
p.on('exit', function (code, signal) {
|
||||||
|
t.ok(p.signalCode !== null || p.exitCode > 0)
|
||||||
|
})
|
||||||
|
})
|
||||||
|
|
||||||
|
test.skip('sodium_mprotect_readonly', function (t) {
|
||||||
|
t.plan(2)
|
||||||
|
const p = fork(require.resolve('./fixtures/mprotect_readonly'))
|
||||||
|
|
||||||
|
p.on('message', function (msg) {
|
||||||
|
t.ok(msg === 'read')
|
||||||
|
})
|
||||||
|
p.on('exit', function (code, signal) {
|
||||||
|
t.ok(p.signalCode !== null || p.exitCode > 0)
|
||||||
|
})
|
||||||
|
})
|
||||||
|
|
||||||
|
test.skip('sodium_mprotect_readwrite', function (t) {
|
||||||
|
t.plan(4)
|
||||||
|
const p = fork(require.resolve('./fixtures/mprotect_readwrite'))
|
||||||
|
|
||||||
|
p.on('message', function (msg) {
|
||||||
|
switch (msg) {
|
||||||
|
case 'read': t.pass()
|
||||||
|
break
|
||||||
|
case 'write': t.pass()
|
||||||
|
break
|
||||||
|
case 'did_write': t.pass()
|
||||||
|
break
|
||||||
|
case 'did_not_write': t.fail()
|
||||||
|
break
|
||||||
|
default: t.fail()
|
||||||
|
break
|
||||||
|
}
|
||||||
|
})
|
||||||
|
p.on('exit', function (code, signal) {
|
||||||
|
t.ok(p.signalCode === null || p.exitCode === 0)
|
||||||
|
})
|
||||||
|
})
|
||||||
|
|
||||||
|
test('sodium_memzero', function (t) {
|
||||||
|
const buf = Buffer.alloc(10, 0xab)
|
||||||
|
const exp = Buffer.alloc(10, 0xab)
|
||||||
|
const zero = Buffer.alloc(10)
|
||||||
|
|
||||||
|
t.alike(buf, exp, 'buffers start out with same content')
|
||||||
|
t.unlike(buf, zero, 'buffer is not zero')
|
||||||
|
|
||||||
|
sodium.sodium_memzero(buf)
|
||||||
|
t.unlike(buf, exp, 'buffers are not longer the same')
|
||||||
|
t.alike(buf, zero, 'buffer is now zeroed')
|
||||||
|
})
|
||||||
|
|
||||||
|
test.skip('sodium_mlock / sodium_munlock', function (t) {
|
||||||
|
const buf = Buffer.alloc(10, 0x18)
|
||||||
|
const exp = Buffer.alloc(10, 0x18)
|
||||||
|
|
||||||
|
sodium.sodium_mlock(buf)
|
||||||
|
t.absent(buf.secure)
|
||||||
|
t.alike(buf, exp, 'mlock did not corrupt data')
|
||||||
|
sodium.sodium_munlock(buf)
|
||||||
|
t.absent(buf.secure)
|
||||||
|
t.alike(buf, Buffer.alloc(10), 'munlock did zero data')
|
||||||
|
})
|
||||||
|
|
||||||
|
test('sodium_malloc', function (t) {
|
||||||
|
const empty = sodium.sodium_malloc(0)
|
||||||
|
const small = sodium.sodium_malloc(1)
|
||||||
|
const large = sodium.sodium_malloc(1e8)
|
||||||
|
|
||||||
|
// sodium-javascript does not set secure prop
|
||||||
|
|
||||||
|
// t.ok(empty.secure)
|
||||||
|
// t.ok(small.secure)
|
||||||
|
// t.ok(large.secure)
|
||||||
|
|
||||||
|
t.ok(empty.length === 0, 'has correct size')
|
||||||
|
t.ok(small.length === 1, 'has correct size')
|
||||||
|
t.ok(large.length === 1e8, 'has correct size')
|
||||||
|
|
||||||
|
// const expected = Buffer.from([0xdb])
|
||||||
|
// expected.secure = true
|
||||||
|
// t.alike(small, expected, 'has canary content')
|
||||||
|
|
||||||
|
// test gc
|
||||||
|
for (let i = 0; i < 1e3; i++) {
|
||||||
|
if (sodium.sodium_malloc(256).length !== 256) {
|
||||||
|
t.fail('allocated incorrect size')
|
||||||
|
}
|
||||||
|
}
|
||||||
|
t.ok(empty.length === 0, 'retained correct size')
|
||||||
|
t.ok(small.length === 1, 'retained correct size')
|
||||||
|
t.ok(large.length === 1e8, 'retained correct size')
|
||||||
|
})
|
||||||
|
|
||||||
|
test('sodium_free', function (t) {
|
||||||
|
if (process.version.startsWith('v10')) {
|
||||||
|
t.comment('Skipping free test on v10')
|
||||||
|
return
|
||||||
|
}
|
||||||
|
const buf = sodium.sodium_malloc(1)
|
||||||
|
t.ok(buf.byteLength === 1)
|
||||||
|
sodium.sodium_free(buf)
|
||||||
|
t.ok(buf.byteLength === 0)
|
||||||
|
})
|
||||||
|
|
||||||
|
test.skip('sodium_malloc bounds', function (t) {
|
||||||
|
t.throws(function () {
|
||||||
|
sodium.sodium_malloc(-1)
|
||||||
|
}, 'too small')
|
||||||
|
t.throws(function () {
|
||||||
|
sodium.sodium_malloc(Number.MAX_SAFE_INTEGER)
|
||||||
|
}, 'too large')
|
||||||
|
})
|
111
test/randombytes.js
Normal file
111
test/randombytes.js
Normal file
@ -0,0 +1,111 @@
|
|||||||
|
/* eslint-disable camelcase */
|
||||||
|
const test = require('brittle')
|
||||||
|
const sodium = require('..')
|
||||||
|
|
||||||
|
test.skip('constants', function (t) {
|
||||||
|
t.alike(typeof sodium.randombytes_SEEDBYTES, 'number', 'randombytes_SEEDBYTES is number')
|
||||||
|
})
|
||||||
|
|
||||||
|
test.skip('randombytes_random', function (t) {
|
||||||
|
for (let i = 0; i < 1e6; i++) {
|
||||||
|
const n = sodium.randombytes_random()
|
||||||
|
if (n > 0xffffffff || n < 0) t.fail()
|
||||||
|
}
|
||||||
|
})
|
||||||
|
|
||||||
|
test.skip('randombytes_uniform', function (t) {
|
||||||
|
const p = 5381
|
||||||
|
for (let i = 0; i < 1e6; i++) {
|
||||||
|
const n = sodium.randombytes_uniform(5381)
|
||||||
|
if (n >= p || n < 0) t.fail()
|
||||||
|
}
|
||||||
|
})
|
||||||
|
|
||||||
|
test('randombytes_buf', function (t) {
|
||||||
|
let buf = null
|
||||||
|
|
||||||
|
buf = Buffer.alloc(10)
|
||||||
|
sodium.randombytes_buf(buf)
|
||||||
|
t.not(buf, Buffer.alloc(10), 'not blank')
|
||||||
|
|
||||||
|
buf = Buffer.alloc(1024)
|
||||||
|
sodium.randombytes_buf(buf)
|
||||||
|
t.not(buf, Buffer.alloc(1024), 'large not blank')
|
||||||
|
})
|
||||||
|
|
||||||
|
test.skip('randombytes_deterministic', function (t) {
|
||||||
|
const seed1 = Buffer.allocUnsafe(sodium.randombytes_SEEDBYTES)
|
||||||
|
const seed2 = Buffer.allocUnsafe(sodium.randombytes_SEEDBYTES)
|
||||||
|
const buf1 = Buffer.alloc(10)
|
||||||
|
const buf2 = Buffer.alloc(10)
|
||||||
|
|
||||||
|
for (let i = 0; i < 1e6; i++) {
|
||||||
|
sodium.randombytes_buf(seed1)
|
||||||
|
sodium.randombytes_buf(seed2)
|
||||||
|
|
||||||
|
sodium.randombytes_buf_deterministic(buf1, seed1)
|
||||||
|
sodium.randombytes_buf_deterministic(buf2, seed1)
|
||||||
|
if (!buf1.equals(buf2)) t.fail('should equal')
|
||||||
|
|
||||||
|
sodium.randombytes_buf_deterministic(buf1, seed1)
|
||||||
|
sodium.randombytes_buf_deterministic(buf2, seed2)
|
||||||
|
if (buf1.equals(buf2)) t.fail('should not equal')
|
||||||
|
|
||||||
|
sodium.randombytes_buf_deterministic(buf1, seed2)
|
||||||
|
sodium.randombytes_buf_deterministic(buf2, seed1)
|
||||||
|
if (buf1.equals(buf2)) t.fail('should not equal')
|
||||||
|
|
||||||
|
sodium.randombytes_buf_deterministic(buf1, seed2)
|
||||||
|
sodium.randombytes_buf_deterministic(buf2, seed2)
|
||||||
|
if (!buf1.equals(buf2)) t.fail('should equal')
|
||||||
|
}
|
||||||
|
})
|
||||||
|
|
||||||
|
test.skip('Various test cases', function (t) {
|
||||||
|
sodium.randombytes_buf(Buffer.alloc(0))
|
||||||
|
sodium.randombytes_buf(new Uint8Array(16))
|
||||||
|
|
||||||
|
t.throws(function () {
|
||||||
|
sodium.randombytes_buf([])
|
||||||
|
})
|
||||||
|
|
||||||
|
t.end()
|
||||||
|
})
|
||||||
|
|
||||||
|
test('Generates random bytes', function (t) {
|
||||||
|
const bufConst = Buffer.alloc(64)
|
||||||
|
sodium.randombytes_buf(bufConst)
|
||||||
|
|
||||||
|
const buf1 = Buffer.alloc(64)
|
||||||
|
for (let i = 0; i < 1e4; i++) {
|
||||||
|
sodium.randombytes_buf(buf1)
|
||||||
|
if (Buffer.compare(buf1, bufConst) === 0) {
|
||||||
|
t.fail('Constant buffer should not be equal')
|
||||||
|
t.end()
|
||||||
|
return
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
t.pass('Generated unique buffers')
|
||||||
|
t.end()
|
||||||
|
})
|
||||||
|
|
||||||
|
test('Exceed quota', function (t) {
|
||||||
|
const buf = Buffer.alloc(1 << 17)
|
||||||
|
sodium.randombytes_buf(buf)
|
||||||
|
|
||||||
|
const scores = new Array(256)
|
||||||
|
scores.fill(0)
|
||||||
|
|
||||||
|
for (const b of buf) {
|
||||||
|
scores[b]++
|
||||||
|
}
|
||||||
|
|
||||||
|
scores
|
||||||
|
.map(cnt => cnt / 256)
|
||||||
|
.forEach(cnt => {
|
||||||
|
if (cnt < 1 && cnt > 3) t.fail('Statistically unreasonable')
|
||||||
|
})
|
||||||
|
|
||||||
|
t.end()
|
||||||
|
})
|
1230
test/vectors.js
Normal file
1230
test/vectors.js
Normal file
File diff suppressed because it is too large
Load Diff
Loading…
Reference in New Issue
Block a user