TS 实现SM4加密 ECB模式
SM4Util.ts
//需要引入 js-base64 包 npm install js-base64
import { fromUint8Array, toUint8Array } from 'js-base64';
interface SM4Context {
mode: number;
isPadding: boolean;
sk: any;
}
export class SM4_Context implements SM4Context {
mode: number;
isPadding: boolean;
sk: any;
constructor(
mode: number = 1,
isPadding: boolean = true,
sk: any = new Array(32),
) {
this.mode = mode;
this.isPadding = isPadding;
this.sk = sk;
}
}
/*
* 国密SM4加密算法
* @date 2020-07-14
*/
var SboxTable = [
0xd6, 0x90, 0xe9, 0xfe, 0xcc, 0xe1, 0x3d, 0xb7, 0x16, 0xb6, 0x14, 0xc2, 0x28,
0xfb, 0x2c, 0x05, 0x2b, 0x67, 0x9a, 0x76, 0x2a, 0xbe, 0x04, 0xc3, 0xaa, 0x44,
0x13, 0x26, 0x49, 0x86, 0x06, 0x99, 0x9c, 0x42, 0x50, 0xf4, 0x91, 0xef, 0x98,
0x7a, 0x33, 0x54, 0x0b, 0x43, 0xed, 0xcf, 0xac, 0x62, 0xe4, 0xb3, 0x1c, 0xa9,
0xc9, 0x08, 0xe8, 0x95, 0x80, 0xdf, 0x94, 0xfa, 0x75, 0x8f, 0x3f, 0xa6, 0x47,
0x07, 0xa7, 0xfc, 0xf3, 0x73, 0x17, 0xba, 0x83, 0x59, 0x3c, 0x19, 0xe6, 0x85,
0x4f, 0xa8, 0x68, 0x6b, 0x81, 0xb2, 0x71, 0x64, 0xda, 0x8b, 0xf8, 0xeb, 0x0f,
0x4b, 0x70, 0x56, 0x9d, 0x35, 0x1e, 0x24, 0x0e, 0x5e, 0x63, 0x58, 0xd1, 0xa2,
0x25, 0x22, 0x7c, 0x3b, 0x01, 0x21, 0x78, 0x87, 0xd4, 0x00, 0x46, 0x57, 0x9f,
0xd3, 0x27, 0x52, 0x4c, 0x36, 0x02, 0xe7, 0xa0, 0xc4, 0xc8, 0x9e, 0xea, 0xbf,
0x8a, 0xd2, 0x40, 0xc7, 0x38, 0xb5, 0xa3, 0xf7, 0xf2, 0xce, 0xf9, 0x61, 0x15,
0xa1, 0xe0, 0xae, 0x5d, 0xa4, 0x9b, 0x34, 0x1a, 0x55, 0xad, 0x93, 0x32, 0x30,
0xf5, 0x8c, 0xb1, 0xe3, 0x1d, 0xf6, 0xe2, 0x2e, 0x82, 0x66, 0xca, 0x60, 0xc0,
0x29, 0x23, 0xab, 0x0d, 0x53, 0x4e, 0x6f, 0xd5, 0xdb, 0x37, 0x45, 0xde, 0xfd,
0x8e, 0x2f, 0x03, 0xff, 0x6a, 0x72, 0x6d, 0x6c, 0x5b, 0x51, 0x8d, 0x1b, 0xaf,
0x92, 0xbb, 0xdd, 0xbc, 0x7f, 0x11, 0xd9, 0x5c, 0x41, 0x1f, 0x10, 0x5a, 0xd8,
0x0a, 0xc1, 0x31, 0x88, 0xa5, 0xcd, 0x7b, 0xbd, 0x2d, 0x74, 0xd0, 0x12, 0xb8,
0xe5, 0xb4, 0xb0, 0x89, 0x69, 0x97, 0x4a, 0x0c, 0x96, 0x77, 0x7e, 0x65, 0xb9,
0xf1, 0x09, 0xc5, 0x6e, 0xc6, 0x84, 0x18, 0xf0, 0x7d, 0xec, 0x3a, 0xdc, 0x4d,
0x20, 0x79, 0xee, 0x5f, 0x3e, 0xd7, 0xcb, 0x39, 0x48,
];
var FK = [0xa3b1bac6, 0x56aa3350, 0x677d9197, 0xb27022dc];
var CK = [
0x00070e15, 0x1c232a31, 0x383f464d, 0x545b6269, 0x70777e85, 0x8c939aa1,
0xa8afb6bd, 0xc4cbd2d9, 0xe0e7eef5, 0xfc030a11, 0x181f262d, 0x343b4249,
0x50575e65, 0x6c737a81, 0x888f969d, 0xa4abb2b9, 0xc0c7ced5, 0xdce3eaf1,
0xf8ff060d, 0x141b2229, 0x30373e45, 0x4c535a61, 0x686f767d, 0x848b9299,
0xa0a7aeb5, 0xbcc3cad1, 0xd8dfe6ed, 0xf4fb0209, 0x10171e25, 0x2c333a41,
0x484f565d, 0x646b7279,
];
const GET_ULONG_BE = function (b: any, i: number) {
return (
((b[i] & 0xff) << 24) |
((b[i 1] & 0xff) << 16) |
((b[i 2] & 0xff) << 8) |
(b[i 3] & 0xff & 0xffffffff)
);
};
const PUT_ULONG_BE = function (n: any, b: any, i: number) {
var t1 = 0xff & (n >> 24);
var t2 = 0xff & (n >> 16);
var t3 = 0xff & (n >> 8);
var t4 = 0xff & n;
b[i] = t1 > 128 ? t1 - 256 : t1;
b[i 1] = t2 > 128 ? t2 - 256 : t2;
b[i 2] = t3 > 128 ? t3 - 256 : t3;
b[i 3] = t4 > 128 ? t4 - 256 : t4;
};
const SHL = function (x: any, n: any) {
return (x & 0xffffffff) << n;
};
const ROTL = function (x: any, n: any) {
var s = SHL(x, n);
var ss = x >> (32 - n);
return SHL(x, n) | (x >> (32 - n));
};
const sm4Lt = function (ka: any) {
var bb = 0;
var c = 0;
var a = new Array(4);
var b = new Array(4);
PUT_ULONG_BE(ka, a, 0);
b[0] = sm4Sbox(a[0]);
b[1] = sm4Sbox(a[1]);
b[2] = sm4Sbox(a[2]);
b[3] = sm4Sbox(a[3]);
bb = GET_ULONG_BE(b, 0);
c = bb ^ ROTL(bb, 2) ^ ROTL(bb, 10) ^ ROTL(bb, 18) ^ ROTL(bb, 24);
return c;
};
const sm4F = function (x0: any, x1: any, x2: any, x3: any, rk: any) {
return x0 ^ sm4Lt(x1 ^ x2 ^ x3 ^ rk);
};
const sm4CalciRK = function (ka: any) {
var bb = 0;
var rk = 0;
var a = new Array(4);
var b = new Array(4);
PUT_ULONG_BE(ka, a, 0);
b[0] = sm4Sbox(a[0]);
b[1] = sm4Sbox(a[1]);
b[2] = sm4Sbox(a[2]);
b[3] = sm4Sbox(a[3]);
bb = GET_ULONG_BE(b, 0);
rk = bb ^ ROTL(bb, 13) ^ ROTL(bb, 23);
return rk;
};
const sm4Sbox = function (inch: any) {
var i = inch & 0xff;
var retVal = SboxTable[i];
return retVal > 128 ? retVal - 256 : retVal;
};
const sm4_setkey_enc = function (ctx: any, key: any) {
if (ctx == null) {
alert('ctx is null!');
return false;
}
if (key == null || key.length < 16) {
alert('key error!');
return false;
}
ctx.mode = 1;
sm4_setkey(ctx.sk, key);
};
//生成解密密钥
const sm4_setkey_dec = function (ctx: any, key: any) {
if (ctx == null) {
Error('ctx is null!');
}
if (key == null || key.length != 16) {
Error('key error!');
}
var i = 0;
ctx.mode = 0;
sm4_setkey(ctx.sk, key);
ctx.sk = ctx.sk.reverse();
};
const sm4_setkey = function (SK: any, key: any) {
var MK = new Array(4);
var k = new Array(36);
// var i = 0;
MK[0] = GET_ULONG_BE(key, 0);
MK[1] = GET_ULONG_BE(key, 4);
MK[2] = GET_ULONG_BE(key, 8);
MK[3] = GET_ULONG_BE(key, 12);
k[0] = MK[0] ^ FK[0];
k[1] = MK[1] ^ FK[1];
k[2] = MK[2] ^ FK[2];
k[3] = MK[3] ^ FK[3];
for (var i = 0; i < 32; i ) {
k[i 4] = k[i] ^ sm4CalciRK(k[i 1] ^ k[i 2] ^ k[i 3] ^ CK[i]);
SK[i] = k[i 4];
}
};
const padding = function (input: any, mode: any) {
if (input == null) {
return null;
}
var ret = null;
if (mode == 1) {
let p = parseInt((16 - (input.length % 16)).toString());
ret = input.slice(0);
for (var i = 0; i < p; i ) {
ret[input.length i] = p;
}
} else {
let p = input[input.length - 1];
ret = input.slice(0, input.length - p);
}
return ret;
};
const sm4_one_round = function (sk: any, input: any, output: any) {
var i = 0;
var ulbuf = new Array(36);
ulbuf[0] = GET_ULONG_BE(input, 0);
ulbuf[1] = GET_ULONG_BE(input, 4);
ulbuf[2] = GET_ULONG_BE(input, 8);
ulbuf[3] = GET_ULONG_BE(input, 12);
while (i < 32) {
ulbuf[i 4] = sm4F(
ulbuf[i],
ulbuf[i 1],
ulbuf[i 2],
ulbuf[i 3],
sk[i],
);
i ;
}
PUT_ULONG_BE(ulbuf[35], output, 0);
PUT_ULONG_BE(ulbuf[34], output, 4);
PUT_ULONG_BE(ulbuf[33], output, 8);
PUT_ULONG_BE(ulbuf[32], output, 12);
};
//ECB处理
const sm4_crypt_ecb = function (ctx: any, input: any) {
if (input == null) {
alert('input is null!');
}
if (ctx.isPadding && ctx.mode == 1) {
input = padding(input, 1);
}
var i = 0;
var length = input.length;
var bous = new Array();
for (; length > 0; length -= 16) {
var out = new Array(16);
var ins = input.slice(i * 16, 16 * (i 1));
sm4_one_round(ctx.sk, ins, out);
bous = bous.concat(out);
i ;
}
var output = bous;
if (ctx.isPadding && ctx.mode == 0) {
output = padding(output, 0);
}
for (var ki = 0; ki < output.length; ki ) {
if (output[ki] < 0) {
output[ki] = output[ki] 256;
}
}
return output;
};
//cbc处理
const sm4_crypt_cbc = function (ctx: any, iv: any, input: any) {
if (iv == null || iv.length != 16) {
alert('iv error!');
}
if (input == null) {
alert('input is null!');
}
if (ctx.isPadding && ctx.mode == 1) {
input = padding(input, 1);
}
// var i = 0;
var length = input.length;
var bous = new Array();
if (ctx.mode == 1) {
let k = 0;
for (; length > 0; length -= 16) {
let out = new Array(16);
let out1 = new Array(16);
let ins = input.slice(k * 16, 16 * (k 1));
for (let i = 0; i < 16; i ) {
out[i] = ins[i] ^ iv[i];
}
sm4_one_round(ctx.sk, out, out1);
iv = out1.slice(0, 16);
bous = bous.concat(out1);
k ;
}
} else {
var temp = [];
let k = 0;
for (; length > 0; length -= 16) {
let out = new Array(16);
let out1 = new Array(16);
let ins = input.slice(k * 16, 16 * (k 1));
temp = ins.slice(0, 16);
sm4_one_round(ctx.sk, ins, out);
for (let i = 0; i < 16; i ) {
out1[i] = out[i] ^ iv[i];
}
iv = temp.slice(0, 16);
bous = bous.concat(out1);
k ;
}
}
var output = bous;
if (ctx.isPadding && ctx.mode == 0) {
output = padding(output, 0);
}
for (var i = 0; i < output.length; i ) {
if (output[i] < 0) {
output[i] = output[i] 256;
}
}
return output;
};
//加密_ECB
const encryptData_ECB = function (plainText: any, secretKey: string) {
try {
var ctx = new SM4_Context(1, true);
var keyBytes = stringToByte(secretKey);
sm4_setkey_enc(ctx, keyBytes);
var encrypted = sm4_crypt_ecb(ctx, stringToByte(plainText));
var cipherText = fromUint8Array(new Uint8Array(encrypted));
// var cipherText = Buffer.from(encrypted).toString('base64');
if (cipherText != null && cipherText.trim().length > 0) {
cipherText.replace(/(\s*|\t|\r|\n)/g, '');
}
return cipherText;
} catch (e) {
// console.error(e);
return null;
}
};
//解密_ECB
const decryptData_ECB = function (cipherText: any, secretKey: string) {
try {
var ctx = new SM4_Context();
ctx.isPadding = true;
ctx.mode = 0;
var keyBytes = stringToByte(secretKey);
sm4_setkey_dec(ctx, keyBytes);
var decrypted = sm4_crypt_ecb(ctx, toUint8Array(cipherText));
return byteToString(decrypted);
} catch (e) {
// console.error(e);
return null;
}
};
//将string转Byte
const stringToByte = function (str: any) {
var bytes = new Array();
var len, c;
len = str.length;
for (var i = 0; i < len; i ) {
c = str.charCodeAt(i);
if (c >= 0x010000 && c <= 0x10ffff) {
bytes.push(((c >> 18) & 0x07) | 0xf0);
bytes.push(((c >> 12) & 0x3f) | 0x80);
bytes.push(((c >> 6) & 0x3f) | 0x80);
bytes.push((c & 0x3f) | 0x80);
} else if (c >= 0x000800 && c <= 0x00ffff) {
bytes.push(((c >> 12) & 0x0f) | 0xe0);
bytes.push(((c >> 6) & 0x3f) | 0x80);
bytes.push((c & 0x3f) | 0x80);
} else if (c >= 0x000080 && c <= 0x0007ff) {
bytes.push(((c >> 6) & 0x1f) | 0xc0);
bytes.push((c & 0x3f) | 0x80);
} else {
bytes.push(c & 0xff);
}
}
return bytes;
};
//Byte转string
const byteToString = function (arr: any) {
if (typeof arr === 'string') {
return arr;
}
var str = '',
_arr = arr;
for (var i = 0; i < _arr.length; i ) {
var one = _arr[i].toString(2),
v = one.match(/^1 ?(?=0)/);
if (v && one.length == 8) {
var bytesLength = v[0].length;
var store = _arr[i].toString(2).slice(7 - bytesLength);
for (var st = 1; st < bytesLength; st ) {
store = _arr[st i].toString(2).slice(2);
}
str = String.fromCharCode(parseInt(store, 2));
i = bytesLength - 1;
} else {
str = String.fromCharCode(_arr[i]);
}
}
return str;
};
export { encryptData_ECB, decryptData_ECB };
这篇好文章是转载于:学新通技术网
- 版权申明: 本站部分内容来自互联网,仅供学习及演示用,请勿用于商业和其他非法用途。如果侵犯了您的权益请与我们联系,请提供相关证据及您的身份证明,我们将在收到邮件后48小时内删除。
- 本站站名: 学新通技术网
- 本文地址: /boutique/detail/tanhcihfaj
系列文章
更多
同类精品
更多
-
photoshop保存的图片太大微信发不了怎么办
PHP中文网 06-15 -
《学习通》视频自动暂停处理方法
HelloWorld317 07-05 -
word里面弄一个表格后上面的标题会跑到下面怎么办
PHP中文网 06-20 -
Android 11 保存文件到外部存储,并分享文件
Luke 10-12 -
photoshop扩展功能面板显示灰色怎么办
PHP中文网 06-14 -
微信公众号没有声音提示怎么办
PHP中文网 03-31 -
excel下划线不显示怎么办
PHP中文网 06-23 -
excel打印预览压线压字怎么办
PHP中文网 06-22 -
TikTok加速器哪个好免费的TK加速器推荐
TK小达人 10-01 -
怎样阻止微信小程序自动打开
PHP中文网 06-13