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