Skip to content

Commit 74e3304

Browse files
Merge pull request #6 from li2qi/sig
refactor: ssl-pinning重写formData表单上传能力与cookie管理能力
2 parents 5846520 + f323d86 commit 74e3304

File tree

11 files changed

+500
-993
lines changed

11 files changed

+500
-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: 219 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,219 @@
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+
switch (method.toUpperCase().trim()) {
42+
case http.RequestMethod.OPTIONS.valueOf():
43+
return http.RequestMethod.OPTIONS;
44+
case http.RequestMethod.GET.valueOf():
45+
return http.RequestMethod.GET;
46+
case http.RequestMethod.HEAD.valueOf():
47+
return http.RequestMethod.HEAD;
48+
case http.RequestMethod.POST.valueOf():
49+
return http.RequestMethod.POST;
50+
case http.RequestMethod.PUT.valueOf():
51+
return http.RequestMethod.PUT;
52+
case http.RequestMethod.DELETE.valueOf():
53+
return http.RequestMethod.DELETE;
54+
case http.RequestMethod.TRACE.valueOf():
55+
return http.RequestMethod.TRACE;
56+
case http.RequestMethod.CONNECT.valueOf():
57+
return http.RequestMethod.CONNECT;
58+
default :
59+
return http.RequestMethod.POST;
60+
}
61+
}
62+
63+
public static handlePkPinning(options: FetchOptions): string {
64+
if (options.sslPinning) {
65+
if (options.sslPinning.certs) {
66+
if (options.pkPinning && Boolean(options.pkPinning)) {
67+
//公钥
68+
return "publicKeyHash";
69+
} else {
70+
return "certKeyHash";
71+
}
72+
} else {
73+
let message: string = "key certs was not found";
74+
hilog.info(0x0001, TAG, message);
75+
return message;
76+
}
77+
} else {
78+
//无证书
79+
let message: string = "sslPinning key was not exist";
80+
hilog.info(0x0001, TAG, message);
81+
return message;
82+
}
83+
}
84+
85+
//Obtain the SHA256 summary of the public key corresponding to the certificate file
86+
static async getPubKeyHashFromCert(filePath: string, context: Context): Promise<string[]>{
87+
let result: string[] = [];
88+
let certUnit8Array: Uint8Array = await this.getCAContent(filePath, context);
89+
let certStr: string = this.uint8ArrayToString(certUnit8Array);
90+
if (certStr) {
91+
if (certStr.search(this.SHA_256) >= 0) {
92+
let pubKeyHash: string[] = certStr.split(this.SHA_256);
93+
pubKeyHash.forEach((pin: string) => {
94+
if (pin.trim().length > 0) {
95+
result.push(pin.trim());
96+
}
97+
})
98+
return result;
99+
} else {
100+
return await this.getPubKeyHash(certUnit8Array, filePath, context);
101+
}
102+
}
103+
}
104+
105+
//Get the file contents
106+
static async getCAContent(ca: string, context: Context): Promise<Uint8Array> {
107+
if (!ca) {
108+
return new Uint8Array();
109+
}
110+
const value: Uint8Array = await new Promise<Uint8Array>(resolve => {
111+
context.resourceManager.getRawFileContent(
112+
ca,
113+
(err: BusinessError, value) => {
114+
if (err) {
115+
throw new Error(JSON.stringify(err));
116+
}
117+
resolve(value);
118+
});
119+
})
120+
return value;
121+
}
122+
123+
// Bytes are rounded into understandable strings
124+
static uint8ArrayToString(array: Uint8Array) {
125+
// Convert UTF-8 encoding to Unicode encoding
126+
let out: string = '';
127+
let index: number = 0;
128+
let len: number = array.length;
129+
while (index < len) {
130+
let character = array[index++];
131+
switch (character >> 4) {
132+
case 0:
133+
case 1:
134+
case 2:
135+
case 3:
136+
case 4:
137+
case 5:
138+
case 6:
139+
case 7:
140+
out += String.fromCharCode(character);
141+
break;
142+
case 12:
143+
case 13:
144+
out += String.fromCharCode(((character & 0x1F) << 6) | (array[index++] & 0x3F));
145+
break;
146+
case 14:
147+
out += String.fromCharCode(((character & 0x0F) << 12) | ((array[index++] & 0x3F) << 6) |
148+
((array[index++] & 0x3F) << 0));
149+
break;
150+
default:
151+
break;
152+
}
153+
}
154+
Logger.info('字节流转成字符串:' + out);
155+
return out;
156+
}
157+
158+
//Obtain the SHA256 summary of the public key corresponding to the Uint8Array
159+
static async getPubKeyHash(certUint8Array: Uint8Array, filePath: string, context: Context): Promise<string[]> {
160+
let result: string[] = [];
161+
if (filePath != "") {
162+
let fixedCert: cert.X509Cert | undefined = await this.getCertFromFile(certUint8Array)
163+
if (fixedCert) {
164+
try {
165+
//获取公钥
166+
let pubKey = fixedCert.getItem(cert.CertItemType.CERT_ITEM_TYPE_PUBLIC_KEY);
167+
let mdSHA256 = cryptoFramework.createMd("SHA256")
168+
mdSHA256.updateSync({ data: pubKey.data });
169+
//公钥摘要计算结果
170+
let mdResult = mdSHA256.digestSync();
171+
let tool = new util.Base64Helper()
172+
//公钥摘要转换为base64编码字符串
173+
result.push(tool.encodeToStringSync(mdResult.data))
174+
Logger.info("getPubKeyHash:" + result)
175+
} catch (e) {
176+
Logger.info('获取公钥摘要失败 ' + e.message);
177+
}
178+
}
179+
}
180+
return result
181+
}
182+
183+
//从文件获取X509证书
184+
static async getCertFromFile(certData: Uint8Array): Promise<cert.X509Cert | undefined> {
185+
let newCert: cert.X509Cert | undefined = undefined
186+
// let certData: Uint8Array = await this.getCAContent(filePath, context);
187+
if (certData) {
188+
let encodingBlob: cert.EncodingBlob = {
189+
data: certData,
190+
encodingFormat: cert.EncodingFormat.FORMAT_PEM
191+
};
192+
await cert.createX509Cert(encodingBlob)
193+
.then((x509Cert: cert.X509Cert) => {
194+
newCert = x509Cert
195+
})
196+
.catch((err: BusinessError) => {
197+
Logger.info(`创建X509证书失败:err code is ${err.code}, err message is ${JSON.stringify(err)}`);
198+
})
199+
}
200+
return newCert
201+
}
202+
203+
//加载文件内容
204+
static getContent(filePath: string): ArrayBuffer | undefined {
205+
let content: ArrayBuffer | undefined = undefined
206+
try {
207+
let buf = new ArrayBuffer(1024 * 64);
208+
let file = fs.openSync(filePath, fs.OpenMode.READ_ONLY);
209+
let readLen = fs.readSync(file.fd, buf, { offset: 0 });
210+
content = buf.slice(0, readLen)
211+
fs.closeSync(file);
212+
} catch (e) {
213+
Logger.info('读取文件内容失败 ' + e.message);
214+
}
215+
return content
216+
}
217+
218+
}
219+

0 commit comments

Comments
 (0)