@ivujs/i-utils 2.1.3 → 2.1.5
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/cjs/clipboard/index.cjs +3 -3
- package/dist/cjs/color/index.cjs +3 -3
- package/dist/cjs/crypto/base64/base64.cjs +4 -4
- package/dist/cjs/crypto/md5/index.cjs +2 -2
- package/dist/cjs/crypto/sha256/index.cjs +4 -4
- package/dist/cjs/crypto/sm3/index.cjs +1 -1
- package/dist/cjs/crypto/sm3/sm3.cjs +1 -1
- package/dist/cjs/crypto/sm4/index.cjs +5 -5
- package/dist/cjs/crypto/sm4/sm4.cjs +11 -11
- package/dist/cjs/date/index.cjs +4 -4
- package/dist/cjs/device/index.cjs +12 -12
- package/dist/cjs/file/index.cjs +9 -8
- package/dist/cjs/math/index.cjs +6 -6
- package/dist/cjs/storage/localStorage.cjs +4 -4
- package/dist/cjs/storage/sessionStorage.cjs +4 -4
- package/dist/cjs/string/index.cjs +9 -9
- package/dist/cjs/validate/index.cjs +1 -1
- package/dist/es/clipboard/index.mjs +3 -3
- package/dist/es/color/index.mjs +3 -3
- package/dist/es/crypto/base64/base64.mjs +4 -4
- package/dist/es/crypto/md5/index.mjs +2 -2
- package/dist/es/crypto/sha256/index.mjs +4 -4
- package/dist/es/crypto/sm3/index.mjs +1 -1
- package/dist/es/crypto/sm3/sm3.mjs +1 -1
- package/dist/es/crypto/sm4/index.mjs +5 -5
- package/dist/es/crypto/sm4/sm4.mjs +11 -11
- package/dist/es/date/index.mjs +4 -4
- package/dist/es/device/index.mjs +12 -12
- package/dist/es/file/index.mjs +9 -8
- package/dist/es/math/index.mjs +6 -6
- package/dist/es/storage/localStorage.mjs +4 -4
- package/dist/es/storage/sessionStorage.mjs +4 -4
- package/dist/es/string/index.mjs +9 -9
- package/dist/es/validate/index.mjs +1 -1
- package/dist/lib/index.full.umd.js +84 -83
- package/dist/lib/index.full.umd.min.js +2 -2
- package/dist/lib/index.full.umd.min.js.map +1 -1
- package/package.json +1 -1
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
/*!
|
|
2
|
-
* @ivujs/i-utils v2.1.
|
|
2
|
+
* @ivujs/i-utils v2.1.5
|
|
3
3
|
* Copyright 2021-2026, <gao911222@163.com>
|
|
4
4
|
* Released under the MIT License.
|
|
5
5
|
*/
|
|
@@ -908,7 +908,7 @@
|
|
|
908
908
|
typeof value === "boolean" || // 布尔值视为非数字
|
|
909
909
|
Array.isArray(value) || // 数组视为非数字
|
|
910
910
|
value === "" || // 空字符串视为非数字
|
|
911
|
-
window.isNaN(Number(value)) // 原生isNaN判断(转数字后是否为NaN)
|
|
911
|
+
(window && window.isNaN(Number(value))) // 原生isNaN判断(转数字后是否为NaN)
|
|
912
912
|
);
|
|
913
913
|
}
|
|
914
914
|
/**
|
|
@@ -1229,7 +1229,7 @@
|
|
|
1229
1229
|
}
|
|
1230
1230
|
// 不符合格式
|
|
1231
1231
|
else {
|
|
1232
|
-
throw new TypeError(
|
|
1232
|
+
throw new TypeError(`toSnakeCase: value should be a string`);
|
|
1233
1233
|
}
|
|
1234
1234
|
}
|
|
1235
1235
|
/**
|
|
@@ -1254,7 +1254,7 @@
|
|
|
1254
1254
|
}
|
|
1255
1255
|
// 不符合格式
|
|
1256
1256
|
else {
|
|
1257
|
-
throw new TypeError("value should be a string");
|
|
1257
|
+
throw new TypeError("toKebabCase: value should be a string");
|
|
1258
1258
|
}
|
|
1259
1259
|
}
|
|
1260
1260
|
/**
|
|
@@ -1282,7 +1282,7 @@
|
|
|
1282
1282
|
}
|
|
1283
1283
|
// 不符合格式
|
|
1284
1284
|
else {
|
|
1285
|
-
throw new TypeError("value should be a string");
|
|
1285
|
+
throw new TypeError("toCamelCase: value should be a string");
|
|
1286
1286
|
}
|
|
1287
1287
|
}
|
|
1288
1288
|
/**
|
|
@@ -1312,7 +1312,7 @@
|
|
|
1312
1312
|
}
|
|
1313
1313
|
// 不符合格式
|
|
1314
1314
|
else {
|
|
1315
|
-
throw new TypeError("value should be a string");
|
|
1315
|
+
throw new TypeError("toPascalCase: value should be a string");
|
|
1316
1316
|
}
|
|
1317
1317
|
}
|
|
1318
1318
|
/* 字符串格式化 */
|
|
@@ -1326,10 +1326,10 @@
|
|
|
1326
1326
|
function padZeroStart(value, maxLength = 2) {
|
|
1327
1327
|
value = String(value).trim();
|
|
1328
1328
|
if (maxLength < 0) {
|
|
1329
|
-
throw new TypeError("maxLength should be greater than 0");
|
|
1329
|
+
throw new TypeError("padZeroStart: maxLength should be greater than 0");
|
|
1330
1330
|
}
|
|
1331
1331
|
if (isNull(value) || isNaN(value)) {
|
|
1332
|
-
throw new
|
|
1332
|
+
throw new TypeError("padZeroStart: value must be a valid number or numeric string");
|
|
1333
1333
|
}
|
|
1334
1334
|
// 前面补0
|
|
1335
1335
|
let len = value.toString().length;
|
|
@@ -1349,10 +1349,10 @@
|
|
|
1349
1349
|
function padZeroEnd(value, maxLength = 2) {
|
|
1350
1350
|
value = String(value).trim();
|
|
1351
1351
|
if (maxLength < 0) {
|
|
1352
|
-
throw new TypeError("maxLength should be greater than 0");
|
|
1352
|
+
throw new TypeError("padZeroEnd: maxLength should be greater than 0");
|
|
1353
1353
|
}
|
|
1354
1354
|
if (isNull(value) || isNaN(value)) {
|
|
1355
|
-
throw new
|
|
1355
|
+
throw new TypeError("padZeroEnd: value must be a valid number or numeric string");
|
|
1356
1356
|
}
|
|
1357
1357
|
// 后面补0
|
|
1358
1358
|
let len = value.toString().length;
|
|
@@ -1438,7 +1438,7 @@
|
|
|
1438
1438
|
money = parseFloat(String(money));
|
|
1439
1439
|
if (money >= maxNum) {
|
|
1440
1440
|
// 超出最大处理数字,抛出异常
|
|
1441
|
-
throw new
|
|
1441
|
+
throw new TypeError("formatRmbChinese: calculated number overflow");
|
|
1442
1442
|
}
|
|
1443
1443
|
if (money === 0) {
|
|
1444
1444
|
chineseStr = cnNums[0] + cnIntLast + cnInteger;
|
|
@@ -3457,7 +3457,7 @@
|
|
|
3457
3457
|
function toDate(value) {
|
|
3458
3458
|
// 为空抛出异常
|
|
3459
3459
|
if (isNull(value)) {
|
|
3460
|
-
throw new TypeError("value cannot be null or undefined");
|
|
3460
|
+
throw new TypeError("toDate: value cannot be null or undefined");
|
|
3461
3461
|
}
|
|
3462
3462
|
// 是日期字符串
|
|
3463
3463
|
if (isString(value)) {
|
|
@@ -3473,7 +3473,7 @@
|
|
|
3473
3473
|
}
|
|
3474
3474
|
// 不支持的日期格式
|
|
3475
3475
|
else {
|
|
3476
|
-
throw new TypeError(`invalid input type: ${typeof value}, expected string or number`);
|
|
3476
|
+
throw new TypeError(`toDate: invalid input type: ${typeof value}, expected string or number`);
|
|
3477
3477
|
}
|
|
3478
3478
|
}
|
|
3479
3479
|
/**
|
|
@@ -3487,11 +3487,11 @@
|
|
|
3487
3487
|
const { format = "yyyy-MM-dd", lang = "zh" } = options;
|
|
3488
3488
|
// 为空抛出异常
|
|
3489
3489
|
if (isNull(date)) {
|
|
3490
|
-
throw new TypeError("date cannot be null or undefined");
|
|
3490
|
+
throw new TypeError("toDateString: date cannot be null or undefined");
|
|
3491
3491
|
}
|
|
3492
3492
|
// 判断是否是日期对象
|
|
3493
3493
|
if (!isDate(date)) {
|
|
3494
|
-
throw new TypeError(`invalid input type: ${typeof date}, expected Date object`);
|
|
3494
|
+
throw new TypeError(`toDateString: invalid input type: ${typeof date}, expected Date object`);
|
|
3495
3495
|
}
|
|
3496
3496
|
// 日期转化替换
|
|
3497
3497
|
const replaceRules = {
|
|
@@ -3746,7 +3746,7 @@
|
|
|
3746
3746
|
return _toFixedFloor(num, decimals);
|
|
3747
3747
|
}
|
|
3748
3748
|
else {
|
|
3749
|
-
throw new
|
|
3749
|
+
throw new TypeError("toFixed: mode is MATH.ROUND 0 or MATH.ROUND_FLOOR");
|
|
3750
3750
|
}
|
|
3751
3751
|
}
|
|
3752
3752
|
/**
|
|
@@ -3767,7 +3767,7 @@
|
|
|
3767
3767
|
}
|
|
3768
3768
|
// 错误保留格式
|
|
3769
3769
|
else {
|
|
3770
|
-
throw new
|
|
3770
|
+
throw new TypeError("toDecimal: mode is MATH.ROUND 0 or MATH.ROUND_FLOOR");
|
|
3771
3771
|
}
|
|
3772
3772
|
}
|
|
3773
3773
|
/* 内部函数 */
|
|
@@ -3830,11 +3830,11 @@
|
|
|
3830
3830
|
// num可能是字符串,先转数字再判断NaN
|
|
3831
3831
|
const numVal = Number(num);
|
|
3832
3832
|
if (isNaN(numVal)) {
|
|
3833
|
-
throw new
|
|
3833
|
+
throw new TypeError(`${num} is NaN`);
|
|
3834
3834
|
}
|
|
3835
3835
|
// 校验小数位数范围
|
|
3836
3836
|
if (decimals < 0 || decimals > 20) {
|
|
3837
|
-
throw new
|
|
3837
|
+
throw new TypeError("_toFixedFloor: decimals places must be between 0 and 20");
|
|
3838
3838
|
}
|
|
3839
3839
|
// 默认为保留的小数点后两位
|
|
3840
3840
|
const dec = Math.max(0, Math.floor(decimals)); // 确保小数位数为非负整数
|
|
@@ -3873,7 +3873,7 @@
|
|
|
3873
3873
|
*/
|
|
3874
3874
|
function _toDecimalRound(num, decimals = 2) {
|
|
3875
3875
|
if (isNaN(Number(num))) {
|
|
3876
|
-
throw new
|
|
3876
|
+
throw new TypeError(`_toDecimalRound: ${num} is not a number`);
|
|
3877
3877
|
}
|
|
3878
3878
|
const n = Math.pow(10, decimals);
|
|
3879
3879
|
return Math.round(Number(num) * n) / n;
|
|
@@ -3886,7 +3886,7 @@
|
|
|
3886
3886
|
*/
|
|
3887
3887
|
function _toDecimalFloor(num, decimals = 2) {
|
|
3888
3888
|
if (isNaN(Number(num))) {
|
|
3889
|
-
throw new
|
|
3889
|
+
throw new TypeError(`_toDecimalFloor: ${num} is not a number`);
|
|
3890
3890
|
}
|
|
3891
3891
|
const n = Math.pow(10, decimals);
|
|
3892
3892
|
return Math.floor(Number(num) * n) / n;
|
|
@@ -4122,15 +4122,16 @@
|
|
|
4122
4122
|
function urlToFile(url) {
|
|
4123
4123
|
return new Promise((resolve, reject) => {
|
|
4124
4124
|
try {
|
|
4125
|
-
window
|
|
4126
|
-
|
|
4127
|
-
res.
|
|
4128
|
-
|
|
4129
|
-
|
|
4125
|
+
window &&
|
|
4126
|
+
window.fetch(url).then((res) => {
|
|
4127
|
+
if (res.status === 200) {
|
|
4128
|
+
res.blob().then((blob) => {
|
|
4129
|
+
blobToFile(blob).then((file) => {
|
|
4130
|
+
resolve(file);
|
|
4131
|
+
});
|
|
4130
4132
|
});
|
|
4131
|
-
}
|
|
4132
|
-
}
|
|
4133
|
-
});
|
|
4133
|
+
}
|
|
4134
|
+
});
|
|
4134
4135
|
}
|
|
4135
4136
|
catch (err) {
|
|
4136
4137
|
console.error(err);
|
|
@@ -4407,7 +4408,7 @@
|
|
|
4407
4408
|
});
|
|
4408
4409
|
const rgb = /^#?([a-f\d]{2})([a-f\d]{2})([a-f\d]{2})$/i.exec(hexStr);
|
|
4409
4410
|
if (!rgb) {
|
|
4410
|
-
throw new
|
|
4411
|
+
throw new TypeError(`hexToRgb: invalid hex color: ${hex}`);
|
|
4411
4412
|
}
|
|
4412
4413
|
color.r = parseInt(rgb[1], 16);
|
|
4413
4414
|
color.g = parseInt(rgb[2], 16);
|
|
@@ -4428,7 +4429,7 @@
|
|
|
4428
4429
|
});
|
|
4429
4430
|
const rgb = /^#?([a-f\d]{2})([a-f\d]{2})([a-f\d]{2})$/i.exec(hexStr);
|
|
4430
4431
|
if (!rgb) {
|
|
4431
|
-
throw new
|
|
4432
|
+
throw new TypeError(`hexToRgba: invalid hex color: ${hex}`);
|
|
4432
4433
|
}
|
|
4433
4434
|
color.r = parseInt(rgb[1], 16);
|
|
4434
4435
|
color.g = parseInt(rgb[2], 16);
|
|
@@ -4449,7 +4450,7 @@
|
|
|
4449
4450
|
});
|
|
4450
4451
|
const rgb = /^#?([a-f\d]{2})([a-f\d]{2})([a-f\d]{2})$/i.exec(hexStr);
|
|
4451
4452
|
if (!rgb) {
|
|
4452
|
-
throw new
|
|
4453
|
+
throw new TypeError(`hexToHsl: invalid hex color: ${hex}`);
|
|
4453
4454
|
}
|
|
4454
4455
|
// 再组装为hsl格式
|
|
4455
4456
|
const r = parseInt(rgb[1], 16) / 255;
|
|
@@ -4990,7 +4991,7 @@
|
|
|
4990
4991
|
*/
|
|
4991
4992
|
const fromUint8Array = function (uint8Array, urlSafe = false) {
|
|
4992
4993
|
if (!(uint8Array instanceof Uint8Array)) {
|
|
4993
|
-
throw new TypeError("fromUint8Array
|
|
4994
|
+
throw new TypeError("fromUint8Array: input must be Uint8Array");
|
|
4994
4995
|
}
|
|
4995
4996
|
const bytes = Array.from(uint8Array);
|
|
4996
4997
|
let result = bytesToBase64Chars(bytes);
|
|
@@ -5007,7 +5008,7 @@
|
|
|
5007
5008
|
*/
|
|
5008
5009
|
const toUint8Array = function (base64Str, urlSafe = false) {
|
|
5009
5010
|
if (typeof base64Str !== "string") {
|
|
5010
|
-
throw new TypeError("toUint8Array
|
|
5011
|
+
throw new TypeError("toUint8Array: input must be string");
|
|
5011
5012
|
}
|
|
5012
5013
|
// 处理URL安全字符
|
|
5013
5014
|
if (urlSafe) {
|
|
@@ -5024,7 +5025,7 @@
|
|
|
5024
5025
|
*/
|
|
5025
5026
|
const fromHex = function (hexStr, urlSafe = false) {
|
|
5026
5027
|
if (typeof hexStr !== "string" || !/^[0-9a-fA-F]+$/.test(hexStr)) {
|
|
5027
|
-
throw new TypeError("fromHex
|
|
5028
|
+
throw new TypeError("fromHex: input must be hex string");
|
|
5028
5029
|
}
|
|
5029
5030
|
// 补全偶数长度
|
|
5030
5031
|
const str = hexStr.length % 2 ? `0${hexStr}` : hexStr;
|
|
@@ -5046,7 +5047,7 @@
|
|
|
5046
5047
|
*/
|
|
5047
5048
|
const toHex = function (base64Str, urlSafe = false) {
|
|
5048
5049
|
if (typeof base64Str !== "string") {
|
|
5049
|
-
throw new TypeError("toHex
|
|
5050
|
+
throw new TypeError("toHex: input must be string");
|
|
5050
5051
|
}
|
|
5051
5052
|
// 处理URL安全字符
|
|
5052
5053
|
if (urlSafe) {
|
|
@@ -5566,7 +5567,7 @@
|
|
|
5566
5567
|
*/
|
|
5567
5568
|
function md5Hmac(str, key) {
|
|
5568
5569
|
if (!str || !key) {
|
|
5569
|
-
throw new
|
|
5570
|
+
throw new TypeError("md5Hmac: missing str or key");
|
|
5570
5571
|
}
|
|
5571
5572
|
return md5$1(str, key, false);
|
|
5572
5573
|
}
|
|
@@ -5578,7 +5579,7 @@
|
|
|
5578
5579
|
*/
|
|
5579
5580
|
function md5HmacRaw(str, key) {
|
|
5580
5581
|
if (!str || !key) {
|
|
5581
|
-
throw new
|
|
5582
|
+
throw new TypeError("md5HmacRaw: missing str or key");
|
|
5582
5583
|
}
|
|
5583
5584
|
return md5$1(str, key, true);
|
|
5584
5585
|
}
|
|
@@ -6155,7 +6156,7 @@
|
|
|
6155
6156
|
*/
|
|
6156
6157
|
function sha256Hmac(str, key) {
|
|
6157
6158
|
if (!str || !key) {
|
|
6158
|
-
throw new
|
|
6159
|
+
throw new TypeError("sha256Hmac: missing str or key");
|
|
6159
6160
|
}
|
|
6160
6161
|
return sha256_hmac(key, str);
|
|
6161
6162
|
}
|
|
@@ -6167,7 +6168,7 @@
|
|
|
6167
6168
|
*/
|
|
6168
6169
|
function sha256HmacRaw(str, key) {
|
|
6169
6170
|
if (!str || !key) {
|
|
6170
|
-
throw new
|
|
6171
|
+
throw new TypeError("sha256HmacRaw: missing str or key");
|
|
6171
6172
|
}
|
|
6172
6173
|
return sha256_hmac_raw(key, str);
|
|
6173
6174
|
}
|
|
@@ -6196,7 +6197,7 @@
|
|
|
6196
6197
|
*/
|
|
6197
6198
|
function sha224Hmac(str, key) {
|
|
6198
6199
|
if (!str || !key) {
|
|
6199
|
-
throw new
|
|
6200
|
+
throw new TypeError("sha224Hmac: missing str or key");
|
|
6200
6201
|
}
|
|
6201
6202
|
return sha224_hmac(key, str);
|
|
6202
6203
|
}
|
|
@@ -6208,7 +6209,7 @@
|
|
|
6208
6209
|
*/
|
|
6209
6210
|
function sha224HmacRaw(str, key) {
|
|
6210
6211
|
if (!str || !key) {
|
|
6211
|
-
throw new
|
|
6212
|
+
throw new TypeError("sha224HmacRaw: missing str or key");
|
|
6212
6213
|
}
|
|
6213
6214
|
return sha224_hmac_raw(key, str);
|
|
6214
6215
|
}
|
|
@@ -6298,7 +6299,7 @@
|
|
|
6298
6299
|
}
|
|
6299
6300
|
else {
|
|
6300
6301
|
arr.push(point);
|
|
6301
|
-
throw new
|
|
6302
|
+
throw new TypeError("utf8ToArray: input is not supported in sm3");
|
|
6302
6303
|
}
|
|
6303
6304
|
}
|
|
6304
6305
|
return arr;
|
|
@@ -6425,7 +6426,7 @@
|
|
|
6425
6426
|
*/
|
|
6426
6427
|
function sm3EncryptHmac(str, key) {
|
|
6427
6428
|
if (!str || !key) {
|
|
6428
|
-
throw new
|
|
6429
|
+
throw new TypeError("sm3EncryptHmac: missing str or key");
|
|
6429
6430
|
}
|
|
6430
6431
|
return encrypt$1(str, key);
|
|
6431
6432
|
}
|
|
@@ -6480,7 +6481,7 @@
|
|
|
6480
6481
|
function hexToUint8Array(str) {
|
|
6481
6482
|
str = str.replace(/\s+/g, ""); // 去除空格
|
|
6482
6483
|
if (str.length % 2 !== 0)
|
|
6483
|
-
throw new
|
|
6484
|
+
throw new TypeError("hexToUint8Array: hex string length must be even from sm4");
|
|
6484
6485
|
const arr = new Uint8Array(str.length / 2);
|
|
6485
6486
|
for (let i = 0; i < str.length; i += 2) {
|
|
6486
6487
|
arr[i / 2] = parseInt(str.substr(i, 2), 16) & 0xff;
|
|
@@ -6542,7 +6543,7 @@
|
|
|
6542
6543
|
return hexToUint8Array(input);
|
|
6543
6544
|
}
|
|
6544
6545
|
}
|
|
6545
|
-
throw new
|
|
6546
|
+
throw new TypeError(`normalizeInput: unsupported input type: ${typeof input} from sm4`);
|
|
6546
6547
|
}
|
|
6547
6548
|
/**
|
|
6548
6549
|
* 标准化密钥/IV为Uint8Array
|
|
@@ -6566,10 +6567,10 @@
|
|
|
6566
6567
|
arr = new Uint8Array(keyOrIv);
|
|
6567
6568
|
}
|
|
6568
6569
|
else {
|
|
6569
|
-
throw new
|
|
6570
|
+
throw new TypeError(`normalizeKeyIv: unsupported ${name} type: ${typeof keyOrIv} from sm4`);
|
|
6570
6571
|
}
|
|
6571
6572
|
if (arr.length !== expectedLength) {
|
|
6572
|
-
throw new
|
|
6573
|
+
throw new TypeError(`normalizeKeyIv: ${name} must be ${expectedLength * 8} bits (${expectedLength} bytes) from sm4`);
|
|
6573
6574
|
}
|
|
6574
6575
|
return arr;
|
|
6575
6576
|
}
|
|
@@ -6621,7 +6622,7 @@
|
|
|
6621
6622
|
function sm4BlockCrypt(inputBlock, outputBlock, roundKeys) {
|
|
6622
6623
|
// 确保输入块是16字节
|
|
6623
6624
|
if (inputBlock.length !== BLOCK_SIZE) {
|
|
6624
|
-
throw new
|
|
6625
|
+
throw new TypeError(`sm4BlockCrypt: input block must be ${BLOCK_SIZE} bytes for block crypt from sm4`);
|
|
6625
6626
|
}
|
|
6626
6627
|
// 字节数组转32比特字数组(4个字,共128比特)
|
|
6627
6628
|
const x = new Uint32Array(4);
|
|
@@ -6716,7 +6717,7 @@
|
|
|
6716
6717
|
// 验证填充合法性
|
|
6717
6718
|
for (let i = 1; i <= paddingCount; i++) {
|
|
6718
6719
|
if (data[data.length - i] !== paddingCount) {
|
|
6719
|
-
throw new
|
|
6720
|
+
throw new TypeError("pkcs7Unpad: invalid PKCS#7 padding from sm4");
|
|
6720
6721
|
}
|
|
6721
6722
|
}
|
|
6722
6723
|
return data.subarray(0, data.length - paddingCount);
|
|
@@ -6739,7 +6740,7 @@
|
|
|
6739
6740
|
} = options;
|
|
6740
6741
|
// 校验模式
|
|
6741
6742
|
if (![SM4_MODE_ECB, SM4_MODE_CBC].includes(mode)) {
|
|
6742
|
-
throw new
|
|
6743
|
+
throw new TypeError(`sm4Core: unsupported mode: ${mode}, only 'ecb' and 'cbc' are supported from sm4`);
|
|
6743
6744
|
}
|
|
6744
6745
|
// 标准化输入、密钥、IV
|
|
6745
6746
|
const input = normalizeInput(inputData, cryptFlag);
|
|
@@ -6754,7 +6755,7 @@
|
|
|
6754
6755
|
processedInput = pkcs7Pad(input);
|
|
6755
6756
|
// 确保填充后是16字节的倍数
|
|
6756
6757
|
if (processedInput.length % BLOCK_SIZE !== 0) {
|
|
6757
|
-
throw new
|
|
6758
|
+
throw new TypeError("sm4Core: PKCS7 padding failed: data length is not multiple of block size from sm4");
|
|
6758
6759
|
}
|
|
6759
6760
|
}
|
|
6760
6761
|
// 生成轮密钥
|
|
@@ -6814,7 +6815,7 @@
|
|
|
6814
6815
|
case SM4_OUTPUT_ARRAYBUFFER:
|
|
6815
6816
|
return finalOutput.buffer;
|
|
6816
6817
|
default:
|
|
6817
|
-
throw new
|
|
6818
|
+
throw new TypeError(`sm4Core: unsupported output format: ${output} from sm4`);
|
|
6818
6819
|
}
|
|
6819
6820
|
}
|
|
6820
6821
|
// ========== 便捷API(函数式,符合设计准则) ==========
|
|
@@ -6826,7 +6827,7 @@
|
|
|
6826
6827
|
function generateIv(outputFormat = SM4_OUTPUT_HEX) {
|
|
6827
6828
|
// 1. 校验浏览器是否支持 crypto
|
|
6828
6829
|
if (!window?.crypto?.getRandomValues) {
|
|
6829
|
-
throw new
|
|
6830
|
+
throw new TypeError("generateIv: your browser does not support secure random generation (crypto API) from sm4");
|
|
6830
6831
|
}
|
|
6831
6832
|
// 2. 生成 16 字节安全随机数
|
|
6832
6833
|
const ivUint8 = new Uint8Array(IV_SIZE);
|
|
@@ -6857,7 +6858,7 @@
|
|
|
6857
6858
|
function generateKey(outputFormat = SM4_OUTPUT_HEX) {
|
|
6858
6859
|
// 校验浏览器/Node环境的安全随机数API
|
|
6859
6860
|
if (!window?.crypto?.getRandomValues && !global?.crypto?.getRandomValues) {
|
|
6860
|
-
throw new
|
|
6861
|
+
throw new TypeError("generateKey: the current environment does not support secure random number generation. please upgrade your browser/Node.js from sm4");
|
|
6861
6862
|
}
|
|
6862
6863
|
// 生成16字节随机数(SM4密钥固定16字节)
|
|
6863
6864
|
const cryptoObj = window?.crypto || global?.crypto;
|
|
@@ -6963,15 +6964,15 @@
|
|
|
6963
6964
|
// 1. 校验模式是否合法
|
|
6964
6965
|
const validModes = Object.values(MODE);
|
|
6965
6966
|
if (!validModes.includes(mode)) {
|
|
6966
|
-
throw new
|
|
6967
|
+
throw new TypeError(`sm4${operation}:unsupported encryption mode "${mode}", supports only ${validModes.join("/")}`);
|
|
6967
6968
|
}
|
|
6968
6969
|
// 2. CBC模式必须传IV
|
|
6969
6970
|
if (mode === MODE.CBC && !iv) {
|
|
6970
|
-
throw new
|
|
6971
|
+
throw new TypeError(`sm4${operation}:the CBC mode must be inputted with an IV (initialization vector)`);
|
|
6971
6972
|
}
|
|
6972
6973
|
// 3. ECB模式禁止传IV(避免误用)
|
|
6973
6974
|
if (mode === MODE.ECB && iv !== undefined) {
|
|
6974
|
-
throw new
|
|
6975
|
+
throw new TypeError(`sm4${operation}: the ECB mode does not require an IV to be passed in. Please do not pass the iv parameter`);
|
|
6975
6976
|
}
|
|
6976
6977
|
// 4. 校验IV长度(如果传了IV)
|
|
6977
6978
|
if (iv) {
|
|
@@ -6993,12 +6994,12 @@
|
|
|
6993
6994
|
ivLength = 0;
|
|
6994
6995
|
}
|
|
6995
6996
|
if (ivLength !== 16) {
|
|
6996
|
-
throw new
|
|
6997
|
+
throw new TypeError(`sm4${operation}:IV must be 16 bytes in length, and the current length is ${ivLength}`);
|
|
6997
6998
|
}
|
|
6998
6999
|
}
|
|
6999
7000
|
// 5. 校验填充模式(仅允许pkcs#7)
|
|
7000
7001
|
if (options.padding && options.padding !== String(PADDING)) {
|
|
7001
|
-
throw new
|
|
7002
|
+
throw new TypeError(`sm4${operation}: only pkcs#7 padding mode is supported, currently being input ${String(options.padding)}`);
|
|
7002
7003
|
}
|
|
7003
7004
|
}
|
|
7004
7005
|
// sm4的配置
|
|
@@ -7614,7 +7615,7 @@
|
|
|
7614
7615
|
* @returns {string} 返回数据
|
|
7615
7616
|
*/
|
|
7616
7617
|
function getLocalStorage(key) {
|
|
7617
|
-
return window.localStorage.getItem(key) || undefined;
|
|
7618
|
+
return (window && window.localStorage.getItem(key)) || undefined;
|
|
7618
7619
|
}
|
|
7619
7620
|
/**
|
|
7620
7621
|
* 设置localStorage缓存数据
|
|
@@ -7622,20 +7623,20 @@
|
|
|
7622
7623
|
* @param {string} value value值
|
|
7623
7624
|
*/
|
|
7624
7625
|
function setLocalStorage(key, value) {
|
|
7625
|
-
window.localStorage.setItem(key, value);
|
|
7626
|
+
window && window.localStorage.setItem(key, value);
|
|
7626
7627
|
}
|
|
7627
7628
|
/**
|
|
7628
7629
|
* 通过key从localStorage缓存中删除数据
|
|
7629
7630
|
* @param {string} key key值
|
|
7630
7631
|
*/
|
|
7631
7632
|
function removeLocalStorage(key) {
|
|
7632
|
-
window.localStorage.removeItem(key);
|
|
7633
|
+
window && window.localStorage.removeItem(key);
|
|
7633
7634
|
}
|
|
7634
7635
|
/**
|
|
7635
7636
|
* 清空localStorage缓存中所有数据
|
|
7636
7637
|
*/
|
|
7637
7638
|
function clearLocalStorage() {
|
|
7638
|
-
window.localStorage.clear();
|
|
7639
|
+
window && window.localStorage.clear();
|
|
7639
7640
|
}
|
|
7640
7641
|
|
|
7641
7642
|
/* sessionStorage存储 */
|
|
@@ -7645,7 +7646,7 @@
|
|
|
7645
7646
|
* @returns {string} 返回数据
|
|
7646
7647
|
*/
|
|
7647
7648
|
function getSessionStorage(key) {
|
|
7648
|
-
return window.sessionStorage.getItem(key) || undefined;
|
|
7649
|
+
return (window && window.sessionStorage.getItem(key)) || undefined;
|
|
7649
7650
|
}
|
|
7650
7651
|
/**
|
|
7651
7652
|
* 设置sessionStorage缓存数据
|
|
@@ -7653,20 +7654,20 @@
|
|
|
7653
7654
|
* @param {string} value value值
|
|
7654
7655
|
*/
|
|
7655
7656
|
function setSessionStorage(key, value) {
|
|
7656
|
-
window.sessionStorage.setItem(key, value);
|
|
7657
|
+
window && window.sessionStorage.setItem(key, value);
|
|
7657
7658
|
}
|
|
7658
7659
|
/**
|
|
7659
7660
|
* 通过key从sessionStorage缓存中删除数据
|
|
7660
7661
|
* @param {string} key key值
|
|
7661
7662
|
*/
|
|
7662
7663
|
function removeSessionStorage(key) {
|
|
7663
|
-
window.sessionStorage.removeItem(key);
|
|
7664
|
+
window && window.sessionStorage.removeItem(key);
|
|
7664
7665
|
}
|
|
7665
7666
|
/**
|
|
7666
7667
|
* 清空sessionStorage缓存中所有数据
|
|
7667
7668
|
*/
|
|
7668
7669
|
function clearSessionStorage() {
|
|
7669
|
-
window.sessionStorage.clear();
|
|
7670
|
+
window && window.sessionStorage.clear();
|
|
7670
7671
|
}
|
|
7671
7672
|
|
|
7672
7673
|
/**
|
|
@@ -7811,7 +7812,7 @@
|
|
|
7811
7812
|
* @returns {Object} 返回浏览器信息
|
|
7812
7813
|
*/
|
|
7813
7814
|
function getBrowserInfo() {
|
|
7814
|
-
const ua = window.navigator.userAgent.toLowerCase();
|
|
7815
|
+
const ua = window && window.navigator.userAgent.toLowerCase();
|
|
7815
7816
|
// ie
|
|
7816
7817
|
const ie = ua.match(/rv:([\d.]+)\) like gecko/) || ua.match(/msie ([\d\.]+)/);
|
|
7817
7818
|
// edge
|
|
@@ -7854,7 +7855,7 @@
|
|
|
7854
7855
|
* @returns {boolean} 返回true和false
|
|
7855
7856
|
*/
|
|
7856
7857
|
function isPhone() {
|
|
7857
|
-
const ua = window.navigator.userAgent;
|
|
7858
|
+
const ua = window && window.navigator.userAgent;
|
|
7858
7859
|
return /Android|webOS|iPhone|iPod|BlackBerry|Windows Phone|IEMobile/i.test(ua);
|
|
7859
7860
|
}
|
|
7860
7861
|
/* 操作系统类型 */
|
|
@@ -7863,7 +7864,7 @@
|
|
|
7863
7864
|
* @returns {boolean} 返回true和false
|
|
7864
7865
|
*/
|
|
7865
7866
|
function isAndroid() {
|
|
7866
|
-
const ua = window.navigator.userAgent;
|
|
7867
|
+
const ua = window && window.navigator.userAgent;
|
|
7867
7868
|
return /Android|BlackBerry/i.test(ua);
|
|
7868
7869
|
}
|
|
7869
7870
|
/**
|
|
@@ -7871,7 +7872,7 @@
|
|
|
7871
7872
|
* @returns {boolean} 返回true和false
|
|
7872
7873
|
*/
|
|
7873
7874
|
function isIos() {
|
|
7874
|
-
const ua = window.navigator.userAgent;
|
|
7875
|
+
const ua = window && window.navigator.userAgent;
|
|
7875
7876
|
return /iPhone|iPad|iPod|iOS/i.test(ua);
|
|
7876
7877
|
}
|
|
7877
7878
|
/**
|
|
@@ -7879,7 +7880,7 @@
|
|
|
7879
7880
|
* @returns {boolean} 返回true和false
|
|
7880
7881
|
*/
|
|
7881
7882
|
function isWindowsPhone() {
|
|
7882
|
-
const ua = window.navigator.userAgent;
|
|
7883
|
+
const ua = window && window.navigator.userAgent;
|
|
7883
7884
|
return /Windows Phone/i.test(ua);
|
|
7884
7885
|
}
|
|
7885
7886
|
/**
|
|
@@ -7887,7 +7888,7 @@
|
|
|
7887
7888
|
* @returns {boolean} 返回true和false
|
|
7888
7889
|
*/
|
|
7889
7890
|
function isWindows() {
|
|
7890
|
-
const ua = window.navigator.userAgent;
|
|
7891
|
+
const ua = window && window.navigator.userAgent;
|
|
7891
7892
|
return /win/i.test(ua);
|
|
7892
7893
|
}
|
|
7893
7894
|
/**
|
|
@@ -7895,7 +7896,7 @@
|
|
|
7895
7896
|
* @returns {boolean} 返回true和false
|
|
7896
7897
|
*/
|
|
7897
7898
|
function isLinux() {
|
|
7898
|
-
const ua = window.navigator.userAgent;
|
|
7899
|
+
const ua = window && window.navigator.userAgent;
|
|
7899
7900
|
return /linux/i.test(ua);
|
|
7900
7901
|
}
|
|
7901
7902
|
/**
|
|
@@ -7903,7 +7904,7 @@
|
|
|
7903
7904
|
* @returns {boolean} 返回true和false
|
|
7904
7905
|
*/
|
|
7905
7906
|
function isMac() {
|
|
7906
|
-
const ua = window.navigator.userAgent;
|
|
7907
|
+
const ua = window && window.navigator.userAgent;
|
|
7907
7908
|
return /mac/i.test(ua);
|
|
7908
7909
|
}
|
|
7909
7910
|
/* 苹果设备类型 */
|
|
@@ -7912,7 +7913,7 @@
|
|
|
7912
7913
|
*@returns {boolean} 返回true和false
|
|
7913
7914
|
*/
|
|
7914
7915
|
function isIphone() {
|
|
7915
|
-
const ua = window.navigator.userAgent;
|
|
7916
|
+
const ua = window && window.navigator.userAgent;
|
|
7916
7917
|
return /iPhone/i.test(ua);
|
|
7917
7918
|
}
|
|
7918
7919
|
/**
|
|
@@ -7920,7 +7921,7 @@
|
|
|
7920
7921
|
*@return {boolean} 返回true和false
|
|
7921
7922
|
*/
|
|
7922
7923
|
function isIpad() {
|
|
7923
|
-
const ua = window.navigator.userAgent;
|
|
7924
|
+
const ua = window && window.navigator.userAgent;
|
|
7924
7925
|
return /iPod/i.test(ua);
|
|
7925
7926
|
}
|
|
7926
7927
|
/* 手机浏览器类型 */
|
|
@@ -7929,7 +7930,7 @@
|
|
|
7929
7930
|
* @returns {boolean} 返回true和false
|
|
7930
7931
|
*/
|
|
7931
7932
|
function isWeixin() {
|
|
7932
|
-
const ua = window.navigator.userAgent;
|
|
7933
|
+
const ua = window && window.navigator.userAgent;
|
|
7933
7934
|
return /MicroMessenger/i.test(ua);
|
|
7934
7935
|
}
|
|
7935
7936
|
/**
|
|
@@ -7937,7 +7938,7 @@
|
|
|
7937
7938
|
* @returns {boolean} 返回true和false
|
|
7938
7939
|
*/
|
|
7939
7940
|
function isQQ() {
|
|
7940
|
-
const ua = window.navigator.userAgent;
|
|
7941
|
+
const ua = window && window.navigator.userAgent;
|
|
7941
7942
|
return /QQ/i.test(ua);
|
|
7942
7943
|
}
|
|
7943
7944
|
|
|
@@ -7983,7 +7984,7 @@
|
|
|
7983
7984
|
*/
|
|
7984
7985
|
function getClipboardText() {
|
|
7985
7986
|
return new Promise((resolve, reject) => {
|
|
7986
|
-
if (window.navigator
|
|
7987
|
+
if (window && window.navigator) {
|
|
7987
7988
|
window.navigator.clipboard
|
|
7988
7989
|
.readText()
|
|
7989
7990
|
.then((text) => {
|
|
@@ -8007,7 +8008,7 @@
|
|
|
8007
8008
|
function setClipboard(data) {
|
|
8008
8009
|
return new Promise((resolve, reject) => {
|
|
8009
8010
|
// 现代浏览器
|
|
8010
|
-
if (window.navigator
|
|
8011
|
+
if (window && window.navigator) {
|
|
8011
8012
|
let clipboardItem = null;
|
|
8012
8013
|
// 是文本类型
|
|
8013
8014
|
if (typeof data === "string") {
|
|
@@ -8040,7 +8041,7 @@
|
|
|
8040
8041
|
function setClipboardText(text) {
|
|
8041
8042
|
return new Promise((resolve, reject) => {
|
|
8042
8043
|
// 现代浏览器
|
|
8043
|
-
if (window.navigator
|
|
8044
|
+
if (window && window.navigator) {
|
|
8044
8045
|
window.navigator.clipboard.writeText(text).then((success) => {
|
|
8045
8046
|
resolve(true);
|
|
8046
8047
|
}, (failed) => {
|