UNPKG

mima-kit

Version:

mima-kit is a cryptographic suite implemented in TypeScript. The goal is to provide an easy-to-use cryptographic library. mima-kit 是一个使用 TypeScript 实现的密码学套件。目标是提供一个简单易用的密码学库。

193 lines (192 loc) 6.55 kB
import { PKCS7_PAD, createCipher } from '../../core/cipher'; import { KitError, U8 } from '../../core/utils'; // * Constants const DELTA = 0x9E3779B9; // * Tiny Encryption Algorithm (TEA) function _tea(K, round) { if (K.length !== 16) { throw new KitError('TEA key must be 16 byte'); } const K32 = new Uint32Array(K.buffer); const sum_delta = (DELTA * round) & 0xFFFFFFFF; const encrypt = (M) => { if (M.length !== 8) { throw new KitError('TEA block must be 8 byte'); } const C = U8.from(M.slice(0)); const C32 = new Uint32Array(C.buffer); let sum = 0; for (let i = 0; i < round; i++) { sum += DELTA; C32[0] += ((C32[1] << 4) + K32[0]) ^ (C32[1] + sum) ^ ((C32[1] >>> 5) + K32[1]); C32[1] += ((C32[0] << 4) + K32[2]) ^ (C32[0] + sum) ^ ((C32[0] >>> 5) + K32[3]); } return C; }; const decrypt = (C) => { if (C.length !== 8) { throw new KitError('TEA block must be 8 byte'); } const M = U8.from(C.slice(0)); const M32 = new Uint32Array(M.buffer); let sum = sum_delta; for (let i = 0; i < round; i++) { M32[1] -= ((M32[0] << 4) + K32[2]) ^ (M32[0] + sum) ^ ((M32[0] >>> 5) + K32[3]); M32[0] -= ((M32[1] << 4) + K32[0]) ^ (M32[1] + sum) ^ ((M32[1] >>> 5) + K32[1]); sum -= DELTA; } return M; }; return { encrypt, decrypt }; } function _xtea(K, round) { if (K.length !== 16) { throw new KitError('XTEA key must be 16 byte'); } const K32 = new Uint32Array(K.buffer); const sum_delta = (DELTA * round) & 0xFFFFFFFF; const encrypt = (M) => { if (M.length !== 8) { throw new KitError('XTEA block must be 8 byte'); } const C = U8.from(M.slice(0)); const C32 = new Uint32Array(C.buffer); let sum = 0; for (let i = 0; i < round; i++) { C32[0] += (C32[1] << 4 ^ C32[1] >>> 5) + C32[1] ^ sum + K32[sum & 3]; sum += DELTA; C32[1] += (C32[0] << 4 ^ C32[0] >>> 5) + C32[0] ^ sum + K32[(sum >>> 11) & 3]; } return C; }; const decrypt = (C) => { if (C.length !== 8) { throw new KitError('XTEA block must be 8 byte'); } const M = U8.from(C.slice(0)); const M32 = new Uint32Array(M.buffer); let sum = sum_delta; for (let i = 0; i < round; i++) { M32[1] -= ((M32[0] << 4 ^ M32[0] >>> 5) + M32[0]) ^ (sum + K32[(sum >>> 11) & 3]); sum -= DELTA; M32[0] -= ((M32[1] << 4 ^ M32[1] >>> 5) + M32[1]) ^ (sum + K32[sum & 3]); } return M; }; return { encrypt, decrypt }; } function _xxtea(K, padding, round) { if (K.length !== 16) { throw new KitError('XTEA key must be 16 byte'); } const K32 = new Uint32Array(K.buffer); const encrypt = (M) => { const C = U8.from(padding(M, 4)); if (C.length < 8 || C.length % 4 !== 0) { throw new KitError('XXTEA block must be a multiple of 4 byte (at least 8 byte)'); } const C32 = new Uint32Array(C.buffer); const n = C32.length; let _round = round || (6 + 52 / n) >>> 0; let sum = 0; let y; let z = C32[n - 1]; let p; while (_round-- > 0) { sum += DELTA; const e = (sum >>> 2) & 3; for (p = 0; p < n - 1; p++) { y = C32[p + 1]; z = C32[p] += (((z >>> 5 ^ y << 2) + (y >>> 3 ^ z << 4)) ^ ((sum ^ y) + (K32[(p & 3) ^ e] ^ z))); } y = C32[0]; z = C32[n - 1] += (((z >>> 5 ^ y << 2) + (y >>> 3 ^ z << 4)) ^ ((sum ^ y) + (K32[(p & 3) ^ e] ^ z))); } return C; }; const decrypt = (C) => { if (C.length % 4 !== 0) { throw new KitError('Decryption error'); } const M = U8.from(C.slice(0)); const M32 = new Uint32Array(M.buffer); const n = M32.length; let _round = round || (6 + 52 / n) >>> 0; let sum = (DELTA * _round) & 0xFFFFFFFF; let y = M32[0]; let z; let p; while (_round-- > 0) { const e = (sum >>> 2) & 3; for (p = n - 1; p > 0; p--) { z = M32[p - 1]; y = M32[p] -= (((z >>> 5 ^ y << 2) + (y >>> 3 ^ z << 4)) ^ ((sum ^ y) + (K32[(p & 3) ^ e] ^ z))); } z = M32[n - 1]; y = M32[0] -= (((z >>> 5 ^ y << 2) + (y >>> 3 ^ z << 4)) ^ ((sum ^ y) + (K32[(p & 3) ^ e] ^ z))); sum -= DELTA; } return padding(M); }; return { encrypt, decrypt }; } /** * 微型加密算法 (TEA) 分组密码算法 * * Tiny Encryption Algorithm (TEA) block cipher algorithm * * @param {number} round - 轮数 / Rounds (default: 32) */ export function tea(round = 32) { if (round <= 0) { throw new KitError('TEA round must be a positive number'); } return createCipher((K) => _tea(K, round), { ALGORITHM: 'TEA', BLOCK_SIZE: 8, KEY_SIZE: 16, MIN_KEY_SIZE: 16, MAX_KEY_SIZE: 16, }); } /** * 扩展微型加密算法 (XTEA) 分组密码算法 * * eXtended Tiny Encryption Algorithm (XTEA) block cipher algorithm * * @param {number} round - 轮数 / Rounds (default: 32) */ export function xtea(round = 32) { if (round <= 0) { throw new KitError('XTEA round must be a positive number'); } return createCipher((K) => _xtea(K, round), { ALGORITHM: 'XTEA', BLOCK_SIZE: 8, KEY_SIZE: 16, MIN_KEY_SIZE: 16, MAX_KEY_SIZE: 16, }); } /** * 纠正块 TEA (XXTEA) 分组密码算法 * * Corrected Block TEA (XXTEA) block cipher algorithm * * @param {Padding} [config.padding] - 填充方式 / Padding method (default: PKCS7) * @param {number} [config.round] - 轮数 / Rounds (default: undefined) * @param {number} [config.BLOCK_SIZE] - 分组大小 / Block size (default: 16) */ export function xxtea(config) { const { BLOCK_SIZE = 16, padding = PKCS7_PAD, round, } = config ?? {}; if (BLOCK_SIZE < 8 || BLOCK_SIZE % 4 !== 0) { throw new KitError('XXTEA block size must be a multiple of 4 byte (at least 8 byte)'); } return createCipher((K) => _xxtea(K, padding, round), { ALGORITHM: 'XXTEA', BLOCK_SIZE, KEY_SIZE: 16, MIN_KEY_SIZE: 16, MAX_KEY_SIZE: 16, }); }