dream-common 1.1.39 → 1.1.41

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