当前位置:   article > 正文

HarmonyOS-AES加解密

ohos.security.cryptoframework进行aes加密解密算法

前言

客户端开发中存在一些需要在传输过程中进行保护的重要信息,比如用户通讯录信息,用户日志等信息。这种情况下就需要采用适当的加密与解密方式。

  1. 作者:张保罗
  2. 链接:https://juejin.cn/post/7340152660224425996

常规的加密方式有AES,RSA 等。本篇中介绍对称加密方式AES,这种对称式加密方式中加密与解密使用相同密钥。

鸿蒙加解密算法框架详细介绍了完整的使用方法供参考

https://developer.harmonyos.com/cn/docs/documentation/doc-references-V3/js-apis-cryptoframework-0000001477981409-V3

鸿蒙官方加解密框架开发指导

https://developer.huawei.com/consumer/cn/doc/harmonyos-guides-V2/cryptoframework-guidelines-0000001544703861-V2

效果展示

f5b058bf80860cb73ca07c27c2d00074.png

原理

  • AES加密
    AES的全称是Advanced Encryption Standard,是最常见的对称加密。AES为分组密码,分组密码也就是把明文分成一组一组的,每组长度相等,每次加密一组数据,直到加密完整个明文。在AES标准规范中,分组长度只能是128位,也就是说,每个分组为16个字节(每个字节8位)。密钥的长度可以使用128位、192位或256位。

  • 对称AES加解密
    算法库目前提供了AES加解密常用的7种加密模式:ECB、CBC、OFB、CFB、CTR、GCM和CCM。AES为分组加密算法,分组长度大小为128位。实际应用中明文最后一组可能不足128位,不足数据可以使用各种padding模式做数据填充。下文中描述了各个padding的区别:

  1. NoPadding:不带填充;

  2. PKCS5:填充字符由一个字节序列组成,每个字节填充该填充字节序列的长度,规定是8字节填充;

  3. PKCS7:填充字符和PKCS5填充方法一致,但是可以在1-255字节之间任意填充;

相关概念

  1. 明文P(plainText):未经加密的数据

  2. 密钥K(key):用来加密明文的密码。在对称加密算法中,加密与解密的密钥是相同的,由双方协商产生,绝不可以泄漏

  3. 密文C(cipherText): 经过加密的数据

  4. 加密函数E(encrypt):C = E(K, P),即将明文和密钥作为参数,传入加密函数密文就可以获得密文

  5. 解密函数D(decrypt):P = D(K, C),即将密文和密钥作为参数,传入解密函数中,就可以获得明文

  6. 初始向量(IV,Initialization Vector):它的作用和MD5的“加盐”有些类似,目的是防止同样的明文块,始终加密成同样的密文块:

实现

  • 本例中实现了AES对用户输入的明文内容进行AES加密并显示

  • 对加密的内容进行解密并显示

  • 密钥和初始向量iv写死了,实际项目中可以根据自己的需要来实现密钥和iv的生成。比如用md5来生成

注意加密过程

由于aes加密后的字节数组,直接转String返回参数有可能存在乱码,所以对返回值做一下处理,将加密的结果转换为base64的字符串。同理,解密时候,需要把字符串先base64处理,再把解密后的内容进行aes解密操作。

  1. 加密实现
  2. 加密(从前往后):明文 -> 加密 -> base64处理 -> 密文
  3. 解密实现
  4. 解密(从后往前):明文 <- 解密 <- base64处理 <- 密文

代码

