赞
踩
客户端开发中存在一些需要在传输过程中进行保护的重要信息,比如用户通讯录信息,用户日志等信息。这种情况下就需要采用适当的加密与解密方式。
- 作者:张保罗
- 链接: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
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的区别:
NoPadding:不带填充;
PKCS5:填充字符由一个字节序列组成,每个字节填充该填充字节序列的长度,规定是8字节填充;
PKCS7:填充字符和PKCS5填充方法一致,但是可以在1-255字节之间任意填充;
相关概念
明文P(plainText):未经加密的数据
密钥K(key):用来加密明文的密码。在对称加密算法中,加密与解密的密钥是相同的,由双方协商产生,绝不可以泄漏
密文C(cipherText): 经过加密的数据
加密函数E(encrypt):C = E(K, P),即将明文和密钥作为参数,传入加密函数密文就可以获得密文
解密函数D(decrypt):P = D(K, C),即将密文和密钥作为参数,传入解密函数中,就可以获得明文
初始向量(IV,Initialization Vector):它的作用和MD5的“加盐”有些类似,目的是防止同样的明文块,始终加密成同样的密文块:
实现
本例中实现了AES对用户输入的明文内容进行AES加密并显示
对加密的内容进行解密并显示
密钥和初始向量iv写死了,实际项目中可以根据自己的需要来实现密钥和iv的生成。比如用md5来生成
注意加密过程
由于aes加密后的字节数组,直接转String返回参数有可能存在乱码,所以对返回值做一下处理,将加密的结果转换为base64的字符串。同理,解密时候,需要把字符串先base64处理,再把解密后的内容进行aes解密操作。
- 加密实现
- 加密(从前往后):明文 -> 加密 -> base64处理 -> 密文
-
-
- 解密实现
- 解密(从后往前):明文 <- 解密 <- base64处理 <- 密文
加密和解密方法
- import util from '@ohos.util';
- import cryptoFramework from '@ohos.security.cryptoFramework';
- import Logger from './Logger';
-
-
-
-
- const TAG: string = '[CipherModel]'
- const AES128: string = 'AES128';
- const AES128_CBC_PKCS5: string = 'AES128|CBC|PKCS5';
- const AES128_PKCS7: string = 'AES128|PKCS7';
-
-
- export class CipherModel {
- stringToUint8Array(str) {
- var arr = [];
- for (var i = 0, j = str.length; i < j; ++i) {
- arr.push(str.charCodeAt(i));
- }
- var tmpArray = new Uint8Array(arr);
- return tmpArray;
- }
-
-
- uint8ArrayToString(array: Uint8Array) {
- let arrayString = '';
- for (let i = 0; i < array.length; i++) {
- arrayString += String.fromCharCode(array[i]);
- }
- return arrayString;
- }
-
-
- aesEncrypt(message: string, key: string, iv: string, callback) {
- let that = new util.Base64Helper();
-
-
- let paramsSpec: cryptoFramework.IvParamsSpec = { iv: { data: this.stringToUint8Array(iv) }, algName: "IvParamsSpec" }
- let aesGenerator = cryptoFramework.createSymKeyGenerator(AES128);
- let cipher = cryptoFramework.createCipher(AES128_CBC_PKCS5);
- let pubKey = that.decodeSync(key);
- let pubKeyBlob: cryptoFramework.DataBlob = { data: pubKey };
- aesGenerator.convertKey(pubKeyBlob, (err, symKey) => {
- if (err) {
- console.error("convertKey: error.");
- return;
- }
- cipher.init(cryptoFramework.CryptoMode.ENCRYPT_MODE, symKey, paramsSpec, (err, data) => {
- let input: cryptoFramework.DataBlob = { data: this.stringToUint8Array(message) };
- cipher.doFinal(input, (err, data) => {
- Logger.info(TAG, "EncryptOutPut is " + data.data);
- let result = that.encodeToStringSync(data.data)
- Logger.info(TAG, "result is " + result);
- callback(result)
- })
- })
- })
- }
-
-
- aesDecrypt(message: string, key: string, iv: string, callback) {
- let paramsSpec: cryptoFramework.IvParamsSpec = { iv: { data: this.stringToUint8Array(iv) }, algName: "IvParamsSpec" }
-
-
- let aesGenerator = cryptoFramework.createSymKeyGenerator(AES128);
- let cipher = cryptoFramework.createCipher(AES128_CBC_PKCS5);
- let that = new util.Base64Helper();
- let pubKey = that.decodeSync(key);
- let pubKeyBlob: cryptoFramework.DataBlob = { data: pubKey };
- aesGenerator.convertKey(pubKeyBlob, (err, symKey) => {
- if (err) {
- console.error("convertKey: error.");
- return;
- }
- cipher.init(cryptoFramework.CryptoMode.DECRYPT_MODE, symKey, paramsSpec, (err, data) => {
- let newMessage = that.decodeSync(message);
- let input: cryptoFramework.DataBlob = { data: newMessage };
- cipher.doFinal(input, (err, data) => {
- Logger.info(TAG, "DecryptOutPut is " + data.data);
- let result = this.uint8ArrayToString(data.data)
- Logger.info(TAG, "result is " + result);
- callback(result)
- })
- })
- })
- }
- }
点击加密按钮
- Row() {
- Button('aes加密').align(Alignment.Start)
- }.width('100%').margin({ left: 12, top: 12 })
- .onClick( () => {
- this.cipherModel.aesEncrypt(
- this.originText,
- this.AES_ENCRYPT_KEY,
- this.AES_IV_STRING,
- (result: string) => {
- Logger.info(this.TAG, `this result = ${JSON.stringify(result)}`);
- this.cipherText = result;
- })
- }
- )
// 点击解密按钮
- Row() {
- Button('aes解密').align(Alignment.Start)
- }.width('100%').margin({ left: 12, top: 12 })
- .onClick(() => {
- if(this.cipherText.toString().length === 0) {
- return;
- }
- this.cipherModel.aesDecrypt(this.cipherText,
- this.AES_ENCRYPT_KEY,
- this.AES_IV_STRING,
- (result: string) => {
- Logger.info(this.TAG, `this result = ${JSON.stringify(result)}`);
- this.decodedText = result;
- })
- })
本文中仅涉及了AES加解密的简单使用,并未根据项目实际需要来调整加密格式参数。如果项目中需要加密的信息数量较多或者需要较强的加密强度。请到官网查看最新版的相关文档,选择最合适的加密方法。
demo代码已上传github https://github.com/kainbro/LearnHamony
由于我还没找到鸿蒙工作,所以还没有拿到鸿蒙最新的sdk。此处使用的是官网的公开版本sdk 9。有些朋友项目中已经拿到华为内部鸿蒙版本,api可能略有不同,请根据最新sdk自行调整变更的api。
关注我获取更多知识或者投稿
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。