README.md
1# 通用密钥管理
2
3### 介绍
4
5本示例介绍了如何使用AES和RSA进行数据加解密,并模拟了服务端和客户端的加解密通信流程。
6
7### 效果图预览
8
9<img src="./common_secret_key_manager.gif" width="300">
10
11**使用说明**:
12
131. 点击输入框,输入任何内容,点击“发送”按钮,页面将会展示客户端和服务端的加解密通信过程。
142. 客户端会在2s后调用模拟服务端的方法,页面将会展示签名验证数据的过程。
15
16### 实现思路
17
181. 创建页面,添加List用于显示加解密流程信息,添加TextInput用于输入数据。详细代码可参考[Index.ets](./entry/src/main/ets/pages/KeyManager.ets)。
19
20 ```typescript
21 @Entry
22 @Component
23 struct KeyManager {
24 ...
25
26 build() {
27 RelativeContainer() {
28 Row() {
29 TextInput({ text: this.message, placeholder: '请输入内容' })
30 .id('input')
31 .onChange((value: string) => {
32 this.message = value;
33 })
34 .layoutWeight(4)
35 ...
36 }
37 ...
38
39 List() {
40 ForEach(this.messageArray, (message: Message) => {
41 ListItem() {
42 Row() {
43 Text(message.message)
44 .padding(10)
45 .fontColor(message.position === MessagePosition.Left ? Color.Blue : Color.Black)
46 .constraintSize({
47 maxWidth: '80%'
48 })
49 .borderRadius(10)
50 .backgroundColor("#F1F1F1")
51 .margin({
52 left: message.position === MessagePosition.Left ? 10 : 0,
53 right: message.position === MessagePosition.Right ? 10 : 0
54 })
55 }
56 ...
57 }
58 })
59 }
60 ...
61 }
62
63 }
64 ```
65
662. 分别实现AES密钥生成方法和加解密方法。详细代码可参考[AesUtils.ets](./entry/src/main/ets/utils/AesUtils.ets)。
67
68 ```typescript
69 /**
70 * 生成AES密钥
71 * @returns AES密钥的16进制字符串
72 */
73 export async function generateAesKey(): Promise<string> {
74 ...
75 }
76
77 /**
78 * AES解密
79 * @param encryptedMessage 已经加密的数据
80 * @param aesKey AES密钥
81 * @returns 解密后的数据
82 */
83 export async function aesGcmDecrypt(encryptedMessage: string, aesKey: string): Promise<string> {
84 ...
85 }
86
87 /**
88 * AES加密
89 * @param textString 需要加密的数据
90 * @param aesKey AES密钥
91 * @returns
92 */
93 export async function aesGcmEncrypt(textString: string, aesKey: string): Promise<string> {
94 ...
95 }
96 ```
97
983. 分别实现RSA密钥生成方法、加解密方法、签名验证方法。详细代码可参考[RsaUtils.ets](./entry/src/main/ets/utils/RsaUtils.ets)。
99
100 ```typescript
101 /**
102 * 生成RSA密钥对
103 * @returns RSA密钥对
104 */
105 export async function generateRsaKey(): Promise<RsaKey | undefined> {
106 ...
107 }
108
109 /**
110 * RSA加密
111 * @param data 需要加密的数据
112 * @param publicKey 公钥
113 * @returns 完成加密的数据
114 */
115 export async function rsaEncryption(data: string, publicKey: string): Promise<string> {
116 ...
117 }
118
119 /**
120 * RSA解密
121 * @param encryptedData 经过加密的数据
122 * @param privateKey 私钥
123 * @returns 解密后的数据
124 */
125 export async function rsaDecryption(encryptedData: string, privateKey: string): Promise<string> {
126 ...
127 return "";
128 }
129
130 /**
131 * 验证签名
132 * @param encryptedData 待验证的数据
133 * @param singedData 签名信息
134 * @param publicKey 公钥
135 * @returns 签名验证是否通过
136 */
137 export async function verify(encryptedData: string, singedData: string, publicKey: string): Promise<boolean> {
138 ...
139 }
140
141 /**
142 * 签名
143 * @param data 需要签名的数据
144 * @param privateKey 私钥
145 * @returns 签名信息
146 */
147 export async function sign(data: string, privateKey: string): Promise<string> {
148 ...
149 }
150 ```
151
1524. 在客户端中进行AES密钥生成、加解密以及RSA加密。详细代码可参考[LocalClient.ets](./entry/src/main/ets/client/LocalClient.ets)。
153
154 ```typescript
155 // 客户端下载公钥
156 async downloadPublicKey() {
157 let publicKeyResult: SignedData = JSON.parse(await this.server.downloadPublicKey());
158 // 验证公钥签名
159 if (await verify(publicKeyResult.encryptedMessage, publicKeyResult.signedMessage,
160 publicKeyResult.encryptedMessage)) {
161 this.publicKey = publicKeyResult.encryptedMessage;
162 }
163 if (this.publicKey === "") {
164 sendProcessMessage("获取公钥失败", MessagePosition.Right);
165 throw new Error('downloadPublicKey failed');
166 }
167 sendProcessMessage("获取公钥成功", MessagePosition.Right);
168 }
169
170 // 发送数据到服务端
171 async sendMessageToServer(message: string): Promise<void> {
172 sendProcessMessage("开始发送数据到服务端...", MessagePosition.Right);
173 // 消息加密
174 let encryptionMessage: string = await this.encryption(message);
175 sendProcessMessage("发送加密数据到服务端...", MessagePosition.Right);
176 // 发送服务端
177 await this.server.receiveMessageFromClient(encryptionMessage);
178 }
179
180 // 从服务端接收数据
181 async receiveMessageFromServer(): Promise<string> {
182 sendProcessMessage("开始接收服务端数据...", MessagePosition.Right);
183 let signMessage: string = await this.server.sendMessageToClient();
184 // 验证签名
185 let signData: SignedData = JSON.parse(signMessage);
186 sendProcessMessage("开始验证签名...", MessagePosition.Right);
187 let isVerified: boolean = await verify(signData.encryptedMessage, signData.signedMessage, this.publicKey);
188 if (isVerified) {
189 sendProcessMessage("签名验证成功,开始解密...", MessagePosition.Right);
190 let decryptedMessage = await aesGcmDecrypt(signData.encryptedMessage, this.aesKey);
191 sendProcessMessage("解密成功,解密结果:" + decryptedMessage, MessagePosition.Right);
192 return decryptedMessage;
193 }
194 sendProcessMessage("签名验证失败", MessagePosition.Right);
195 return "签名验证失败";
196 }
197
198 // 加密
199 async encryption(message: string): Promise<string> {
200 if (!this.publicKey) {
201 sendProcessMessage("本地未找到公钥,开始下载...", MessagePosition.Right);
202 // 获取公钥
203 await this.downloadPublicKey();
204 sendProcessMessage("公钥下载成功", MessagePosition.Right);
205 }
206 if (this.aesKey === "") {
207 sendProcessMessage("本地未找到AES密钥,开始生成...", MessagePosition.Right);
208 // 生成AES密钥
209 this.aesKey = await generateAesKey();
210 sendProcessMessage(`AES密钥生成成功,密钥:${this.aesKey},开始发送到服务端...`, MessagePosition.Right);
211 // 将AES密钥发送到服务端
212 await this.sendAesKeyToServer();
213 }
214 sendProcessMessage(`客户端开始加密数据...`, MessagePosition.Right);
215 let encryptionResult: string = await aesGcmEncrypt(message, this.aesKey);
216 sendProcessMessage(`客户端加密成功,加密结果:${encryptionResult}`, MessagePosition.Right);
217 // 使用AES加密数据
218 return encryptionResult;
219 }
220
221 // 发送AES密钥到服务端
222 async sendAesKeyToServer() {
223 sendProcessMessage(`AES密钥进行加密...`, MessagePosition.Right);
224 // 对AES密钥使用公钥进行加密
225 let encryptedAesKey: string = await rsaEncryption(this.aesKey, this.publicKey);
226 sendProcessMessage(`加密成功,加密结果:${encryptedAesKey},开始发送到服务端...`, MessagePosition.Right);
227 // 将加密后的AES密钥发送到服务端
228 await this.server.receiveKeyFromClient(encryptedAesKey);
229 }
230 ```
231
2325. 在客户端中进行AES密钥生成、加解密以及RSA加密。详细代码可参考[LocalClient.ets](./entry/src/main/ets/client/LocalClient.ets)。
233
234 ```typescript
235 //生成证书
236 async createKey() {
237 sendProcessMessage("模拟服务端开始生成证书", MessagePosition.Left);
238 let rsaKey: RsaKey | undefined = await generateRsaKey()
239 if (rsaKey) {
240 this.publicKey = rsaKey.publicKey;
241 this.privateKey = rsaKey.privateKey;
242 sendProcessMessage("模拟服务端生成证书成功,公钥:" + this.publicKey, MessagePosition.Left);
243 }
244 }
245
246 // 模拟公钥下载
247 async downloadPublicKey(): Promise<string> {
248 if (this.publicKey === "") {
249 // 创建密钥
250 await this.createKey();
251 }
252 // 对公钥进行签名
253 let signResult: string = await sign(this.publicKey, this.privateKey);
254 let publicKeyResult: SignedData = { encryptedMessage: this.publicKey, signedMessage: signResult };
255 return JSON.stringify(publicKeyResult);
256 }
257
258 async receiveKeyFromClient(encryptedAesKey: string) {
259 sendProcessMessage(`模拟服务端接收到AES密钥:${encryptedAesKey}`, MessagePosition.Left);
260 this.aesKey = await rsaDecryption(encryptedAesKey, this.privateKey);
261 sendProcessMessage(`模拟服务端AES密钥解密成功,AES密钥为:${this.aesKey}`, MessagePosition.Left);
262 Logger.info(TAG, 'receive key from client success, server aesKey:' + this.aesKey);
263 }
264
265 // 获取客户端消息
266 async receiveMessageFromClient(message: string): Promise<void> {
267 sendProcessMessage("模拟服务端接收到数据,开始解密...", MessagePosition.Left);
268 // 解密
269 let decryptedMessage = await aesGcmDecrypt(message, this.aesKey);
270 sendProcessMessage(`模拟服务端解密成功,解密结果:${decryptedMessage}`, MessagePosition.Left);
271 // 存储
272 this.messageStorage.push(decryptedMessage);
273 }
274
275 async sendMessageToClient(): Promise<string> {
276 let needSendMessage: string = "这是模拟服务端返回的测试数据," + this.messageStorage[this.messageStorage.length-1];
277 sendProcessMessage(`模拟服务端开始发送数据,将要发送的数据是:${needSendMessage}`, MessagePosition.Left);
278 sendProcessMessage(`模拟服务端开始加密数据:${needSendMessage}`, MessagePosition.Left);
279 let encryptedMessage: string = await aesGcmEncrypt(needSendMessage, this.aesKey);
280 sendProcessMessage(`模拟服务端加密成功,加密结果:${encryptedMessage}`, MessagePosition.Left);
281 // 签名
282 sendProcessMessage(`模拟服务端开始签名数据...`, MessagePosition.Left);
283 let signedMessage: string = await sign(encryptedMessage, this.privateKey);
284 sendProcessMessage(`模拟服务端签名成功,签名结果:${signedMessage}`, MessagePosition.Left);
285 let signData: SignedData = { encryptedMessage: encryptedMessage, signedMessage: signedMessage };
286 // 发送消息
287 return JSON.stringify(signData);
288 }
289 ```
290
291### 工程结构&模块类型
292
293```
294KeyManger // har类型
295|---client
296| |---LocalClient.ets // 模拟客户端
297|---pages
298| |---KeyManager.ets // 应用页面
299|---server
300| |---LocalMockServer.ets // 模拟服务端
301|---utils
302| |---AesUtils.ets // AES加密工具类
303| |---Logger.ets // 日志打印类
304| |---RsaUtils.ets // RSA加密工具类
305| |---Utils.ets // 其他公用方法
306```
307
308### 模块依赖
309
310无
311
312### 相关权限
313
314无
315
316### 约束与限制
317
3181. 本示例仅支持标准系统上运行。
319
3202. 本示例为Stage模型,从API version 12开始支持。SDK版本号:5.0.0.71 Release,镜像版本号:OpenHarmony 5.0.1.107。
321
3223. 本示例需要使用DevEco Studio 5.0.4 Release (Build Version: 5.0.11.100, built on March 28, 2025)编译运行。
323
324### 下载
325
326如需单独下载本工程,执行如下命令:
327
328```shell
329git init
330git config core.sparsecheckout true
331echo code/BasicFeature/Security/KeyManager/ > .git/info/sparse-checkout
332git remote add origin https://gitee.com/openharmony/applications_app_samples.git
333git pull origin master
334```
335
336### 参考资料
337
338[加解密算法库框架cryptoFramework](https://docs.openharmony.cn/pages/v5.1/zh-cn/application-dev/reference/apis-crypto-architecture-kit/js-apis-cryptoFramework.md#cryptoframeworkcreatesymkeygenerator)
339
340[使用RSA非对称密钥(PKCS1模式)加解密](https://docs.openharmony.cn/pages/v5.1/zh-cn/application-dev/security/CryptoArchitectureKit/crypto-rsa-asym-encrypt-decrypt-pkcs1.md)
341
342[使用AES对称密钥(GCM模式)加解密](https://docs.openharmony.cn/pages/v5.1/zh-cn/application-dev/security/CryptoArchitectureKit/crypto-aes-sym-encrypt-decrypt-gcm.md)
343
344[使用RSA密钥对(PKCS1模式)签名验签](https://docs.openharmony.cn/pages/v5.1/zh-cn/application-dev/security/CryptoArchitectureKit/crypto-rsa-sign-sig-verify-pkcs1.md)
345
346
347