Skip to content

Commit 145f424

Browse files
committed
refactor: ssl-pinning重写formData表单上传能力与cookie管理能力
1 parent d0b9898 commit 145f424

File tree

11 files changed

+504
-993
lines changed

11 files changed

+504
-993
lines changed

harmony/ssl_pinning/oh-package.json5

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,6 @@
66
"author": "",
77
"license": "Apache-2.0",
88
"dependencies": {
9-
"@rnoh/react-native-openharmony": "file:../react_native_openharmony",
10-
"@ohos/httpclient": "2.0.2"
9+
"@rnoh/react-native-openharmony": "file:../react_native_openharmony"
1110
}
1211
}

harmony/ssl_pinning/src/main/ets/cookies/CookieStore.ts renamed to harmony/ssl_pinning/src/main/ets/CookieStore.ts

Lines changed: 29 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -23,36 +23,53 @@
2323
*/
2424

2525
import dataStorage from '@ohos.data.storage'
26-
import featureAbility from '@ohos.ability.featureAbility'
27-
import { CookiePolicy } from './httpcookieutils';
28-
import { Logger } from '../Logger';
26+
import Logger from './Logger';
27+
2928

3029
function CookieStore(cacheDir) {
31-
var cookieJSON, path = null;
3230
this.path = cacheDir;
33-
console.info('httpclient- CookieStore path: ' + this.path);
31+
Logger.info('httpclient- CookieStore path: ' + this.path);
3432
}
3533

