@tmsfe/tms-core 0.0.158 → 0.0.160
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/package.json +1 -1
- package/src/encrypt/encrypt-util.ts +114 -30
- package/src/encrypt/index.ts +30 -16
- package/src/encrypt/md5.js +1 -0
- package/src/md5.js +1 -1
- package/src/navbarUtils.js +1 -1
package/package.json
CHANGED
|
@@ -3,6 +3,7 @@
|
|
|
3
3
|
* 暴露出来的工具函数封装原则:不可以向外throw错误,返回执行结果统一格式:{ success: boolean, msg: string, res: any }
|
|
4
4
|
* https://iwiki.woa.com/p/4013041987#1.-RSA+AES-%E5%88%87%E6%8D%A2-Curve25519+XSalsa20%EF%BC%9A
|
|
5
5
|
*/
|
|
6
|
+
import md5 from './md5';
|
|
6
7
|
/* eslint-disable @typescript-eslint/no-require-imports */
|
|
7
8
|
const ecc = require('./nacl.min.js');
|
|
8
9
|
const base64Util = require('./nacl-util.min.js');
|
|
@@ -106,12 +107,10 @@ const eccUtil = {
|
|
|
106
107
|
method: 'POST',
|
|
107
108
|
data,
|
|
108
109
|
enableHttp2: true,
|
|
109
|
-
success: (
|
|
110
|
-
|
|
111
|
-
resolve(success);
|
|
110
|
+
success: () => {
|
|
111
|
+
resolve(true);
|
|
112
112
|
},
|
|
113
113
|
fail: () => {
|
|
114
|
-
eccUtil._updateGlobalPublicKeyInfo(true);
|
|
115
114
|
resolve(false);
|
|
116
115
|
},
|
|
117
116
|
});
|
|
@@ -135,10 +134,10 @@ const eccUtil = {
|
|
|
135
134
|
return new baseUtil.BaseRespFac(success);
|
|
136
135
|
},
|
|
137
136
|
_privateKeyInfo: null,
|
|
138
|
-
getPrivateKeyInfo: (): CryptoKeyInfo => {
|
|
137
|
+
getPrivateKeyInfo: (forceUpdate = false): CryptoKeyInfo => {
|
|
139
138
|
if (!wx.$_publicKey) return null;
|
|
140
139
|
const serverPubInfo = wx.$_publicKey;
|
|
141
|
-
if (!eccUtil._privateKeyInfo || eccUtil._privateKeyInfo.serverPubId !== serverPubInfo.pubId) {
|
|
140
|
+
if (forceUpdate || !eccUtil._privateKeyInfo || eccUtil._privateKeyInfo.serverPubId !== serverPubInfo.pubId) {
|
|
142
141
|
const keyPair = ecc.box.keyPair(); // 生成客户端公钥私钥
|
|
143
142
|
eccUtil._privateKeyInfo = {
|
|
144
143
|
serverPubId: serverPubInfo.pubId, // 服务端公钥id
|
|
@@ -156,27 +155,83 @@ const eccUtil = {
|
|
|
156
155
|
switch (code) {
|
|
157
156
|
case 0:
|
|
158
157
|
return { retry: false, success: true };
|
|
159
|
-
case
|
|
160
|
-
return { retry: false, success: false };
|
|
161
|
-
case 11305: // 公钥id无效
|
|
158
|
+
case 11305: // 公钥id无效
|
|
162
159
|
case 11306: { // 公钥过期
|
|
163
|
-
|
|
164
|
-
|
|
165
|
-
|
|
160
|
+
// 1. 获取公钥
|
|
161
|
+
eccUtil._refreshPubKeyInfo(true).then((genPubSuccess) => {
|
|
162
|
+
genPubSuccess && eccUtil.getPrivateKeyInfo(); // 2. 生成私钥
|
|
163
|
+
});
|
|
166
164
|
return { retry: true, success: false };
|
|
167
165
|
}
|
|
168
|
-
case
|
|
169
|
-
|
|
166
|
+
case 11308: { // 密钥对有问题
|
|
167
|
+
eccUtil.getPrivateKeyInfo(true); // 重新生成私钥
|
|
168
|
+
return { retry: true, success: false };
|
|
169
|
+
}
|
|
170
|
+
case 11300: // 解密失败
|
|
170
171
|
case 11301:
|
|
171
172
|
case 11302:
|
|
172
173
|
case 11303:
|
|
173
174
|
case 11304:
|
|
174
|
-
case
|
|
175
|
+
case 11307: // 加密未开启
|
|
176
|
+
return { retry: true, success: false };
|
|
177
|
+
case 11309:
|
|
175
178
|
return { retry: false, success: false };
|
|
176
179
|
default: // 其他网关错误码
|
|
177
180
|
return { retry: false, success: true };
|
|
178
181
|
}
|
|
179
182
|
},
|
|
183
|
+
_getSignSharedByte: () => baseUtil.decUrl('mEufQpM1n5J8-OZZoJE7ucYMC2suTjfsHUq_6z5cyh8'),
|
|
184
|
+
// 计算客户端加密签名
|
|
185
|
+
getClientCryptoSign: (data = {}, header = {}, sharedByte): string => {
|
|
186
|
+
const obj = baseUtil.formatHeader(Object.assign({}, data, header));
|
|
187
|
+
// 1. 生成签名前的字符串
|
|
188
|
+
const str = Object.keys(obj).filter(item => obj[item])
|
|
189
|
+
.sort()
|
|
190
|
+
.reduce((pre, cur) => {
|
|
191
|
+
pre.push(`${cur}=${obj[cur]}`);
|
|
192
|
+
return pre;
|
|
193
|
+
}, [])
|
|
194
|
+
.join('&');
|
|
195
|
+
// 2. md5
|
|
196
|
+
const md5Str = md5(str);
|
|
197
|
+
const nonce = ecc.randomBytes(ecc.box.nonceLength);
|
|
198
|
+
const encrypted = ecc.box.after(md5Str, nonce, sharedByte);
|
|
199
|
+
const combined = new Uint8Array(nonce.length + encrypted.length);
|
|
200
|
+
combined.set(nonce);
|
|
201
|
+
combined.set(encrypted, nonce.length);
|
|
202
|
+
return baseUtil.encUrl(combined);
|
|
203
|
+
},
|
|
204
|
+
// 验证服务端加密签名
|
|
205
|
+
verifyServerCryptoSign: (traceId: string, resHeader = {}): boolean => {
|
|
206
|
+
const formatHeader = baseUtil.formatHeader(resHeader);
|
|
207
|
+
const signStr = formatHeader['x-crypto-sign'];
|
|
208
|
+
const obj = {
|
|
209
|
+
'x-encrypt-key': formatHeader['x-encrypt-key'],
|
|
210
|
+
'x-encrypt-response': formatHeader['x-encrypt-response'],
|
|
211
|
+
'x-response-header-name': formatHeader['x-response-header-name'],
|
|
212
|
+
'x-encrypted-headers': formatHeader['x-encrypted-headers'],
|
|
213
|
+
'x-crypto-enable': formatHeader['x-crypto-enable'],
|
|
214
|
+
'content-type': formatHeader['content-type'],
|
|
215
|
+
'x-gateway-code': formatHeader['x-gateway-code'],
|
|
216
|
+
'x-crypto-pub-id': formatHeader['x-crypto-pub-id'],
|
|
217
|
+
'x-crypto-pub-key': formatHeader['x-crypto-pub-key'],
|
|
218
|
+
'x-crypto-pub-exp': formatHeader['x-crypto-pub-exp'],
|
|
219
|
+
'x-crypto-path': formatHeader['x-crypto-path'],
|
|
220
|
+
'x-trace-id': traceId,
|
|
221
|
+
};
|
|
222
|
+
const msg = baseUtil.decUrl(signStr);
|
|
223
|
+
const decrypted = ecc.sign.open(msg, eccUtil._getSignSharedByte());
|
|
224
|
+
const str = Object.keys(obj).filter(item => obj[item])
|
|
225
|
+
.sort()
|
|
226
|
+
.reduce((pre, cur) => {
|
|
227
|
+
pre.push(`${cur}=${obj[cur]}`);
|
|
228
|
+
return pre;
|
|
229
|
+
}, [])
|
|
230
|
+
.join('&');
|
|
231
|
+
const preHashArr = md5(str);
|
|
232
|
+
const verified = preHashArr.length === decrypted.length && preHashArr.every((v, i) => v === decrypted[i]);
|
|
233
|
+
return verified;
|
|
234
|
+
},
|
|
180
235
|
/* eslint-enable complexity */
|
|
181
236
|
execEncrypt: (input: string, ignoreNull = false): BaseResp<{
|
|
182
237
|
cryptoKeyInfo: CryptoKeyInfo,
|
|
@@ -357,23 +412,30 @@ const reqEncrypt = (method: string, data: any, header: {
|
|
|
357
412
|
if (!success) {
|
|
358
413
|
return new baseUtil.BaseRespFac(null, false, `请求Header加密失败: ${msg}`);
|
|
359
414
|
}
|
|
415
|
+
const cryptoHeader = {
|
|
416
|
+
'X-Crypto-Mode': '2', // ecc加密模式
|
|
417
|
+
'X-Encrypted-Headers': res.encryptedContent,
|
|
418
|
+
'X-Encrypt-Pub': res.cryptoKeyInfo.serverPubId,
|
|
419
|
+
'X-Encrypt-Key': res.cryptoKeyInfo.clientPublicKey,
|
|
420
|
+
'X-Encrypt-Response': '3', // 加密,二进制
|
|
421
|
+
'X-Response-Header-Name': encryptedResponseHeaderName,
|
|
422
|
+
'Content-Type': 'text/plain',
|
|
423
|
+
};
|
|
424
|
+
const cryptoSign = eccUtil.getClientCryptoSign(baseUtil._isObject(finalData) ? finalData : {
|
|
425
|
+
body: finalData,
|
|
426
|
+
}, cryptoHeader, res.cryptoKeyInfo.sharedByte);
|
|
360
427
|
return new baseUtil.BaseRespFac({
|
|
361
428
|
cryptoKeyInfo: res.cryptoKeyInfo,
|
|
362
429
|
data: finalData,
|
|
363
430
|
header: {
|
|
364
|
-
|
|
365
|
-
'X-Crypto-
|
|
366
|
-
'X-Encrypted-Headers': res.encryptedContent,
|
|
367
|
-
'X-Encrypt-Pub': res.cryptoKeyInfo.serverPubId,
|
|
368
|
-
'X-Encrypt-Key': res.cryptoKeyInfo.clientPublicKey,
|
|
369
|
-
'X-Encrypt-Response': '3', // 加密,二进制
|
|
370
|
-
'X-Response-Header-Name': encryptedResponseHeaderName,
|
|
431
|
+
...cryptoHeader,
|
|
432
|
+
'X-Crypto-Sign': cryptoSign,
|
|
371
433
|
},
|
|
372
434
|
});
|
|
373
435
|
};
|
|
374
436
|
// 解密请求结果
|
|
375
|
-
const resDecrypt = async (header, data, cryptoKeyInfo: CryptoKeyInfo): Promise<BaseResp<{
|
|
376
|
-
retry: boolean,
|
|
437
|
+
const resDecrypt = async (requestTraceId: string, header, data, cryptoKeyInfo: CryptoKeyInfo): Promise<BaseResp<{
|
|
438
|
+
retry: boolean, // 是否需要明文重试
|
|
377
439
|
header: any,
|
|
378
440
|
data: any,
|
|
379
441
|
}>> => {
|
|
@@ -397,13 +459,19 @@ const resDecrypt = async (header, data, cryptoKeyInfo: CryptoKeyInfo): Promise<B
|
|
|
397
459
|
}
|
|
398
460
|
const { retry, success: gwSuccess } = await eccUtil.resolveGwCode(gatewayCode);
|
|
399
461
|
if (!gwSuccess) {
|
|
462
|
+
// 网关加密流程出现问题,需要验证网关签名
|
|
463
|
+
const verified = eccUtil.verifyServerCryptoSign(requestTraceId, header);
|
|
464
|
+
if (!verified) {
|
|
465
|
+
// 验证失败,表示请求被篡改
|
|
466
|
+
return new baseUtil.BaseRespFac({ header: null, data: null, retry: false }, false, '响应被篡改');
|
|
467
|
+
}
|
|
400
468
|
return new baseUtil.BaseRespFac({ header: null, data: null, retry }, false, `网关返回错误码: ${gatewayCode}`);
|
|
401
469
|
}
|
|
402
470
|
let decryptedHeaders = {};
|
|
403
471
|
if (encryptedResponseHeaderName) { // 解密响应Header
|
|
404
472
|
const { success, msg, res } = eccUtil.execDecrypt(baseUtil.decUrl(encryptedHeaders), cryptoKeyInfo);
|
|
405
473
|
if (!success) {
|
|
406
|
-
return new baseUtil.BaseRespFac({ header: null, data: null, retry:
|
|
474
|
+
return new baseUtil.BaseRespFac({ header: null, data: null, retry: true }, false, `解密响应Header失败: ${msg}`);
|
|
407
475
|
}
|
|
408
476
|
decryptedHeaders = JSON.parse(res);
|
|
409
477
|
}
|
|
@@ -411,7 +479,7 @@ const resDecrypt = async (header, data, cryptoKeyInfo: CryptoKeyInfo): Promise<B
|
|
|
411
479
|
const cipher = needDecode ? baseUtil.decUrl(data) : new Uint8Array(data);
|
|
412
480
|
const { success, msg, res } = eccUtil.execDecrypt(cipher, cryptoKeyInfo);
|
|
413
481
|
if (!success) {
|
|
414
|
-
return new baseUtil.BaseRespFac({ header: null, data: null, retry:
|
|
482
|
+
return new baseUtil.BaseRespFac({ header: null, data: null, retry: true }, false, `解密响应Body失败: ${msg}`);
|
|
415
483
|
}
|
|
416
484
|
const decryptedBody = JSON.parse(res); // 解密响应Body
|
|
417
485
|
return new baseUtil.BaseRespFac({
|
|
@@ -424,24 +492,40 @@ const resDecrypt = async (header, data, cryptoKeyInfo: CryptoKeyInfo): Promise<B
|
|
|
424
492
|
});
|
|
425
493
|
} catch (e) {
|
|
426
494
|
// 因为上面的逻辑有parse, 所以这里再加一个catch
|
|
427
|
-
return new baseUtil.BaseRespFac({ header: null, data: null, retry:
|
|
495
|
+
return new baseUtil.BaseRespFac({ header: null, data: null, retry: true }, false, `解密响应Body失败: ${JSON.stringify(e)}`);
|
|
428
496
|
}
|
|
429
497
|
};
|
|
430
498
|
// 处理接下来的请求开关
|
|
431
499
|
let dealEncryptionSwitching = false;
|
|
432
|
-
const dealEncryptionSwitch = async (path: string, resHeader): Promise<
|
|
500
|
+
const dealEncryptionSwitch = async (path: string, traceId: string, resHeader): Promise<boolean> => {
|
|
433
501
|
if ((!resHeader || dealEncryptionSwitching)) {
|
|
434
502
|
return;
|
|
435
503
|
}
|
|
436
504
|
dealEncryptionSwitching = true;
|
|
437
505
|
const formatHeader = baseUtil.formatHeader(resHeader);
|
|
438
506
|
if (formatHeader['x-crypto-enable'] === '0') {
|
|
439
|
-
|
|
507
|
+
// 网关加密验签,验签通过才能执行关闭
|
|
508
|
+
const verified = eccUtil.verifyServerCryptoSign(traceId, formatHeader);
|
|
509
|
+
if (verified) {
|
|
510
|
+
eccUtil.closeCrypto();
|
|
511
|
+
}
|
|
440
512
|
} else if (formatHeader['x-crypto-enable'] === '1') {
|
|
441
|
-
|
|
513
|
+
if ([
|
|
514
|
+
`${baseUtil.getSinanHost()}/user/login`,
|
|
515
|
+
`${baseUtil.getSinanHost()}/basic/crypto/lastkey`,
|
|
516
|
+
].indexOf(path) > -1) {
|
|
517
|
+
const verified = eccUtil.verifyServerCryptoSign(traceId, formatHeader);
|
|
518
|
+
if (!verified) {
|
|
519
|
+
// 验签失败,表示请求被篡改
|
|
520
|
+
dealEncryptionSwitching = false;
|
|
521
|
+
return false;
|
|
522
|
+
}
|
|
523
|
+
eccUtil._updateGlobalPublicKeyInfo(false, formatHeader);
|
|
524
|
+
}
|
|
442
525
|
await eccUtil.openCrypto();
|
|
443
526
|
} // 0是关闭,1是开启, 2是保持
|
|
444
527
|
dealEncryptionSwitching = false;
|
|
528
|
+
return true;
|
|
445
529
|
};
|
|
446
530
|
|
|
447
531
|
const encryptUtil = {
|
package/src/encrypt/index.ts
CHANGED
|
@@ -71,6 +71,7 @@ function proxyWxRequest(): void {
|
|
|
71
71
|
value(options: any) {
|
|
72
72
|
const { url, method, data, header = {}, success, fail, complete, dataType, responseType } = options;
|
|
73
73
|
const traceparent = genTraceparent();
|
|
74
|
+
const traceId = traceparent.split('-')[1];
|
|
74
75
|
const originalOptions = { ...options };
|
|
75
76
|
|
|
76
77
|
// 如果用户自定义了dataType或者responseType,则不做处理
|
|
@@ -79,7 +80,7 @@ function proxyWxRequest(): void {
|
|
|
79
80
|
originalRequestApi.call(this, {
|
|
80
81
|
...originalOptions,
|
|
81
82
|
success: (res) => {
|
|
82
|
-
encryptUtil.dealEncryptionSwitch(url, res.header);
|
|
83
|
+
encryptUtil.dealEncryptionSwitch(url, traceId, res.header);
|
|
83
84
|
success?.call(this, res);
|
|
84
85
|
},
|
|
85
86
|
header: { ...header, Traceparent: traceparent },
|
|
@@ -94,9 +95,14 @@ function proxyWxRequest(): void {
|
|
|
94
95
|
util.logInfo(url, traceparent, msg);
|
|
95
96
|
originalRequestApi.call(this, {
|
|
96
97
|
...originalOptions,
|
|
97
|
-
success: (res) => {
|
|
98
|
-
encryptUtil.dealEncryptionSwitch(url, res.header);
|
|
99
|
-
|
|
98
|
+
success: async (res) => {
|
|
99
|
+
const dealSuccess = await encryptUtil.dealEncryptionSwitch(url, traceId, res.header);
|
|
100
|
+
if (dealSuccess) {
|
|
101
|
+
success?.call(this, res);
|
|
102
|
+
} else {
|
|
103
|
+
util.reportFunc(url, traceparent, `加密验签不通过: ${JSON.stringify(res)}`);
|
|
104
|
+
fail?.call(this, new Error('加密验签不通过'));
|
|
105
|
+
}
|
|
100
106
|
},
|
|
101
107
|
header: { ...header, Traceparent: traceparent },
|
|
102
108
|
});
|
|
@@ -115,26 +121,34 @@ function proxyWxRequest(): void {
|
|
|
115
121
|
responseType: 'arraybuffer',
|
|
116
122
|
success: async (result) => {
|
|
117
123
|
const { header: resHeader, data: resData } = result;
|
|
118
|
-
const { success:
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
encryptUtil.dealEncryptionSwitch(url, resHeader);
|
|
122
|
-
success?.call(this, res);
|
|
123
|
-
const completeRes: any = await completePromp;
|
|
124
|
-
completeRes.header = resHeader;
|
|
125
|
-
completeRes.data = resData;
|
|
126
|
-
complete?.call(this, completeRes);
|
|
127
|
-
} else {
|
|
124
|
+
const { success: decSuccess, msg, res } = await encryptUtil
|
|
125
|
+
.resDecrypt(traceId, resHeader, resData, cryptoKeyInfo);
|
|
126
|
+
if (res.retry) { // 解密出现问题,需要明文重试
|
|
128
127
|
util.reportFunc(url, traceparent, `解密失败:${msg}`);
|
|
128
|
+
const newTraceparent = genTraceparent();
|
|
129
|
+
const traceId = newTraceparent.split('-')[1];
|
|
129
130
|
originalRequestApi.call(this, {
|
|
130
131
|
...originalOptions,
|
|
131
132
|
success: (res) => {
|
|
132
|
-
encryptUtil.dealEncryptionSwitch(url, res.header);
|
|
133
|
+
encryptUtil.dealEncryptionSwitch(url, traceId, res.header);
|
|
133
134
|
success?.call(this, res);
|
|
134
135
|
},
|
|
135
|
-
header: { ...header, Traceparent:
|
|
136
|
+
header: { ...header, Traceparent: newTraceparent },
|
|
136
137
|
});
|
|
138
|
+
return;
|
|
139
|
+
}
|
|
140
|
+
if (decSuccess) {
|
|
141
|
+
util.logInfo(url, traceparent, '解密成功');
|
|
142
|
+
encryptUtil.dealEncryptionSwitch(url, traceId, resHeader);
|
|
143
|
+
success?.call(this, res);
|
|
144
|
+
} else { // 不支持明文重试,且解密失败
|
|
145
|
+
util.reportFunc(url, traceparent, `解密失败:${msg}`);
|
|
146
|
+
fail?.call(this, new Error(msg));
|
|
137
147
|
}
|
|
148
|
+
const completeRes: any = await completePromp;
|
|
149
|
+
completeRes.header = resHeader;
|
|
150
|
+
completeRes.data = resData;
|
|
151
|
+
complete?.call(this, completeRes);
|
|
138
152
|
},
|
|
139
153
|
fail: async (err) => {
|
|
140
154
|
fail?.call(this, err);
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
function safeAdd(x,y){const lsw=(x&0xffff)+(y&0xffff);const msw=(x>>16)+(y>>16)+(lsw>>16);return(msw<<16)|(lsw&0xffff)}function bitRotateLeft(num,cnt){return(num<<cnt)|(num>>>(32-cnt))}function md5cmn(q,a,b,x,s,t){return safeAdd(bitRotateLeft(safeAdd(safeAdd(a,q),safeAdd(x,t)),s),b)}function md5ff(a,b,c,d,x,s,t){return md5cmn((b&c)|(~b&d),a,b,x,s,t)}function md5gg(a,b,c,d,x,s,t){return md5cmn((b&d)|(c&~d),a,b,x,s,t)}function md5hh(a,b,c,d,x,s,t){return md5cmn(b^c^d,a,b,x,s,t)}function md5ii(a,b,c,d,x,s,t){return md5cmn(c^(b|~d),a,b,x,s,t)}function binlMD5(x,len){x[len>>5]|=0x80<<len%32;x[(((len+64)>>>9)<<4)+14]=len;let a=1732584193;let b=-271733879;let c=-1732584194;let d=271733878;for(let i=0;i<x.length;i+=16){const olda=a;const oldb=b;const oldc=c;const oldd=d;a=md5ff(a,b,c,d,x[i],7,-680876936);d=md5ff(d,a,b,c,x[i+1],12,-389564586);c=md5ff(c,d,a,b,x[i+2],17,606105819);b=md5ff(b,c,d,a,x[i+3],22,-1044525330);a=md5ff(a,b,c,d,x[i+4],7,-176418897);d=md5ff(d,a,b,c,x[i+5],12,1200080426);c=md5ff(c,d,a,b,x[i+6],17,-1473231341);b=md5ff(b,c,d,a,x[i+7],22,-45705983);a=md5ff(a,b,c,d,x[i+8],7,1770035416);d=md5ff(d,a,b,c,x[i+9],12,-1958414417);c=md5ff(c,d,a,b,x[i+10],17,-42063);b=md5ff(b,c,d,a,x[i+11],22,-1990404162);a=md5ff(a,b,c,d,x[i+12],7,1804603682);d=md5ff(d,a,b,c,x[i+13],12,-40341101);c=md5ff(c,d,a,b,x[i+14],17,-1502002290);b=md5ff(b,c,d,a,x[i+15],22,1236535329);a=md5gg(a,b,c,d,x[i+1],5,-165796510);d=md5gg(d,a,b,c,x[i+6],9,-1069501632);c=md5gg(c,d,a,b,x[i+11],14,643717713);b=md5gg(b,c,d,a,x[i],20,-373897302);a=md5gg(a,b,c,d,x[i+5],5,-701558691);d=md5gg(d,a,b,c,x[i+10],9,38016083);c=md5gg(c,d,a,b,x[i+15],14,-660478335);b=md5gg(b,c,d,a,x[i+4],20,-405537848);a=md5gg(a,b,c,d,x[i+9],5,568446438);d=md5gg(d,a,b,c,x[i+14],9,-1019803690);c=md5gg(c,d,a,b,x[i+3],14,-187363961);b=md5gg(b,c,d,a,x[i+8],20,1163531501);a=md5gg(a,b,c,d,x[i+13],5,-1444681467);d=md5gg(d,a,b,c,x[i+2],9,-51403784);c=md5gg(c,d,a,b,x[i+7],14,1735328473);b=md5gg(b,c,d,a,x[i+12],20,-1926607734);a=md5hh(a,b,c,d,x[i+5],4,-378558);d=md5hh(d,a,b,c,x[i+8],11,-2022574463);c=md5hh(c,d,a,b,x[i+11],16,1839030562);b=md5hh(b,c,d,a,x[i+14],23,-35309556);a=md5hh(a,b,c,d,x[i+1],4,-1530992060);d=md5hh(d,a,b,c,x[i+4],11,1272893353);c=md5hh(c,d,a,b,x[i+7],16,-155497632);b=md5hh(b,c,d,a,x[i+10],23,-1094730640);a=md5hh(a,b,c,d,x[i+13],4,681279174);d=md5hh(d,a,b,c,x[i],11,-358537222);c=md5hh(c,d,a,b,x[i+3],16,-722521979);b=md5hh(b,c,d,a,x[i+6],23,76029189);a=md5hh(a,b,c,d,x[i+9],4,-640364487);d=md5hh(d,a,b,c,x[i+12],11,-421815835);c=md5hh(c,d,a,b,x[i+15],16,530742520);b=md5hh(b,c,d,a,x[i+2],23,-995338651);a=md5ii(a,b,c,d,x[i],6,-198630844);d=md5ii(d,a,b,c,x[i+7],10,1126891415);c=md5ii(c,d,a,b,x[i+14],15,-1416354905);b=md5ii(b,c,d,a,x[i+5],21,-57434055);a=md5ii(a,b,c,d,x[i+12],6,1700485571);d=md5ii(d,a,b,c,x[i+3],10,-1894986606);c=md5ii(c,d,a,b,x[i+10],15,-1051523);b=md5ii(b,c,d,a,x[i+1],21,-2054922799);a=md5ii(a,b,c,d,x[i+8],6,1873313359);d=md5ii(d,a,b,c,x[i+15],10,-30611744);c=md5ii(c,d,a,b,x[i+6],15,-1560198380);b=md5ii(b,c,d,a,x[i+13],21,1309151649);a=md5ii(a,b,c,d,x[i+4],6,-145523070);d=md5ii(d,a,b,c,x[i+11],10,-1120210379);c=md5ii(c,d,a,b,x[i+2],15,718787259);b=md5ii(b,c,d,a,x[i+9],21,-343485551);a=safeAdd(a,olda);b=safeAdd(b,oldb);c=safeAdd(c,oldc);d=safeAdd(d,oldd)}return[a,b,c,d]}function binl2rstr(input){let output='';const length32=input.length*32;for(let i=0;i<length32;i+=8){output+=String.fromCharCode((input[i>>5]>>>i%32)&0xff)}return output}function rstr2binl(input){const output=[];output[(input.length>>2)-1]=undefined;for(let i=0;i<output.length;i+=1){output[i]=0}const length8=input.length*8;for(let i=0;i<length8;i+=8){output[i>>5]|=(input.charCodeAt(i/8)&0xff)<<i%32}return output}function rstrMD5(s){return binl2rstr(binlMD5(rstr2binl(s),s.length*8))}function str2rstrUTF8(input){return unescape(encodeURIComponent(input))}function rawMD5(s){return rstrMD5(str2rstrUTF8(s))}function rstr2uint8array(input){const output=new Uint8Array(input.length);for(let i=0;i<input.length;i++){output[i]=input.charCodeAt(i)}return output}function md5(string){return rstr2uint8array(rawMD5(string))}export default md5;
|
package/src/md5.js
CHANGED
|
@@ -356,7 +356,7 @@ function hexHMACMD5(k, d) {
|
|
|
356
356
|
*
|
|
357
357
|
* @param {string} string Input string
|
|
358
358
|
* @param {string} [key] HMAC key
|
|
359
|
-
* @param {
|
|
359
|
+
* @param {string} [raw] Raw output switch
|
|
360
360
|
* @returns {string} MD5 output
|
|
361
361
|
*/
|
|
362
362
|
function md5(string, key, raw) {
|
package/src/navbarUtils.js
CHANGED
|
@@ -151,7 +151,7 @@ const getNavBarConfigData = () => { // eslint-disable-line require-jsdoc
|
|
|
151
151
|
statusBarHeight = isIOS ? StatusBarHeightOnIOS : StatusBarHeightOnAndroid;
|
|
152
152
|
}
|
|
153
153
|
|
|
154
|
-
const enable = compareVersion(version, '7.0.0') >= 0 || brand === 'devtools'; // 微信版本是否支持自定义顶栏,不支持时自动隐藏
|
|
154
|
+
const enable = compareVersion(version, '7.0.0') >= 0 || brand === 'devtools' || platform === 'ohos'; // 微信版本是否支持自定义顶栏,不支持时自动隐藏
|
|
155
155
|
const enterOptions = getEnterOptions();
|
|
156
156
|
if (enable) {
|
|
157
157
|
return { enable, ...calculateNavBarLayout(isIOS, statusBarHeight, enterOptions.apiCategory) };
|