sm-crypto
国密算法sm2、sm3和sm4的js版。
PS: 小程序移植版:https://github.com/wechat-miniprogram/sm-crypto
PS: java 移植版(感谢 @antherd 提供):https://github.com/antherd/sm-crypto/
安装
npm install --save sm-crypto
sm2
获取密钥对
const sm2 = require('sm-crypto').sm2
let keypair = sm2.generateKeyPairHex()
publicKey = keypair.publicKey // 公钥
privateKey = keypair.privateKey // 私钥
// 默认生成公钥 130 位太长,可以压缩公钥到 66 位
const compressedPublicKey = sm2.compressPublicKeyHex(publicKey) // compressedPublicKey 和 publicKey 等价
sm2.comparePublicKeyHex(publicKey, compressedPublicKey) // 判断公钥是否等价
// 自定义随机数,参数会直接透传给 jsbn 库的 BigInteger 构造器
// 注意:开发者使用自定义随机数,需要自行确保传入的随机数符合密码学安全
let keypair2 = sm2.generateKeyPairHex('123123123123123')
let keypair3 = sm2.generateKeyPairHex(256, SecureRandom)
let verifyResult = sm2.verifyPublicKey(publicKey) // 验证公钥
verifyResult = sm2.verifyPublicKey(compressedPublicKey) // 验证公钥
加密解密
const sm2 = require('sm-crypto').sm2
const cipherMode = 1 // 1 - C1C3C2,0 - C1C2C3,默认为1
let encryptData = sm2.doEncrypt(msgString, publicKey, cipherMode) // 加密结果
let decryptData = sm2.doDecrypt(encryptData, privateKey, cipherMode) // 解密结果
encryptData = sm2.doEncrypt(msgArray, publicKey, cipherMode) // 加密结果,输入数组
decryptData = sm2.doDecrypt(encryptData, privateKey, cipherMode, {output: 'array'}) // 解密结果,输出数组
签名验签
ps:理论上来说,只做纯签名是最快的。
const sm2 = require('sm-crypto').sm2
// 纯签名 + 生成椭圆曲线点
let sigValueHex = sm2.doSignature(msg, privateKey) // 签名
let verifyResult = sm2.doVerifySignature(msg, sigValueHex, publicKey) // 验签结果
// 纯签名
let sigValueHex2 = sm2.doSignature(msg, privateKey, {
pointPool: [sm2.getPoint(), sm2.getPoint(), sm2.getPoint(), sm2.getPoint()], // 传入事先已生成好的椭圆曲线点,可加快签名速度
}) // 签名
let verifyResult2 = sm2.doVerifySignature(msg, sigValueHex2, publicKey) // 验签结果
// 纯签名 + 生成椭圆曲线点 + der编解码
let sigValueHex3 = sm2.doSignature(msg, privateKey, {
der: true,
}) // 签名
let verifyResult3 = sm2.doVerifySignature(msg, sigValueHex3, publicKey, {
der: true,
}) // 验签结果
// 纯签名 + 生成椭圆曲线点 + sm3杂凑
let sigValueHex4 = sm2.doSignature(msg, privateKey, {
hash: true,
}) // 签名
let verifyResult4 = sm2.doVerifySignature(msg, sigValueHex4, publicKey, {
hash: true,
}) // 验签结果
// 纯签名 + 生成椭圆曲线点 + sm3杂凑(不做公钥推导)
let sigValueHex5 = sm2.doSignature(msg, privateKey, {
hash: true,
publicKey, // 传入公钥的话,可以去掉sm3杂凑中推导公钥的过程,速度会比纯签名 + 生成椭圆曲线点 + sm3杂凑快
})
let verifyResult5 = sm2.doVerifySignature(msg, sigValueHex5, publicKey, {
hash: true,
publicKey,
})
// 纯签名 + 生成椭圆曲线点 + sm3杂凑 + 不做公钥推 + 添加 userId(长度小于 8192)
// 默认 userId 值为 1234567812345678
let sigValueHex6 = sm2.doSignature(msgString, privateKey, {
hash: true,
publicKey,
userId: 'testUserId',
})
let verifyResult6 = sm2.doVerifySignature(msgString, sigValueHex6, publicKey, {
hash: true,
userId: 'testUserId',
})
获取椭圆曲线点
const sm2 = require('sm-crypto').sm2
let point = sm2.getPoint() // 获取一个椭圆曲线点,可在sm2签名时传入
sm3
const sm3 = require('sm-crypto').sm3
let hashData = sm3('abc') // 杂凑
// hmac
hashData = sm3('abc', {
key: 'daac25c1512fe50f79b0e4526b93f5c0e1460cef40b6dd44af13caec62e8c60e0d885f3c6d6fb51e530889e6fd4ac743a6d332e68a0f2a3923f42585dceb93e9', // 要求为 16 进制串或字节数组
})
sm4
加密
const sm4 = require('sm-crypto').sm4
const msg = 'hello world! 我是 juneandgreen.' // 可以为 utf8 串或字节数组
const key = '0123456789abcdeffedcba9876543210' // 可以为 16 进制串或字节数组,要求为 128 比特
let encryptData = sm4.encrypt(msg, key) // 加密,默认输出 16 进制字符串,默认使用 pkcs#7 填充(传 pkcs#5 也会走 pkcs#7 填充)
let encryptData = sm4.encrypt(msg, key, {padding: 'none'}) // 加密,不使用 padding
let encryptData = sm4.encrypt(msg, key, {padding: 'none', output: 'array'}) // 加密,不使用 padding,输出为字节数组
let encryptData = sm4.encrypt(msg, key, {mode: 'cbc', iv: 'fedcba98765432100123456789abcdef'}) // 加密,cbc 模式
解密
const sm4 = require('sm-crypto').sm4
const encryptData = '0e395deb10f6e8a17e17823e1fd9bd98a1bff1df508b5b8a1efb79ec633d1bb129432ac1b74972dbe97bab04f024e89c' // 可以为 16 进制串或字节数组
const key = '0123456789abcdeffedcba9876543210' // 可以为 16 进制串或字节数组,要求为 128 比特
let decryptData = sm4.decrypt(encryptData, key) // 解密,默认输出 utf8 字符串,默认使用 pkcs#7 填充(传 pkcs#5 也会走 pkcs#7 填充)
let decryptData = sm4.decrypt(encryptData, key, {padding: 'none'}) // 解密,不使用 padding
let decryptData = sm4.decrypt(encryptData, key, {padding: 'none', output: 'array'}) // 解密,不使用 padding,输出为字节数组
let decryptData = sm4.decrypt(encryptData, key, {mode: 'cbc', iv: 'fedcba98765432100123456789
备注:
var base64js = require('base64-js')
const {sm2} = require("sm-crypto");
const UINT8_BLOCK = 16;
const Sbox = [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];
const 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 FK = [0xa3b1bac6, 0x56aa3350, 0x677d9197, 0xb27022dc];
/**
* 将字符串转为Unicode数组
* @example "1234" => [49, 50, 51, 52];
* @param {String} str 要转换的字符串
* @returns {Number[]} 转换后的数组
*/
const stringToArray = (str) => {
if (!/string/gi.test(Object.prototype.toString.call(str))) {
str = JSON.stringify(str);
}
return unescape(encodeURIComponent(str)).split("").map(val => val.charCodeAt());
}
const rotateLeft = (x, y) => {
return x << y | x >>> (32 - y);
}
const tauTransform = (a) => {
return Sbox[a >>> 24 & 0xff] << 24 | Sbox[a >>> 16 & 0xff] << 16 | Sbox[a >>> 8 & 0xff] << 8 | Sbox[a & 0xff];
}
const tTransform1 = (z) => {
let b = tauTransform(z);
let c = b ^ rotateLeft(b, 2) ^ rotateLeft(b, 10) ^ rotateLeft(b, 18) ^ rotateLeft(b, 24);
return c
}
const tTransform2 = (z) => {
let b = tauTransform(z);
let c = b ^ rotateLeft(b, 13) ^ rotateLeft(b, 23);
return c
}
const EncryptRoundKeys = (key) => {
const keys = [];
const mk = [key[0] << 24 | key[1] << 16 | key[2] << 8 | key[3], key[4] << 24 | key[5] << 16 | key[6] << 8 | key[7], key[8] << 24 | key[9] << 16 | key[10] << 8 | key[11], key[12] << 24 | key[13] << 16 | key[14] << 8 | key[15]];
let k = new Array(36);
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 (let i = 0; i < 32; i++) {
k[i + 4] = k[i] ^ tTransform2(k[i + 1] ^ k[i + 2] ^ k[i + 3] ^ CK[i]);
keys[i] = k[i + 4];
}
return keys;
}
const getChainBlock = (arr, baseIndex = 0) => {
let block = [arr[baseIndex] << 24 | arr[baseIndex + 1] << 16 | arr[baseIndex + 2] << 8 | arr[baseIndex + 3], arr[baseIndex + 4] << 24 | arr[baseIndex + 5] << 16 | arr[baseIndex + 6] << 8 | arr[baseIndex + 7], arr[baseIndex + 8] << 24 | arr[baseIndex + 9] << 16 | arr[baseIndex + 10] << 8 | arr[baseIndex + 11], arr[baseIndex + 12] << 24 | arr[baseIndex + 13] << 16 | arr[baseIndex + 14] << 8 | arr[baseIndex + 15]];
return block;
}
const doBlockCrypt = (blockData, roundKeys) => {
let xBlock = new Array(36);
blockData.forEach((val, index) => xBlock[index] = val);
// loop to process 32 rounds crypt
for (let i = 0; i < 32; i++) {
xBlock[i + 4] = xBlock[i] ^ tTransform1(xBlock[i + 1] ^ xBlock[i + 2] ^ xBlock[i + 3] ^ roundKeys[i]);
}
let yBlock = [xBlock[35], xBlock[34], xBlock[33], xBlock[32]];
return yBlock;
}
const padding = (originalBuffer) => {
if (originalBuffer === null) {
return null;
}
let paddingLength = UINT8_BLOCK - originalBuffer.length % UINT8_BLOCK;
let paddedBuffer = new Array(originalBuffer.length + paddingLength);
originalBuffer.forEach((val, index) => paddedBuffer[index] = val);
paddedBuffer.fill(paddingLength, originalBuffer.length);
return paddedBuffer;
}
const dePadding = (paddedBuffer) => {
if (paddedBuffer === null) {
return null;
}
let paddingLength = paddedBuffer[paddedBuffer.length - 1];
let originalBuffer = paddedBuffer.slice(0, paddedBuffer.length - paddingLength);
return originalBuffer;
}
const check = (name, str) => {
if (!str || str.length != 16) {
console.error(`${name} should be a 16 bytes string.`);
return false;
}
return true;
}
/**
* CBC加密模式
* @example encrypt_cbc("1234", "1234567890123456", "1234567890123456") => "K++iI4IhSGMnEJZT/jv1ow=="
* @param {any} plaintext 要加密的数据
* @param {String} key
* @param {String} iv
* @param {String} mode base64 | "text"
* @returns {String} 加密后的字符串
*/
const encrypt_cbc = (plaintext, key, iv, mode = "base64") => {
if (!check("iv", iv) && !check("key", key)) {
return;
}
let encryptRoundKeys = EncryptRoundKeys(stringToArray(key));
let plainByteArray = stringToArray(plaintext);
let padded = padding(plainByteArray);
let blockTimes = padded.length / UINT8_BLOCK;
let outArray = [];
// init chain with iv (transform to uint32 block)
let chainBlock = getChainBlock(stringToArray(iv));
// console.log(padded, blockTimes, encryptRoundKeys, chainBlock);
for (let i = 0; i < blockTimes; i++) {
// extract the 16 bytes block data for this round to encrypt
let roundIndex = i * UINT8_BLOCK;
let block = getChainBlock(padded, roundIndex);
// xor the chain block
chainBlock[0] = chainBlock[0] ^ block[0];
chainBlock[1] = chainBlock[1] ^ block[1];
chainBlock[2] = chainBlock[2] ^ block[2];
chainBlock[3] = chainBlock[3] ^ block[3];
// use chain block to crypt
let cipherBlock = doBlockCrypt(chainBlock, encryptRoundKeys);
// make the cipher block be part of next chain block
chainBlock = cipherBlock;
for (let l = 0; l < UINT8_BLOCK; l++) {
outArray[roundIndex + l] = cipherBlock[parseInt(l / 4)] >> ((3 - l) % 4 * 8) & 0xff;
}
}
// cipher array to string
if (mode === 'base64') {
return base64js.fromByteArray(outArray);
} else {
// text
return decodeURIComponent(escape(String.fromCharCode(...outArray)));
}
}
/**
* ECB加密模式
* @example encrypt_cbc("1234", "1234567890123456") => "woPrxebr8Xvyo1qG8QxAUA=="
* @param {any} plaintext 要加密的数据
* @param {String} key
* @param {String} iv
* @param {String} mode base64 | "text"
* @returns {String} 加密后的字符串
*/
const encrypt_ecb = (plaintext, key, mode = "base64") => {
if (!check("iv", iv)) {
return;
}
let encryptRoundKeys = EncryptRoundKeys(stringToArray(key));
let plainByteArray = stringToArray(plaintext);
let padded = padding(plainByteArray);
let blockTimes = padded.length / UINT8_BLOCK;
let outArray = [];
// CBC mode
// init chain with iv (transform to uint32 block)
for (let i = 0; i < blockTimes; i++) {
// extract the 16 bytes block data for this round to encrypt
let roundIndex = i * UINT8_BLOCK;
let block = getChainBlock(padded, roundIndex);
let cipherBlock = doBlockCrypt(block, encryptRoundKeys);
for (let l = 0; l < UINT8_BLOCK; l++) {
outArray[roundIndex + l] = cipherBlock[parseInt(l / 4)] >> ((3 - l) % 4 * 8) & 0xff;
}
}
// cipher array to string
if (mode === 'base64') {
return base64js.fromByteArray(outArray);
} else {
// text
return decodeURIComponent(escape(String.fromCharCode(...outArray)));
}
}
/**
* CBC解密模式
* @example decrypt_cbc("K++iI4IhSGMnEJZT/jv1ow==", "1234567890123456", "1234567890123456") => "1234"
* @param {any} plaintext 要解密的数据
* @param {String} key
* @param {String} iv
* @param {String} mode base64 | "text"
* @returns {String} 解密后的字符串
*/
const decrypt_cbc = (ciphertext, key, iv, mode = "base64") => {
if (!check("iv", iv) && !check("key", key)) {
return;
}
// get cipher byte array
let cipherByteArray = null;
let decryptRoundKeys = EncryptRoundKeys(stringToArray(key)).reverse();
if (mode === 'base64') {
// cipher is base64 string
cipherByteArray = base64js.toByteArray(ciphertext);
} else {
// cipher is text
cipherByteArray = stringToArray(ciphertext);
}
let blockTimes = cipherByteArray.length / UINT8_BLOCK;
let outArray = [];
// init chain with iv (transform to uint32 block)
let chainBlock = getChainBlock(stringToArray(iv));
// console.log(cipherByteArray, decryptRoundKeys, chainBlock)
for (let i = 0; i < blockTimes; i++) {
// extract the 16 bytes block data for this round to encrypt
let roundIndex = i * UINT8_BLOCK;
// make Uint8Array to Uint32Array block
let block = getChainBlock(cipherByteArray, roundIndex);
// reverse the round keys to decrypt
let plainBlockBeforeXor = doBlockCrypt(block, decryptRoundKeys);
// xor the chain block
let plainBlock = [chainBlock[0] ^ plainBlockBeforeXor[0], chainBlock[1] ^ plainBlockBeforeXor[1], chainBlock[2] ^ plainBlockBeforeXor[2], chainBlock[3] ^ plainBlockBeforeXor[3]];
// make the cipher block be part of next chain block
chainBlock = block;
for (let l = 0; l < UINT8_BLOCK; l++) {
outArray[roundIndex + l] = plainBlock[parseInt(l / 4)] >> ((3 - l) % 4 * 8) & 0xff;
}
}
// depadding the decrypted data
let depaddedPlaintext = dePadding(outArray);
// transform data to utf8 string
return decodeURIComponent(escape(String.fromCharCode(...depaddedPlaintext)));
}
/**
* ECB解密模式
* @example decrypt_ecb("woPrxebr8Xvyo1qG8QxAUA==", "1234567890123456") => "1234"
* @param {any} plaintext 要解密的数据
* @param {String} key
* @param {String} iv
* @param {String} mode base64 | "text"
* @returns {String} 解密后的字符串
*/
const decrypt_ecb = (ciphertext, key, mode = "base64") => {
if (!check("iv", iv)) {
return;
}
// get cipher byte array
let decryptRoundKeys = EncryptRoundKeys(stringToArray(key)).reverse();
let cipherByteArray = null;
if (mode === 'base64') {
// cipher is base64 string
cipherByteArray = base64js.toByteArray(ciphertext);
} else {
// cipher is text
cipherByteArray = stringToArray(ciphertext);
}
let blockTimes = cipherByteArray.length / UINT8_BLOCK;
let outArray = [];
for (let i = 0; i < blockTimes; i++) {
// extract the 16 bytes block data for this round to encrypt
let roundIndex = i * UINT8_BLOCK;
// make Uint8Array to Uint32Array block
let block = getChainBlock(cipherByteArray, roundIndex);
// reverse the round keys to decrypt
let plainBlock = doBlockCrypt(block, decryptRoundKeys);
for (let l = 0; l < UINT8_BLOCK; l++) {
outArray[roundIndex + l] = plainBlock[parseInt(l / 4)] >> ((3 - l) % 4 * 8) & 0xff;
}
}
// depadding the decrypted data
let depaddedPlaintext = dePadding(outArray);
// transform data to utf8 string
return decodeURIComponent(escape(String.fromCharCode(...depaddedPlaintext)));
}
function n(t, e) {
const i = [];
for (let n = t.length - 1; n >= 0; n--) i[n] = 255 & (t[n] ^ e[n]);
return i
}
function r(t, e) {
const i = [];
for (let n = t.length - 1; n >= 0; n--) i[n] = t[n] & e[n] & 255;
return i
}
function a(t, e) {
const i = [];
for (let n = t.length - 1; n >= 0; n--) i[n] = 255 & (t[n] | e[n]);
return i
}
function l(t, e, i, o) {
return o >= 0 && o <= 15 ? n(n(t, e), i) : a(a(r(t, e), r(t, i)), r(e, i))
}
function u(t, e, i, o) {
return o >= 0 && o <= 15 ? n(n(t, e), i) : a(r(t, e), r(function (t) {
const e = [];
for (let i = t.length - 1; i >= 0; i--) e[i] = 255 & ~t[i];
return e
}(t), i))
}
function o(t, e) {
const i = [];
let n = 0;
for (let r = t.length - 1; r >= 0; r--) {
const a = t[r] + e[r] + n;
a > 255 ? (n = 1, i[r] = 255 & a) : (n = 0, i[r] = 255 & a)
}
return i
}
function i(t, e) {
const i = [], n = ~~(e / 8), r = e % 8;
for (let a = 0, o = t.length; a < o; a++) i[a] = (t[(a + n) % o] << r & 255) + (t[(a + n + 1) % o] >>> 8 - r & 255);
return i
}
function s(t) {
return n(n(t, i(t, 9)), i(t, 17))
}
function hh(t, e) {
const r = [], a = [];
for (let i = 0; i < 16; i++) {
const t = 4 * i;
r.push(e.slice(t, t + 4))
}
for (let o = 16; o < 68; o++) r.push(n(n((h = n(n(r[o - 16], r[o - 9]), i(r[o - 3], 15)), n(n(h, i(h, 15)), i(h, 23))), i(r[o - 13], 7)), r[o - 6]));
var h;
for (let i = 0; i < 64; i++) a.push(n(r[i], r[i + 4]));
const c = [121, 204, 69, 25], d = [122, 135, 157, 138];
let f, p, m, g, v = t.slice(0, 4), y = t.slice(4, 8), _ = t.slice(8, 12), b = t.slice(12, 16), w = t.slice(16, 20),
x = t.slice(20, 24), M = t.slice(24, 28), S = t.slice(28, 32);
for (let k = 0; k < 64; k++) {
const t = k >= 0 && k <= 15 ? c : d;
f = i(o(o(i(v, 12), w), i(t, k)), 7), p = n(f, i(v, 12)), m = o(o(o(l(v, y, _, k), b), p), a[k]), g = o(o(o(u(w, x, M, k), S), f), r[k]), b = _, _ = i(y, 9), y = v, v = m, S = M, M = i(x, 19), x = w, w = s(g)
}
return n([].concat(v, y, _, b, w, x, M, S), t)
}
function signData(t) {
const e = "string" == typeof t ? function (t) {
const e = [];
for (let i = 0, n = t.length; i < n; i++) {
const n = t.codePointAt(i);
if (n <= 127) e.push(n); else if (n <= 2047) e.push(192 | n >>> 6), e.push(128 | 63 & n); else if (n <= 55295 || n >= 57344 && n <= 65535) e.push(224 | n >>> 12), e.push(128 | n >>> 6 & 63), e.push(128 | 63 & n); else {
if (!(n >= 65536 && n <= 1114111)) throw e.push(n), new Error("input is not supported");
i++, e.push(240 | n >>> 18 & 28), e.push(128 | n >>> 12 & 63), e.push(128 | n >>> 6 & 63), e.push(128 | 63 & n)
}
}
return e
}(t) : Array.prototype.slice.call(t);
let i = 8 * e.length, n = i % 512;
n = n >= 448 ? 512 - n % 448 - 1 : 448 - n - 1;
const r = new Array((n - 7) / 8);
for (let u = 0, h = r.length; u < h; u++) r[u] = 0;
const a = [];
i = i.toString(2);
for (let u = 7; u >= 0; u--) if (i.length > 8) {
const t = i.length - 8;
a[u] = parseInt(i.substr(t), 2), i = i.substr(0, t)
} else i.length > 0 ? (a[u] = parseInt(i, 2), i = "") : a[u] = 0;
const o = [].concat(e, [128], r, a), s = o.length / 64;
let l = [115, 128, 22, 111, 73, 20, 178, 185, 23, 36, 66, 215, 218, 138, 6, 0, 169, 111, 48, 188, 22, 49, 56, 170, 227, 141, 238, 77, 176, 251, 14, 78];
for (let u = 0; u < s; u++) {
const t = 64 * u;
l = hh(l, o.slice(t, t + 64))
}
return l.map(t => 1 === (t = t.toString(16)).length ? "0" + t : t).join("")
}
function strToBytes(e) {
let c = new Array, n = 0;
for (let u = 0; u < e.length; u++) {
var a = encodeURI(e[u]);
if (1 == a.length) c[n++] = a.charCodeAt(0); else {
let e = a.split("%");
for (var t = 1; t < e.length; t++) c[n++] = parseInt("0x" + e[t])
}
}
return c
}
function bytesToHex(e) {
let c = "";
for (let n = 0; n < e.length; n++) {
let a = e[n].toString(16);
1 == a.length && (a = "0" + a), c += a
}
return c
}
function encryptData(data) {
data = sm2.doEncrypt('加密值', 'publickey', 0)
return '04' + data;
}
转载至:https://www.npmjs.com/package/hwa_sm-crypto