3634
CookieStore.prototype.setCacheDir = function setCacheDir(filePath) {
3735
this.path = filePath;
3836
}
3937
CookieStore.prototype.readCookie = function readCookie(hostname) {
40-
console.info('httpclient- CookieStore readCookie: ' + hostname);
41-
let storage = dataStorage.getStorageSync(this.path + '/cookiestore');
38+
Logger.info('httpclient- CookieStore readCookie: ' + hostname);
39+
let storage = dataStorage.getStorageSync(this.path + '/cookieStore');
4240
let cookieJSON = storage.getSync(hostname, '')
4341
storage.flushSync();
42+
Logger.info('httpclient- CookieStore readCookie: ' + cookieJSON);
4443
return cookieJSON;
4544
}
46-
CookieStore.prototype.writeCookie = function writeCookie(hostname, cookieJSON) {
47-
console.info('httpclient- CookieStore writeCookie: ' + hostname + ',cookieJSON:' + cookieJSON + ',path:' + this.path);
48-
let storage = dataStorage.getStorageSync(this.path + '/cookiestore');
45+
CookieStore.prototype.writeCookie = async function writeCookie(hostname, cookieJSON) {
46+
Logger.info('httpclient- CookieStore writeCookie: ' + hostname + ',cookieJSON:' + cookieJSON + ',path:' + this.path);
47+
let storage = dataStorage.getStorageSync(this.path + '/cookieStore');
48+
//保存所有的domain
49+
let allDomainKey: string = "allDomainKey"
50+
if (storage.hasSync(allDomainKey)) {
51+
let allDomain : string = JSON.stringify(await storage.get(allDomainKey,""));
52+
if (allDomain.search(hostname) == -1) {
53+
allDomain += allDomain.concat(";").concat(hostname)
54+
storage.putSync(allDomainKey, allDomain)
55+
}
56+
} else {
57+
storage.putSync(allDomainKey, hostname)
58+
}
59+
storage.putSync(hostname, cookieJSON)
60+
storage.flushSync();
61+
}
62+
63+
CookieStore.prototype.getCookieDomain = function getCookieDomain(hostname, cookieJSON) {
64+
Logger.info('httpclient- CookieStore writeCookie: ' + hostname + ',cookieJSON:' + cookieJSON + ',path:' + this.path);
65+
let storage = dataStorage.getStorageSync(this.path + '/cookieStore');
4966
storage.putSync(hostname, cookieJSON)
5067
storage.flushSync();
5168
}
5269

5370
CookieStore.prototype.deleteCookie = function deleteCookie(hostname) {
54-
console.info('httpclient- CookieStore deleteCookie: ' + hostname + ',path:' + this.path);
55-
let storage = dataStorage.getStorageSync(this.path + '/cookiestore');
71+
Logger.info('httpclient- CookieStore deleteCookie: ' + hostname + ',path:' + this.path);
72+
let storage = dataStorage.getStorageSync(this.path + '/cookieStore');
5673
storage.has(hostname, function (err, isExist) {
5774
if (isExist) {
5875
storage.delete(hostname, function (err) {

harmony/ssl_pinning/src/main/ets/CustomInterceptor.ts

Lines changed: 0 additions & 52 deletions
This file was deleted.
Lines changed: 223 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,223 @@
1+
/**
2+
* MIT License
3+
*
4+
* Copyright (C) 2024 Huawei Device Co., Ltd.
5+
*
6+
* Permission is hereby granted, free of charge, to any person obtaining a copy
7+
* of this software and associated documentation files (the "Software"), to deal
8+
* in the Software without restriction, including without limitation the rights
9+
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
10+
* copies of the Software, and to permit persons to whom the Software is
11+
* furnished to do so, subject to the following conditions:
12+
*
13+
* The above copyright notice and this permission notice shall be included in all
14+
* copies or substantial portions of the Software.
15+
*
16+
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
17+
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
18+
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
19+
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
20+
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
21+
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
22+
* SOFTWARE.
23+
*/
24+
25+
import {JSON, util } from '@kit.ArkTS';
26+
import hilog from '@ohos.hilog';
27+
import fs from '@ohos.file.fs';
28+
import { FetchOptions } from './EventType';
29+
import { http } from '@kit.NetworkKit';
30+
import { cert } from '@kit.DeviceCertificateKit';
31+
import { cryptoFramework } from '@kit.CryptoArchitectureKit';
32+
import { BusinessError } from '@kit.BasicServicesKit';
33+
import { Context } from '@kit.AbilityKit';
34+
import Logger from './Logger';
35+
36+
const TAG: string = "HandleParameterUtils --> "
37+
38+
export class HandleParameterUtils {
39+
static SHA_256: string = "sha256/"
40+
public static requestMethod(method: string): http.RequestMethod{
41+
if (method.toUpperCase().trim() == http.RequestMethod.OPTIONS) {
42+
return http.RequestMethod.OPTIONS;
43+
}
44+
if (method.toUpperCase().trim() == http.RequestMethod.GET) {
45+
return http.RequestMethod.GET;
46+
}
47+
if (method.toUpperCase().trim() == http.RequestMethod.HEAD) {
48+
return http.RequestMethod.HEAD;
49+
}
50+
if (method.toUpperCase().trim() == http.RequestMethod.POST) {
51+
return http.RequestMethod.POST;
52+
}
53+
if (method.toUpperCase().trim() == http.RequestMethod.PUT) {
54+
return http.RequestMethod.PUT;
55+
}
56+
if (method.toUpperCase().trim() == http.RequestMethod.DELETE) {
57+
return http.RequestMethod.DELETE;
58+
}
59+
if (method.toUpperCase().trim() == http.RequestMethod.TRACE) {
60+
return http.RequestMethod.TRACE;
61+
}
62+
if (method.toUpperCase().trim() == http.RequestMethod.CONNECT) {
63+
return http.RequestMethod.CONNECT;
64+
}
65+
}
66+
67+
public static handlePkPinning(options: FetchOptions): string {
68+
if (options.sslPinning) {
69+
if (options.sslPinning.certs) {
70+
if (options.pkPinning && Boolean(options.pkPinning)) {
71+
//公钥
72+
return "publicKeyHash";
73+
} else {
74+
return "certKeyHash";
75+
}
76+
} else {
77+
let message: string = "key certs was not found";
78+
hilog.info(0x0001, TAG, message);
79+
return message;
80+
}
81+
} else {
82+
//无证书
83+
let message: string = "sslPinning key was not exist";
84+
hilog.info(0x0001, TAG, message);
85+
return message;
86+
}
87+
}
88+
89+
//Obtain the SHA256 summary of the public key corresponding to the certificate file
90+
static async getPubKeyHashFromCert(filePath: string, context: Context): Promise<string[]>{
91+
let result: string[] = [];
92+
let certUnit8Array: Uint8Array = await this.getCAContent(filePath, context);
93+
let certStr: string = this.uint8ArrayToString(certUnit8Array);
94+
if (certStr) {
95+
if (certStr.search(this.SHA_256) >= 0) {
96+
let pubKeyHash: string[] = certStr.split(this.SHA_256);
97+
pubKeyHash.forEach((pin: string) => {
98+
if (pin.trim().length > 0) {
99+
result.push(pin.trim());
100+
}
101+
})
102+
return result;
103+
} else {
104+
return await this.getPubKeyHash(certUnit8Array, filePath, context);
105+
}
106+
}
107+
}
108+
109+
//Get the file contents
110+
static async getCAContent(ca: string, context: Context): Promise<Uint8Array> {
111+
if (!ca) {
112+
return new Uint8Array();
113+
}
114+
const value: Uint8Array = await new Promise<Uint8Array>(resolve => {
115+
context.resourceManager.getRawFileContent(
116+
ca,
117+
(err: BusinessError, value) => {
118+
if (err) {
119+
throw new Error(JSON.stringify(err));
120+
}
121+
resolve(value);
122+
});
123+
})
124+
return value;
125+
}
126+
127+
// Bytes are rounded into understandable strings
128+
static uint8ArrayToString(array: Uint8Array) {
129+
// Convert UTF-8 encoding to Unicode encoding
130+
let out: string = '';
131+
let index: number = 0;
132+
let len: number = array.length;
133+
while (index < len) {
134+
let character = array[index++];
135+
switch (character >> 4) {
136+
case 0:
137+
case 1:
138+
case 2:
139+
case 3:
140+
case 4:
141+
case 5:
142+
case 6:
143+
case 7:
144+
out += String.fromCharCode(character);
145+
break;
146+
case 12:
147+
case 13:
148+
out += String.fromCharCode(((character & 0x1F) << 6) | (array[index++] & 0x3F));
149+
break;
150+
case 14:
151+
out += String.fromCharCode(((character & 0x0F) << 12) | ((array[index++] & 0x3F) << 6) |
152+
((array[index++] & 0x3F) << 0));
153+
break;
154+
default:
155+
break;
156+
}
157+
}
158+
Logger.info('字节流转成字符串:' + out);
159+
return out;
160+
}
161+
162+
//Obtain the SHA256 summary of the public key corresponding to the Uint8Array
163+
static async getPubKeyHash(certUint8Array: Uint8Array, filePath: string, context: Context): Promise<string[]> {
164+
let result: string[] = [];
165+
if (filePath != "") {
166+
let fixedCert: cert.X509Cert | undefined = await this.getCertFromFile(certUint8Array)
167+
if (fixedCert) {
168+
try {
169+
//获取公钥
170+
let pubKey = fixedCert.getItem(cert.CertItemType.CERT_ITEM_TYPE_PUBLIC_KEY);
171+
let mdSHA256 = cryptoFramework.createMd("SHA256")
172+
mdSHA256.updateSync({ data: pubKey.data });
173+
//公钥摘要计算结果
174+
let mdResult = mdSHA256.digestSync();
175+
let tool = new util.Base64Helper()
176+
//公钥摘要转换为base64编码字符串
177+
result.push(tool.encodeToStringSync(mdResult.data))
178+
Logger.info("getPubKeyHash:" + result)
179+
} catch (e) {
180+
Logger.info('获取公钥摘要失败 ' + e.message);
181+
}
182+
}
183+
}
184+
return result
185+
}
186+
187+
//从文件获取X509证书
188+
static async getCertFromFile(certData: Uint8Array): Promise<cert.X509Cert | undefined> {
189+
let newCert: cert.X509Cert | undefined = undefined
190+
// let certData: Uint8Array = await this.getCAContent(filePath, context);
191+
if (certData) {
192+
let encodingBlob: cert.EncodingBlob = {
193+
data: certData,
194+
encodingFormat: cert.EncodingFormat.FORMAT_PEM
195+
};
196+
await cert.createX509Cert(encodingBlob)
197+
.then((x509Cert: cert.X509Cert) => {
198+
newCert = x509Cert
199+
})
200+
.catch((err: BusinessError) => {
201+
Logger.info(`创建X509证书失败:err code is ${err.code}, err message is ${JSON.stringify(err)}`);
202+
})
203+
}
204+
return newCert
205+
}
206+
207+
//加载文件内容
208+
static getContent(filePath: string): ArrayBuffer | undefined {
209+
let content: ArrayBuffer | undefined = undefined
210+
try {
211+
let buf = new ArrayBuffer(1024 * 64);
212+
let file = fs.openSync(filePath, fs.OpenMode.READ_ONLY);
213+
let readLen = fs.readSync(file.fd, buf, { offset: 0 });
214+
content = buf.slice(0, readLen)
215+
fs.closeSync(file);
216+
} catch (e) {
217+
Logger.info('读取文件内容失败 ' + e.message);
218+
}
219+
return content
220+
}
221+
222+
}
223+

0 commit comments

Comments
 (0)