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
This commit is contained in:
parent
51f8fbc2d3
commit
b44f83f0a8
159
crypto_aead.js
Normal file
159
crypto_aead.js
Normal 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
crypto_box.js
Normal file
105
crypto_box.js
Normal 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;
|
||||
}
|
@ -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
crypto_hash.js
Normal file
25
crypto_hash.js
Normal 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
crypto_hash_sha256.js
Normal file
18
crypto_hash_sha256.js
Normal 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
|
||||
}
|
33
crypto_kx.js
Normal file
33
crypto_kx.js
Normal file
@ -0,0 +1,33 @@
|
||||
const { crypto_scalarmult_base } = require('./crypto_scalarmult')
|
||||
const { crypto_generichash } = require('./crypto_generichash')
|
||||
const { randombytes_buf } = require('./randombytes')
|
||||
const assert = require('nanoassert')
|
||||
|
||||
var crypto_kx_SEEDBYTES = 32
|
||||
var crypto_kx_PUBLICKEYBYTES = 32
|
||||
var 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
|
||||
}
|
20
crypto_onetimeauth.js
Normal file
20
crypto_onetimeauth.js
Normal 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
crypto_scalarmult.js
Normal file
77
crypto_scalarmult.js
Normal 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
crypto_secretbox.js
Normal file
93
crypto_secretbox.js
Normal 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 : ''))
|
||||
}
|
@ -1,5 +1,7 @@
|
||||
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
|
||||
|
319
crypto_sign.js
Normal file
319
crypto_sign.js
Normal 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)
|
||||
seed.copy(sk)
|
||||
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 : ''))
|
||||
}
|
@ -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
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)
|
||||
}
|
34
crypto_verify.js
Normal file
34
crypto_verify.js
Normal 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
ed25519.js
Normal file
483
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
|
||||
}
|
@ -5,7 +5,10 @@
|
||||
"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"
|
||||
},
|
||||
|
360
poly1305.js
Normal file
360
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
|
Loading…
Reference in New Issue
Block a user