加密和解密方法

  1. import util from '@ohos.util';
  2. import cryptoFramework from '@ohos.security.cryptoFramework';
  3. import Logger from './Logger';
  4. const TAG: string = '[CipherModel]'
  5. const AES128: string = 'AES128';
  6. const AES128_CBC_PKCS5: string = 'AES128|CBC|PKCS5';
  7. const AES128_PKCS7: string = 'AES128|PKCS7';
  8. export class CipherModel {
  9. stringToUint8Array(str) {
  10. var arr = [];
  11. for (var i = 0, j = str.length; i < j; ++i) {
  12. arr.push(str.charCodeAt(i));
  13. }
  14. var tmpArray = new Uint8Array(arr);
  15. return tmpArray;
  16. }
  17. uint8ArrayToString(array: Uint8Array) {
  18. let arrayString = '';
  19. for (let i = 0; i < array.length; i++) {
  20. arrayString += String.fromCharCode(array[i]);
  21. }
  22. return arrayString;
  23. }
  24. aesEncrypt(message: string, key: string, iv: string, callback) {
  25. let that = new util.Base64Helper();
  26. let paramsSpec: cryptoFramework.IvParamsSpec = { iv: { data: this.stringToUint8Array(iv) }, algName: "IvParamsSpec" }
  27. let aesGenerator = cryptoFramework.createSymKeyGenerator(AES128);
  28. let cipher = cryptoFramework.createCipher(AES128_CBC_PKCS5);
  29. let pubKey = that.decodeSync(key);
  30. let pubKeyBlob: cryptoFramework.DataBlob = { data: pubKey };
  31. aesGenerator.convertKey(pubKeyBlob, (err, symKey) => {
  32. if (err) {
  33. console.error("convertKey: error.");
  34. return;
  35. }
  36. cipher.init(cryptoFramework.CryptoMode.ENCRYPT_MODE, symKey, paramsSpec, (err, data) => {
  37. let input: cryptoFramework.DataBlob = { data: this.stringToUint8Array(message) };
  38. cipher.doFinal(input, (err, data) => {
  39. Logger.info(TAG, "EncryptOutPut is " + data.data);
  40. let result = that.encodeToStringSync(data.data)
  41. Logger.info(TAG, "result is " + result);
  42. callback(result)
  43. })
  44. })
  45. })
  46. }
  47. aesDecrypt(message: string, key: string, iv: string, callback) {
  48. let paramsSpec: cryptoFramework.IvParamsSpec = { iv: { data: this.stringToUint8Array(iv) }, algName: "IvParamsSpec" }
  49. let aesGenerator = cryptoFramework.createSymKeyGenerator(AES128);
  50. let cipher = cryptoFramework.createCipher(AES128_CBC_PKCS5);
  51. let that = new util.Base64Helper();
  52. let pubKey = that.decodeSync(key);
  53. let pubKeyBlob: cryptoFramework.DataBlob = { data: pubKey };
  54. aesGenerator.convertKey(pubKeyBlob, (err, symKey) => {
  55. if (err) {
  56. console.error("convertKey: error.");
  57. return;
  58. }
  59. cipher.init(cryptoFramework.CryptoMode.DECRYPT_MODE, symKey, paramsSpec, (err, data) => {
  60. let newMessage = that.decodeSync(message);
  61. let input: cryptoFramework.DataBlob = { data: newMessage };
  62. cipher.doFinal(input, (err, data) => {
  63. Logger.info(TAG, "DecryptOutPut is " + data.data);
  64. let result = this.uint8ArrayToString(data.data)
  65. Logger.info(TAG, "result is " + result);
  66. callback(result)
  67. })
  68. })
  69. })
  70. }
  71. }

点击加密按钮

  1. Row() {
  2. Button('aes加密').align(Alignment.Start)
  3. }.width('100%').margin({ left: 12, top: 12 })
  4. .onClick( () => {
  5. this.cipherModel.aesEncrypt(
  6. this.originText,
  7. this.AES_ENCRYPT_KEY,
  8. this.AES_IV_STRING,
  9. (result: string) => {
  10. Logger.info(this.TAG, `this result = ${JSON.stringify(result)}`);
  11. this.cipherText = result;
  12. })
  13. }
  14. )

// 点击解密按钮

  1. Row() {
  2. Button('aes解密').align(Alignment.Start)
  3. }.width('100%').margin({ left: 12, top: 12 })
  4. .onClick(() => {
  5. if(this.cipherText.toString().length === 0) {
  6. return;
  7. }
  8. this.cipherModel.aesDecrypt(this.cipherText,
  9. this.AES_ENCRYPT_KEY,
  10. this.AES_IV_STRING,
  11. (result: string) => {
  12. Logger.info(this.TAG, `this result = ${JSON.stringify(result)}`);
  13. this.decodedText = result;
  14. })
  15. })

总结

本文中仅涉及了AES加解密的简单使用,并未根据项目实际需要来调整加密格式参数。如果项目中需要加密的信息数量较多或者需要较强的加密强度。请到官网查看最新版的相关文档,选择最合适的加密方法。

demo代码已上传github https://github.com/kainbro/LearnHamony

由于我还没找到鸿蒙工作,所以还没有拿到鸿蒙最新的sdk。此处使用的是官网的公开版本sdk 9。有些朋友项目中已经拿到华为内部鸿蒙版本,api可能略有不同,请根据最新sdk自行调整变更的api。

关注我获取更多知识或者投稿

377c2cc0a51c80ab5d716a3187553914.jpeg

16daf585671aaef85e9226a58f4f2e54.jpeg

声明:本文内容由网友自发贡献,不代表【wpsshop博客】立场,版权归原作者所有,本站不承担相应法律责任。如您发现有侵权的内容,请联系我们。转载请注明出处:https://www.wpsshop.cn/w/小小林熬夜学编程/article/detail/279964
推荐阅读
相关标签
  

闽ICP备14008679号