js-speck
v0.1.0
Published
SPECK block cipher implementation for JavaScript and TypeScript.
Maintainers
Readme
js-speck
SPECK block cipher implementation for JavaScript and TypeScript.
The first release focuses on byte-oriented core APIs for:
- Speck32/64: 32-bit block size, 64-bit key size, 22 rounds
- Speck48/72: 48-bit block size, 72-bit key size, 22 rounds
- Speck48/96: 48-bit block size, 96-bit key size, 23 rounds
- Speck64/96: 64-bit block size, 96-bit key size, 26 rounds
- Speck64/128: 64-bit block size, 128-bit key size, 27 rounds
- Speck96/96: 96-bit block size, 96-bit key size, 28 rounds
- Speck96/144: 96-bit block size, 144-bit key size, 29 rounds
- Speck128/128: 128-bit block size, 128-bit key size, 32 rounds
- Speck128/192: 128-bit block size, 192-bit key size, 33 rounds
- Speck128/256: 128-bit block size, 256-bit key size, 34 rounds
- byte-array encryption and decryption for complete blocks
This package works with byte data only. It does not encode or decode UTF-8, hex, or Base64 for you. Modes and padding are intentionally not part of the core API.
Install
npm install js-speckUsage
import {
speck32_64,
speck48_72,
speck48_96,
speck64_96,
speck64_128,
speck96_96,
speck96_144,
speck128_128,
speck128_192,
speck128_256
} from 'js-speck';
const key = new Uint8Array(16);
const data = new Uint8Array(16);
const encrypted = speck64_128.encrypt(key, data);
const decrypted = speck64_128.decrypt(key, encrypted);The core API does not pad input. data.length must be a multiple of the
selected variant's block size.
When typed arrays are unavailable, the core API falls back to plain number
arrays.
ES Modules
import { speck64_128 } from 'js-speck';
const encrypted = speck64_128.encrypt(key, data);
const decrypted = speck64_128.decrypt(key, encrypted);CommonJS
const { speck64_128 } = require('js-speck');
const encrypted = speck64_128.encrypt(key, data);
const decrypted = speck64_128.decrypt(key, encrypted);TypeScript
import { speck64_128, ByteInput, ByteArray } from 'js-speck';
const key: ByteInput = new Uint8Array(16);
const data: ByteInput = new Uint8Array(8);
const encrypted: ByteArray = speck64_128.encrypt(key, data);Browser Script
Use the IIFE build when loading directly with a script tag.
<script src="./dist/speck.iife.min.js"></script>
<script>
const encrypted = jsSpeck.speck64_128.encrypt(key, data);
</script>Web Worker
The IIFE build also works with importScripts.
importScripts('./dist/speck.iife.min.js');
const encrypted = jsSpeck.speck64_128.encrypt(key, data);RequireJS
Use the UMD build for AMD loaders.
require(['./dist/speck.umd.min'], function (jsSpeck) {
const encrypted = jsSpeck.speck64_128.encrypt(key, data);
});Bundlers
Bundlers should use the package entry point.
import { speck64_128 } from 'js-speck';CryptoJS Adapter
The optional CryptoJS adapter registers the SPECK variants whose block size can be represented as whole CryptoJS 32-bit words:
CryptoJS.Speck32_64CryptoJS.Speck64_96CryptoJS.Speck64_128CryptoJS.Speck96_96CryptoJS.Speck96_144CryptoJS.Speck128_128CryptoJS.Speck128_192CryptoJS.Speck128_256
Speck48/72 and Speck48/96 are not registered because CryptoJS block ciphers use
a 32-bit-word blockSize, and a 48-bit block is 1.5 CryptoJS words. CryptoJS is
responsible for modes, padding, and formatters for the registered variants.
ES modules:
import CryptoJS from 'crypto-js';
import { registerSpeck } from 'js-speck/crypto-js';
registerSpeck(CryptoJS);
const key = CryptoJS.enc.Hex.parse('0001020308090a0b1011121318191a1b');
const iv = CryptoJS.enc.Hex.parse('0000000000000000');
const message = CryptoJS.enc.Utf8.parse('message');
const encrypted = CryptoJS.Speck64_128.encrypt(message, key, {
iv,
mode: CryptoJS.mode.CTR,
padding: CryptoJS.pad.NoPadding
});CommonJS:
const CryptoJS = require('crypto-js');
const { registerSpeck } = require('js-speck/crypto-js');
registerSpeck(CryptoJS);API
type ByteInput = ArrayBuffer | Uint8Array | readonly number[];
type ByteArray = Uint8Array | number[];
type WordArray = Uint32Array | number[];
speck32_64.encrypt(key: ByteInput, data: ByteInput): ByteArray;
speck32_64.decrypt(key: ByteInput, data: ByteInput): ByteArray;
speck32_64.expandKey(keyWords: WordArray): WordArray;
speck32_64.encryptWords(keyWords: WordArray, dataWords: WordArray): WordArray;
speck32_64.decryptWords(keyWords: WordArray, dataWords: WordArray): WordArray;
speck32_64.encryptWordsWithRoundKey(roundKeys: WordArray, dataWords: WordArray): WordArray;
speck32_64.decryptWordsWithRoundKey(roundKeys: WordArray, dataWords: WordArray): WordArray;
speck48_72.encrypt(key: ByteInput, data: ByteInput): ByteArray;
speck48_72.decrypt(key: ByteInput, data: ByteInput): ByteArray;
speck48_96.encrypt(key: ByteInput, data: ByteInput): ByteArray;
speck48_96.decrypt(key: ByteInput, data: ByteInput): ByteArray;
speck64_96.encrypt(key: ByteInput, data: ByteInput): ByteArray;
speck64_96.decrypt(key: ByteInput, data: ByteInput): ByteArray;
speck64_128.encrypt(key: ByteInput, data: ByteInput): ByteArray;
speck64_128.decrypt(key: ByteInput, data: ByteInput): ByteArray;
speck96_96.encrypt(key: ByteInput, data: ByteInput): ByteArray;
speck96_96.decrypt(key: ByteInput, data: ByteInput): ByteArray;
speck96_144.encrypt(key: ByteInput, data: ByteInput): ByteArray;
speck96_144.decrypt(key: ByteInput, data: ByteInput): ByteArray;
speck128_128.encrypt(key: ByteInput, data: ByteInput): ByteArray;
speck128_128.decrypt(key: ByteInput, data: ByteInput): ByteArray;
speck128_192.encrypt(key: ByteInput, data: ByteInput): ByteArray;
speck128_192.decrypt(key: ByteInput, data: ByteInput): ByteArray;
speck128_256.encrypt(key: ByteInput, data: ByteInput): ByteArray;
speck128_256.decrypt(key: ByteInput, data: ByteInput): ByteArray;
// Each variant exposes the same word-level helpers as Speck32/64.
registerSpeck(CryptoJS: object): object;Byte Order
The core byte API accepts and returns bytes. Internally, keys, plaintext blocks, and ciphertext blocks are interpreted as little-endian words. Speck32/64 uses 16-bit words, Speck48 variants use 24-bit words, Speck64 variants use 32-bit words, Speck96 variants use 48-bit words, and Speck128 variants use 64-bit words.
For word-level helpers, Speck96 and Speck128 variants represent each cipher word as two 32-bit lanes in little-endian order: low 32 bits first, then high 16 or 32 bits. Prefer the byte API unless an adapter needs direct block access.
The Speck32/64 reference vector used in the tests is:
key 0001080910111819
plaintext 4c697465
ciphertext f24268a8The Speck48/72 reference vector used in the tests is:
key 00010208090a101112
plaintext 72616c6c7920
ciphertext dc5a38a549c0The Speck48/96 reference vector used in the tests is:
key 00010208090a10111218191a
plaintext 74686973206d
ciphertext 5d44b6105e73The Speck64/96 reference vector used in the tests is:
key 0001020308090a0b10111213
plaintext 65616e7320466174
ciphertext 6c947541ec52799fThe Speck64/128 reference vector used in the tests is:
key 0001020308090a0b1011121318191a1b
plaintext 2d4375747465723b
ciphertext 8b024e4548a56f8cThe Speck96/96 reference vector used in the tests is:
key 00010203040508090a0b0c0d
plaintext 207468652070696c6c617220
ciphertext 12e785d8e391fa7308a70147The Speck96/144 reference vector used in the tests is:
key 00010203040508090a0b0c0d101112131415
plaintext 6f6620647573742074686174
ciphertext bcba8e3d3642895817109732The Speck128/128 reference vector used in the tests is:
key 000102030405060708090a0b0c0d0e0f
plaintext 206d616465206974206571756976616c
ciphertext 180d575cdffe60786532787951985da6The Speck128/192 reference vector used in the tests is:
key 000102030405060708090a0b0c0d0e0f1011121314151617
plaintext 656e7420746f20436869656620486172
ciphertext 86183ce05d18bcf9665513133acfe41bThe Speck128/256 reference vector used in the tests is:
key 000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f
plaintext 706f6f6e65722e20496e2074686f7365
ciphertext 438f189c8db4ee4e3ef5c00504010941In word notation, this corresponds to the commonly published vector:
key 1b1a1918 13121110 0b0a0908 03020100
plaintext 3b726574 7475432d
ciphertext 8c6fa548 454e028bSecurity Notes
SPECK is a lightweight block cipher family. Use a well-reviewed authenticated encryption scheme for new general-purpose applications whenever possible.
Modes such as CTR do not authenticate ciphertext. Never reuse the same key and counter stream for different messages.
License
MIT
