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 实现的密码学套件。目标是提供一个简单易用的密码学库。
189 lines (188 loc) • 6.61 kB
JavaScript
import { createCipher, PKCS7_PAD } 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, K.byteOffset, K.byteLength >> 2);
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);
const C32 = new Uint32Array(C.buffer, C.byteOffset, C.byteLength >> 2);
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);
const M32 = new Uint32Array(M.buffer, M.byteOffset, M.byteLength >> 2);
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, K.byteOffset, K.byteLength >> 2);
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);
const C32 = new Uint32Array(C.buffer, C.byteOffset, C.byteLength >> 2);
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);
const M32 = new Uint32Array(M.buffer, M.byteOffset, M.byteLength >> 2);
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('XXTEA key must be 16 byte');
}
const K32 = new Uint32Array(K.buffer, K.byteOffset, K.byteLength >> 2);
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, C.byteOffset, C.byteLength >> 2);
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);
const M32 = new Uint32Array(M.buffer, M.byteOffset, M.byteLength >> 2);
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
*/
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,
});
}