Skip to content

Commit

Permalink
Added ESM support
Browse files Browse the repository at this point in the history
- Import `tweetnacl/esm[/index.mjs]` or `tweetnacl/esm/fast[/index.mjs]`
  to use ESM. Importing (or requiring) `tweetnacl` will use the UMD build.
- Breaking change: Consumers need to explicitly set the PRNG by
  calling `setPRNG` , `setGlobalCryptoPRNG`, or `setNodeCryptoPRNG` if
  they're using functions such as `signKeyPair` (nacl.sign.keyPair) and
  `boxKeyPair` (nacl.box.keyPair).
  This needs to be done to remove module side-effects.
- nacl.js, nacl.min.js, nacl-fast.js, and nacl-fast.min.js are now
  compiled using Vite from ESM to UMD format. Because of this,
  the size of the outputs slightly increased.
- Tested; All tests passed!  Ran test.html, test-quick.html,
  test-fast.html, and test-quick-fast.html in Chrome 102.0.5005.115.
  Did npm run test using Node v16.15.0,
- Not yet linted...
  • Loading branch information
bmdelacruz committed Jun 22, 2022
1 parent 6a9594a commit 5c4460f
Show file tree
Hide file tree
Showing 56 changed files with 8,021 additions and 3,518 deletions.
30 changes: 30 additions & 0 deletions build.mjs
Original file line number Diff line number Diff line change
@@ -0,0 +1,30 @@
import { build } from 'vite';
import { fileURLToPath } from 'url';
import { resolve, dirname } from 'path';

const projectDir = dirname(fileURLToPath(import.meta.url));

/** @type {[entry: string, minify: boolean, fast: boolean][]} */
const entries = [
[resolve(projectDir, "umd/index.mjs"), false, false],
[resolve(projectDir, "umd/index.mjs"), true, false],
[resolve(projectDir, "umd/fast.mjs"), false, true],
[resolve(projectDir, "umd/fast.mjs"), true, true],
];

for (const [entry, minify, fast] of entries) {
await build({
build: {
lib: {
entry,
name: "nacl",
formats: ["umd"],
fileName: () => `nacl${fast ? '-fast' : ''}${minify ? '.min' : ''}.js`
},
minify: minify && 'esbuild',
emptyOutDir: false,
outDir: '.',
},
clearScreen: false,
});
}
10 changes: 10 additions & 0 deletions esm/array.mjs
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
export function checkArrayTypes() {
for (var i = 0; i < arguments.length; i++) {
if (!(arguments[i] instanceof Uint8Array))
throw new TypeError('unexpected type, use Uint8Array');
}
}

export function cleanup(arr) {
for (var i = 0; i < arr.length; i++) arr[i] = 0;
}
62 changes: 62 additions & 0 deletions esm/box.mjs
Original file line number Diff line number Diff line change
@@ -0,0 +1,62 @@
import { checkArrayTypes } from './array.mjs';
import { secretbox, secretboxOpen } from './secretbox.mjs';
import { crypto_scalarmult_base } from './lowlevel/scalarmult.mjs';
import {
crypto_box_beforenm,
crypto_box_keypair,
crypto_box_BEFORENMBYTES,
crypto_box_PUBLICKEYBYTES,
crypto_box_SECRETKEYBYTES
} from './lowlevel/box.mjs';

export {
crypto_box_PUBLICKEYBYTES as boxPublicKeyLength,
crypto_box_SECRETKEYBYTES as boxSecretKeyLength,
crypto_box_BEFORENMBYTES as boxSharedKeyLength,
crypto_box_NONCEBYTES as boxNonceLength,
} from './lowlevel/box.mjs';

export {
secretbox as boxAfter,
secretboxOpen as boxOpenAfter,
secretboxOverheadLength as boxOverheadLength,
} from './secretbox.mjs';

export function box(msg, nonce, publicKey, secretKey) {
var k = boxBefore(publicKey, secretKey);
return secretbox(msg, nonce, k);
}

export function checkBoxLengths(pk, sk) {
if (pk.length !== crypto_box_PUBLICKEYBYTES) throw new Error('bad public key size');
if (sk.length !== crypto_box_SECRETKEYBYTES) throw new Error('bad secret key size');
}

export function boxBefore(publicKey, secretKey) {
checkArrayTypes(publicKey, secretKey);
checkBoxLengths(publicKey, secretKey);
var k = new Uint8Array(crypto_box_BEFORENMBYTES);
crypto_box_beforenm(k, publicKey, secretKey);
return k;
}

export function boxOpen(msg, nonce, publicKey, secretKey) {
var k = boxBefore(publicKey, secretKey);
return secretboxOpen(msg, nonce, k);
}

