Skip to content

Commit

Permalink
Consolidate webcrypto directory into single file
Browse files Browse the repository at this point in the history
  • Loading branch information
paulmillr committed Jan 2, 2024
1 parent a91a39b commit b58c936
Show file tree
Hide file tree
Showing 21 changed files with 189 additions and 183 deletions.
2 changes: 0 additions & 2 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -9,5 +9,3 @@ node_modules
/esm/*.js.map
/esm/*.d.ts.map
/lib
/webcrypto/
/esm/webcrypto/
19 changes: 9 additions & 10 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -76,7 +76,7 @@ import { xchacha20poly1305 } from '@noble/ciphers/chacha';
```js
import { xchacha20poly1305 } from '@noble/ciphers/chacha';
import { utf8ToBytes } from '@noble/ciphers/utils';
import { randomBytes } from '@noble/ciphers/webcrypto/utils';
import { randomBytes } from '@noble/ciphers/webcrypto';
const key = randomBytes(32);
const nonce = randomBytes(24);
const chacha = xchacha20poly1305(key, nonce);
Expand All @@ -90,7 +90,7 @@ const data_ = chacha.decrypt(ciphertext); // utils.bytesToUtf8(data_) === data
```js
import { gcm } from '@noble/ciphers/aes';
import { utf8ToBytes } from '@noble/ciphers/utils';
import { randomBytes } from '@noble/ciphers/webcrypto/utils';
import { randomBytes } from '@noble/ciphers/webcrypto';
const key = randomBytes(32);
const nonce = randomBytes(24);
const aes = gcm(key, nonce);
Expand Down Expand Up @@ -124,7 +124,7 @@ const nonce2 = hexToBytes('9610467513de0bbd7c4cc2c3c64069f1802086fbd3232b13');

```js
import { xchacha20poly1305 } from '@noble/ciphers/chacha';
import { managedNonce } from '@noble/ciphers/webcrypto/utils'
import { managedNonce } from '@noble/ciphers/webcrypto'
import { hexToBytes, utf8ToBytes } from '@noble/ciphers/utils';
const key = hexToBytes('fa686bfdffd3758f6377abbc23bf3d9bdc1a0dda4a6e7f8dbdd579fa1ff6d7e1');
const chacha = managedNonce(xchacha20poly1305)(key); // manages nonces for you
Expand All @@ -138,7 +138,7 @@ const data_ = chacha.decrypt(ciphertext);
```js
import { chacha20poly1305 } from '@noble/ciphers/chacha';
import { utf8ToBytes } from '@noble/ciphers/utils';
import { randomBytes } from '@noble/ciphers/webcrypto/utils';
import { randomBytes } from '@noble/ciphers/webcrypto';

const key = randomBytes(32);
const nonce = randomBytes(12);
Expand Down Expand Up @@ -166,7 +166,7 @@ import { chacha20, xchacha20, chacha8, chacha12 } from '@noble/ciphers/chacha';

// Utilities
import { bytesToHex, hexToBytes, bytesToUtf8, utf8ToBytes } from '@noble/ciphers/utils';
import { managedNonce, randomBytes } from '@noble/ciphers/webcrypto/utils';
import { managedNonce, randomBytes } from '@noble/ciphers/webcrypto';
```

## Implementations
Expand Down Expand Up @@ -217,7 +217,7 @@ Check out [PDF](http://cr.yp.to/chacha/chacha-20080128.pdf) and [wiki](https://e

```js
import { gcm, siv, ctr, cbc, ecb } from '@noble/ciphers/aes';
import { randomBytes } from '@noble/ciphers/webcrypto/utils';
import { randomBytes } from '@noble/ciphers/webcrypto';
const plaintext = new Uint8Array(32).fill(16);
const key = randomBytes(32); // 24 for AES-192, 16 for AES-128
for (let cipher of [gcm, siv]) {
Expand Down Expand Up @@ -254,8 +254,7 @@ Check out [AES internals and block modes](#aes-internals-and-block-modes).
### Webcrypto AES

```js
import { gcm, ctr, cbc } from '@noble/ciphers/webcrypto/aes';
import { randomBytes } from '@noble/ciphers/webcrypto/utils';
import { gcm, ctr, cbc, randomBytes } from '@noble/ciphers/webcrypto';
const plaintext = new Uint8Array(32).fill(16);
const key = randomBytes(32);
for (const cipher of [gcm]) {
Expand Down Expand Up @@ -310,7 +309,7 @@ Format-preserving encryption algorithm (FPE-FF1) specified in NIST Special Publi
### Managed nonces

```js
import { managedNonce } from '@noble/ciphers/webcrypto/utils';
import { managedNonce } from '@noble/ciphers/webcrypto';
import { gcm, siv, ctr, cbc, ecb } from '@noble/ciphers/aes';
import { xsalsa20poly1305 } from '@noble/ciphers/salsa';
import { chacha20poly1305, xchacha20poly1305 } from '@noble/ciphers/chacha';
Expand Down Expand Up @@ -620,7 +619,7 @@ console.log(aes.utils.bytesToUtf8(plaintext) === message);

import { gcm } from '@noble/ciphers/aes';
import { bytesToUtf8, utf8ToBytes } from '@noble/ciphers/utils';
import { managedNonce } from '@noble/ciphers/webcrypto/utils';
import { managedNonce } from '@noble/ciphers/webcrypto';
const aes = managedNonce(gcm)(key);
const ciphertext = aes.encrypt(utf8ToBytes(message));
const plaintext = aes.decrypt(key, ciphertext);
Expand Down
2 changes: 1 addition & 1 deletion benchmark/aes.js
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
import { utils as butils } from 'micro-bmark';
import { createCipheriv, createDecipheriv } from 'node:crypto';

import * as webcrypto from '@noble/ciphers/webcrypto/aes';
import * as webcrypto from '@noble/ciphers/webcrypto';
import { concatBytes } from '@noble/ciphers/utils';
import * as aes from '@noble/ciphers/aes';
import {
Expand Down
2 changes: 1 addition & 1 deletion benchmark/cross_test.test.js
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import { deepStrictEqual } from 'assert';
import { deepStrictEqual } from 'node:assert';
import { should, describe } from 'micro-should';
import { CIPHERS } from './aead.js';

Expand Down
9 changes: 4 additions & 5 deletions benchmark/package-lock.json

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

36 changes: 15 additions & 21 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,6 @@
"files": [
"esm",
"src",
"webcrypto",
"*.js",
"*.js.map",
"*.d.ts",
Expand All @@ -17,7 +16,7 @@
"bench:install": "cd benchmark && npm install && cd ../../",
"build": "npm run build:clean; tsc && tsc -p tsconfig.esm.json",
"build:release": "cd build; npm i; npm run build",
"build:clean": "rm *.{js,d.ts,js.map,d.ts.map} esm/*.{js,d.ts,js.map,d.ts.map} 2> /dev/null; rm -r webcrypto esm/webcrypto 2> /dev/null",
"build:clean": "rm *.{js,d.ts,js.map,d.ts.map} esm/*.{js,d.ts,js.map,d.ts.map} 2> /dev/null",
"lint": "prettier --check 'src/**/*.{js,ts}' 'test/**/*.{js,ts,mjs}'",
"format": "prettier --write 'src/**/*.{js,ts}' 'test/**/*.{js,ts,mjs}'",
"test": "node test/index.js"
Expand All @@ -44,15 +43,6 @@
"import": "./esm/index.js",
"default": "./index.js"
},
"./webcrypto/crypto": {
"types": "./webcrypto/crypto.d.ts",
"node": {
"import": "./esm/webcrypto/cryptoNode.js",
"default": "./webcrypto/cryptoNode.js"
},
"import": "./esm/webcrypto/crypto.js",
"default": "./webcrypto/crypto.js"
},
"./_micro": {
"types": "./_micro.d.ts",
"import": "./esm/_micro.js",
Expand All @@ -68,6 +58,15 @@
"import": "./esm/_polyval.js",
"default": "./_polyval.js"
},
"./crypto": {
"types": "./crypto.d.ts",
"node": {
"import": "./esm/cryptoNode.js",
"default": "./cryptoNode.js"
},
"import": "./esm/crypto.js",
"default": "./crypto.js"
},
"./aes": {
"types": "./aes.d.ts",
"import": "./esm/aes.js",
Expand Down Expand Up @@ -98,20 +97,15 @@
"import": "./esm/index.js",
"default": "./index.js"
},
"./webcrypto/aes": {
"types": "./webcrypto/aes.d.ts",
"import": "./esm/webcrypto/aes.js",
"default": "./webcrypto/aes.js"
},
"./webcrypto/utils": {
"types": "./webcrypto/utils.d.ts",
"import": "./esm/webcrypto/utils.js",
"default": "./webcrypto/utils.js"
"./webcrypto": {
"types": "./webcrypto.d.ts",
"import": "./esm/webcrypto.js",
"default": "./webcrypto.js"
}
},
"browser": {
"node:crypto": false,
"./webcrypto/crypto": "./webcrypto/crypto.js"
"./crypto": "./crypto.js"
},
"keywords": [
"salsa20",
Expand Down
23 changes: 12 additions & 11 deletions src/_micro.ts
Original file line number Diff line number Diff line change
Expand Up @@ -7,9 +7,10 @@
// prettier-ignore
import {
Cipher, XorStream, createView, setBigUint64, wrapCipher,
bytesToHex, concatBytes, ensureBytes, equalBytes, hexToNumber, numberToBytesBE,
bytesToHex, concatBytes, equalBytes, hexToNumber, numberToBytesBE,
} from './utils.js';
import { createCipher, rotl } from './_arx.js';
import { bytes as abytes } from './_assert.js';

function bytesToNumberLE(bytes: Uint8Array): bigint {
return hexToNumber(bytesToHex(Uint8Array.from(bytes).reverse()));
Expand Down Expand Up @@ -195,8 +196,8 @@ const _0 = BigInt(0);
const _1 = BigInt(1);
// Can be speed-up using BigUint64Array, but would be more complicated
export function poly1305(msg: Uint8Array, key: Uint8Array): Uint8Array {
ensureBytes(msg);
ensureBytes(key);
abytes(msg);
abytes(key);
let acc = _0;
const r = bytesToNumberLE(key.subarray(0, 16)) & CLAMP_R;
const s = bytesToNumberLE(key.subarray(16));
Expand Down Expand Up @@ -242,11 +243,11 @@ function computeTag(
export const xsalsa20poly1305 = wrapCipher(
{ blockSize: 64, nonceLength: 24, tagLength: 16 },
function xsalsa20poly1305(key: Uint8Array, nonce: Uint8Array) {
ensureBytes(key);
ensureBytes(nonce);
abytes(key);
abytes(nonce);
return {
encrypt: (plaintext: Uint8Array) => {
ensureBytes(plaintext);
abytes(plaintext);
const m = concatBytes(new Uint8Array(32), plaintext);
const c = xsalsa20(key, nonce, m);
const authKey = c.subarray(0, 32);
Expand All @@ -255,7 +256,7 @@ export const xsalsa20poly1305 = wrapCipher(
return concatBytes(tag, data);
},
decrypt: (ciphertext: Uint8Array) => {
ensureBytes(ciphertext);
abytes(ciphertext);
if (ciphertext.length < 16) throw new Error('encrypted data must be at least 16 bytes');
const c = concatBytes(new Uint8Array(16), ciphertext);
const authKey = xsalsa20(key, nonce, new Uint8Array(32));
Expand All @@ -280,17 +281,17 @@ export const _poly1305_aead =
(key: Uint8Array, nonce: Uint8Array, AAD?: Uint8Array): Cipher => {
const tagLength = 16;
const keyLength = 32;
ensureBytes(key, keyLength);
ensureBytes(nonce);
abytes(key, keyLength);
abytes(nonce);
return {
encrypt: (plaintext: Uint8Array) => {
ensureBytes(plaintext);
abytes(plaintext);
const res = fn(key, nonce, plaintext, undefined, 1);
const tag = computeTag(fn, key, nonce, res, AAD);
return concatBytes(res, tag);
},
decrypt: (ciphertext: Uint8Array) => {
ensureBytes(ciphertext);
abytes(ciphertext);
if (ciphertext.length < tagLength)
throw new Error(`encrypted data must be at least ${tagLength} bytes`);
const passedTag = ciphertext.subarray(-tagLength);
Expand Down
6 changes: 3 additions & 3 deletions src/_poly1305.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
import { exists as aexists, output as aoutput } from './_assert.js';
import { Input, ensureBytes, toBytes, Hash } from './utils.js';
import { exists as aexists, bytes as abytes, output as aoutput } from './_assert.js';
import { Input, toBytes, Hash } from './utils.js';

// Poly1305 is a fast and parallel secret-key message-authentication code.
// https://cr.yp.to/mac.html, https://cr.yp.to/mac/poly1305-20050329.pdf
Expand All @@ -19,7 +19,7 @@ class Poly1305 implements Hash<Poly1305> {

constructor(key: Input) {
key = toBytes(key);
ensureBytes(key, 32);
abytes(key, 32);
const t0 = u8to16(key, 0);
const t1 = u8to16(key, 2);
const t2 = u8to16(key, 4);
Expand Down
6 changes: 3 additions & 3 deletions src/_polyval.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
import { createView, toBytes, Input, Hash, u32, ensureBytes } from './utils.js';
import { exists as aexists, output as aoutput } from './_assert.js';
import { createView, toBytes, Input, Hash, u32 } from './utils.js';
import { bytes as abytes, exists as aexists, output as aoutput } from './_assert.js';

// GHash from AES-GCM and its little-endian "mirror image" Polyval from AES-SIV.
// Implemented in terms of GHash with conversion function for keys
Expand Down Expand Up @@ -76,7 +76,7 @@ class GHASH implements Hash<GHASH> {
// We select bits per window adaptively based on expectedLength
constructor(key: Input, expectedLength?: number) {
key = toBytes(key);
ensureBytes(key, 16);
abytes(key, 16);
const kView = createView(key);
let k0 = kView.getUint32(0, false);
let k1 = kView.getUint32(4, false);
Expand Down
Loading

0 comments on commit b58c936

Please sign in to comment.