Compare commits

..
18 Commits
Author SHA1 Message Date
Mathias Buus fc90cbedba 0.6.0 2020-06-18 17:16:43 +02:00
Mathias Buus 63fb70028e bump sodium-test 2020-06-18 17:15:53 +02:00
Mathias Buus f033af88bd copy -> set 2020-06-18 17:12:00 +02:00
Christophe Diederichs b44f83f0a8 Split library into modules (#20)
* crypto_stream: signature change needed to modularise

* move ed25519 arithmetic to separate module

* module: poly1305

* module: crypto_scalarmult

* module: crypto_hash

* module: crypto_sign

* module: crypto_secretbox

* move verify functions to crypto_verify module

* leftover crypto_stream functions

* module: crypto_onetimeauth

* module: crypto_box

* tidy up

* require ed25519.js

* update: crypto_hash

* add chacha20; align API with PR#21

* update sha512 to wasm module

* fix bugs in crypto_sign

* be standard

* add: crypto_box_seed_keypair; alias crypto_kx methods to crypto_box

* scalarmult: import curve methods; be standard

* correction: crypto_kx is not actually an alias of crypto_box

* export _9 constant field element

* add: crypto_box_seed_keypair

* removed duplicate module.exports declaraion

* declare constants about exports

* rename memzero -> sodium-memzero

* update sodium_memzero function to arr.fill(0)

* tidy: remove legacy functions

* added: crypto_aead_chacha20poly1305_ietf methods

* listen to linter

* add assertions

* chacha: readUint32Le generalised for uint8array; aead: standard fix

* add null check on ad param

* added: sodium_memcmp

* export sodium_memcmp

* export crypto_verify module

* sodium_memcmp returns boolean

* added: sodium_is_zero

* catch syntax error

* throw if crypto_aead cannot validate, fix typo in crypto_verify

* move chacha20 alg to external module

* use Uint8Arrays instead of buffers

* change checks to assertions

* bump to chacha 1.0.3 - remove Buffer dependency

* reduce code branching, align return values with sodium-native

* add sha-wasm deps to package.json

* standard fixes

* bump chacha20 to 1.0.4: remove Buffer dep

* move crypto_hash_sha256 to module to uncouple wasm dependencies

* add endian check: all other modules require members of this set

* correct filename: crypto_hash_sha256

* export constant: crypto_hash_sha512_BYTES
2020-06-18 17:09:03 +02:00
Mathias Buus 51f8fbc2d3 0.5.6 2020-03-04 14:52:37 +01:00
Mathias Buus f790621e60 add sodium_malloc 2020-03-04 14:50:09 +01:00
Fedor Indutny 4e42b942a5 crypto_box: fix keypair, implement seal/seal_open
Secret Key is a random nonce, and public key is a point on elliptic
curve.

`crypto_box_seal`/`crypto_box_seal_open` are implemented using existing
primitives and newly exported `core_hsalsa20` in `xsalsa20`
2019-11-14 09:27:36 +01:00
Daniel Regeci 49587c3d7f crypto_box_keypair - rename arguments to pk,sk 2018-03-19 18:07:17 +00:00
Daniel Regeci 92aee452df crypto_box_keypair 2018-03-19 18:07:17 +00:00
Mathias Buus e1ca83f1bd 0.5.5 2018-03-19 19:03:43 +01:00
Peter van Hardenberg c81ef709d1 react-native doesn't want crypto set to an empty module (#14)
React-Native is sort of like a browser, sort of a native environment. On react-native we don't have the browser's crypto implementation, so we need to require react-native-crypto. We can rewrite the module requirement to do that using the extraNodeModules feature in rn-cli.config.js, but the metro packager assumes that if there's a "browser" field in package.json that it's relevant to react-native libraries unless there's also a "react-native" field. Hurray.

Anyway, this silly little patch tells metro not to replace crypto with an empty module but actually to use whatever you currently have crypto set to (which is not solved here, so you'll still have to do that.)
2018-03-19 18:58:24 +01:00
Jim Pick 4e1c69ba13 Change crypto_kdf_KEYBYTES to be 32 and use subarray instead of slice
Thanks to Emil Bayes for the advice.
2018-03-03 17:24:12 +00:00
Jim Pick 5159d68fa9 In kdf, truncate key before passing to blake to match sodium-native behaviour
Currently, sodium-native and sodium-javascript are returning different
hashes. The code in hyperdrive passes a 64 byte secret key to the kdf,
but only 32 bytes are used by the native version, but all 64 bytes are
used in the javascript version. As a result, hyperdrive secret keys
can't be imported/exported across the two sodium implementations.

https://gist.github.com/jimpick/3e869522eddaad77ac1bc9e64f36e1a7
2018-03-03 17:24:12 +00:00
Mathias Buus 5ccdcdee17 0.5.4 2017-11-19 13:16:51 +01:00
Mathias Buus 48081c6896 ignore crypto in the browser 2017-11-19 13:16:35 +01:00
Mathias Buus b1741bfdae 0.5.3 2017-11-17 12:09:34 +01:00
Mathias Buus f7de366eec fix shorthash_ready being deprecated 2017-11-17 12:07:52 +01:00
Mathias Buus 51e11143e5 fix siphash24 not having ready 2017-11-17 10:43:01 +01:00
20 changed files with 1844 additions and 1861 deletions
+159
View File
@@ -0,0 +1,159 @@
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('./poly1305.js')
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(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(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 !== 0) {
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
}
+105
View File
@@ -0,0 +1,105 @@
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_secretbox_open_easy, crypto_secretbox_easy } = require('./crypto_secretbox')
const xsalsa20 = require('xsalsa20')
const assert = require('nanoassert')
var crypto_box_PUBLICKEYBYTES = 32,
crypto_box_SECRETKEYBYTES = 32,
crypto_box_BEFORENMBYTES = 32,
crypto_box_NONCEBYTES = 24,
crypto_box_ZEROBYTES = 32,
crypto_box_BOXZEROBYTES = 16,
crypto_box_SEALBYTES = 48,
crypto_box_SEEDBYTES = 32,
crypto_box_BEFORENMBYTES = 32
module.exports = {
crypto_box_keypair,
crypto_box_seed_keypair,
crypto_box_seal,
crypto_box_seal_open,
crypto_box_PUBLICKEYBYTES,
crypto_box_SECRETKEYBYTES,
crypto_box_BEFORENMBYTES,
crypto_box_NONCEBYTES,
crypto_box_ZEROBYTES,
crypto_box_BOXZEROBYTES,
crypto_box_SEALBYTES,
crypto_box_SEEDBYTES,
crypto_box_BEFORENMBYTES
}
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 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 (var i = 0; i < arr.length; i++) arr[i] = 0;
}
+2
View File
@@ -1,5 +1,7 @@
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_BYTES_MIN = blake2b.BYTES_MIN
module.exports.crypto_generichash_BYTES_MAX = blake2b.BYTES_MAX
+25
View File
@@ -0,0 +1,25 @@
const sha512 = require('sha512-wasm')
const assert = require('nanoassert')
if (new Uint16Array([1])[0] !== 1) throw new Error('Big endian architecture is not supported.')
var crypto_hash_sha512_BYTES = 64
var 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
}
+18
View File
@@ -0,0 +1,18 @@
const sha256 = require('sha256-wasm')
const assert = require('nanoassert')
if (new Uint16Array([1])[0] !== 1) throw new Error('Big endian architecture is not supported.')
var 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
}
+2 -2
View File
@@ -6,7 +6,7 @@ module.exports.crypto_kdf_PRIMITIVE = 'blake2b'
module.exports.crypto_kdf_BYTES_MIN = 16
module.exports.crypto_kdf_BYTES_MAX = 64
module.exports.crypto_kdf_CONTEXTBYTES = 8
module.exports.crypto_kdf_KEYBYTES = 64
module.exports.crypto_kdf_KEYBYTES = 32
function STORE64_LE(dest, int) {
var mul = 1
@@ -29,7 +29,7 @@ module.exports.crypto_kdf_derive_from_key = function crypto_kdf_derive_from_key
STORE64_LE(salt, subkey_id)
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)
}
+24 -70
View File
@@ -1,79 +1,33 @@
var assert = require('nanoassert')
var randombytes_buf = require('./randombytes').randombytes_buf
var generichash = require('./crypto_generichash')
var crypto_scalarmult_base = require('./crypto_scalarmult').crypto_scalarmult_base
const { crypto_scalarmult_base } = require('./crypto_scalarmult')
const { crypto_generichash } = require('./crypto_generichash')
const { randombytes_buf } = require('./randombytes')
const assert = require('nanoassert')
exports.crypto_kx_PUBLICKEYBYTES = 32
exports.crypto_kx_SECRETKEYBYTES = 32
exports.crypto_kx_SEEDBYTES = 32
exports.crypto_kx_SESSIONKEYBYTES = 32
exports.crypto_kx_PRIMITIVE = ''
var crypto_kx_SEEDBYTES = 32
var crypto_kx_PUBLICKEYBYTES = 32
var crypto_kx_SECRETKEYBYTES = 32
exports.crypto_kx_keypair = function (pk, sk) {
assert(sk.byteLength >= exports.crypto_kx_SECRETKEYBYTES, 'sk must be at least crypto_kx_SECRETKEYBYTES')
assert(pk.byteLength >= exports.crypto_kx_PUBLICKEYBYTES, 'pk must be at least crypto_kx_PUBLICKEYBYTES')
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.subarray(0, exports.crypto_kx_SECRETKEYBYTES))
crypto_scalarmult_base(
pk.subarray(0, exports.crypto_kx_PUBLICKEYBYTES),
sk.subarray(0, exports.crypto_kx_SECRETKEYBYTES)
)
randombytes_buf(sk, crypto_kx_SECRETKEYBYTES)
return crypto_scalarmult_base(pk, sk)
}
exports.crypto_kx_seed_keypair = function (pk, sk, seed) {
assert(sk.byteLength >= exports.crypto_kx_SECRETKEYBYTES, 'sk must be at least crypto_kx_SECRETKEYBYTES')
assert(pk.byteLength >= exports.crypto_kx_PUBLICKEYBYTES, 'pk must be at least crypto_kx_PUBLICKEYBYTES')
assert(seed.byteLength >= exports.crypto_kx_SEEDBYTES, 'seed must be at least crypto_kx_SEEDBYTES')
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")
generichash.crypto_generichash(
sk.subarray(0, exports.crypto_kx_SECRETKEYBYTES),
seed.subarray(0, exports.crypto_kx_SEEDBYTES)
)
crypto_scalarmult_base(
pk.subarray(0, exports.crypto_kx_PUBLICKEYBYTES),
sk.subarray(0, exports.crypto_kx_SECRETKEYBYTES)
)
crypto_generichash(sk, seed)
return crypto_scalarmult_base(pk, sk)
}
exports.crypto_kx_client_session_keys = calc.bind(null, false)
exports.crypto_kx_server_session_keys = calc.bind(null, true)
function calc (server, rx, tx, pk, sk, remote_pk) {
if (rx == null) rx = tx
if (tx == null) tx = rx
assert(rx >= exports.crypto_kx_SESSIONKEYBYTES, 'rx must be at least crypto_kx_SESSIONKEYBYTES')
assert(tx >= exports.crypto_kx_SESSIONKEYBYTES, 'tx should be at least crypto_kx_SESSIONKEYBYTES')
assert(sk.byteLength >= exports.crypto_kx_SECRETKEYBYTES, 'sk must be at least crypto_kx_SECRETKEYBYTES')
assert(pk.byteLength >= exports.crypto_kx_PUBLICKEYBYTES, 'pk must be at least crypto_kx_PUBLICKEYBYTES')
assert(remote_pk.byteLength >= exports.crypto_kx_PUBLICKEYBYTES, 'remote_pk must be at least crypto_kx_PUBLICKEYBYTES')
rx = rx.subarray(0, exports.crypto_kx_SESSIONKEYBYTES)
tx = tx.subarray(0, exports.crypto_kx_SESSIONKEYBYTES)
sk = sk.subarray(0, exports.crypto_kx_SECRETKEYBYTES)
pk = pk.subarray(0, exports.crypto_kx_PUBLICKEYBYTES)
remote_pk = remote_pk.subarray(0, exports.crypto_kx_PUBLICKEYBYTES)
var keys = new Uint8Array(2 * exports.crypto_kx_SESSIONKEYBYTES)
var hash = generichash.crypto_generichash_instance(null, keys.byteLength)
var q = new Uint8Array(scalarmult.crypto_scalarmult_BYTES)
scalarmult.crypto_scalamult(q, sk, remote_pk)
hash.update(q)
q.fill(0)
// if server, then remote_pk == client_pk
hash.update(server ? remote_pk : pk)
hash.update(server ? pk : remote_pk)
hash.final(keys)
// TODO clear out hash
rx.set(keys.subarray(0, exports.crypto_kx_SESSIONKEYBYTES))
tx.set(keys.subarray(exports.crypto_kx_SESSIONKEYBYTES))
module.exports = {
crypto_kx_keypair,
crypto_kx_seed_keypair,
crypto_kx_SEEDBYTES,
crypto_kx_SECRETKEYBYTES,
crypto_kx_PUBLICKEYBYTES
}
+20
View File
@@ -0,0 +1,20 @@
const poly1305 = require('./poly1305')
const { crypto_verify_16 } = require('./crypto_verify')
module.exports = {
crypto_onetimeauth,
crypto_onetimeauth_verify
}
function crypto_onetimeauth(out, outpos, m, mpos, n, k) {
var s = new poly1305(k);
s.update(m, mpos, n);
s.finish(out, outpos);
return 0;
}
function crypto_onetimeauth_verify(h, hpos, m, mpos, n, k) {
var x = new Uint8Array(16);
crypto_onetimeauth(x,0,m,mpos,n,k);
return crypto_verify_16(h,hpos,x,0);
}
+77
View File
@@ -0,0 +1,77 @@
const { _9, _121665, gf, inv25519, pack25519, unpack25519, sel25519, A, M, Z, S } = require('./ed25519.js')
var crypto_scalarmult_BYTES = 32
var crypto_scalarmult_SCALARBYTES = 32
var crypto_scalarmult_BYTES = 32
var 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 : ''))
}
+93
View File
@@ -0,0 +1,93 @@
var { crypto_stream, crypto_stream_xor } = require('./crypto_stream')
var { crypto_onetimeauth, crypto_onetimeauth_verify } = require('./crypto_onetimeauth')
var crypto_secretbox_KEYBYTES = 32,
crypto_secretbox_NONCEBYTES = 24,
crypto_secretbox_ZEROBYTES = 32,
crypto_secretbox_BOXZEROBYTES = 16,
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, d, n, k) {
var i
if (d < 32) return -1
crypto_stream_xor(c, m, n, k)
crypto_onetimeauth(c, 16, c, 32, d - 32, c)
for (i = 0; i < 16; i++) c[i] = 0
return 0
}
function crypto_secretbox_open (m, c, d, n, k) {
var i
var x = new Uint8Array(32)
if (d < 32) return -1
crypto_stream(x, n, k)
if (crypto_onetimeauth_verify(c, 16, c, 32, d - 32, x) !== 0) return -1
crypto_stream_xor(m, c, n, k)
for (i = 0; i < 32; i++) m[i] = 0
return 0
}
function crypto_secretbox_detached (o, mac, msg, n, k) {
check(mac, crypto_secretbox_MACBYTES)
var tmp = new Uint8Array(msg.length + mac.length)
crypto_secretbox_easy(tmp, msg, n, k)
o.set(tmp.subarray(0, msg.length))
mac.set(tmp.subarray(msg.length))
}
function crypto_secretbox_open_detached (msg, o, mac, n, k) {
check(mac, crypto_secretbox_MACBYTES)
var tmp = new Uint8Array(o.length + mac.length)
tmp.set(o)
tmp.set(mac, msg.length)
return crypto_secretbox_open_easy(msg, tmp, n, k)
}
function crypto_secretbox_easy(o, msg, n, k) {
check(msg, 0)
check(o, msg.length + crypto_secretbox_MACBYTES)
check(n, crypto_secretbox_NONCEBYTES)
check(k, crypto_secretbox_KEYBYTES)
var i
var m = new Uint8Array(crypto_secretbox_ZEROBYTES + msg.length)
var c = new Uint8Array(m.length)
for (i = 0; i < msg.length; i++) m[i + crypto_secretbox_ZEROBYTES] = msg[i]
crypto_secretbox(c, m, m.length, n, k)
for (i = crypto_secretbox_BOXZEROBYTES; i < c.length; i++) o[i - crypto_secretbox_BOXZEROBYTES] = c[i]
}
function crypto_secretbox_open_easy(msg, box, n, k) {
check(box, crypto_secretbox_MACBYTES)
check(msg, box.length - crypto_secretbox_MACBYTES)
check(n, crypto_secretbox_NONCEBYTES)
check(k, crypto_secretbox_KEYBYTES)
var i
var c = new Uint8Array(crypto_secretbox_BOXZEROBYTES + box.length)
var m = new Uint8Array(c.length)
for (i = 0; i < box.length; i++) c[i + crypto_secretbox_BOXZEROBYTES] = box[i]
if (c.length < 32) return false
if (crypto_secretbox_open(m, c, c.length, n, k) !== 0) return false
for (i = crypto_secretbox_ZEROBYTES; i < m.length; i++) msg[i - crypto_secretbox_ZEROBYTES] = m[i]
return true
}
function check (buf, len) {
if (!buf || (len && buf.length < len)) throw new Error('Argument must be a buffer' + (len ? ' of length ' + len : ''))
}
+2 -5
View File
@@ -1,17 +1,14 @@
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_BYTES = siphash.BYTES
exports.crypto_shorthash_KEYBYTES = siphash.KEYBYTES
exports.crypto_shorthash_WASM_SUPPORTED = siphash.WASM_SUPPORTED
exports.crypto_shorthash_WASM_LOADED = siphash.WASM_LOADED
exports.crypto_shorthash_ready = siphash.ready
exports.crypto_shorthash = shorthash
siphash.ready(function () {
exports.crypto_shorthash_WASM_LOADED = siphash.WASM_LOADED
})
function shorthash (out, data, key, noAssert) {
siphash(data, key, out, noAssert)
}
+319
View File
@@ -0,0 +1,319 @@
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('./ed25519')
const { randombytes } = require('./randombytes')
const crypto_sign_BYTES = 64,
crypto_sign_PUBLICKEYBYTES = 32,
crypto_sign_SECRETKEYBYTES = 64,
crypto_sign_SEEDBYTES = 32
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
}
function set25519(r, a) {
var i;
for (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) {
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, q, b);
add(q, p);
add(p, p);
cswap(p, q, 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];
return 0;
}
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), i;
for (i = 0; i < 64; i++) x[i] = r[i];
for (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 (var 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 -1;
if (par25519(r[0]) === (p[31]>>7)) Z(r[0], gf0, r[0]);
M(r[3], r[0], r[1]);
return 0;
}
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;
}
for (i = 0; i < n; i++) msg[i] = sm[i + 64];
mlen = n;
return true;
}
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 check (buf, len) {
if (!buf || (len && buf.length < len)) throw new Error('Argument must be a buffer' + (len ? ' of length ' + len : ''))
}
+8 -5
View File
@@ -1,17 +1,20 @@
var 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_NONCEBYTES = 24
exports.crypto_stream_PRIMITIVE = 'xsalsa20'
exports.crypto_stream = function (out, nonce, key) {
out.fill(0)
exports.crypto_stream_xor(out, out, nonce, key)
exports.crypto_stream = function (c, nonce, key) {
c.fill(0)
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)
xor.update(inp, out)
xor.update(m, c)
xor.final()
}
+84
View 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)
}
+34
View File
@@ -0,0 +1,34 @@
const assert = require('nanoassert')
module.exports = {
crypto_verify_16,
crypto_verify_32,
sodium_memcmp,
sodium_is_zero
}
function vn (x, xi, y, yi, n) {
var i, d = 0
for (i = 0; i < n; i++) d |= x[xi + i] ^ y[yi + i]
return (1 & ((d - 1) >>> 8)) - 1
}
function crypto_verify_16(x, xi, y, yi) {
return vn(x, xi, y, yi, 16)
}
function crypto_verify_32(x, xi, y, yi) {
return vn(x, xi, y, yi, 32)
}
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
}
+483
View 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
}
+17 -1776
View File
File diff suppressed because it is too large Load Diff
+11 -2
View File
@@ -1,18 +1,27 @@
{
"name": "sodium-javascript",
"version": "0.5.2",
"version": "0.6.0",
"description": "WIP - a pure javascript version of sodium-native",
"main": "index.js",
"dependencies": {
"blake2b": "^2.1.1",
"chacha20-universal": "^1.0.4",
"nanoassert": "^1.0.0",
"sha256-wasm": "^1.3.0",
"sha512-wasm": "^1.2.0",
"siphash24": "^1.0.1",
"xsalsa20": "^1.0.0"
},
"devDependencies": {
"browser-run": "^4.0.2",
"browserify": "^14.1.0",
"sodium-test": "^0.7.0"
"sodium-test": "^0.9.0"
},
"browser": {
"crypto": false
},
"react-native": {
"crypto": "crypto"
},
"scripts": {
"browser": "browserify test.js | browser-run",
+360
View 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
+1 -1
View File
@@ -21,7 +21,7 @@ var randombytes = (function () {
return browserBytes
} else if (typeof require !== 'undefined') {
// Node.js.
crypto = require('cry' + 'pto');
crypto = require('crypto')
if (crypto && crypto.randomBytes) {
return nodeBytes
}