export function boxKeyPair() {
var pk = new Uint8Array(crypto_box_PUBLICKEYBYTES);
var sk = new Uint8Array(crypto_box_SECRETKEYBYTES);
crypto_box_keypair(pk, sk);
return { publicKey: pk, secretKey: sk };
}

export function boxKeyPairFromSecretKey(secretKey) {
checkArrayTypes(secretKey);
if (secretKey.length !== crypto_box_SECRETKEYBYTES)
throw new Error('bad secret key size');
var pk = new Uint8Array(crypto_box_PUBLICKEYBYTES);
crypto_scalarmult_base(pk, secretKey);
return { publicKey: pk, secretKey: new Uint8Array(secretKey) };
}
58 changes: 58 additions & 0 deletions esm/fast/box.mjs
Original file line number Diff line number Diff line change
@@ -0,0 +1,58 @@
import { checkBoxLengths } from '../box.mjs';
import { checkArrayTypes } from '../array.mjs';
import { secretbox, secretboxOpen } from '../secretbox.mjs';
import {
crypto_box_keypair,
crypto_box_beforenm,
crypto_box_BEFORENMBYTES,
crypto_box_PUBLICKEYBYTES,
crypto_box_SECRETKEYBYTES,
} from './lowlevel/box.mjs'
import { crypto_scalarmult_base } from './lowlevel/scalarmult.mjs';

export {
boxNonceLength,
boxOverheadLength,
boxPublicKeyLength,
boxSecretKeyLength,
boxSharedKeyLength,
} from '../box.mjs';

export {
secretbox as boxAfter,
secretboxOpen as boxOpenAfter,
} from './secretbox.mjs';

export function box(msg, nonce, publicKey, secretKey) {
var k = boxBefore(publicKey, secretKey);
return secretbox(msg, nonce, k);
}

export function boxBefore(publicKey, secretKey) {
checkArrayTypes(publicKey, secretKey);
checkBoxLengths(publicKey, secretKey);
var k = new Uint8Array(crypto_box_BEFORENMBYTES);
crypto_box_beforenm(k, publicKey, secretKey);
return k;
}

export function boxOpen(msg, nonce, publicKey, secretKey) {
var k = boxBefore(publicKey, secretKey);
return secretboxOpen(msg, nonce, k);
}

export function boxKeyPair() {
var pk = new Uint8Array(crypto_box_PUBLICKEYBYTES);
var sk = new Uint8Array(crypto_box_SECRETKEYBYTES);
crypto_box_keypair(pk, sk);
return { publicKey: pk, secretKey: sk };
}

export function boxKeyPairFromSecretKey(secretKey) {
checkArrayTypes(secretKey);
if (secretKey.length !== crypto_box_SECRETKEYBYTES)
throw new Error('bad secret key size');
var pk = new Uint8Array(crypto_box_PUBLICKEYBYTES);
crypto_scalarmult_base(pk, secretKey);
return { publicKey: pk, secretKey: new Uint8Array(secretKey) };
}
15 changes: 15 additions & 0 deletions esm/fast/hash.mjs
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
import { checkArrayTypes } from '../array.mjs';
import { crypto_hash, crypto_hash_BYTES } from './lowlevel/hash.mjs';

export { crypto_hash_BYTES as hashLength } from './lowlevel/hash.mjs';

/**
* @param {Uint8Array} msg
* @returns {Uint8Array}
*/
export function hash(msg) {
checkArrayTypes(msg);
var h = new Uint8Array(crypto_hash_BYTES);
crypto_hash(h, msg, msg.length);
return h;
}
56 changes: 56 additions & 0 deletions esm/fast/index.d.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,56 @@
export interface BoxKeyPair {
publicKey: Uint8Array;
secretKey: Uint8Array;
}

export interface SignKeyPair {
publicKey: Uint8Array;
secretKey: Uint8Array;
}

export function randomBytes(n: number): Uint8Array;

export function secretbox(msg: Uint8Array, nonce: Uint8Array, key: Uint8Array): Uint8Array;
export function secretboxOpen(box: Uint8Array, nonce: Uint8Array, key: Uint8Array): Uint8Array | null;
export const secretboxKeyLength: number;
export const secretboxNonceLength: number;
export const secretboxOverheadLength: number;

export function scalarMult(n: Uint8Array, p: Uint8Array): Uint8Array;
export function scalarMultBase(n: Uint8Array): Uint8Array;
export const scalarMultScalarLength: number;
export const scalarMultGroupElementLength: number;

