dream-common 1.1.36 → 1.1.40

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/index.js CHANGED
@@ -16,5 +16,7 @@ export default {
16
16
  ...require('./lib/json'),
17
17
  ...require('./lib/CryptoJS/Base58'),
18
18
  ...require('./lib/CryptoJS/HttpData'),
19
- ...require('./lib/CryptoJS/AesUtils')
19
+ ...require('./lib/CryptoJS/AesUtils'),
20
+ ...require('./lib/CryptoJS/Base64Utils'),
21
+ ...require('./lib/CryptoJS/HttpRequest')
20
22
  }
@@ -0,0 +1,115 @@
1
+ // utils/Base64Utils.js
2
+
3
+ /**
4
+ * 字符串 → Base64
5
+ * @param {string} str - UTF-8 字符串
6
+ * @returns {string} Base64 编码结果
7
+ */
8
+ export const stringToBase64 = (str) => {
9
+ if (typeof Buffer !== 'undefined') {
10
+ return Buffer.from(str, 'utf8').toString('base64');
11
+ }
12
+ // 浏览器环境
13
+ const encoder = new TextEncoder();
14
+ const bytes = encoder.encode(str);
15
+ let binary = '';
16
+ for (let i = 0; i < bytes.length; i++) {
17
+ binary += String.fromCharCode(bytes[i]);
18
+ }
19
+ return btoa(binary);
20
+ }
21
+
22
+ /**
23
+ * Base64 → 字符串
24
+ * @param {string} base64
25
+ * @returns {string} 原始 UTF-8 字符串
26
+ */
27
+ export const base64ToString = (base64) => {
28
+ if (typeof Buffer !== 'undefined') {
29
+ return Buffer.from(base64, 'base64').toString('utf8');
30
+ }
31
+ // 浏览器环境
32
+ const binary = atob(base64.replace(/[^A-Za-z0-9+/]/g, ''));
33
+ const bytes = new Uint8Array(binary.length);
34
+ for (let i = 0; i < binary.length; i++) {
35
+ bytes[i] = binary.charCodeAt(i);
36
+ }
37
+ const decoder = new TextDecoder();
38
+ return decoder.decode(bytes);
39
+ }
40
+
41
+ /**
42
+ * Uint8Array → Base64
43
+ * @param {Uint8Array} bytes
44
+ * @returns {string}
45
+ */
46
+ export const uint8ArrayToBase64 = (bytes) => {
47
+ if (typeof Buffer !== 'undefined') {
48
+ return Buffer.from(bytes).toString('base64');
49
+ }
50
+ let binary = '';
51
+ for (let i = 0; i < bytes.length; i++) {
52
+ binary += String.fromCharCode(bytes[i]);
53
+ }
54
+ return btoa(binary);
55
+ }
56
+
57
+ /**
58
+ * Base64 → Uint8Array
59
+ * @param {string} base64
60
+ * @returns {Uint8Array}
61
+ */
62
+ export const base64ToUint8Array = (base64) => {
63
+ if (typeof Buffer !== 'undefined') {
64
+ return new Uint8Array(Buffer.from(base64, 'base64'));
65
+ }
66
+ const binary = atob(base64.replace(/[^A-Za-z0-9+/]/g, ''));
67
+ const bytes = new Uint8Array(binary.length);
68
+ for (let i = 0; i < binary.length; i++) {
69
+ bytes[i] = binary.charCodeAt(i);
70
+ }
71
+ return bytes;
72
+ }
73
+
74
+ /**
75
+ * Hex 字符串 → Uint8Array
76
+ * @param {string} hex - 如 'a1b2c3'
77
+ * @returns {Uint8Array}
78
+ */
79
+ export const hexToUint8Array = (hex) => {
80
+ if (hex.length % 2 !== 0) throw new Error('Invalid hex length');
81
+ const bytes = new Uint8Array(hex.length / 2);
82
+ for (let i = 0; i < bytes.length; i++) {
83
+ bytes[i] = parseInt(hex.substr(i * 2, 2), 16);
84
+ }
85
+ return bytes;
86
+ }
87
+
88
+ /**
89
+ * Uint8Array → 小写 Hex 字符串
90
+ * @param {Uint8Array} bytes
91
+ * @returns {string}
92
+ */
93
+ export const uint8ArrayToHex = (bytes) => {
94
+ return Array.from(bytes, byte => byte.toString(16).padStart(2, '0')).join('');
95
+ }
96
+
97
+ /**
98
+ * Hex → Base64
99
+ * @param {string} hex
100
+ * @returns {string}
101
+ */
102
+ export const hexToBase64 = (hex) => {
103
+ const bytes = this.hexToUint8Array(hex);
104
+ return this.uint8ArrayToBase64(bytes);
105
+ }
106
+
107
+ /**
108
+ * Base64 → Hex
109
+ * @param {string} base64
110
+ * @returns {string}
111
+ */
112
+ export const base64ToHex = (base64) => {
113
+ const bytes = this.base64ToUint8Array(base64);
114
+ return this.uint8ArrayToHex(bytes);
115
+ }
@@ -0,0 +1,147 @@
1
+ // utils/secureData.js
2
+
3
+ import {
4
+ sm2,
5
+ sm4
6
+ } from 'sm-crypto';
7
+ import {base64ToHex, hexToBase64} from './Base64Utils.js';
8
+ import {md5} from './md5.js';
9
+ import {uuid} from '../uuid.js';
10
+
11
+
12
+ /**
13
+ * 创建安全请求基础结构(支持传入部分字段进行覆盖)
14
+ * @param {Object} request - 可选:包含 appId、data 及其他可覆盖字段
15
+ * @returns {Object} 完整的 SecureBaseRequest 对象
16
+ */
17
+ export function createSecureData(request = {}) {
18
+ const now = Date.now();
19
+ const defaults = {
20
+ version: '1.0.0',
21
+ signType: 'SM2',
22
+ encType: 'SM4',
23
+ timestamp: now,
24
+ nonceStr: uuid(),
25
+ encData: '',
26
+ signData: ''
27
+ };
28
+
29
+ return {
30
+ ...defaults,
31
+ ...request, // 👈 用传入的 request 覆盖默认值
32
+ };
33
+ }
34
+
35
+ /**
36
+ * 1️⃣ 打包安全数据:签名 + 加密
37
+ * @param request
38
+ * @param {string} privateKey - 64位十六进制 SM2 私钥
39
+ * @param {boolean} [useBase64=false] - encData 是否用 Base64 编码(否则为 hex)
40
+ * @returns {Object} 可直接发送的请求对象(不含 data 字段)
41
+ */
42
+ export function encryptSecureData(request = {}, privateKey, useBase64 = true) {
43
+ // 1. 生成签名原文(排除 encData, signData, data)
44
+ const signSource = objectToSignString(request, 'encData', 'signData', 'data');
45
+ // 2. SM2 签名(DER 格式,与 Java Bouncy Castle 兼容)
46
+ const signValueStr = sm2.doSignature(signSource, privateKey, {
47
+ der: true
48
+ }).toLowerCase();
49
+
50
+ const signValue = useBase64 ? hexToBase64(signValueStr) : signValueStr;
51
+ // 3. 生成 SM4 密钥和 IV(通过 MD5)
52
+ const keyHex = md5_32(signValue); // 32 hex → 16 bytes
53
+ const ivHex = md5_32(signSource); // 32 hex → 16 bytes
54
+
55
+ // 4. 序列化业务数据
56
+ const dataJson = typeof request.data === 'string' ? request.data : JSON.stringify(request.data);
57
+
58
+ // 5. SM4 加密(CBC + PKCS#7)
59
+ const encDataHex = sm4.encrypt(dataJson, keyHex, {
60
+ iv: ivHex,
61
+ mode: 'cbc',
62
+ padding: 'pkcs#7',
63
+ cipherType: 1, // hex output
64
+ });
65
+
66
+ // 6. 转换为最终格式(hex 或 base64)
67
+ const encData = useBase64 ? hexToBase64(encDataHex) : encDataHex;
68
+
69
+ // 7. 返回可传输对象(移除 data)
70
+ const {
71
+ data: _,
72
+ ...transmittable
73
+ } = {
74
+ ...request,
75
+ signData: signValue,
76
+ encData,
77
+ };
78
+ return transmittable;
79
+ }
80
+
81
+ /**
82
+ * 2️⃣ 验证签名(用于调试)
83
+ * @param {Object} request - 接收到的请求对象(含 signData, encData 等)
84
+ * @param {string} publicKey - 130位十六进制 SM2 公钥(以 "04" 开头)
85
+ * @param useBase64
86
+ * @returns {boolean}
87
+ */
88
+ export function verifySecureSign(request, publicKey, useBase64 = true) {
89
+ const signSource = objectToSignString(request, 'encData', 'signData', 'data');
90
+ const signatureHex = useBase64 ? base64ToHex(request.signData) : request.signData;
91
+ return sm2.doVerifySignature(signSource, signatureHex, publicKey, {
92
+ der: true
93
+ }) // 验签结果
94
+
95
+ }
96
+
97
+ /**
98
+ * 3️⃣ 解包安全数据:解密并返回原始 data
99
+ * @param {Object} request - 接收到的请求对象
100
+ * @param {string} privateKey - 64位十六进制 SM2 私钥(用于重算 key/iv)
101
+ * @param {boolean} [useBase64=false] - encData 是否为 Base64 编码
102
+ * @returns {any} 原始 data(自动 JSON.parse,若失败则返回字符串)
103
+ */
104
+ export function decryptSecureData(request, privateKey, useBase64 = true) {
105
+ // 1. 重算签名原文(用于生成 key/iv)
106
+ const signSource = objectToSignString(request, 'encData', 'signData', 'data');
107
+ const lvHax = md5_32(signSource);
108
+ const keyHax = md5_32(request.signData);
109
+
110
+ // 3. 处理 encData(base64 → hex)
111
+
112
+ const encDataHex = useBase64 ? base64ToHex(request.encData) : request.encData;
113
+
114
+ // 4. SM4 解密
115
+ const decrypted = sm4.decrypt(encDataHex, keyHax, {
116
+ iv: lvHax,
117
+ mode: 'cbc',
118
+ padding: 'pkcs#7',
119
+ cipherType: 1, // input is hex
120
+ });
121
+ // 5. 尝试解析 JSON
122
+ try {
123
+ return JSON.parse(decrypted);
124
+ } catch (e) {
125
+ return decrypted; // 原始字符串
126
+ }
127
+ }
128
+
129
+
130
+ /**
131
+ * 将对象转为签名字符串(排除指定字段 + 字典序)
132
+ */
133
+ function objectToSignString(obj, ...excludeFields) {
134
+ const excludes = new Set(excludeFields);
135
+ return Object.keys(obj)
136
+ .filter(key => !excludes.has(key))
137
+ .sort()
138
+ .map(key => `${key}=${obj[key] != null ? String(obj[key]) : ''}`)
139
+ .join('&');
140
+ }
141
+
142
+ /**
143
+ * 生成 MD5(32位小写 hex)
144
+ */
145
+ function md5_32(str) {
146
+ return md5(str);
147
+ }
package/package.json CHANGED
@@ -1,10 +1,11 @@
1
1
  {
2
2
  "name": "dream-common",
3
- "version": "1.1.36",
3
+ "version": "1.1.40",
4
4
  "description": "",
5
5
  "main": "index.js",
6
6
  "scripts": {
7
- "test": "echo \"Error: no test specified\" && exit 1"
7
+ "test": "echo \"Error: no test specified\" && exit 1",
8
+ "check:updates": "npx npm-check-updates"
8
9
  },
9
10
  "repository": {
10
11
  "type": "git",
@@ -14,8 +15,7 @@
14
15
  "license": "ISC",
15
16
  "dependencies": {
16
17
  "bs58": "^6.0.0",
17
- "crypto-js": "^4.2.0"
18
+ "crypto-js": "^4.2.0",
19
+ "sm-crypto": "^0.4.0"
18
20
  }
19
21
  }
20
-
21
-