1. 介绍
HarmonyOS(鸿蒙)SDK API9支持两种对称加密算法:a. AES(Advanced Encryption Standard) b.3DES(也称为 3DESede 或 TripleDES).
官方也给出了一些样例使用代码,可供开发者参考。
本篇从实践出发,完整的通过代码方式来深入了解HarmonyOS中的对称加密用法。
2. 基础概念
字符串样例:AES256|EBC|PKCS5
- 密钥算法 : AES
- 密文组长度 : 256
- 分组模式 : EBC
- 填充模式 : PCKCS5
关于“AES算法”,“分组模式”,“填充模式”的具体概念,可自行搜索。
3. 实践
加密使用的测试数据源有两个,具体见下图
- “125字节” (即,占用了125个字节的字符串)
- “128字节” (即,占用了128个字节的字符串)
3.1 MMI入口
3.2 AES加解密
3DES加密算法密文分组长度有三种:128,192,256;支持7种分组模式:ECB,CBC,OFB,CFB,CTR,GCM,CCM;支持3种填充模式:NoPadding, PKCS5, PKCS7
本篇仅以256密文组长度做为实践验证,默认选择“128字节”数据集
片段代码以 “AES256|ECB|PKCS5” 为例
3.2.1 加密
- 生成对动态密钥
//导入加密框架
import cryptoFramework from '@ohos.security.cryptoFramework';
......
//创建密钥生成器,参数为(密钥算法+密文组长度,如:AES256)
let symKeyGenerator = cryptoFramework.createSymKeyGenerator('AES256');
//生成对称密钥
let promiseSymKey = symKeyGenerator.generateSymKey();
//获取密钥
promiseSymKey( key => {
//动态密钥
this.symBinKey = key.getEncoded().data;
})
- 初始化Cipher
//创建Cipher
globalCipher = cryptoFramework.createCipher('AES256|ECB|PKCS5');
//初始化Cipher
let mode = cryptoFramework.CryptoMode.ENCRYPT_MODE;
globalCipher.init(mode, key, null)
- 加密
//文字转换为Uint8Array
const encoder = new util.TextEncoder()
let u8a_encoder = encoder.encodeInto('测试')
//封装Uint8Array 数据,必须是一个带data属性的对象
let plainText = { data: u8a_encoder };
//开始加密
let promiseUpdate = globalCipher.update(plainText);
//获取加密结果
promiseUpdate( result => {
//密文
let this.cipherText = result.data
})
- 结束加密
上述虽然已经完成了加密,但是需要加密的文字字节长度不一定是128的整数倍,所以使用填充模式会弥补不足位的数据,并且在update之后,采用doFinal的方式结束最终加密
//结束加密
let promiseFinal = globalCipher.doFinal(null);
//获取剩余结果
promiseFinal( finalResult => {
if(finalResult != null){
//剩余加密结果
let authTag = finalResult.data
}
})
3.2.2 解密
- 生成密钥对象
我们这里使用加密过程中产生的密钥数据。注意此密钥数据不能直接用来构建Key对象(即 密钥对象),正确的方法是通过API来生成密钥对象
//准备密钥数据,this.symBinKey 是上述过程生成的密钥
let keyMaterialBlob: cryptoFramework.DataBlob = { data: this.symBinKey };
//创建密钥生成器,参数为(密钥算法+密文组长度,如:AES256)
let symKeyGenerator = cryptoFramework.createSymKeyGenerator('AES256');
//密钥生成器使用密钥数据,开始生成密钥对象
symKeyGenerator.convertKey(keyMaterialBlob).then( key => {
//key 为生成的密钥对象
})
- 初始化Cipher
//创建Cipher
globalCipher = cryptoFramework.createCipher('AES256|EBC|PKCS5');
//初始化Cipher,参数key由第一步生成
let mode = cryptoFramework.CryptoMode.DECRYPT_MODE;
globalCipher.init(mode, key, null)
- 解密
//mergeResult 代表密文,本篇文章中,此值来源于上述加密结果
let promiseUpdate = globalCipher.update({ data: mergeResult });
- 结束解密
//结束解密
let promiseFinal = globalCipher.doFinal(null);
//获取剩余结果
promiseFinal( finalResult => {
if(finalResult != null){
//有剩余解密结果
} else {
//无剩余解密结果
}
})
3.2.3 注意点
- 采用GCM分组模式时,需要设置 ‘GcmParamsSpec’ 参数
- 采用CCM分组模式时,需要设置 ‘CcmParamsSpec’ 参数
- 采用CBC,OFB,CFB,CTR模式时,可以使用 ‘IvParamsSpec’ 参数
- 如果选择了"NoPadding"填充模式,需要明文的字节长度如果不是128的整数倍,则会出现截断现象,这种情况算做正常。
- 不要并发加密
- 加密/解密行为之间需要有时间间隔
3.2.4 源码
import cryptoFramework from '@ohos.security.cryptoFramework';
import util from '@ohos.util';
import Logger from '../../common/Logger';
import OriginData from './OriginData';
import emitter from "@ohos.events.emitter";
/**
* 对称密钥
* 密钥算法:AES
* 密钥规格格式:密钥算法名称 + 密钥长度
* 密钥长度:128,192,256
* 密钥规格列表:AES128, AES192, AES256
*
* 对称加密
* 加密算法:AES
* 加密规格格式:密钥算法名称 + 密钥长度 + 分组模式 + 填充模式
* 密钥长度&