export function box(msg: Uint8Array, nonce: Uint8Array, publicKey: Uint8Array, secretKey: Uint8Array): Uint8Array;
export function boxBefore(publicKey: Uint8Array, secretKey: Uint8Array): Uint8Array;
export function boxAfter(msg: Uint8Array, nonce: Uint8Array, key: Uint8Array): Uint8Array;
export function boxOpen(msg: Uint8Array, nonce: Uint8Array, publicKey: Uint8Array, secretKey: Uint8Array): Uint8Array | null;
export function boxOpenAfter(box: Uint8Array, nonce: Uint8Array, key: Uint8Array): Uint8Array | null;
export function boxKeyPair(): BoxKeyPair;
export function boxKeyPairFromSecretKey(secretKey: Uint8Array): BoxKeyPair;
export const boxPublicKeyLength: number;
export const boxSecretKeyLength: number;
export const boxSharedKeyLength: number;
export const boxNonceLength: number;
export const boxOverheadLength: number;

export function sign(msg: Uint8Array, secretKey: Uint8Array): Uint8Array;
export function signOpen(signedMsg: Uint8Array, publicKey: Uint8Array): Uint8Array | null;
export function signDetached(msg: Uint8Array, secretKey: Uint8Array): Uint8Array;
export function signDetachedVerify(msg: Uint8Array, sig: Uint8Array, publicKey: Uint8Array): boolean;
export function signKeyPair(): SignKeyPair;
export function signKeyPairFromSecretKey(secretKey: Uint8Array): SignKeyPair;
export function signKeyPairFromSeed(secretKey: Uint8Array): SignKeyPair;
export const signPublicKeyLength: number;
export const signSecretKeyLength: number;
export const signSeedLength: number;
export const signSignatureLength: number;

export function hash (msg: Uint8Array): Uint8Array;
export const hashLength: number;

export function verify(x: Uint8Array, y: Uint8Array): boolean;

export function setPRNG(prng: (target: Uint8Array, length: number) => void): void;
export function setGlobalCryptoPRNG(): void;
export function setNodeCryptoPRNG(): void;
53 changes: 53 additions & 0 deletions esm/fast/index.mjs
Original file line number Diff line number Diff line change
@@ -0,0 +1,53 @@
export {
verify,
randomBytes,
setPRNG,
setGlobalCryptoPRNG,
setNodeCryptoPRNG,
} from '../index.mjs';

export {
secretbox,
secretboxOpen,
secretboxKeyLength,
secretboxNonceLength,
secretboxOverheadLength,
} from './secretbox.mjs';

export {
scalarMult,
scalarMultBase,
scalarMultScalarLength,
scalarMultGroupElementLength,
} from './scalarmult.mjs';

export {
box,
boxBefore,
boxAfter,
boxOpen,
boxOpenAfter,
boxKeyPair,
boxKeyPairFromSecretKey,
boxPublicKeyLength,
boxSecretKeyLength,
boxSharedKeyLength,
boxNonceLength,
boxOverheadLength,
} from './box.mjs';

export {
sign,
signOpen,
signDetached,
signDetachedVerify,
signKeyPair,
signKeyPairFromSecretKey,
signKeyPairFromSeed,
signPublicKeyLength,
signSecretKeyLength,
signSeedLength,
signSignatureLength,
} from './sign.mjs';

export { hash, hashLength } from './hash.mjs';
40 changes: 40 additions & 0 deletions esm/fast/lowlevel/box.mjs
Original file line number Diff line number Diff line change
@@ -0,0 +1,40 @@
import { _0 } from '../../lowlevel/box.mjs';
import { randombytes } from '../../prng.mjs';
import { sigma } from '../../lowlevel/stream.mjs';
import { crypto_core_hsalsa20 } from './stream.mjs';
import { crypto_scalarmult, crypto_scalarmult_base } from './scalarmult.mjs';
import { crypto_secretbox, crypto_secretbox_open } from './secretbox.mjs';

export { crypto_secretbox as crypto_box_afternm } from './secretbox.mjs';

export {
crypto_box_PUBLICKEYBYTES,
crypto_box_SECRETKEYBYTES,
crypto_box_BEFORENMBYTES,
crypto_box_NONCEBYTES,
crypto_box_ZEROBYTES,
crypto_box_BOXZEROBYTES,
} from '../../lowlevel/box.mjs';

export function crypto_box_beforenm(k, y, x) {
var s = new Uint8Array(32);
crypto_scalarmult(s, x, y);
return crypto_core_hsalsa20(k, _0, s, sigma);
}

export function crypto_box(c, m, d, n, y, x) {
var k = new Uint8Array(32);
crypto_box_beforenm(k, y, x);
return /* crypto_box_afternm */ crypto_secretbox(c, m, d, n, k);
}

export function crypto_box_open(m, c, d, n, y, x) {
var k = new Uint8Array(32);
crypto_box_beforenm(k, y, x);
return /* crypto_box_open_afternm */ crypto_secretbox_open(m, c, d, n, k);
}

export function crypto_box_keypair(y, x) {
randombytes(x, 32);
return crypto_scalarmult_base(y, x);
}
Loading

0 comments on commit 5c4460f

Please sign in to comment.