@stablelib/chacha
Advanced tools
Comparing version
// Copyright (C) 2016 Dmitry Chestnykh | ||
// MIT License. See LICENSE file for details. | ||
import { describe, expect, it } from 'vitest'; | ||
import { streamXOR, stream } from "./chacha"; | ||
@@ -5,0 +6,0 @@ import { encode, decode } from "@stablelib/hex"; |
@@ -1,17 +0,15 @@ | ||
"use strict"; | ||
// Copyright (C) 2016 Dmitry Chestnykh | ||
// MIT License. See LICENSE file for details. | ||
Object.defineProperty(exports, "__esModule", { value: true }); | ||
var chacha_1 = require("./chacha"); | ||
var benchmark_1 = require("@stablelib/benchmark"); | ||
var buf16K = benchmark_1.byteSeq(16 << 10); | ||
var buf8192 = benchmark_1.byteSeq(8192); | ||
var buf1111 = benchmark_1.byteSeq(1111); | ||
var buf64 = benchmark_1.byteSeq(64); | ||
var key = benchmark_1.byteSeq(32); | ||
var nonce = benchmark_1.byteSeq(8); | ||
benchmark_1.report("ChaCha20 xor 16K", benchmark_1.benchmark(function () { return chacha_1.streamXOR(key, nonce, buf16K, buf16K); }, buf16K.length)); | ||
benchmark_1.report("ChaCha20 xor 8K", benchmark_1.benchmark(function () { return chacha_1.streamXOR(key, nonce, buf8192, buf8192); }, buf8192.length)); | ||
benchmark_1.report("ChaCha20 xor 1111", benchmark_1.benchmark(function () { return chacha_1.streamXOR(key, nonce, buf1111, buf1111); }, buf1111.length)); | ||
benchmark_1.report("ChaCha20 xor 64", benchmark_1.benchmark(function () { return chacha_1.streamXOR(key, nonce, buf64, buf64); }, buf64.length)); | ||
import { streamXOR } from "./chacha"; | ||
import { benchmark, report, byteSeq } from "@stablelib/benchmark"; | ||
const buf16K = byteSeq(16 << 10); | ||
const buf8192 = byteSeq(8192); | ||
const buf1111 = byteSeq(1111); | ||
const buf64 = byteSeq(64); | ||
const key = byteSeq(32); | ||
const nonce = byteSeq(8); | ||
report("ChaCha20 xor 16K", benchmark(() => streamXOR(key, nonce, buf16K, buf16K), buf16K.length)); | ||
report("ChaCha20 xor 8K", benchmark(() => streamXOR(key, nonce, buf8192, buf8192), buf8192.length)); | ||
report("ChaCha20 xor 1111", benchmark(() => streamXOR(key, nonce, buf1111, buf1111), buf1111.length)); | ||
report("ChaCha20 xor 64", benchmark(() => streamXOR(key, nonce, buf64, buf64), buf64.length)); | ||
//# sourceMappingURL=chacha.bench.js.map |
@@ -1,48 +0,46 @@ | ||
"use strict"; | ||
// Copyright (C) 2016 Dmitry Chestnykh | ||
// MIT License. See LICENSE file for details. | ||
Object.defineProperty(exports, "__esModule", { value: true }); | ||
/** | ||
* Package chacha implements ChaCha stream cipher. | ||
*/ | ||
var binary_1 = require("@stablelib/binary"); | ||
var wipe_1 = require("@stablelib/wipe"); | ||
import { writeUint32LE } from "@stablelib/binary"; | ||
import { wipe } from "@stablelib/wipe"; | ||
// Number of ChaCha rounds (ChaCha20). | ||
var ROUNDS = 20; | ||
const ROUNDS = 20; | ||
// Applies the ChaCha core function to 16-byte input, | ||
// 32-byte key key, and puts the result into 64-byte array out. | ||
function core(out, input, key) { | ||
var j0 = 0x61707865; // "expa" -- ChaCha's "sigma" constant | ||
var j1 = 0x3320646E; // "nd 3" for 32-byte keys | ||
var j2 = 0x79622D32; // "2-by" | ||
var j3 = 0x6B206574; // "te k" | ||
var j4 = (key[3] << 24) | (key[2] << 16) | (key[1] << 8) | key[0]; | ||
var j5 = (key[7] << 24) | (key[6] << 16) | (key[5] << 8) | key[4]; | ||
var j6 = (key[11] << 24) | (key[10] << 16) | (key[9] << 8) | key[8]; | ||
var j7 = (key[15] << 24) | (key[14] << 16) | (key[13] << 8) | key[12]; | ||
var j8 = (key[19] << 24) | (key[18] << 16) | (key[17] << 8) | key[16]; | ||
var j9 = (key[23] << 24) | (key[22] << 16) | (key[21] << 8) | key[20]; | ||
var j10 = (key[27] << 24) | (key[26] << 16) | (key[25] << 8) | key[24]; | ||
var j11 = (key[31] << 24) | (key[30] << 16) | (key[29] << 8) | key[28]; | ||
var j12 = (input[3] << 24) | (input[2] << 16) | (input[1] << 8) | input[0]; | ||
var j13 = (input[7] << 24) | (input[6] << 16) | (input[5] << 8) | input[4]; | ||
var j14 = (input[11] << 24) | (input[10] << 16) | (input[9] << 8) | input[8]; | ||
var j15 = (input[15] << 24) | (input[14] << 16) | (input[13] << 8) | input[12]; | ||
var x0 = j0; | ||
var x1 = j1; | ||
var x2 = j2; | ||
var x3 = j3; | ||
var x4 = j4; | ||
var x5 = j5; | ||
var x6 = j6; | ||
var x7 = j7; | ||
var x8 = j8; | ||
var x9 = j9; | ||
var x10 = j10; | ||
var x11 = j11; | ||
var x12 = j12; | ||
var x13 = j13; | ||
var x14 = j14; | ||
var x15 = j15; | ||
for (var i = 0; i < ROUNDS; i += 2) { | ||
let j0 = 0x61707865; // "expa" -- ChaCha's "sigma" constant | ||
let j1 = 0x3320646E; // "nd 3" for 32-byte keys | ||
let j2 = 0x79622D32; // "2-by" | ||
let j3 = 0x6B206574; // "te k" | ||
let j4 = (key[3] << 24) | (key[2] << 16) | (key[1] << 8) | key[0]; | ||
let j5 = (key[7] << 24) | (key[6] << 16) | (key[5] << 8) | key[4]; | ||
let j6 = (key[11] << 24) | (key[10] << 16) | (key[9] << 8) | key[8]; | ||
let j7 = (key[15] << 24) | (key[14] << 16) | (key[13] << 8) | key[12]; | ||
let j8 = (key[19] << 24) | (key[18] << 16) | (key[17] << 8) | key[16]; | ||
let j9 = (key[23] << 24) | (key[22] << 16) | (key[21] << 8) | key[20]; | ||
let j10 = (key[27] << 24) | (key[26] << 16) | (key[25] << 8) | key[24]; | ||
let j11 = (key[31] << 24) | (key[30] << 16) | (key[29] << 8) | key[28]; | ||
let j12 = (input[3] << 24) | (input[2] << 16) | (input[1] << 8) | input[0]; | ||
let j13 = (input[7] << 24) | (input[6] << 16) | (input[5] << 8) | input[4]; | ||
let j14 = (input[11] << 24) | (input[10] << 16) | (input[9] << 8) | input[8]; | ||
let j15 = (input[15] << 24) | (input[14] << 16) | (input[13] << 8) | input[12]; | ||
let x0 = j0; | ||
let x1 = j1; | ||
let x2 = j2; | ||
let x3 = j3; | ||
let x4 = j4; | ||
let x5 = j5; | ||
let x6 = j6; | ||
let x7 = j7; | ||
let x8 = j8; | ||
let x9 = j9; | ||
let x10 = j10; | ||
let x11 = j11; | ||
let x12 = j12; | ||
let x13 = j13; | ||
let x14 = j14; | ||
let x15 = j15; | ||
for (let i = 0; i < ROUNDS; i += 2) { | ||
x0 = x0 + x4 | 0; | ||
@@ -145,18 +143,18 @@ x12 ^= x0; | ||
} | ||
binary_1.writeUint32LE(x0 + j0 | 0, out, 0); | ||
binary_1.writeUint32LE(x1 + j1 | 0, out, 4); | ||
binary_1.writeUint32LE(x2 + j2 | 0, out, 8); | ||
binary_1.writeUint32LE(x3 + j3 | 0, out, 12); | ||
binary_1.writeUint32LE(x4 + j4 | 0, out, 16); | ||
binary_1.writeUint32LE(x5 + j5 | 0, out, 20); | ||
binary_1.writeUint32LE(x6 + j6 | 0, out, 24); | ||
binary_1.writeUint32LE(x7 + j7 | 0, out, 28); | ||
binary_1.writeUint32LE(x8 + j8 | 0, out, 32); | ||
binary_1.writeUint32LE(x9 + j9 | 0, out, 36); | ||
binary_1.writeUint32LE(x10 + j10 | 0, out, 40); | ||
binary_1.writeUint32LE(x11 + j11 | 0, out, 44); | ||
binary_1.writeUint32LE(x12 + j12 | 0, out, 48); | ||
binary_1.writeUint32LE(x13 + j13 | 0, out, 52); | ||
binary_1.writeUint32LE(x14 + j14 | 0, out, 56); | ||
binary_1.writeUint32LE(x15 + j15 | 0, out, 60); | ||
writeUint32LE(x0 + j0 | 0, out, 0); | ||
writeUint32LE(x1 + j1 | 0, out, 4); | ||
writeUint32LE(x2 + j2 | 0, out, 8); | ||
writeUint32LE(x3 + j3 | 0, out, 12); | ||
writeUint32LE(x4 + j4 | 0, out, 16); | ||
writeUint32LE(x5 + j5 | 0, out, 20); | ||
writeUint32LE(x6 + j6 | 0, out, 24); | ||
writeUint32LE(x7 + j7 | 0, out, 28); | ||
writeUint32LE(x8 + j8 | 0, out, 32); | ||
writeUint32LE(x9 + j9 | 0, out, 36); | ||
writeUint32LE(x10 + j10 | 0, out, 40); | ||
writeUint32LE(x11 + j11 | 0, out, 44); | ||
writeUint32LE(x12 + j12 | 0, out, 48); | ||
writeUint32LE(x13 + j13 | 0, out, 52); | ||
writeUint32LE(x14 + j14 | 0, out, 56); | ||
writeUint32LE(x15 + j15 | 0, out, 60); | ||
} | ||
@@ -186,4 +184,3 @@ /** | ||
*/ | ||
function streamXOR(key, nonce, src, dst, nonceInplaceCounterLength) { | ||
if (nonceInplaceCounterLength === void 0) { nonceInplaceCounterLength = 0; } | ||
export function streamXOR(key, nonce, src, dst, nonceInplaceCounterLength = 0) { | ||
// We only support 256-bit keys. | ||
@@ -196,4 +193,4 @@ if (key.length !== 32) { | ||
} | ||
var nc; | ||
var counterLength; | ||
let nc; | ||
let counterLength; | ||
if (nonceInplaceCounterLength === 0) { | ||
@@ -218,8 +215,8 @@ if (nonce.length !== 8 && nonce.length !== 12) { | ||
// Allocate temporary space for ChaCha block. | ||
var block = new Uint8Array(64); | ||
for (var i = 0; i < src.length; i += 64) { | ||
const block = new Uint8Array(64); | ||
for (let i = 0; i < src.length; i += 64) { | ||
// Generate a block. | ||
core(block, nc, key); | ||
// XOR block bytes with src into dst. | ||
for (var j = i; j < i + 64 && j < src.length; j++) { | ||
for (let j = i; j < i + 64 && j < src.length; j++) { | ||
dst[j] = src[j] ^ block[j - i]; | ||
@@ -231,10 +228,9 @@ } | ||
// Cleanup temporary space. | ||
wipe_1.wipe(block); | ||
wipe(block); | ||
if (nonceInplaceCounterLength === 0) { | ||
// Cleanup counter. | ||
wipe_1.wipe(nc); | ||
wipe(nc); | ||
} | ||
return dst; | ||
} | ||
exports.streamXOR = streamXOR; | ||
/** | ||
@@ -251,10 +247,8 @@ * Generate ChaCha20 stream for the given 32-byte key and 8-byte or 12-byte | ||
*/ | ||
function stream(key, nonce, dst, nonceInplaceCounterLength) { | ||
if (nonceInplaceCounterLength === void 0) { nonceInplaceCounterLength = 0; } | ||
wipe_1.wipe(dst); | ||
export function stream(key, nonce, dst, nonceInplaceCounterLength = 0) { | ||
wipe(dst); | ||
return streamXOR(key, nonce, dst, dst, nonceInplaceCounterLength); | ||
} | ||
exports.stream = stream; | ||
function incrementCounter(counter, pos, len) { | ||
var carry = 1; | ||
let carry = 1; | ||
while (len--) { | ||
@@ -261,0 +255,0 @@ carry = carry + (counter[pos] & 0xff) | 0; |
@@ -1,10 +0,9 @@ | ||
"use strict"; | ||
// Copyright (C) 2016 Dmitry Chestnykh | ||
// MIT License. See LICENSE file for details. | ||
Object.defineProperty(exports, "__esModule", { value: true }); | ||
var chacha_1 = require("./chacha"); | ||
var hex_1 = require("@stablelib/hex"); | ||
import { describe, expect, it } from 'vitest'; | ||
import { streamXOR, stream } from "./chacha"; | ||
import { encode, decode } from "@stablelib/hex"; | ||
function seq(len) { | ||
var x = new Uint8Array(len); | ||
for (var i = 0; i < len; i++) { | ||
const x = new Uint8Array(len); | ||
for (let i = 0; i < len; i++) { | ||
x[i] = i & 0xff; | ||
@@ -14,35 +13,35 @@ } | ||
} | ||
describe("chacha.streamXOR", function () { | ||
var key = seq(32); | ||
var nonce8 = seq(8); | ||
var nonce12 = seq(12); | ||
it("should decrypt what it encrypted (8-byte nonce, 17-byte input)", function () { | ||
var original = seq(17); | ||
var encrypted = new Uint8Array(original.length); | ||
var decrypted = new Uint8Array(original.length); | ||
chacha_1.streamXOR(key, nonce8, original, encrypted); | ||
describe("chacha.streamXOR", () => { | ||
const key = seq(32); | ||
const nonce8 = seq(8); | ||
const nonce12 = seq(12); | ||
it("should decrypt what it encrypted (8-byte nonce, 17-byte input)", () => { | ||
const original = seq(17); | ||
const encrypted = new Uint8Array(original.length); | ||
const decrypted = new Uint8Array(original.length); | ||
streamXOR(key, nonce8, original, encrypted); | ||
expect(encrypted).not.toEqual(original); | ||
chacha_1.streamXOR(key, nonce8, encrypted, decrypted); | ||
streamXOR(key, nonce8, encrypted, decrypted); | ||
expect(decrypted).toEqual(original); | ||
}); | ||
it("should decrypt what it encrypted (8-byte nonce, 155-byte input)", function () { | ||
var original = seq(155); | ||
var encrypted = new Uint8Array(original.length); | ||
var decrypted = new Uint8Array(original.length); | ||
chacha_1.streamXOR(key, nonce8, original, encrypted); | ||
it("should decrypt what it encrypted (8-byte nonce, 155-byte input)", () => { | ||
const original = seq(155); | ||
const encrypted = new Uint8Array(original.length); | ||
const decrypted = new Uint8Array(original.length); | ||
streamXOR(key, nonce8, original, encrypted); | ||
expect(encrypted).not.toEqual(original); | ||
chacha_1.streamXOR(key, nonce8, encrypted, decrypted); | ||
streamXOR(key, nonce8, encrypted, decrypted); | ||
expect(decrypted).toEqual(original); | ||
}); | ||
it("should decrypt what it encrypted (12-byte nonce, 155-byte input)", function () { | ||
var original = seq(155); | ||
var encrypted = new Uint8Array(original.length); | ||
var decrypted = new Uint8Array(original.length); | ||
chacha_1.streamXOR(key, nonce12, original, encrypted); | ||
it("should decrypt what it encrypted (12-byte nonce, 155-byte input)", () => { | ||
const original = seq(155); | ||
const encrypted = new Uint8Array(original.length); | ||
const decrypted = new Uint8Array(original.length); | ||
streamXOR(key, nonce12, original, encrypted); | ||
expect(encrypted).not.toEqual(original); | ||
chacha_1.streamXOR(key, nonce12, encrypted, decrypted); | ||
streamXOR(key, nonce12, encrypted, decrypted); | ||
expect(decrypted).toEqual(original); | ||
}); | ||
}); | ||
var vectors = [ | ||
const vectors = [ | ||
{ | ||
@@ -79,9 +78,9 @@ key: "0000000000000000000000000000000000000000000000000000000000000000", | ||
]; | ||
describe("chacha.stream", function () { | ||
it("should generate test vectors", function () { | ||
vectors.forEach(function (v) { | ||
var key = hex_1.decode(v.key); | ||
var nonce = hex_1.decode(v.nonce); | ||
var dst = chacha_1.stream(key, nonce, new Uint8Array(v.stream.length / 2)); | ||
expect(hex_1.encode(dst, true)).toBe(v.stream); | ||
describe("chacha.stream", () => { | ||
it("should generate test vectors", () => { | ||
vectors.forEach(v => { | ||
const key = decode(v.key); | ||
const nonce = decode(v.nonce); | ||
const dst = stream(key, nonce, new Uint8Array(v.stream.length / 2)); | ||
expect(encode(dst, true)).toBe(v.stream); | ||
}); | ||
@@ -88,0 +87,0 @@ }); |
{ | ||
"name": "@stablelib/chacha", | ||
"version": "1.0.1", | ||
"version": "2.0.0", | ||
"description": "ChaCha stream cipher", | ||
"main": "./lib/chacha.js", | ||
"type": "module", | ||
"typings": "./lib/chacha.d.ts", | ||
@@ -18,14 +19,14 @@ "author": "Dmitry Chestnykh", | ||
"build": "tsc", | ||
"test": "jasmine JASMINE_CONFIG_PATH=../../configs/jasmine.json", | ||
"test": "vitest run", | ||
"bench": "node ./lib/chacha.bench.js" | ||
}, | ||
"dependencies": { | ||
"@stablelib/binary": "^1.0.1", | ||
"@stablelib/wipe": "^1.0.1" | ||
"@stablelib/binary": "^2.0.0", | ||
"@stablelib/wipe": "^2.0.0" | ||
}, | ||
"devDependencies": { | ||
"@stablelib/benchmark": "^1.0.1", | ||
"@stablelib/hex": "^1.0.1" | ||
"@stablelib/benchmark": "^2.0.0", | ||
"@stablelib/hex": "^2.0.0" | ||
}, | ||
"gitHead": "03dadf27703120d54e6be8436525228ee1c4299b" | ||
"gitHead": "ecfe9109b3c05419fd3ffc16da6c8255b08ad64f" | ||
} |
{ | ||
"extends": "../../configs/tsconfig.json", | ||
"compilerOptions": { | ||
"target": "es5", | ||
"module": "commonjs", | ||
"strict": true, | ||
"noUnusedParameters": true, | ||
"noImplicitReturns": true, | ||
"noUnusedLocals": true, | ||
"removeComments": false, | ||
"preserveConstEnums": true, | ||
"moduleResolution": "node", | ||
"newLine": "LF", | ||
"sourceMap": true, | ||
"declaration": true, | ||
"outDir": "lib", | ||
"lib": [ | ||
"es5", | ||
"es2015.promise", | ||
"dom", | ||
"scripthost" | ||
] | ||
}, | ||
@@ -23,0 +6,0 @@ "exclude": [ |
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
16
6.67%Yes
NaN46905
-1.73%704
-2.9%+ Added
+ Added
+ Added
- Removed
- Removed
- Removed
Updated
Updated