@noble/ciphers
Advanced tools
Comparing version 0.1.3 to 0.1.4
@@ -23,1 +23,2 @@ declare function number(n: number): void; | ||
export default assert; | ||
//# sourceMappingURL=_assert.d.ts.map |
@@ -15,1 +15,2 @@ import { Input, Hash } from './utils.js'; | ||
}; | ||
//# sourceMappingURL=_poly1305.d.ts.map |
export declare function polyval(h: Uint8Array, data: Uint8Array): Uint8Array; | ||
//# sourceMappingURL=_polyval.d.ts.map |
@@ -11,1 +11,2 @@ export type SalsaOpts = { | ||
export declare const salsaBasic: (opts: SalsaOpts) => (key: Uint8Array, nonce: Uint8Array, data: Uint8Array, output?: Uint8Array, counter?: number) => Uint8Array; | ||
//# sourceMappingURL=_salsa.d.ts.map |
@@ -5,7 +5,7 @@ "use strict"; | ||
// Basic utils for salsa-like ciphers | ||
// Check out _slow.ts for descriptive documentation. | ||
// Check out _micro.ts for descriptive documentation. | ||
const _assert_js_1 = require("./_assert.js"); | ||
const utils_js_1 = require("./utils.js"); | ||
/* | ||
RFC7539 requires multi-step cipher stream, where | ||
RFC8439 requires multi-step cipher stream, where | ||
authKey starts with counter: 0, actual msg with counter: 1. | ||
@@ -60,2 +60,4 @@ | ||
const sigma32_32 = (0, utils_js_1.u32)(sigma32); | ||
// Is byte array aligned to 4 byte offset (u32)? | ||
const isAligned32 = (b) => !(b.byteOffset % 4); | ||
const salsaBasic = (opts) => { | ||
@@ -128,4 +130,5 @@ const { core, rounds, counterRight, counterLen, allow128bitKeys, extendNonceFn, blockLen } = (0, utils_js_1.checkOpts)({ rounds: 20, counterRight: false, counterLen: 8, allow128bitKeys: true, blockLen: 64 }, opts); | ||
const n32 = (0, utils_js_1.u32)(nonce); | ||
const d32 = (0, utils_js_1.u32)(data); | ||
const o32 = (0, utils_js_1.u32)(output); | ||
// Make sure that buffers aligned to 4 bytes | ||
const d32 = isAligned32(data) && (0, utils_js_1.u32)(data); | ||
const o32 = isAligned32(output) && (0, utils_js_1.u32)(output); | ||
toClean.push(b32); | ||
@@ -138,4 +141,4 @@ const len = data.length; | ||
const take = Math.min(blockLen, len - pos); | ||
// Fast path: we have at least one block in input | ||
if (take === blockLen) { | ||
// full block && aligned to 4 bytes | ||
if (take === blockLen && o32 && d32) { | ||
const pos32 = pos / 4; | ||
@@ -142,0 +145,0 @@ if (pos % 4 !== 0) |
@@ -1,10 +0,53 @@ | ||
import * as utils from './utils.js'; | ||
export declare function hchacha(c: Uint32Array, key: Uint8Array, src: Uint8Array, dst: Uint8Array): Uint8Array; | ||
import { Cipher } from './utils.js'; | ||
/** | ||
* hchacha helper method, used primarily in xchacha, to hash | ||
* key and nonce into key' and nonce'. | ||
* Same as chachaCore, but there doesn't seem to be a way to move the block | ||
* out without 25% performance hit. | ||
*/ | ||
export declare function hchacha(c: Uint32Array, key: Uint8Array, src: Uint8Array, out: Uint8Array): Uint8Array; | ||
/** | ||
* Original, non-RFC chacha20 from DJB. 8-byte nonce, 8-byte counter. | ||
*/ | ||
export declare const chacha20orig: (key: Uint8Array, nonce: Uint8Array, data: Uint8Array, output?: Uint8Array | undefined, counter?: number) => Uint8Array; | ||
/** | ||
* ChaCha stream cipher. Conforms to RFC 8439 (IETF, TLS). 12-byte nonce, 4-byte counter. | ||
* With 12-byte nonce, it's not safe to use fill it with random (CSPRNG), due to collision chance. | ||
*/ | ||
export declare const chacha20: (key: Uint8Array, nonce: Uint8Array, data: Uint8Array, output?: Uint8Array | undefined, counter?: number) => Uint8Array; | ||
/** | ||
* XChaCha eXtended-nonce ChaCha. 24-byte nonce. | ||
* With 24-byte nonce, it's safe to use fill it with random (CSPRNG). | ||
* https://datatracker.ietf.org/doc/html/draft-irtf-cfrg-xchacha | ||
*/ | ||
export declare const xchacha20: (key: Uint8Array, nonce: Uint8Array, data: Uint8Array, output?: Uint8Array | undefined, counter?: number) => Uint8Array; | ||
/** | ||
* Reduced 8-round chacha, described in original paper. | ||
*/ | ||
export declare const chacha8: (key: Uint8Array, nonce: Uint8Array, data: Uint8Array, output?: Uint8Array | undefined, counter?: number) => Uint8Array; | ||
/** | ||
* Reduced 12-round chacha, described in original paper. | ||
*/ | ||
export declare const chacha12: (key: Uint8Array, nonce: Uint8Array, data: Uint8Array, output?: Uint8Array | undefined, counter?: number) => Uint8Array; | ||
export declare const _poly1305_aead: (fn: typeof chacha20) => (key: Uint8Array, nonce: Uint8Array, AAD?: Uint8Array) => utils.Cipher; | ||
export declare const chacha20_poly1305: (key: Uint8Array, nonce: Uint8Array, AAD?: Uint8Array) => utils.Cipher; | ||
export declare const xchacha20_poly1305: (key: Uint8Array, nonce: Uint8Array, AAD?: Uint8Array) => utils.Cipher; | ||
/** | ||
* AEAD algorithm from RFC 8439. | ||
* Salsa20 and chacha (RFC 8439) use poly1305 differently. | ||
* We could have composed them similar to: | ||
* https://github.com/paulmillr/scure-base/blob/b266c73dde977b1dd7ef40ef7a23cc15aab526b3/index.ts#L250 | ||
* But it's hard because of authKey: | ||
* In salsa20, authKey changes position in salsa stream. | ||
* In chacha, authKey can't be computed inside computeTag, it modifies the counter. | ||
*/ | ||
export declare const _poly1305_aead: (fn: typeof chacha20) => (key: Uint8Array, nonce: Uint8Array, AAD?: Uint8Array) => Cipher; | ||
/** | ||
* 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 declare const chacha20_poly1305: (key: Uint8Array, nonce: Uint8Array, AAD?: Uint8Array) => Cipher; | ||
/** | ||
* 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 declare const xchacha20_poly1305: (key: Uint8Array, nonce: Uint8Array, AAD?: Uint8Array) => Cipher; | ||
//# sourceMappingURL=chacha.d.ts.map |
"use strict"; | ||
Object.defineProperty(exports, "__esModule", { value: true }); | ||
exports.xchacha20_poly1305 = exports.chacha20_poly1305 = exports._poly1305_aead = exports.chacha12 = exports.chacha8 = exports.xchacha20 = exports.chacha20 = exports.chacha20orig = exports.hchacha = void 0; | ||
const utils = require("./utils.js"); | ||
const utils_js_1 = require("./utils.js"); | ||
const _poly1305_js_1 = require("./_poly1305.js"); | ||
@@ -12,2 +12,5 @@ const _salsa_js_1 = require("./_salsa.js"); | ||
const rotl = (a, b) => (a << b) | (a >>> (32 - b)); | ||
/** | ||
* ChaCha core function. | ||
*/ | ||
// prettier-ignore | ||
@@ -107,7 +110,13 @@ function chachaCore(c, k, n, out, cnt, rounds = 20) { | ||
} | ||
/** | ||
* hchacha helper method, used primarily in xchacha, to hash | ||
* key and nonce into key' and nonce'. | ||
* Same as chachaCore, but there doesn't seem to be a way to move the block | ||
* out without 25% performance hit. | ||
*/ | ||
// prettier-ignore | ||
function hchacha(c, key, src, dst) { | ||
const k32 = utils.u32(key); | ||
const i32 = utils.u32(src); | ||
const o32 = utils.u32(dst); | ||
function hchacha(c, key, src, out) { | ||
const k32 = (0, utils_js_1.u32)(key); | ||
const i32 = (0, utils_js_1.u32)(src); | ||
const o32 = (0, utils_js_1.u32)(out); | ||
let x00 = c[0], x01 = c[1], x02 = c[2], x03 = c[3]; | ||
@@ -191,8 +200,13 @@ let x04 = k32[0], x05 = k32[1], x06 = k32[2], x07 = k32[3]; | ||
o32[7] = x15; | ||
return dst; | ||
return out; | ||
} | ||
exports.hchacha = hchacha; | ||
// Original DJB ChaCha20, 8 bytes nonce, 8 bytes counter | ||
/** | ||
* Original, non-RFC chacha20 from DJB. 8-byte nonce, 8-byte counter. | ||
*/ | ||
exports.chacha20orig = (0, _salsa_js_1.salsaBasic)({ core: chachaCore, counterRight: false, counterLen: 8 }); | ||
// Also known as chacha20-tls (IETF), 12 bytes nonce, 4 bytes counter | ||
/** | ||
* ChaCha stream cipher. Conforms to RFC 8439 (IETF, TLS). 12-byte nonce, 4-byte counter. | ||
* With 12-byte nonce, it's not safe to use fill it with random (CSPRNG), due to collision chance. | ||
*/ | ||
exports.chacha20 = (0, _salsa_js_1.salsaBasic)({ | ||
@@ -204,3 +218,7 @@ core: chachaCore, | ||
}); | ||
// xchacha draft RFC https://datatracker.ietf.org/doc/html/draft-irtf-cfrg-xchacha | ||
/** | ||
* XChaCha eXtended-nonce ChaCha. 24-byte nonce. | ||
* With 24-byte nonce, it's safe to use fill it with random (CSPRNG). | ||
* https://datatracker.ietf.org/doc/html/draft-irtf-cfrg-xchacha | ||
*/ | ||
exports.xchacha20 = (0, _salsa_js_1.salsaBasic)({ | ||
@@ -213,3 +231,5 @@ core: chachaCore, | ||
}); | ||
// Reduced-round chacha, described in original paper | ||
/** | ||
* Reduced 8-round chacha, described in original paper. | ||
*/ | ||
exports.chacha8 = (0, _salsa_js_1.salsaBasic)({ | ||
@@ -221,2 +241,5 @@ core: chachaCore, | ||
}); | ||
/** | ||
* Reduced 12-round chacha, described in original paper. | ||
*/ | ||
exports.chacha12 = (0, _salsa_js_1.salsaBasic)({ | ||
@@ -243,5 +266,5 @@ core: chachaCore, | ||
const num = new Uint8Array(16); | ||
const view = utils.createView(num); | ||
utils.setBigUint64(view, 0, BigInt(AAD ? AAD.length : 0), true); | ||
utils.setBigUint64(view, 8, BigInt(data.length), true); | ||
const view = (0, utils_js_1.createView)(num); | ||
(0, utils_js_1.setBigUint64)(view, 0, BigInt(AAD ? AAD.length : 0), true); | ||
(0, utils_js_1.setBigUint64)(view, 8, BigInt(data.length), true); | ||
h.update(num); | ||
@@ -252,13 +275,15 @@ const res = h.digest(); | ||
}; | ||
// salsa and chacha (RFC 7539) use poly1305 differently. | ||
// We could have composed them such as in: | ||
// https://github.com/paulmillr/scure-base/blob/b266c73dde977b1dd7ef40ef7a23cc15aab526b3/index.ts#L250 | ||
// But authKey construction makes it hard: | ||
// - salsa: authKey changes position in salsa stream | ||
// - chacha: authKey can't be computed inside computeTag, it modifies the counter | ||
// Algo from RFC 7539. | ||
/** | ||
* AEAD algorithm from RFC 8439. | ||
* Salsa20 and chacha (RFC 8439) use poly1305 differently. | ||
* We could have composed them similar to: | ||
* https://github.com/paulmillr/scure-base/blob/b266c73dde977b1dd7ef40ef7a23cc15aab526b3/index.ts#L250 | ||
* But it's hard because of authKey: | ||
* In salsa20, authKey changes position in salsa stream. | ||
* In chacha, authKey can't be computed inside computeTag, it modifies the counter. | ||
*/ | ||
const _poly1305_aead = (fn) => (key, nonce, AAD) => { | ||
const tagLength = 16; | ||
utils.ensureBytes(key, 32); | ||
utils.ensureBytes(nonce); | ||
(0, utils_js_1.ensureBytes)(key, 32); | ||
(0, utils_js_1.ensureBytes)(nonce); | ||
return { | ||
@@ -279,3 +304,3 @@ tagLength, | ||
const tag = computeTag(fn, key, nonce, data, AAD); | ||
if (!utils.equalBytes(realTag, tag)) | ||
if (!(0, utils_js_1.equalBytes)(realTag, tag)) | ||
throw new Error('Wrong tag'); | ||
@@ -287,4 +312,13 @@ return fn(key, nonce, data, undefined, 1); | ||
exports._poly1305_aead = _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. | ||
*/ | ||
exports.chacha20_poly1305 = (0, exports._poly1305_aead)(exports.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). | ||
*/ | ||
exports.xchacha20_poly1305 = (0, exports._poly1305_aead)(exports.xchacha20); | ||
//# sourceMappingURL=chacha.js.map |
// Basic utils for salsa-like ciphers | ||
// Check out _slow.ts for descriptive documentation. | ||
// Check out _micro.ts for descriptive documentation. | ||
import assert from './_assert.js'; | ||
import { u32, utf8ToBytes, checkOpts } from './utils.js'; | ||
/* | ||
RFC7539 requires multi-step cipher stream, where | ||
RFC8439 requires multi-step cipher stream, where | ||
authKey starts with counter: 0, actual msg with counter: 1. | ||
@@ -56,2 +56,4 @@ | ||
const sigma32_32 = u32(sigma32); | ||
// Is byte array aligned to 4 byte offset (u32)? | ||
const isAligned32 = (b) => !(b.byteOffset % 4); | ||
export const salsaBasic = (opts) => { | ||
@@ -124,4 +126,5 @@ const { core, rounds, counterRight, counterLen, allow128bitKeys, extendNonceFn, blockLen } = checkOpts({ rounds: 20, counterRight: false, counterLen: 8, allow128bitKeys: true, blockLen: 64 }, opts); | ||
const n32 = u32(nonce); | ||
const d32 = u32(data); | ||
const o32 = u32(output); | ||
// Make sure that buffers aligned to 4 bytes | ||
const d32 = isAligned32(data) && u32(data); | ||
const o32 = isAligned32(output) && u32(output); | ||
toClean.push(b32); | ||
@@ -134,4 +137,4 @@ const len = data.length; | ||
const take = Math.min(blockLen, len - pos); | ||
// Fast path: we have at least one block in input | ||
if (take === blockLen) { | ||
// full block && aligned to 4 bytes | ||
if (take === blockLen && o32 && d32) { | ||
const pos32 = pos / 4; | ||
@@ -138,0 +141,0 @@ if (pos % 4 !== 0) |
@@ -1,2 +0,2 @@ | ||
import * as utils from './utils.js'; | ||
import { createView, ensureBytes, equalBytes, setBigUint64, u32 } from './utils.js'; | ||
import { poly1305 } from './_poly1305.js'; | ||
@@ -9,2 +9,5 @@ import { salsaBasic } from './_salsa.js'; | ||
const rotl = (a, b) => (a << b) | (a >>> (32 - b)); | ||
/** | ||
* ChaCha core function. | ||
*/ | ||
// prettier-ignore | ||
@@ -104,7 +107,13 @@ function chachaCore(c, k, n, out, cnt, rounds = 20) { | ||
} | ||
/** | ||
* hchacha helper method, used primarily in xchacha, to hash | ||
* key and nonce into key' and nonce'. | ||
* Same as chachaCore, but there doesn't seem to be a way to move the block | ||
* out without 25% performance hit. | ||
*/ | ||
// prettier-ignore | ||
export function hchacha(c, key, src, dst) { | ||
const k32 = utils.u32(key); | ||
const i32 = utils.u32(src); | ||
const o32 = utils.u32(dst); | ||
export function hchacha(c, key, src, out) { | ||
const k32 = u32(key); | ||
const i32 = u32(src); | ||
const o32 = u32(out); | ||
let x00 = c[0], x01 = c[1], x02 = c[2], x03 = c[3]; | ||
@@ -188,7 +197,12 @@ let x04 = k32[0], x05 = k32[1], x06 = k32[2], x07 = k32[3]; | ||
o32[7] = x15; | ||
return dst; | ||
return out; | ||
} | ||
// Original DJB ChaCha20, 8 bytes nonce, 8 bytes counter | ||
/** | ||
* Original, non-RFC chacha20 from DJB. 8-byte nonce, 8-byte counter. | ||
*/ | ||
export const chacha20orig = salsaBasic({ core: chachaCore, counterRight: false, counterLen: 8 }); | ||
// Also known as chacha20-tls (IETF), 12 bytes nonce, 4 bytes counter | ||
/** | ||
* ChaCha stream cipher. Conforms to RFC 8439 (IETF, TLS). 12-byte nonce, 4-byte counter. | ||
* With 12-byte nonce, it's not safe to use fill it with random (CSPRNG), due to collision chance. | ||
*/ | ||
export const chacha20 = salsaBasic({ | ||
@@ -200,3 +214,7 @@ core: chachaCore, | ||
}); | ||
// xchacha draft RFC https://datatracker.ietf.org/doc/html/draft-irtf-cfrg-xchacha | ||
/** | ||
* XChaCha eXtended-nonce ChaCha. 24-byte nonce. | ||
* With 24-byte nonce, it's safe to use fill it with random (CSPRNG). | ||
* https://datatracker.ietf.org/doc/html/draft-irtf-cfrg-xchacha | ||
*/ | ||
export const xchacha20 = salsaBasic({ | ||
@@ -209,3 +227,5 @@ core: chachaCore, | ||
}); | ||
// Reduced-round chacha, described in original paper | ||
/** | ||
* Reduced 8-round chacha, described in original paper. | ||
*/ | ||
export const chacha8 = salsaBasic({ | ||
@@ -217,2 +237,5 @@ core: chachaCore, | ||
}); | ||
/** | ||
* Reduced 12-round chacha, described in original paper. | ||
*/ | ||
export const chacha12 = salsaBasic({ | ||
@@ -239,5 +262,5 @@ core: chachaCore, | ||
const num = new Uint8Array(16); | ||
const view = utils.createView(num); | ||
utils.setBigUint64(view, 0, BigInt(AAD ? AAD.length : 0), true); | ||
utils.setBigUint64(view, 8, BigInt(data.length), true); | ||
const view = createView(num); | ||
setBigUint64(view, 0, BigInt(AAD ? AAD.length : 0), true); | ||
setBigUint64(view, 8, BigInt(data.length), true); | ||
h.update(num); | ||
@@ -248,13 +271,15 @@ const res = h.digest(); | ||
}; | ||
// salsa and chacha (RFC 7539) use poly1305 differently. | ||
// We could have composed them such as in: | ||
// https://github.com/paulmillr/scure-base/blob/b266c73dde977b1dd7ef40ef7a23cc15aab526b3/index.ts#L250 | ||
// But authKey construction makes it hard: | ||
// - salsa: authKey changes position in salsa stream | ||
// - chacha: authKey can't be computed inside computeTag, it modifies the counter | ||
// Algo from RFC 7539. | ||
/** | ||
* AEAD algorithm from RFC 8439. | ||
* Salsa20 and chacha (RFC 8439) use poly1305 differently. | ||
* We could have composed them similar to: | ||
* https://github.com/paulmillr/scure-base/blob/b266c73dde977b1dd7ef40ef7a23cc15aab526b3/index.ts#L250 | ||
* But it's hard because of authKey: | ||
* In salsa20, authKey changes position in salsa stream. | ||
* In chacha, authKey can't be computed inside computeTag, it modifies the counter. | ||
*/ | ||
export const _poly1305_aead = (fn) => (key, nonce, AAD) => { | ||
const tagLength = 16; | ||
utils.ensureBytes(key, 32); | ||
utils.ensureBytes(nonce); | ||
ensureBytes(key, 32); | ||
ensureBytes(nonce); | ||
return { | ||
@@ -275,3 +300,3 @@ tagLength, | ||
const tag = computeTag(fn, key, nonce, data, AAD); | ||
if (!utils.equalBytes(realTag, tag)) | ||
if (!equalBytes(realTag, tag)) | ||
throw new Error('Wrong tag'); | ||
@@ -282,4 +307,13 @@ return fn(key, nonce, data, undefined, 1); | ||
}; | ||
/** | ||
* 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); | ||
/** | ||
* 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); | ||
//# sourceMappingURL=chacha.js.map |
@@ -10,3 +10,5 @@ import { ensureBytes, u32, equalBytes } from './utils.js'; | ||
const rotl = (a, b) => (a << b) | (a >>> (32 - b)); | ||
// NOTE: same as hsalsa, but we cannot move out block without 25% perf loss :( | ||
/** | ||
* Salsa20 core function. | ||
*/ | ||
// prettier-ignore | ||
@@ -75,2 +77,8 @@ function salsaCore(c, k, i, out, cnt, rounds = 20) { | ||
} | ||
/** | ||
* hsalsa hashing function, used primarily in xsalsa, to hash | ||
* key and nonce into key' and nonce'. | ||
* Same as salsaCore, but there doesn't seem to be a way to move the block | ||
* out without 25% performance hit. | ||
*/ | ||
// prettier-ignore | ||
@@ -130,3 +138,11 @@ export function hsalsa(c, key, nonce, out) { | ||
} | ||
/** | ||
* Salsa20 from original paper. | ||
* With 12-byte nonce, it's not safe to use fill it with random (CSPRNG), due to collision chance. | ||
*/ | ||
export const salsa20 = salsaBasic({ core: salsaCore, counterRight: true }); | ||
/** | ||
* xsalsa20 eXtended-nonce salsa. | ||
* With 24-byte nonce, it's safe to use fill it with random (CSPRNG). | ||
*/ | ||
export const xsalsa20 = salsaBasic({ | ||
@@ -138,3 +154,7 @@ core: salsaCore, | ||
}); | ||
// Also known as 'tweetnacl secretbox' | ||
/** | ||
* xsalsa20-poly1305 eXtended-nonce salsa. | ||
* 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, nonce) => { | ||
@@ -180,2 +200,11 @@ const tagLength = 16; | ||
}; | ||
/** | ||
* Alias to xsalsa20poly1305, for compatibility with libsodium / nacl | ||
*/ | ||
export function secretbox(key, nonce) { | ||
ensureBytes(key); | ||
ensureBytes(nonce); | ||
const xs = xsalsa20_poly1305(key, nonce); | ||
return { seal: xs.encrypt, open: xs.decrypt }; | ||
} | ||
//# sourceMappingURL=salsa.js.map |
@@ -14,3 +14,3 @@ /*! noble-ciphers - MIT License (c) 2023 Paul Miller (paulmillr.com) */ | ||
throw new Error('Non little-endian hardware is not supported'); | ||
const hexes = Array.from({ length: 256 }, (v, i) => i.toString(16).padStart(2, '0')); | ||
const hexes = /* @__PURE__ */ Array.from({ length: 256 }, (_, i) => i.toString(16).padStart(2, '0')); | ||
/** | ||
@@ -17,0 +17,0 @@ * @example bytesToHex(Uint8Array.from([0xca, 0xfe, 0x01, 0x23])) // 'cafe0123' |
@@ -1,2 +0,2 @@ | ||
import * as utils from '../utils.js'; | ||
import { createView, setBigUint64 } from '../utils.js'; | ||
import { polyval } from '../_polyval.js'; | ||
@@ -47,3 +47,3 @@ import { getWebcryptoSubtle } from './utils.js'; | ||
block[15] |= 0x80; | ||
let view = utils.createView(block); | ||
let view = createView(block); | ||
let output = new Uint8Array(input.length); | ||
@@ -68,3 +68,3 @@ for (let pos = 0; pos < input.length;) { | ||
deriveBlock.set(nonce, 4); | ||
const view = utils.createView(deriveBlock); | ||
const view = createView(deriveBlock); | ||
for (const derivedKey of [authKey, encKey]) { | ||
@@ -85,7 +85,7 @@ for (let i = 0; i < derivedKey.length; i += 8) { | ||
const block = new Uint8Array(lenPos + 16); | ||
const view = utils.createView(block); | ||
const view = createView(block); | ||
block.set(AAD); | ||
block.set(data, dataPos); | ||
utils.setBigUint64(view, lenPos, BigInt(AAD.length * 8), true); | ||
utils.setBigUint64(view, lenPos + 8, BigInt(data.length * 8), true); | ||
setBigUint64(view, lenPos, BigInt(AAD.length * 8), true); | ||
setBigUint64(view, lenPos + 8, BigInt(data.length * 8), true); | ||
// Compute the expected tag by XORing S_s and the nonce, clearing the | ||
@@ -92,0 +92,0 @@ // most significant bit of the last byte and encrypting with the |
{ | ||
"name": "@noble/ciphers", | ||
"version": "0.1.3", | ||
"version": "0.1.4", | ||
"description": "Auditable & minimal JS implementation of Salsa20, ChaCha, Poly1305 & AES-SIV", | ||
@@ -20,3 +20,3 @@ "files": [ | ||
"build:release": "cd build; npm i; npm run build", | ||
"build:clean": "rm *.{js,d.ts,js.map,d.ts.map} esm/*.{js,js.map,d.ts.map} webcrypto esm/webcrypto 2> /dev/null", | ||
"build:clean": "rm -r *.{js,d.ts,js.map,d.ts.map} esm/*.{js,d.ts,js.map,d.ts.map} webcrypto esm/webcrypto 2> /dev/null", | ||
"lint": "prettier --check 'src/**/*.{js,ts}' 'test/**/*.{js,ts,mjs}'", | ||
@@ -57,6 +57,6 @@ "format": "prettier --write 'src/**/*.{js,ts}' 'test/**/*.{js,ts,mjs}'", | ||
}, | ||
"./_slow": { | ||
"types": "./_slow.d.ts", | ||
"import": "./esm/_slow.js", | ||
"default": "./_slow.js" | ||
"./_micro": { | ||
"types": "./_micro.d.ts", | ||
"import": "./esm/_micro.js", | ||
"default": "./_micro.js" | ||
}, | ||
@@ -63,0 +63,0 @@ "./_poly1305": { |
100
README.md
@@ -15,5 +15,2 @@ # noble-ciphers | ||
`_slow` file contains minimal, readable implementation of algorithms. | ||
Other files contain unrolled loops, which are fast, but less auditable. | ||
### This library belongs to _noble_ crypto | ||
@@ -79,4 +76,5 @@ | ||
// All algoritms, written in minimal, auditable way | ||
import * as ciphers from '@noble/ciphers/_slow'; | ||
// All algoritms, written in minimal, auditable way. | ||
// Other files contain unrolled loops, which are 5x faster, but less auditable. | ||
import * as ciphers from '@noble/ciphers/_micro'; | ||
``` | ||
@@ -325,65 +323,61 @@ | ||
encrypt (32B) | ||
├─salsa x 1,562,500 ops/sec @ 640ns/op | ||
├─chacha x 1,968,503 ops/sec @ 508ns/op | ||
├─xsalsa x 969,932 ops/sec @ 1μs/op | ||
├─xchacha x 959,692 ops/sec @ 1μs/op | ||
├─xsalsa20_poly1305 x 554,631 ops/sec @ 1μs/op | ||
├─chacha20_poly1305 x 542,888 ops/sec @ 1μs/op | ||
└─xchacha20poly1305 x 346,140 ops/sec @ 2μs/op | ||
├─salsa x 1,210,653 ops/sec @ 826ns/op | ||
├─chacha x 1,440,922 ops/sec @ 694ns/op | ||
├─xsalsa x 846,023 ops/sec @ 1μs/op | ||
├─xchacha x 842,459 ops/sec @ 1μs/op | ||
├─xsalsa20_poly1305 x 562,746 ops/sec @ 1μs/op | ||
├─chacha20_poly1305 x 468,603 ops/sec @ 2μs/op | ||
└─xchacha20poly1305 x 311,623 ops/sec @ 3μs/op | ||
encrypt (64B) | ||
├─salsa x 1,392,757 ops/sec @ 718ns/op | ||
├─chacha x 1,709,401 ops/sec @ 585ns/op | ||
├─xsalsa x 892,857 ops/sec @ 1μs/op | ||
├─xchacha x 888,099 ops/sec @ 1μs/op | ||
├─xsalsa20_poly1305 x 476,871 ops/sec @ 2μs/op | ||
├─chacha20_poly1305 x 488,997 ops/sec @ 2μs/op | ||
└─xchacha20poly1305 x 326,157 ops/sec @ 3μs/op | ||
├─salsa x 1,310,615 ops/sec @ 763ns/op | ||
├─chacha x 1,577,287 ops/sec @ 634ns/op | ||
├─xsalsa x 864,304 ops/sec @ 1μs/op | ||
├─xchacha x 862,068 ops/sec @ 1μs/op | ||
├─xsalsa20_poly1305 x 481,000 ops/sec @ 2μs/op | ||
├─chacha20_poly1305 x 446,627 ops/sec @ 2μs/op | ||
└─xchacha20poly1305 x 302,480 ops/sec @ 3μs/op | ||
encrypt (1KB) | ||
├─salsa x 219,780 ops/sec @ 4μs/op | ||
├─chacha x 227,634 ops/sec @ 4μs/op | ||
├─xsalsa x 204,290 ops/sec @ 4μs/op | ||
├─xchacha x 203,873 ops/sec @ 4μs/op | ||
├─xsalsa20_poly1305 x 116,049 ops/sec @ 8μs/op | ||
├─chacha20_poly1305 x 116,522 ops/sec @ 8μs/op | ||
└─xchacha20poly1305 x 103,487 ops/sec @ 9μs/op | ||
├─salsa x 356,506 ops/sec @ 2μs/op | ||
├─chacha x 380,952 ops/sec @ 2μs/op | ||
├─xsalsa x 312,891 ops/sec @ 3μs/op | ||
├─xchacha x 318,674 ops/sec @ 3μs/op | ||
├─xsalsa20_poly1305 x 143,864 ops/sec @ 6μs/op | ||
├─chacha20_poly1305 x 141,703 ops/sec @ 7μs/op | ||
└─xchacha20poly1305 x 122,895 ops/sec @ 8μs/op | ||
encrypt (8KB) | ||
├─salsa x 30,695 ops/sec @ 32μs/op | ||
├─chacha x 30,817 ops/sec @ 32μs/op | ||
├─xsalsa x 30,193 ops/sec @ 33μs/op | ||
├─xchacha x 30,255 ops/sec @ 33μs/op | ||
├─xsalsa20_poly1305 x 17,402 ops/sec @ 57μs/op | ||
├─chacha20_poly1305 x 17,513 ops/sec @ 57μs/op | ||
└─xchacha20poly1305 x 17,208 ops/sec @ 58μs/op | ||
├─salsa x 56,170 ops/sec @ 17μs/op | ||
├─chacha x 57,997 ops/sec @ 17μs/op | ||
├─xsalsa x 54,758 ops/sec @ 18μs/op | ||
├─xchacha x 56,085 ops/sec @ 17μs/op | ||
├─xsalsa20_poly1305 x 23,203 ops/sec @ 43μs/op | ||
├─chacha20_poly1305 x 23,482 ops/sec @ 42μs/op | ||
└─xchacha20poly1305 x 22,900 ops/sec @ 43μs/op | ||
encrypt (1MB) | ||
├─salsa x 249 ops/sec @ 4ms/op | ||
├─chacha x 250 ops/sec @ 3ms/op | ||
├─xsalsa x 249 ops/sec @ 4ms/op | ||
├─xchacha x 250 ops/sec @ 3ms/op | ||
├─xsalsa20_poly1305 x 142 ops/sec @ 7ms/op | ||
├─chacha20_poly1305 x 143 ops/sec @ 6ms/op | ||
└─xchacha20poly1305 x 143 ops/sec @ 6ms/op | ||
├─salsa x 462 ops/sec @ 2ms/op | ||
├─chacha x 473 ops/sec @ 2ms/op | ||
├─xsalsa x 463 ops/sec @ 2ms/op | ||
├─xchacha x 474 ops/sec @ 2ms/op | ||
├─xsalsa20_poly1305 x 190 ops/sec @ 5ms/op | ||
├─chacha20_poly1305 x 193 ops/sec @ 5ms/op | ||
└─xchacha20poly1305 x 192 ops/sec @ 5ms/op | ||
``` | ||
How does this compare to other implementations? | ||
Compare to other implementations (slow is `_micro.ts`): | ||
- node.js native code is 3-10x faster than noble-ciphers | ||
- tweetnacl is 25% slower than noble-ciphers on 1KB+ inputs | ||
- noble-slow "slow, but more readable" version of noble-ciphers is 3-8x slower | ||
(check out `_slow.ts`) | ||
``` | ||
xsalsa20_poly1305 (encrypt, 1MB) | ||
├─tweetnacl x 112 ops/sec @ 8ms/op | ||
├─noble x 142 ops/sec @ 7ms/op | ||
└─noble-slow x 20 ops/sec @ 47ms/op | ||
├─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) | ||
├─node x 1,369 ops/sec @ 729μs/op | ||
├─stablelib x 120 ops/sec @ 8ms/op | ||
├─noble x 142 ops/sec @ 7ms/op | ||
└─noble-slow x 19 ops/sec @ 51ms/op | ||
├─node x 1,360 ops/sec @ 735μs/op | ||
├─stablelib x 117 ops/sec @ 8ms/op | ||
├─noble x 193 ops/sec @ 5ms/op | ||
└─micro x 19 ops/sec @ 50ms/op | ||
``` | ||
@@ -390,0 +384,0 @@ |
import { Cipher } from './utils.js'; | ||
/** | ||
* hsalsa hashing function, used primarily in xsalsa, to hash | ||
* key and nonce into key' and nonce'. | ||
* Same as salsaCore, but there doesn't seem to be a way to move the block | ||
* out without 25% performance hit. | ||
*/ | ||
export declare function hsalsa(c: Uint32Array, key: Uint8Array, nonce: Uint8Array, out: Uint8Array): Uint8Array; | ||
/** | ||
* Salsa20 from original paper. | ||
* With 12-byte nonce, it's not safe to use fill it with random (CSPRNG), due to collision chance. | ||
*/ | ||
export declare const salsa20: (key: Uint8Array, nonce: Uint8Array, data: Uint8Array, output?: Uint8Array | undefined, counter?: number) => Uint8Array; | ||
/** | ||
* xsalsa20 eXtended-nonce salsa. | ||
* With 24-byte nonce, it's safe to use fill it with random (CSPRNG). | ||
*/ | ||
export declare const xsalsa20: (key: Uint8Array, nonce: Uint8Array, data: Uint8Array, output?: Uint8Array | undefined, counter?: number) => Uint8Array; | ||
/** | ||
* xsalsa20-poly1305 eXtended-nonce salsa. | ||
* With 24-byte nonce, it's safe to use fill it with random (CSPRNG). | ||
* Also known as secretbox from libsodium / nacl. | ||
*/ | ||
export declare const xsalsa20_poly1305: (key: Uint8Array, nonce: Uint8Array) => Cipher; | ||
/** | ||
* Alias to xsalsa20poly1305, for compatibility with libsodium / nacl | ||
*/ | ||
export declare function secretbox(key: Uint8Array, nonce: Uint8Array): { | ||
seal: (plaintext: Uint8Array) => Uint8Array; | ||
open: (ciphertext: Uint8Array) => Uint8Array; | ||
}; | ||
//# sourceMappingURL=salsa.d.ts.map |
36
salsa.js
"use strict"; | ||
Object.defineProperty(exports, "__esModule", { value: true }); | ||
exports.xsalsa20_poly1305 = exports.xsalsa20 = exports.salsa20 = exports.hsalsa = void 0; | ||
exports.secretbox = exports.xsalsa20_poly1305 = exports.xsalsa20 = exports.salsa20 = exports.hsalsa = void 0; | ||
const utils_js_1 = require("./utils.js"); | ||
@@ -13,3 +13,5 @@ const _salsa_js_1 = require("./_salsa.js"); | ||
const rotl = (a, b) => (a << b) | (a >>> (32 - b)); | ||
// NOTE: same as hsalsa, but we cannot move out block without 25% perf loss :( | ||
/** | ||
* Salsa20 core function. | ||
*/ | ||
// prettier-ignore | ||
@@ -78,2 +80,8 @@ function salsaCore(c, k, i, out, cnt, rounds = 20) { | ||
} | ||
/** | ||
* hsalsa hashing function, used primarily in xsalsa, to hash | ||
* key and nonce into key' and nonce'. | ||
* Same as salsaCore, but there doesn't seem to be a way to move the block | ||
* out without 25% performance hit. | ||
*/ | ||
// prettier-ignore | ||
@@ -134,3 +142,11 @@ function hsalsa(c, key, nonce, out) { | ||
exports.hsalsa = hsalsa; | ||
/** | ||
* Salsa20 from original paper. | ||
* With 12-byte nonce, it's not safe to use fill it with random (CSPRNG), due to collision chance. | ||
*/ | ||
exports.salsa20 = (0, _salsa_js_1.salsaBasic)({ core: salsaCore, counterRight: true }); | ||
/** | ||
* xsalsa20 eXtended-nonce salsa. | ||
* With 24-byte nonce, it's safe to use fill it with random (CSPRNG). | ||
*/ | ||
exports.xsalsa20 = (0, _salsa_js_1.salsaBasic)({ | ||
@@ -142,3 +158,7 @@ core: salsaCore, | ||
}); | ||
// Also known as 'tweetnacl secretbox' | ||
/** | ||
* xsalsa20-poly1305 eXtended-nonce salsa. | ||
* With 24-byte nonce, it's safe to use fill it with random (CSPRNG). | ||
* Also known as secretbox from libsodium / nacl. | ||
*/ | ||
const xsalsa20_poly1305 = (key, nonce) => { | ||
@@ -185,2 +205,12 @@ const tagLength = 16; | ||
exports.xsalsa20_poly1305 = xsalsa20_poly1305; | ||
/** | ||
* Alias to xsalsa20poly1305, for compatibility with libsodium / nacl | ||
*/ | ||
function secretbox(key, nonce) { | ||
(0, utils_js_1.ensureBytes)(key); | ||
(0, utils_js_1.ensureBytes)(nonce); | ||
const xs = (0, exports.xsalsa20_poly1305)(key, nonce); | ||
return { seal: xs.encrypt, open: xs.decrypt }; | ||
} | ||
exports.secretbox = secretbox; | ||
//# sourceMappingURL=salsa.js.map |
// Basic utils for salsa-like ciphers | ||
// Check out _slow.ts for descriptive documentation. | ||
// Check out _micro.ts for descriptive documentation. | ||
import assert from './_assert.js'; | ||
@@ -7,3 +7,3 @@ import { u32, utf8ToBytes, checkOpts } from './utils.js'; | ||
/* | ||
RFC7539 requires multi-step cipher stream, where | ||
RFC8439 requires multi-step cipher stream, where | ||
authKey starts with counter: 0, actual msg with counter: 1. | ||
@@ -77,2 +77,5 @@ | ||
// Is byte array aligned to 4 byte offset (u32)? | ||
const isAligned32 = (b: Uint8Array) => !(b.byteOffset % 4); | ||
export const salsaBasic = (opts: SalsaOpts) => { | ||
@@ -151,4 +154,5 @@ const { core, rounds, counterRight, counterLen, allow128bitKeys, extendNonceFn, blockLen } = | ||
const n32 = u32(nonce); | ||
const d32 = u32(data); | ||
const o32 = u32(output); | ||
// Make sure that buffers aligned to 4 bytes | ||
const d32 = isAligned32(data) && u32(data); | ||
const o32 = isAligned32(output) && u32(output); | ||
toClean.push(b32); | ||
@@ -160,4 +164,4 @@ const len = data.length; | ||
const take = Math.min(blockLen, len - pos); | ||
// Fast path: we have at least one block in input | ||
if (take === blockLen) { | ||
// full block && aligned to 4 bytes | ||
if (take === blockLen && o32 && d32) { | ||
const pos32 = pos / 4; | ||
@@ -164,0 +168,0 @@ if (pos % 4 !== 0) throw new Error('Salsa/ChaCha: wrong block position'); |
@@ -1,2 +0,2 @@ | ||
import * as utils from './utils.js'; | ||
import { Cipher, createView, ensureBytes, equalBytes, setBigUint64, u32 } from './utils.js'; | ||
import { poly1305 } from './_poly1305.js'; | ||
@@ -12,2 +12,5 @@ import { salsaBasic } from './_salsa.js'; | ||
/** | ||
* ChaCha core function. | ||
*/ | ||
// prettier-ignore | ||
@@ -77,7 +80,13 @@ function chachaCore(c: Uint32Array, k: Uint32Array, n: Uint32Array, out: Uint32Array, cnt: number, rounds = 20): void { | ||
} | ||
/** | ||
* hchacha helper method, used primarily in xchacha, to hash | ||
* key and nonce into key' and nonce'. | ||
* Same as chachaCore, but there doesn't seem to be a way to move the block | ||
* out without 25% performance hit. | ||
*/ | ||
// prettier-ignore | ||
export function hchacha(c: Uint32Array, key: Uint8Array, src: Uint8Array, dst: Uint8Array): Uint8Array { | ||
const k32 = utils.u32(key); | ||
const i32 = utils.u32(src); | ||
const o32 = utils.u32(dst); | ||
export function hchacha(c: Uint32Array, key: Uint8Array, src: Uint8Array, out: Uint8Array): Uint8Array { | ||
const k32 = u32(key); | ||
const i32 = u32(src); | ||
const o32 = u32(out); | ||
let x00 = c[0], x01 = c[1], x02 = c[2], x03 = c[3]; | ||
@@ -136,7 +145,12 @@ let x04 = k32[0], x05 = k32[1], x06 = k32[2], x07 = k32[3]; | ||
o32[7] = x15; | ||
return dst; | ||
return out; | ||
} | ||
// Original DJB ChaCha20, 8 bytes nonce, 8 bytes counter | ||
/** | ||
* Original, non-RFC chacha20 from DJB. 8-byte nonce, 8-byte counter. | ||
*/ | ||
export const chacha20orig = salsaBasic({ core: chachaCore, counterRight: false, counterLen: 8 }); | ||
// Also known as chacha20-tls (IETF), 12 bytes nonce, 4 bytes counter | ||
/** | ||
* ChaCha stream cipher. Conforms to RFC 8439 (IETF, TLS). 12-byte nonce, 4-byte counter. | ||
* With 12-byte nonce, it's not safe to use fill it with random (CSPRNG), due to collision chance. | ||
*/ | ||
export const chacha20 = salsaBasic({ | ||
@@ -149,3 +163,7 @@ core: chachaCore, | ||
// xchacha draft RFC https://datatracker.ietf.org/doc/html/draft-irtf-cfrg-xchacha | ||
/** | ||
* XChaCha eXtended-nonce ChaCha. 24-byte nonce. | ||
* With 24-byte nonce, it's safe to use fill it with random (CSPRNG). | ||
* https://datatracker.ietf.org/doc/html/draft-irtf-cfrg-xchacha | ||
*/ | ||
export const xchacha20 = salsaBasic({ | ||
@@ -159,3 +177,5 @@ core: chachaCore, | ||
// Reduced-round chacha, described in original paper | ||
/** | ||
* Reduced 8-round chacha, described in original paper. | ||
*/ | ||
export const chacha8 = salsaBasic({ | ||
@@ -167,2 +187,6 @@ core: chachaCore, | ||
}); | ||
/** | ||
* Reduced 12-round chacha, described in original paper. | ||
*/ | ||
export const chacha12 = salsaBasic({ | ||
@@ -195,5 +219,5 @@ core: chachaCore, | ||
const num = new Uint8Array(16); | ||
const view = utils.createView(num); | ||
utils.setBigUint64(view, 0, BigInt(AAD ? AAD.length : 0), true); | ||
utils.setBigUint64(view, 8, BigInt(data.length), true); | ||
const view = createView(num); | ||
setBigUint64(view, 0, BigInt(AAD ? AAD.length : 0), true); | ||
setBigUint64(view, 8, BigInt(data.length), true); | ||
h.update(num); | ||
@@ -205,15 +229,17 @@ const res = h.digest(); | ||
// salsa and chacha (RFC 7539) use poly1305 differently. | ||
// We could have composed them such as in: | ||
// https://github.com/paulmillr/scure-base/blob/b266c73dde977b1dd7ef40ef7a23cc15aab526b3/index.ts#L250 | ||
// But authKey construction makes it hard: | ||
// - salsa: authKey changes position in salsa stream | ||
// - chacha: authKey can't be computed inside computeTag, it modifies the counter | ||
// Algo from RFC 7539. | ||
/** | ||
* AEAD algorithm from RFC 8439. | ||
* Salsa20 and chacha (RFC 8439) use poly1305 differently. | ||
* We could have composed them similar to: | ||
* https://github.com/paulmillr/scure-base/blob/b266c73dde977b1dd7ef40ef7a23cc15aab526b3/index.ts#L250 | ||
* But it's hard because of authKey: | ||
* In salsa20, authKey changes position in salsa stream. | ||
* In chacha, authKey can't be computed inside computeTag, it modifies the counter. | ||
*/ | ||
export const _poly1305_aead = | ||
(fn: typeof chacha20) => | ||
(key: Uint8Array, nonce: Uint8Array, AAD?: Uint8Array): utils.Cipher => { | ||
(key: Uint8Array, nonce: Uint8Array, AAD?: Uint8Array): Cipher => { | ||
const tagLength = 16; | ||
utils.ensureBytes(key, 32); | ||
utils.ensureBytes(nonce); | ||
ensureBytes(key, 32); | ||
ensureBytes(nonce); | ||
return { | ||
@@ -234,3 +260,3 @@ tagLength, | ||
const tag = computeTag(fn, key, nonce, data, AAD); | ||
if (!utils.equalBytes(realTag, tag)) throw new Error('Wrong tag'); | ||
if (!equalBytes(realTag, tag)) throw new Error('Wrong tag'); | ||
return fn(key, nonce, data, undefined, 1); | ||
@@ -241,3 +267,12 @@ }, | ||
/** | ||
* 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); | ||
/** | ||
* 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); |
@@ -13,3 +13,5 @@ import { ensureBytes, u32, equalBytes, Cipher } from './utils.js'; | ||
// NOTE: same as hsalsa, but we cannot move out block without 25% perf loss :( | ||
/** | ||
* Salsa20 core function. | ||
*/ | ||
// prettier-ignore | ||
@@ -57,2 +59,9 @@ function salsaCore(c: Uint32Array, k: Uint32Array, i: Uint32Array, out: Uint32Array, cnt: number, rounds = 20): void { | ||
} | ||
/** | ||
* hsalsa hashing function, used primarily in xsalsa, to hash | ||
* key and nonce into key' and nonce'. | ||
* Same as salsaCore, but there doesn't seem to be a way to move the block | ||
* out without 25% performance hit. | ||
*/ | ||
// prettier-ignore | ||
@@ -97,3 +106,12 @@ export function hsalsa(c: Uint32Array, key: Uint8Array, nonce: Uint8Array, out: Uint8Array): Uint8Array { | ||
/** | ||
* Salsa20 from original paper. | ||
* With 12-byte nonce, it's not safe to use fill it with random (CSPRNG), due to collision chance. | ||
*/ | ||
export const salsa20 = salsaBasic({ core: salsaCore, counterRight: true }); | ||
/** | ||
* xsalsa20 eXtended-nonce salsa. | ||
* With 24-byte nonce, it's safe to use fill it with random (CSPRNG). | ||
*/ | ||
export const xsalsa20 = salsaBasic({ | ||
@@ -106,3 +124,7 @@ core: salsaCore, | ||
// Also known as 'tweetnacl secretbox' | ||
/** | ||
* xsalsa20-poly1305 eXtended-nonce salsa. | ||
* 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 => { | ||
@@ -146,1 +168,11 @@ const tagLength = 16; | ||
}; | ||
/** | ||
* Alias to xsalsa20poly1305, for compatibility with libsodium / nacl | ||
*/ | ||
export function secretbox(key: Uint8Array, nonce: Uint8Array) { | ||
ensureBytes(key); | ||
ensureBytes(nonce); | ||
const xs = xsalsa20_poly1305(key, nonce); | ||
return { seal: xs.encrypt, open: xs.decrypt }; | ||
} |
@@ -24,3 +24,5 @@ /*! noble-ciphers - MIT License (c) 2023 Paul Miller (paulmillr.com) */ | ||
const hexes = Array.from({ length: 256 }, (v, i) => i.toString(16).padStart(2, '0')); | ||
const hexes = /* @__PURE__ */ Array.from({ length: 256 }, (_, i) => | ||
i.toString(16).padStart(2, '0') | ||
); | ||
/** | ||
@@ -27,0 +29,0 @@ * @example bytesToHex(Uint8Array.from([0xca, 0xfe, 0x01, 0x23])) // 'cafe0123' |
@@ -1,2 +0,2 @@ | ||
import * as utils from '../utils.js'; | ||
import { AsyncCipher, createView, setBigUint64 } from '../utils.js'; | ||
import { polyval } from '../_polyval.js'; | ||
@@ -48,3 +48,3 @@ import { getWebcryptoSubtle } from './utils.js'; | ||
block[15] |= 0x80; | ||
let view = utils.createView(block); | ||
let view = createView(block); | ||
let output = new Uint8Array(input.length); | ||
@@ -69,3 +69,3 @@ for (let pos = 0; pos < input.length; ) { | ||
deriveBlock.set(nonce, 4); | ||
const view = utils.createView(deriveBlock); | ||
const view = createView(deriveBlock); | ||
for (const derivedKey of [authKey, encKey]) { | ||
@@ -85,3 +85,3 @@ for (let i = 0; i < derivedKey.length; i += 8) { | ||
AAD: Uint8Array | ||
): Promise<utils.AsyncCipher> { | ||
): Promise<AsyncCipher> { | ||
const { encKey, authKey } = await deriveKeys(key, nonce); | ||
@@ -92,7 +92,7 @@ const computeTag = async (data: Uint8Array, AAD: Uint8Array) => { | ||
const block = new Uint8Array(lenPos + 16); | ||
const view = utils.createView(block); | ||
const view = createView(block); | ||
block.set(AAD); | ||
block.set(data, dataPos); | ||
utils.setBigUint64(view, lenPos, BigInt(AAD.length * 8), true); | ||
utils.setBigUint64(view, lenPos + 8, BigInt(data.length * 8), true); | ||
setBigUint64(view, lenPos, BigInt(AAD.length * 8), true); | ||
setBigUint64(view, lenPos + 8, BigInt(data.length * 8), true); | ||
// Compute the expected tag by XORing S_s and the nonce, clearing the | ||
@@ -99,0 +99,0 @@ // most significant bit of the last byte and encrypting with the |
@@ -63,1 +63,2 @@ /*! noble-ciphers - MIT License (c) 2023 Paul Miller (paulmillr.com) */ | ||
export {}; | ||
//# sourceMappingURL=utils.d.ts.map |
@@ -21,3 +21,3 @@ "use strict"; | ||
throw new Error('Non little-endian hardware is not supported'); | ||
const hexes = Array.from({ length: 256 }, (v, i) => i.toString(16).padStart(2, '0')); | ||
const hexes = /* @__PURE__ */ Array.from({ length: 256 }, (_, i) => i.toString(16).padStart(2, '0')); | ||
/** | ||
@@ -24,0 +24,0 @@ * @example bytesToHex(Uint8Array.from([0xca, 0xfe, 0x01, 0x23])) // 'cafe0123' |
@@ -31,1 +31,2 @@ export declare const aes_128_ctr: (key: Uint8Array, nonce: Uint8Array) => { | ||
}; | ||
//# sourceMappingURL=aes.d.ts.map |
export declare const crypto: any; | ||
//# sourceMappingURL=crypto.d.ts.map |
export declare const crypto: any; | ||
//# sourceMappingURL=cryptoNode.d.ts.map |
@@ -8,1 +8,2 @@ import type { AsyncCipher } from '../utils.js'; | ||
export declare function BinaryFF1(key: Uint8Array, tweak?: Uint8Array): AsyncCipher; | ||
//# sourceMappingURL=ff1.d.ts.map |
@@ -1,2 +0,2 @@ | ||
import * as utils from '../utils.js'; | ||
import { AsyncCipher } from '../utils.js'; | ||
export declare function deriveKeys(key: Uint8Array, nonce: Uint8Array): Promise<{ | ||
@@ -6,2 +6,3 @@ authKey: Uint8Array; | ||
}>; | ||
export declare function aes_256_gcm_siv(key: Uint8Array, nonce: Uint8Array, AAD: Uint8Array): Promise<utils.AsyncCipher>; | ||
export declare function aes_256_gcm_siv(key: Uint8Array, nonce: Uint8Array, AAD: Uint8Array): Promise<AsyncCipher>; | ||
//# sourceMappingURL=siv.d.ts.map |
"use strict"; | ||
Object.defineProperty(exports, "__esModule", { value: true }); | ||
exports.aes_256_gcm_siv = exports.deriveKeys = void 0; | ||
const utils = require("../utils.js"); | ||
const utils_js_1 = require("../utils.js"); | ||
const _polyval_js_1 = require("../_polyval.js"); | ||
const utils_js_1 = require("./utils.js"); | ||
const utils_js_2 = require("./utils.js"); | ||
/** | ||
@@ -18,3 +18,3 @@ * AES-GCM-SIV: classic AES-GCM with nonce-misuse resistance. | ||
const mode = { name: `AES-CBC`, length: key.length * 8 }; | ||
const cr = (0, utils_js_1.getWebcryptoSubtle)(); | ||
const cr = (0, utils_js_2.getWebcryptoSubtle)(); | ||
const wKey = await cr.importKey('raw', key, mode, true, ['encrypt']); | ||
@@ -51,3 +51,3 @@ const cipher = await cr.encrypt({ name: `aes-cbc`, iv: IV, counter: IV, length: 64 }, wKey, msg); | ||
block[15] |= 0x80; | ||
let view = utils.createView(block); | ||
let view = (0, utils_js_1.createView)(block); | ||
let output = new Uint8Array(input.length); | ||
@@ -72,3 +72,3 @@ for (let pos = 0; pos < input.length;) { | ||
deriveBlock.set(nonce, 4); | ||
const view = utils.createView(deriveBlock); | ||
const view = (0, utils_js_1.createView)(deriveBlock); | ||
for (const derivedKey of [authKey, encKey]) { | ||
@@ -90,7 +90,7 @@ for (let i = 0; i < derivedKey.length; i += 8) { | ||
const block = new Uint8Array(lenPos + 16); | ||
const view = utils.createView(block); | ||
const view = (0, utils_js_1.createView)(block); | ||
block.set(AAD); | ||
block.set(data, dataPos); | ||
utils.setBigUint64(view, lenPos, BigInt(AAD.length * 8), true); | ||
utils.setBigUint64(view, lenPos + 8, BigInt(data.length * 8), true); | ||
(0, utils_js_1.setBigUint64)(view, lenPos, BigInt(AAD.length * 8), true); | ||
(0, utils_js_1.setBigUint64)(view, lenPos + 8, BigInt(data.length * 8), true); | ||
// Compute the expected tag by XORing S_s and the nonce, clearing the | ||
@@ -97,0 +97,0 @@ // most significant bit of the last byte and encrypting with the |
@@ -6,1 +6,2 @@ /** | ||
export declare function getWebcryptoSubtle(): any; | ||
//# sourceMappingURL=utils.d.ts.map |
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
License Policy Violation
LicenseThis package is not allowed per your license policy. Review the package's license to ensure compliance.
Found 1 instance in 1 package
License Policy Violation
LicenseThis package is not allowed per your license policy. Review the package's license to ensure compliance.
Found 1 instance in 1 package
440541
109
5841
397