From 664e9fd53413bcdd6a10a86cdcd1bd49fd45d0f0 Mon Sep 17 00:00:00 2001 From: Paul Miller Date: Tue, 18 Jul 2023 06:52:42 +0000 Subject: [PATCH] Rename xchacha20_poly1305 to xchacha20poly1305 (and others) --- README.md | 45 ++++++++++++++++++------------------ benchmark/aead.js | 12 +++++----- benchmark/cross_test.test.js | 11 +++++---- src/_micro.ts | 8 +++---- src/chacha.ts | 4 ++-- src/salsa.ts | 4 ++-- test/basic.test.js | 26 ++++++++++----------- 7 files changed, 56 insertions(+), 54 deletions(-) diff --git a/README.md b/README.md index 29085ff..8b2151b 100644 --- a/README.md +++ b/README.md @@ -42,7 +42,7 @@ If you don't like NPM, a standalone ```js // import * from '@noble/ciphers'; // Error // Use sub-imports for tree-shaking, to ensure small size of your apps -import { xsalsa20_poly1305 } from '@noble/ciphers/salsa'; +import { xsalsa20poly1305 } from '@noble/ciphers/salsa'; import { utf8ToBytes } from '@noble/ciphers/utils'; import { randomBytes } from '@noble/ciphers/webcrypto/utils'; @@ -51,20 +51,20 @@ const nonce = randomBytes(24); const data = utf8ToBytes('hello, noble'); // strings must be converted to Uint8Array // XSalsa20 -const stream_s = xsalsa20_poly1305(key, nonce); +const stream_s = xsalsa20poly1305(key, nonce); const encrypted_s = stream_s.encrypt(data); stream_s.decrypt(encrypted_s); // === data // XChaCha -import { xchacha20_poly1305 } from '@noble/ciphers/salsa'; -const stream_xc = xchacha20_poly1305(key, nonce); +import { xchacha20poly1305 } from '@noble/ciphers/salsa'; +const stream_xc = xchacha20poly1305(key, nonce); const encrypted_xc = stream_xc.encrypt(data); stream_xc.decrypt(encrypted_xc); // === data // ChaCha -import { chacha20_poly1305 } from '@noble/ciphers/chacha'; +import { chacha20poly1305 } from '@noble/ciphers/chacha'; const nonce12 = randomBytes(12); -const stream_c = chacha20_poly1305(key, nonce12); +const stream_c = chacha20poly1305(key, nonce12); const encrypted_c = stream_c.encrypt(data); stream_c.decrypt(encrypted_c); // === data ``` @@ -151,7 +151,7 @@ of a random function. See [RFC draft](https://datatracker.ietf.org/doc/draft-irt ### Salsa ```js -import { xsalsa20_poly1305, secretbox } from '@noble/ciphers/salsa'; +import { xsalsa20poly1305 } from '@noble/ciphers/salsa'; import { utf8ToBytes } from '@noble/ciphers/utils'; import { randomBytes } from '@noble/ciphers/webcrypto/utils'; @@ -159,11 +159,12 @@ const key = randomBytes(32); const data = utf8ToBytes('hello, noble'); // strings must be converted to Uint8Array const nonce = randomBytes(24); -const stream_x = xsalsa20_poly1305(key, nonce); // === secretbox(key, nonce) +const stream_x = xsalsa20poly1305(key, nonce); // === secretbox(key, nonce) const ciphertext = stream_x.encrypt(data); // === secretbox.seal(data) const plaintext = stream_x.decrypt(ciphertext); // === secretbox.open(ciphertext) -// We provide sodium secretbox alias, which is just xsalsa20_poly1305 +// We provide sodium secretbox alias, which is just xsalsa20poly1305 +import { secretbox } from '@noble/ciphers/salsa'; const box = secretbox(key, nonce); const ciphertext = box.seal(plaintext); const plaintext = box.open(ciphertext); @@ -194,7 +195,7 @@ alias and corresponding seal / open methods. ### ChaCha ```js -import { chacha20_poly1305, xchacha20_poly1305 } from '@noble/ciphers/chacha'; +import { chacha20poly1305, xchacha20poly1305 } from '@noble/ciphers/chacha'; import { utf8ToBytes } from '@noble/ciphers/utils'; import { randomBytes } from '@noble/ciphers/webcrypto/utils'; @@ -202,12 +203,12 @@ const key = randomBytes(32); const data = utf8ToBytes('hello, noble'); // strings must be converted to Uint8Array const nonce12 = randomBytes(12); // chacha uses 96-bit nonce -const stream_c = chacha20_poly1305(key, nonce12); +const stream_c = chacha20poly1305(key, nonce12); const ciphertext_c = stream_c.encrypt(data); const plaintext_c = stream_c.decrypt(ciphertext_c); // === data const nonce24 = randomBytes(24); // xchacha uses 192-bit nonce -const stream_xc = xchacha20_poly1305(key, nonce24); +const stream_xc = xchacha20poly1305(key, nonce24); const ciphertext_xc = stream_xc.encrypt(data); const plaintext_xc = stream_xc.decrypt(ciphertext_xc); // === data @@ -332,20 +333,20 @@ Benchmark results on Apple M2 with node v20: ``` encrypt (64B) -├─xsalsa20_poly1305 x 484,966 ops/sec @ 2μs/op -├─chacha20_poly1305 x 442,282 ops/sec @ 2μs/op +├─xsalsa20poly1305 x 484,966 ops/sec @ 2μs/op +├─chacha20poly1305 x 442,282 ops/sec @ 2μs/op └─xchacha20poly1305 x 300,842 ops/sec @ 3μs/op encrypt (1KB) -├─xsalsa20_poly1305 x 143,905 ops/sec @ 6μs/op -├─chacha20_poly1305 x 141,663 ops/sec @ 7μs/op +├─xsalsa20poly1305 x 143,905 ops/sec @ 6μs/op +├─chacha20poly1305 x 141,663 ops/sec @ 7μs/op └─xchacha20poly1305 x 122,639 ops/sec @ 8μs/op encrypt (8KB) -├─xsalsa20_poly1305 x 23,373 ops/sec @ 42μs/op -├─chacha20_poly1305 x 23,683 ops/sec @ 42μs/op +├─xsalsa20poly1305 x 23,373 ops/sec @ 42μs/op +├─chacha20poly1305 x 23,683 ops/sec @ 42μs/op └─xchacha20poly1305 x 23,066 ops/sec @ 43μs/op encrypt (1MB) -├─xsalsa20_poly1305 x 193 ops/sec @ 5ms/op -├─chacha20_poly1305 x 196 ops/sec @ 5ms/op +├─xsalsa20poly1305 x 193 ops/sec @ 5ms/op +├─chacha20poly1305 x 196 ops/sec @ 5ms/op └─xchacha20poly1305 x 195 ops/sec @ 5ms/op ``` @@ -377,12 +378,12 @@ encrypt (1MB) Compare to other implementations: ``` -xsalsa20_poly1305 (encrypt, 1MB) +xsalsa20poly1305 (encrypt, 1MB) ├─tweetnacl x 108 ops/sec @ 9ms/op ├─noble x 190 ops/sec @ 5ms/op └─micro x 21 ops/sec @ 47ms/op -chacha20_poly1305 (encrypt, 1MB) +chacha20poly1305 (encrypt, 1MB) ├─node x 1,360 ops/sec @ 735μs/op ├─stablelib x 117 ops/sec @ 8ms/op ├─noble x 193 ops/sec @ 5ms/op diff --git a/benchmark/aead.js b/benchmark/aead.js index 0a8ccc2..10d751d 100644 --- a/benchmark/aead.js +++ b/benchmark/aead.js @@ -3,8 +3,8 @@ import { compare, utils as butils } from 'micro-bmark'; import { createCipheriv, createDecipheriv } from 'node:crypto'; import { concatBytes } from '@noble/ciphers/utils'; -import { xchacha20_poly1305, chacha20_poly1305 } from '@noble/ciphers/chacha'; -import { xsalsa20_poly1305 } from '@noble/ciphers/salsa'; +import { xchacha20poly1305 as xchacha20_poly1305, chacha20poly1305 as chacha20_poly1305 } from '@noble/ciphers/chacha'; +import { xsalsa20poly1305 as xsalsa20_poly1305 } from '@noble/ciphers/salsa'; import * as micro from '@noble/ciphers/_micro'; import { ChaCha20Poly1305 as StableChachaPoly } from '@stablelib/chacha20poly1305'; @@ -82,8 +82,8 @@ export const CIPHERS = { decrypt: (buf, opts) => chacha20_poly1305(opts.key, opts.nonce).decrypt(buf), }, micro: { - encrypt: (buf, opts) => micro.chacha20_poly1305(opts.key, opts.nonce).encrypt(buf), - decrypt: (buf, opts) => micro.chacha20_poly1305(opts.key, opts.nonce).decrypt(buf), + encrypt: (buf, opts) => micro.chacha20poly1305(opts.key, opts.nonce).encrypt(buf), + decrypt: (buf, opts) => micro.chacha20poly1305(opts.key, opts.nonce).decrypt(buf), }, }, xchacha20poly1305: { @@ -97,8 +97,8 @@ export const CIPHERS = { decrypt: (buf, opts) => xchacha20_poly1305(opts.key, opts.nonce).decrypt(buf), }, micro: { - encrypt: (buf, opts) => micro.xchacha20_poly1305(opts.key, opts.nonce).encrypt(buf), - decrypt: (buf, opts) => micro.xchacha20_poly1305(opts.key, opts.nonce).decrypt(buf), + encrypt: (buf, opts) => micro.xchacha20poly1305(opts.key, opts.nonce).encrypt(buf), + decrypt: (buf, opts) => micro.xchacha20poly1305(opts.key, opts.nonce).decrypt(buf), }, }, }; diff --git a/benchmark/cross_test.test.js b/benchmark/cross_test.test.js index de1cf54..0a90cf8 100644 --- a/benchmark/cross_test.test.js +++ b/benchmark/cross_test.test.js @@ -1,15 +1,16 @@ import { deepStrictEqual, throws } from 'assert'; import { should, describe } from 'micro-should'; -import { CIPHERS } from './index.js'; +import { CIPHERS } from './aead.js'; describe('Big', () => { should('secretbox', () => { - const big4g = new Uint8Array(2 ** 32 - 32).fill(7); + const big4g = new Uint8Array(2 ** 32 - 32).fill(7); // 4GB - 32b const libs = CIPHERS.xsalsa20_poly1305; - const nacl4 = libs.tweetnacl.encrypt(big4g, libs.opts); - const noble4 = libs.noble.encrypt(big4g, libs.opts); + const { opts } = libs; + const nacl4 = libs.tweetnacl.encrypt(big4g, opts); + const noble4 = libs.noble.encrypt(big4g, opts); deepStrictEqual(noble4, nacl4, 'noble encrypt'); - deepStrictEqual(libs.noble.decrypt(noble4, libs.opts), big4g, 'noble decrypt'); + deepStrictEqual(libs.noble.decrypt(noble4, opts), big4g, 'noble decrypt'); }); }); diff --git a/src/_micro.ts b/src/_micro.ts index 96ac10e..0046c20 100644 --- a/src/_micro.ts +++ b/src/_micro.ts @@ -238,7 +238,7 @@ function computeTag( /** * xsalsa20-poly1305 eXtended-nonce (24 bytes) salsa. */ -export function xsalsa20_poly1305(key: Uint8Array, nonce: Uint8Array) { +export function xsalsa20poly1305(key: Uint8Array, nonce: Uint8Array) { u.ensureBytes(key); u.ensureBytes(nonce); return { @@ -269,7 +269,7 @@ export function xsalsa20_poly1305(key: Uint8Array, nonce: Uint8Array) { export function secretbox(key: Uint8Array, nonce: Uint8Array) { u.ensureBytes(key); u.ensureBytes(nonce); - const xs = xsalsa20_poly1305(key, nonce); + const xs = xsalsa20poly1305(key, nonce); return { seal: xs.encrypt, open: xs.decrypt }; } @@ -304,10 +304,10 @@ export const _poly1305_aead = /** * chacha20-poly1305 12-byte-nonce chacha. */ -export const chacha20_poly1305 = _poly1305_aead(chacha20); +export const chacha20poly1305 = _poly1305_aead(chacha20); /** * xchacha20-poly1305 eXtended-nonce (24 bytes) chacha. * With 24-byte nonce, it's safe to use fill it with random (CSPRNG). */ -export const xchacha20_poly1305 = _poly1305_aead(xchacha20); +export const xchacha20poly1305 = _poly1305_aead(xchacha20); diff --git a/src/chacha.ts b/src/chacha.ts index 678a248..473df3f 100644 --- a/src/chacha.ts +++ b/src/chacha.ts @@ -259,10 +259,10 @@ export const _poly1305_aead = * ChaCha20-Poly1305 from RFC 8439. * With 12-byte nonce, it's not safe to use fill it with random (CSPRNG), due to collision chance. */ -export const chacha20_poly1305 = _poly1305_aead(chacha20); +export const chacha20poly1305 = _poly1305_aead(chacha20); /** * XChaCha20-Poly1305 extended-nonce chacha. * https://datatracker.ietf.org/doc/html/draft-irtf-cfrg-xchacha * With 24-byte nonce, it's safe to use fill it with random (CSPRNG). */ -export const xchacha20_poly1305 = _poly1305_aead(xchacha20); +export const xchacha20poly1305 = _poly1305_aead(xchacha20); diff --git a/src/salsa.ts b/src/salsa.ts index ef2163c..495cbcb 100644 --- a/src/salsa.ts +++ b/src/salsa.ts @@ -123,7 +123,7 @@ export const xsalsa20 = salsaBasic({ * With 24-byte nonce, it's safe to use fill it with random (CSPRNG). * Also known as secretbox from libsodium / nacl. */ -export const xsalsa20_poly1305 = (key: Uint8Array, nonce: Uint8Array): Cipher => { +export const xsalsa20poly1305 = (key: Uint8Array, nonce: Uint8Array): Cipher => { const tagLength = 16; ensureBytes(key, 32); ensureBytes(nonce, 24); @@ -168,6 +168,6 @@ export const xsalsa20_poly1305 = (key: Uint8Array, nonce: Uint8Array): Cipher => export function secretbox(key: Uint8Array, nonce: Uint8Array) { ensureBytes(key); ensureBytes(nonce); - const xs = xsalsa20_poly1305(key, nonce); + const xs = xsalsa20poly1305(key, nonce); return { seal: xs.encrypt, open: xs.decrypt }; } diff --git a/test/basic.test.js b/test/basic.test.js index c598248..4ebe4fb 100644 --- a/test/basic.test.js +++ b/test/basic.test.js @@ -1,14 +1,14 @@ const { deepStrictEqual, throws } = require('assert'); const { should, describe } = require('micro-should'); const { hex, base64 } = require('@scure/base'); -const { salsa20, hsalsa, xsalsa20, xsalsa20_poly1305 } = require('../salsa.js'); +const { salsa20, hsalsa, xsalsa20, xsalsa20poly1305 } = require('../salsa.js'); const { chacha20, chacha20orig, hchacha, xchacha20, - chacha20_poly1305, - xchacha20_poly1305, + chacha20poly1305, + xchacha20poly1305, } = require('../chacha.js'); const { poly1305 } = require('../_poly1305.js'); const slow = require('../_micro.js'); @@ -216,17 +216,17 @@ describe('poly1305', () => { } }); }; - t('Chacha20Poly1305', stable_chacha_poly, chacha20_poly1305); - t('Xchacha20Poly1305', stable_xchacha_poly, xchacha20_poly1305); - t('Chacha20Poly1305', stable_chacha_poly, slow.chacha20_poly1305); - t('Xchacha20Poly1305', stable_xchacha_poly, slow.xchacha20_poly1305); + t('Chacha20Poly1305', stable_chacha_poly, chacha20poly1305); + t('Xchacha20Poly1305', stable_xchacha_poly, xchacha20poly1305); + t('Chacha20Poly1305', stable_chacha_poly, slow.chacha20poly1305); + t('Xchacha20Poly1305', stable_xchacha_poly, slow.xchacha20poly1305); }); should('tweetnacl secretbox compat', () => { for (let i = 0; i < tweetnacl_secretbox.length; i++) { const v = tweetnacl_secretbox[i]; const [key, nonce, msg, exp] = v.map(base64.decode); - const c = xsalsa20_poly1305(key, nonce); + const c = xsalsa20poly1305(key, nonce); deepStrictEqual(hex.encode(c.encrypt(msg)), hex.encode(exp), i); deepStrictEqual(hex.encode(c.decrypt(exp)), hex.encode(msg), i); const cSlow = slow.xsalsa20_poly1305(key, nonce); @@ -240,7 +240,7 @@ should('handle byte offsets correctly', () => { const data = new Uint8Array(sample.buffer, 1); const key = new Uint8Array(32).fill(2); const nonce12 = new Uint8Array(12).fill(3); - const stream_c = chacha20_poly1305(key, nonce12); + const stream_c = chacha20poly1305(key, nonce12); const encrypted_c = stream_c.encrypt(data); stream_c.decrypt(encrypted_c); // === data }); @@ -271,10 +271,10 @@ describe('Wycheproof', () => { } }); }; - t('wycheproof_chacha20_poly1305', wycheproof_chacha20_poly1305, chacha20_poly1305); - t('wycheproof_xchacha20_poly1305', wycheproof_xchacha20_poly1305, xchacha20_poly1305); - t('wycheproof_chacha20_poly1305', wycheproof_chacha20_poly1305, slow.chacha20_poly1305); - t('wycheproof_xchacha20_poly1305', wycheproof_xchacha20_poly1305, slow.xchacha20_poly1305); + t('wycheproof_chacha20_poly1305', wycheproof_chacha20_poly1305, chacha20poly1305); + t('wycheproof_xchacha20_poly1305', wycheproof_xchacha20_poly1305, xchacha20poly1305); + t('wycheproof_chacha20_poly1305', wycheproof_chacha20_poly1305, slow.chacha20poly1305); + t('wycheproof_xchacha20_poly1305', wycheproof_xchacha20_poly1305, slow.xchacha20poly1305); }); if (require.main === module) should.run();