• Home
Name Date Size #Lines LOC

..--

AppScope/22-Oct-2025-4239

entry/22-Oct-2025-1,2981,173

hvigor/22-Oct-2025-2322

.gitignoreD22-Oct-2025133 1212

README.mdD22-Oct-202512.9 KiB347292

build-profile.json5D22-Oct-20251.3 KiB5756

code-linter.json5D22-Oct-20251.4 KiB4746

common_secret_key_manager.gifD22-Oct-20253.1 MiB

hvigorfile.tsD22-Oct-2025843 225

oh-package.json5D22-Oct-2025809 2624

ohosTest.mdD22-Oct-2025753 136

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
310311
312### 相关权限
313
314315
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