
1. 项目概述为什么要在HarmonyOS应用中实现混合加密在HarmonyOS应用开发中尤其是涉及用户隐私、支付信息、健康数据等敏感信息的“便捷生活”类应用数据安全是开发者必须直面的第一道关卡。单纯使用对称加密如AES速度快但密钥分发和管理是难题单纯使用非对称加密如RSA解决了密钥分发问题但加密速度慢不适合大数据量。因此业界公认的最佳实践是采用RSA与AES混合加密方案。这个项目就是要在HarmonyOS 5环境下从零开始构建一套高效、安全且易于集成的混合加密模块。简单来说它的核心流程是用RSA加密随机的AES密钥再用这个AES密钥去加密实际要传输或存储的业务数据。接收方则用自己的RSA私钥解密出AES密钥再用AES密钥解密出原始数据。这样既利用了RSA在密钥交换上的安全性又享受了AES在处理大量数据时的高性能。对于HarmonyOS开发者而言实现这套方案不仅是满足应用上架安全审核的基础要求更是构建用户信任、提升产品专业度的关键。接下来我将结合在金融和IoT领域的实战经验拆解从原理到代码落地的全过程并分享那些官方文档里不会写的“坑”和技巧。2. 核心方案设计与技术选型2.1 混合加密流程拆解一套完整的混合加密流程远不止调用两个API那么简单。它需要严谨的流程设计和异常处理。下图清晰地展示了从数据发送方到接收方的完整闭环发送方加密端流程生成随机AES密钥每次加密会话都应使用一个全新的、足够长度的随机密钥如AES-256。使用AES密钥加密业务数据采用合适的模式如GCM对明文数据进行加密得到密文。使用接收方的RSA公钥加密AES密钥将步骤1生成的AES密钥用RSA公钥加密。组装传输数据包将AES加密后的数据密文、RSA加密后的AES密钥、以及必要的初始向量IV等参数按约定格式如JSON、Protocol Buffers组装发送给接收方。接收方解密端流程解析数据包从接收到的数据中分离出各个部分。使用RSA私钥解密AES密钥用自己的RSA私钥解密出原始的AES密钥。使用AES密钥解密业务数据用解密得到的AES密钥配合IV等参数解密出原始明文数据。这个流程确保了即使网络传输被监听攻击者也只能拿到用RSA公钥加密的AES密钥和用AES加密的数据。在没有RSA私钥的情况下他无法破解AES密钥也就无法解密任何业务数据。2.2 HarmonyOS 5 加密API选型与考量HarmonyOS 5的ohos.security.cryptoFramework提供了丰富的密码学套件。我们的选型必须基于安全性、性能和易用性。1. RSA 密钥对生成与算法参数密钥长度2048位是当前安全底线考虑到移动设备性能和未来安全期推荐使用。虽然3072位更安全但加解密耗时会增加需根据业务敏感度权衡。绝对不要使用1024位。算法标识使用RSA2048|PKCS1。PKCS1是广泛兼容的填充方案。虽然OAEP在理论上更安全可抵抗选择密文攻击但某些老旧的后端服务可能不支持选择前需与后端对齐。密钥存储这是重中之重。私钥绝不能硬编码在代码中或存储在普通文件里。必须使用HarmonyOS提供的密钥库KeyStore能力将私钥保存在由TEE可信执行环境保护的安全区域。公钥则可以安全地分发或硬编码在客户端。2. AES 算法参数密钥长度无脑选择AES256。AES128理论上仍安全但在算力飞速发展的今天AES256提供的额外安全边际是值得的。工作模式GCM模式是首选。它同时提供了加密和认证完整性校验避免了“加密但不验证”导致的数据可能被篡改的风险。如果因为兼容性问题不能使用GCM则选择CBC模式但必须结合HMAC来保证数据完整性。初始向量IV每次加密都必须使用一个密码学安全的随机数作为IV且IV不需要保密可以随密文一起传输。绝对禁止重复使用同一个IV和密钥的组合。3. 数据序列化格式为了便于网络传输和跨平台解析推荐使用JSON。它的结构清晰易于调试。在性能要求极高的场景可以考虑Protocol Buffers但会引入额外的复杂度。注意算法和参数的选择不是一成不变的。务必与你的服务端团队达成一致确保两端使用完全相同的算法标识、填充模式和编码格式如Base64或Hex。一个常见的坑是前端用Base64输出后端却期待Hex字符串导致解密失败。3. 核心模块实现与代码详解下面我们进入实战环节。我将分模块展示关键代码并解释每一行背后的意图和注意事项。3.1 密钥管理模块安全存储的基石密钥管理是安全体系的根基。私钥泄露一切加密形同虚设。// 导入加解密框架 import cryptoFramework from ohos.security.cryptoFramework; import util from ohos.util; export class HybridEncryptionManager { private keyAlias: string my_app_rsa_keypair_2048; // 密钥别名 private rsaKeyGen: cryptoFramework.AsyKeyGenerator; // RSA密钥生成器 private aesKeyGen: cryptoFramework.SymKeyGenerator; // AES密钥生成器 constructor() { // 初始化RSA密钥生成器 (2048位, PKCS1填充) this.rsaKeyGen cryptoFramework.createAsyKeyGenerator(RSA2048|PKCS1); // 初始化AES密钥生成器 (256位) this.aesKeyGen cryptoFramework.createSymKeyGenerator(AES256); } // 1. 生成并安全保存RSA密钥对 async generateAndSaveRSAKeyPair(): Promisevoid { try { // 首先尝试从密钥库获取避免重复生成 let keyPair: cryptoFramework.KeyPair; try { keyPair await this.rsaKeyGen.convertKey(null, keyAlias${this.keyAlias}); console.info(RSA密钥对已存在直接使用。); } catch (error) { // 如果不存在则生成新的 console.info(密钥库中未找到RSA密钥对开始生成...); keyPair await this.rsaKeyGen.generateKeyPair(); // 将密钥对保存到密钥库私钥受到硬件级保护 await this.rsaKeyGen.saveKeyPair(keyPair, keyAlias${this.keyAlias}); console.info(RSA密钥对已生成并安全保存。); } // 获取公钥用于加密AES密钥或分发给他人 const pubKey keyPair.pubKey; // 通常我们需要将公钥转换为Base64或PEM格式进行传输或存储 const pubKeyData await pubKey.getEncoded(); const pubKeyBase64 util.base64EncodeSync(pubKeyData.data); console.info(RSA公钥(Base64): ${pubKeyBase64.substring(0, 50)}...); } catch (error) { console.error(生成/保存RSA密钥对失败: ${error.code}, ${error.message}); throw new Error(密钥初始化失败请检查系统安全环境。); } } // 2. 从密钥库获取RSA密钥对 async getRSAKeyPair(): PromisecryptoFramework.KeyPair { try { // 此操作不会导出私钥明文私钥始终在安全环境中 const keyPair await this.rsaKeyGen.convertKey(null, keyAlias${this.keyAlias}); return keyPair; } catch (error) { console.error(获取RSA密钥对失败请确认密钥已生成: ${error.message}); throw new Error(获取密钥失败请先调用generateAndSaveRSAKeyPair。); } } }关键点解析keyAlias是密钥在密钥库中的唯一标识。应用卸载后该别名对应的密钥会被清除。convertKey用于从密钥库中获取密钥对象。注意即使获取到KeyPair对象你也无法直接导出私钥的字节数据这由系统强制保护。saveKeyPair将生成的密钥对存入密钥库。这是保护私钥的关键一步。异常处理密钥操作涉及底层安全硬件可能因设备不支持、用户未设置锁屏密码等原因失败必须进行细致捕获和用户友好提示。3.2 加密过程实现构建安全数据包加密端负责生成会话密钥、加密数据并打包。// 接上类 HybridEncryptionManager // 3. 执行混合加密 async encryptData(plainText: string, receiverPubKeyBase64: string): Promisestring { // 参数校验 if (!plainText || !receiverPubKeyBase64) { throw new Error(明文和接收方公钥为必填参数。); } let aesCipher: cryptoFramework.Cipher; let rsaCipher: cryptoFramework.Cipher; try { // --- 第一步生成本次会话的随机AES密钥和IV --- const aesKey: cryptoFramework.SymKey await this.aesKeyGen.generateSymKey(); // 生成随机IV对于GCM模式通常需要12字节96位 const iv cryptoFramework.createRandom(12); // 12字节 96位 // --- 第二步使用AES-GCM加密业务明文 --- aesCipher cryptoFramework.createCipher(AES256|GCM|PKCS7); await aesCipher.init(cryptoFramework.CryptoMode.ENCRYPT_MODE, aesKey, { iv: iv, // GCM模式可以附加认证数据AAD用于验证未加密的头部信息此处示例未使用 // aad: someAdditionalData }); // 将字符串明文转为Unit8Array const plainTextData new util.TextEncoder().encode(plainText); const encryptData await aesCipher.update(plainTextData); const aesFinalData await aesCipher.doFinal(null); // GCM模式doFinal可能返回认证标签 // 合并加密结果 const cipherTextData util.concat(encryptData.data, aesFinalData.data); const cipherTextBase64 util.base64EncodeSync(cipherTextData); // IV也需要传输 const ivBase64 util.base64EncodeSync(iv); // --- 第三步使用接收方RSA公钥加密AES密钥 --- // 将Base64格式的公钥转换回Key对象 const pubKeyData util.base64DecodeSync(receiverPubKeyBase64); const receiverPubKey await this.rsaKeyGen.convertKey(pubKeyData.buffer, null); rsaCipher cryptoFramework.createCipher(RSA2048|PKCS1); await rsaCipher.init(cryptoFramework.CryptoMode.ENCRYPT_MODE, receiverPubKey, null); // 获取AES密钥的原始数据注意只有对称密钥可以导出非对称私钥不能 const aesKeyData await aesKey.getEncoded(); const encryptedAesKeyData await rsaCipher.doFinal(aesKeyData.data); const encryptedAesKeyBase64 util.base64EncodeSync(encryptedAesKeyData.data); // --- 第四步组装数据包 --- const dataPacket { version: 1.0, cipherText: cipherTextBase64, // AES加密后的业务数据 encryptedAesKey: encryptedAesKeyBase64, // RSA加密后的AES密钥 iv: ivBase64, // AES使用的初始向量 mode: AES256-GCM, // 明确告知对方算法 // 可以添加时间戳防止重放攻击 timestamp: new Date().getTime() }; return JSON.stringify(dataPacket); } catch (error) { console.error(加密过程失败: ${error.code}, ${error.message}); throw new Error(数据加密失败: ${error.message}); } }关键点与避坑指南随机性cryptoFramework.createRandom(12)用于生成IV确保其密码学安全性。不要使用Math.random()。AES-GCM的doFinal在GCM模式下doFinal返回的可能是认证标签Tag需要与update返回的密文一起组合成最终密文。具体组合方式需查阅文档示例中进行了简单拼接在实际复杂场景下需要明确区分密文和Tag。密钥导出aesKey.getEncoded()可以导出对称密钥的字节数据用于RSA加密。但之前生成的RSA私钥keyPair.priKey调用getEncoded()会失败这是系统设计的保护机制。数据包设计包含了算法标识mode这为未来算法升级提供了灵活性。timestamp可用于服务端进行简单的重放攻击检测需结合签名或MAC才更安全。3.3 解密过程实现还原原始信息解密端持有自己的RSA私钥负责解包、解密密钥和数据。// 接上类 HybridEncryptionManager // 4. 执行混合解密 async decryptData(encryptedPacket: string): Promisestring { let dataPacket: any; try { dataPacket JSON.parse(encryptedPacket); } catch (error) { throw new Error(数据包格式错误无法解析JSON。); } // 校验必要字段 const requiredFields [cipherText, encryptedAesKey, iv, mode]; for (const field of requiredFields) { if (!dataPacket[field]) { throw new Error(数据包缺少必要字段: ${field}); } } // 可选校验算法模式是否支持 if (dataPacket.mode ! AES256-GCM) { throw new Error(不支持的加密模式: ${dataPacket.mode}); } let rsaCipher: cryptoFramework.Cipher; let aesCipher: cryptoFramework.Cipher; try { // --- 第一步用自己的RSA私钥解密出AES密钥 --- const keyPair await this.getRSAKeyPair(); // 从密钥库获取自己的密钥对 rsaCipher cryptoFramework.createCipher(RSA2048|PKCS1); // 注意这里是DECRYPT_MODE并且使用私钥 await rsaCipher.init(cryptoFramework.CryptoMode.DECRYPT_MODE, keyPair.priKey, null); const encryptedAesKeyData util.base64DecodeSync(dataPacket.encryptedAesKey); const aesKeyData await rsaCipher.doFinal(encryptedAesKeyData.buffer); // 将解密出的字节数据转换为AES密钥对象 const aesKey await this.aesKeyGen.convertKey(aesKeyData.buffer); // --- 第二步使用解密出的AES密钥和IV解密业务数据 --- const iv util.base64DecodeSync(dataPacket.iv); const cipherTextData util.base64DecodeSync(dataPacket.cipherText); aesCipher cryptoFramework.createCipher(AES256|GCM|PKCS7); await aesCipher.init(cryptoFramework.CryptoMode.DECRYPT_MODE, aesKey, { iv: iv }); // 注意GCM解密时需要将密文可能包含Tag传入update和doFinal // 这里假设cipherTextData是完整的密文Tag。更严谨的做法是分开传输。 const decryptData await aesCipher.update(cipherTextData); const aesFinalData await aesCipher.doFinal(null); // 验证Tag如果失败会抛出异常 // 合并解密结果并转为字符串 const plainTextData util.concat(decryptData.data, aesFinalData?.data || new Uint8Array()); const plainText new util.TextDecoder().decode(plainTextData.buffer); return plainText; } catch (error) { // 特别处理解密失败的情况可能是密钥不对或数据被篡改 if (error.code 17620001 || error.message.includes(decryption)) { // 假设的失败码需根据实际SDK调整 console.error(解密失败可能原因1. 数据包非本设备加密2. 数据在传输中被篡改3. 密钥不匹配。); throw new Error(解密失败数据可能无效或已损坏。); } console.error(解密过程发生未知错误: ${error.code}, ${error.message}); throw error; } } }解密端的核心挑战GCM解密验证GCM模式在doFinal()时会自动验证认证标签Tag。如果Tag验证失败数据被篡改doFinal()会直接抛出异常。这是GCM模式提供数据完整性保护的关键。错误处理解密失败的错误信息不能直接展示给用户避免信息泄露但日志需要详细记录以便开发者排查是网络数据错误、密钥问题还是算法不匹配。密钥转换this.aesKeyGen.convertKey(aesKeyData.buffer)将RSA解密后得到的字节序列重新转换回HarmonyOS加密框架可识别的SymKey对象这是继续用于AES解密的前提。4. 在UI中的集成与调用示例我们将上述管理器封装好后在UI页面例如一个包含输入框和按钮的“安全记事本”页面中的调用就变得非常清晰。// pages/EncryptDemo.ets import { HybridEncryptionManager } from ../utils/HybridEncryptionManager; import promptAction from ohos.promptAction; Entry Component struct EncryptDemoPage { private cryptoManager: HybridEncryptionManager new HybridEncryptionManager(); // 假设这是从服务器安全获取的接收方公钥此处为示例硬编码实际应从网络获取 private receiverPublicKey: string MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAu6H...很长一串Base64; State message: string ; State encryptedPacket: string ; State decryptedMessage: string ; async aboutToAppear() { // 页面加载时初始化本地密钥对 try { await this.cryptoManager.generateAndSaveRSAKeyPair(); promptAction.showToast({ message: 本地密钥初始化成功 }); } catch (error) { promptAction.showToast({ message: 密钥初始化失败: ${error.message} }); } } // 加密按钮事件 async onEncrypt() { if (!this.message.trim()) { promptAction.showToast({ message: 请输入要加密的内容 }); return; } try { this.encryptedPacket await this.cryptoManager.encryptData(this.message, this.receiverPublicKey); promptAction.showToast({ message: 加密成功数据包已生成 }); // 在实际应用中这里会将 encryptedPacket 发送给服务器或接收方 console.info(加密后的数据包:, this.encryptedPacket); } catch (error) { promptAction.showToast({ message: 加密失败: ${error.message} }); } } // 解密按钮事件 (模拟接收方行为使用本地私钥解密) async onDecrypt() { if (!this.encryptedPacket.trim()) { promptAction.showToast({ message: 请先加密生成数据包 }); return; } try { this.decryptedMessage await this.cryptoManager.decryptData(this.encryptedPacket); promptAction.showToast({ message: 解密成功 }); } catch (error) { promptAction.showToast({ message: 解密失败: ${error.message} }); this.decryptedMessage ; } } build() { Column({ space: 20 }) { TextInput({ placeholder: 输入要加密的敏感信息... }) .width(90%) .height(80) .onChange((value: string) { this.message value; }) Button(加密数据) .width(50%) .onClick(() this.onEncrypt()) Text(加密后的数据包JSON格式:) .fontSize(14) .width(90%) Text(this.encryptedPacket ? this.encryptedPacket.substring(0, 100) ... : ) .width(90%) .fontSize(12) .fontColor(Color.Gray) Button(解密数据) .width(50%) .onClick(() this.onDecrypt()) Text(解密后的原文:) .fontSize(14) .width(90%) Text(this.decryptedMessage) .width(90%) .fontSize(16) .fontColor(Color.Black) } .width(100%) .height(100%) .padding(20) .justifyContent(FlexAlign.Start) } }UI集成的要点异步操作所有加解密操作都是异步的必须使用async/await并妥善处理加载状态避免UI卡死。用户反馈使用promptAction及时给用户成功或失败的提示。密钥获取示例中receiverPublicKey是硬编码的真实场景下需要通过HTTPS等安全信道从服务器动态获取甚至可以实现密钥轮换机制。数据展示加密后的数据包通常是Base64字符串很长在UI上只做截断展示即可。5. 进阶优化与安全加固基础功能实现后我们需要从工程和安全角度进行加固使其能应对更复杂的生产环境。5.1 性能优化连接池与异步流水线频繁创建Cipher和KeyGenerator对象有开销。对于高频加密场景如聊天应用可以考虑使用简单的对象池。export class CryptoPool { private static aesGcmCipherPool: cryptoFramework.Cipher[] []; private static rsaCipherPool: cryptoFramework.Cipher[] []; static async getAesGcmCipher(mode: cryptoFramework.CryptoMode, key: cryptoFramework.SymKey, params: cryptoFramework.GcmParams): PromisecryptoFramework.Cipher { let cipher this.aesGcmCipherPool.pop(); if (!cipher) { cipher cryptoFramework.createCipher(AES256|GCM|PKCS7); } await cipher.init(mode, key, params); return cipher; } static releaseAesGcmCipher(cipher: cryptoFramework.Cipher) { // 重置或清理Cipher状态后放回池中 // 注意HarmonyOS的Cipher对象可能没有标准的reset方法需查阅API。 // 如果无法安全重置则不建议使用对象池直接创建新对象。 this.aesGcmCipherPool.push(cipher); } // ... 类似地实现RSA Cipher池 }注意密码学对象的重用必须非常小心。确保在放回池子前该对象的所有内部状态如缓存的块数据都被安全清除。如果SDK不提供明确的reset方法对象池可能引入安全风险此时“每次创建新对象”反而是更安全简单的选择。5.2 防御性编程与完整性校验混合加密解决了机密性问题但还需要防范重放攻击和确保数据完整性。添加消息认证码MAC或签名对于重要的指令或交易数据可以在整个数据包或包含时间戳的特定字段上计算HMAC或者使用发送方的RSA私钥进行签名。接收方验证MAC或签名通过后才进行解密。时间戳与Nonce在数据包中加入服务器时间戳和一次性随机数Nonce服务端维护一个短期的“已使用Nonce缓存”或检查时间戳是否在合理窗口内如±5分钟可以有效抵御重放攻击。数据包版本控制在数据包中加入version字段为未来算法升级、字段增减提供兼容性路径。interface EnhancedDataPacket { version: string; cipherText: string; encryptedAesKey: string; iv: string; mode: string; timestamp: number; // 防御重放 nonce: string; // 一次性随机数防御重放 signature?: string; // 可选发送方对整个数据包的签名或HMAC }5.3 密钥生命周期管理密钥轮换即使是RSA密钥对也应制定轮换策略。例如应用可以每隔一段时间如90天在后台生成新的密钥对并将新公钥上传到服务器。服务器在返回数据时使用客户端当前生效的公钥加密。密钥销毁当用户注销账户或卸载应用时应调用系统API尝试清除密钥库中该应用相关的所有密钥。虽然HarmonyOS在应用卸载时会自动清理其keyAlias下的密钥但显式调用是更佳实践。多设备同步如果应用支持多设备登录需要考虑如何安全地同步或分发公钥。一个常见方案是每个设备生成自己的密钥对将公钥上传到中心服务器。当A设备要给B设备发消息时先从服务器获取B设备的公钥进行加密。6. 常见问题排查与实战心得在实际开发和联调中你会遇到各种各样的问题。下面是我总结的“排坑指南”。6.1 典型错误与解决方案速查表问题现象可能原因排查步骤与解决方案RSA解密失败报“解密错误”或“数据长度错误”1. 使用的公钥/私钥不匹配。2. 加密端和解密端的RSA填充模式不一致如一个用PKCS1一个用OAEP。3. 传输过程中Base64编码/解码出错。1.核对密钥确保加密端使用的公钥正是解密端持有的私钥对应的公钥。打印并对比公钥的Base64前/后几位。2.确认算法标识双方必须使用完全相同的算法字符串如RSA2048|PKCS1。3.检查编解码在加密后和解密前分别打印encryptedAesKey的Base64字符串确保完全一致。注意URL安全的Base64与标准Base64的区别。AES-GCM解密失败doFinal()抛出异常1. IV不一致。加密和解密使用的IV不同。2. 认证标签Tag缺失或错误。GCM密文被截断或篡改。3. 附加认证数据AAD在加解密时不一致。1.核对IV确保IV被正确地从数据包中取出并解码。2.检查密文完整性网络传输是否完整cipherText是否包含了完整的密文和Tag有些实现需要将Tag单独传输和拼接。3.核对AAD如果加密时使用了aad参数解密时必须传入完全相同的aad。“密钥库操作失败”或“初始化密钥生成器失败”1. 设备不支持安全硬件或未启用锁屏密码。2. 应用权限不足。3. 密钥别名已存在但格式不符。1.检查设备提示用户设置设备锁屏密码PIN、图案、指纹等这是使用密钥库的前提。2.检查权限确认应用已申请ohos.permission.ACCESS_BIOMETRIC和ohos.permission.ACCESS_KEYCHAIN等必要权限。3.清理旧密钥在开发调试时可以尝试先删除旧密钥如果API支持或更改keyAlias重新生成。加密/解密过程非常慢1. RSA运算本身较慢特别是在低端设备上。2. 加密的数据量过大。1.性能预期RSA加密/解密一个AES密钥几十字节的耗时在可接受范围。如果慢检查是否误用了RSA去加密大量业务数据。2.数据分块AES加密大数据是快的。如果仍慢检查是否在主线程进行加密操作应使用Worker线程。与服务器Java/Python等联调失败1. 双方算法参数不完全对等如AES密钥长度、GCM的Tag长度。2. 数据格式不一致如服务器期望Hex客户端发送了Base64。3. 服务器使用的密码学库默认行为不同。1.逐项对齐像对合同一样对齐每一项RSA密钥长度、填充方案、AES密钥长度、模式、IV长度、Tag长度、数据编码格式。2.编写测试用例双方使用一个固定的明文、固定的密钥进行加密比对中间每一步的输出如加密后的AES密钥、IV、密文定位分歧点。3.查阅服务器库文档了解服务器端库如Java的JCEPython的cryptography的默认参数。6.2 调试技巧与日志策略分步日志在encryptData和decryptData方法的关键步骤如生成IV后、加密AES密钥后、组装数据包前打印关键变量的Base64或Hex值。这些日志在联调时是无价之宝。对比测试编写一个单元测试在HarmonyOS本地模拟加密和解密全过程确保自洽。然后再与服务器联调。使用固定向量在调试阶段可以暂时将随机生成的IV和AES密钥固定为已知值这样每次运行结果都一致便于比对。上线前务必改回随机生成错误码转换cryptoFramework的错误码通常是数字。在catch块中不仅打印error.message更要打印error.code并根据官方文档查询其具体含义。6.3 安全红线提醒私钥不出门牢记你的RSA私钥在任何情况下都不应该离开设备的安全存储KeyStore。任何要求你“导出私钥”、“发送私钥”的方案都是错误的。公钥传输需可信如何安全地获取对方的公钥通常通过HTTPS从可信服务器下载或者通过扫码等二次确认方式交换。要防范中间人攻击在首次交换时替换公钥。不要自己实现加密算法绝对不要试图用Math.random()生成密钥或者自己写RSA、AES的代码。始终使用经过严格审计的系统级或行业标准库如HarmonyOS的cryptoFramework。及时更新与废弃关注密码学进展。如果未来RSA-2048被证明不再安全或者有新的更优算法如基于椭圆曲线的加密需要有计划地推动应用和服务器端算法升级。在数据包中设计version字段就是为了这一天。实现这样一套混合加密机制初看有些复杂但一旦搭建起来它就成为了你应用底层一个可靠、透明的安全支柱。在HarmonyOS生态中深耕处理好数据安全这类基础而关键的问题能让你的应用在众多竞品中建立起真正的专业壁垒。