HarmonyOS鸿蒙Next ohos.security.cryptoFramework加解密框架使用使用
HarmonyOS鸿蒙Next ohos.security.cryptoFramework加解密框架使用使用 使用的国密,需要使用sm2与sm4结合的加解密组合。
3 回复
sm2 使用公钥 加密sm4 的密钥demo如下
@Entry
@Component
struct SM2Crypto {
@State message: string = '点击开始';
build() {
Row() {
Column() {
Text(this.message)
.fontSize(50)
.fontWeight(FontWeight.Bold)
.onClick(() => {
main();
})
}
.width('100%')
}
.height('100%')
}
}
// 加密消息
async function encryptMessagePromise(publicKey: cryptoFramework.PubKey, plainText: cryptoFramework.DataBlob) {
let cipher = cryptoFramework.createCipher('SM2_256|SM3');
await cipher.init(cryptoFramework.CryptoMode.ENCRYPT_MODE, publicKey, null);
let encryptData = await cipher.doFinal(plainText);
return encryptData;
}
// 解密消息
async function decryptMessagePromise(privateKey: cryptoFramework.PriKey, cipherText: cryptoFramework.DataBlob) {
let decoder = cryptoFramework.createCipher('SM2_256|SM3');
await decoder.init(cryptoFramework.CryptoMode.DECRYPT_MODE, privateKey, null);
let decryptData = await decoder.doFinal(cipherText);
return decryptData;
}
export async function convertStrToPriKey(keyStr: string): Promise<cryptoFramework.PriKey> {
let sk = BigInt("0x" + keyStr)
let priKeySpec: cryptoFramework.ECCPriKeySpec = {
params: cryptoFramework.ECCKeyUtil.genECCCommonParamsSpec('NID_sm2'),
sk: sk,
algName: "SM2",
specType: cryptoFramework.AsyKeySpecType.PRIVATE_KEY_SPEC
}
let keypairGenerator = cryptoFramework.createAsyKeyGeneratorBySpec(priKeySpec)
return await keypairGenerator.generatePriKey()
}
export async function convertStrToPubKey(keyStr: string): Promise<cryptoFramework.PubKey> {
let pubKeyStr = keyStr.startsWith("04") ? keyStr.slice(2) : keyStr
let pkPart1 = pubKeyStr.slice(0, pubKeyStr.length / 2)
let pkPart2 = pubKeyStr.slice(pubKeyStr.length / 2)
let pk: cryptoFramework.Point = {
x: BigInt("0x" + pkPart1),
y: BigInt("0x" + pkPart2),
}
let pubKeySpec: cryptoFramework.ECCPubKeySpec = {
params: cryptoFramework.ECCKeyUtil.genECCCommonParamsSpec('NID_sm2'),
pk: pk,
algName: "SM2",
specType: cryptoFramework.AsyKeySpecType.PUBLIC_KEY_SPEC
}
let keypairGenerator = cryptoFramework.createAsyKeyGeneratorBySpec(pubKeySpec)
return await keypairGenerator.generatePubKey()
}
function detachSM2CipherText(cipherText: cryptoFramework.DataBlob): string {
let spec: cryptoFramework.SM2CipherTextSpec = cryptoFramework.SM2CryptoUtil.getCipherTextSpec(cipherText, 'C1C3C2');
let c1str: string = "04" + spec.xCoordinate.toString(16) + spec.yCoordinate.toString(16);
let c1: Uint8Array = new Uint8Array(buffer.from(c1str, 'utf-8').buffer);
let c2: Uint8Array = spec.cipherTextData;
let c3: Uint8Array = spec.hashData;
let c1c2c3: Uint8Array = new Uint8Array(c1.length + c2.length + c3.length);
c1c2c3.set(c1);
c1c2c3.set(c2, c1.length);
c1c2c3.set(c3, c1.length + c2.length);
return new util.Base64Helper().encodeToStringSync(c1c2c3);
}
// SM2 main代码
async function main() {
let base64 = new util.Base64Helper();
let pubKeyStr2 = "BJZL3PngK3I93QcMCyCUbbN8DuoSjp0fn2AjtnGWDklz2Zrt4Nw0AUYtnk4/2D+/YNNQCvuvawFBn4yBnlu9jIA=";
let u8aP = base64.decodeSync(pubKeyStr2)
console.error('Uint8Array u8aP result string:' + u8aP);
let buf = buffer.from(u8aP);
console.log('hex u8aP result string:' + buf.toString('hex'));
let hexpubKeyStr = "04964bdcf9e02b723ddd070c0b20946db37c0eea128e9d1f9f6023b671960e4973d99aede0dc3401462d9e4e3fd83fbf60d3500afbaf6b01419f8c819e5bbd8c80"
let pubKey = await convertStrToPubKey(hexpubKeyStr)
// 此处为明文
let message = 'sm4密钥';
// 把字符串按utf-8解码为Uint8Array
let plainText: cryptoFramework.DataBlob = { data: new Uint8Array(buffer.from(message, 'utf-8').buffer) };
let encryptText = await encryptMessagePromise(pubKey, plainText);
console.error("encryptText=======>" + buffer.from(encryptText.data).toString('hex'))
// reslut 是加密后的密文数据
let spec: cryptoFramework.SM2CipherTextSpec = cryptoFramework.SM2CryptoUtil.getCipherTextSpec(encryptText, 'C1C3C2');
let str = "04" + spec.xCoordinate.toString(16) + spec.yCoordinate.toString(16) + buffer.from(spec.cipherTextData).toString('hex') + buffer.from(spec.hashData).toString('hex')
console.error("C1C2C3解码后16进制数据=======>" + str)
let Base64Str = base64.encodeToStringSync(new Uint8Array(buffer.from(str, 'hex').buffer))
console.error("C1C2C3解码后数据Base64Str=======>" + Base64Str)
}
export class ASN1Util {
static BOOLEAN: string = "01";
static INTEGER: string = "02";
static BIT_STRING: string = "03";
static OCTET_STRING: string = "04";
static NULL: string = "05";
static REAL: string = "09";
static ENUMERATED: string = "0a";
static SEQUENCE: string = "30";
static SET: string = "31";
}
export class SM2_Ciphertext {
// 用于将SM2裸密文数据序列化
i2d_SM2_Ciphertext(primal_data: string): string {
let sm2_sequence = new SM2_SEQUENCE();
sm2_sequence.C1x = primal_data.slice(0, 64);
primal_data = primal_data.slice(64, primal_data.length);
sm2_sequence.C1y = primal_data.slice(0, 64);
primal_data = primal_data.slice(64, primal_data.length);
sm2_sequence.C3 = primal_data.slice(0, 64);
primal_data = primal_data.slice(64, primal_data.length);
sm2_sequence.C2 = primal_data;
let C1x_title: string = (Number.parseInt("0x" + sm2_sequence.C1x.slice(0, 2)) > 127) ? "022100" : "0220";
let C1y_title: string = (Number.parseInt("0x" + sm2_sequence.C1y.slice(0, 2)) > 127) ? "022100" : "0220";
let C3_title: string = "0420";
let C2_title: string = "04" + this.genLenHex(sm2_sequence.C2);
let sequence_message: string = C1x_title + sm2_sequence.C1x + C1y_title + sm2_sequence.C1y + C3_title + sm2_sequence.C3 + C2_title + sm2_sequence.C2;
let sequence_lenHex: string = this.genLenHex(sequence_message);
let standard_data = "30" + sequence_lenHex + sequence_message;
return standard_data;
}
// 用于将标准SM2密文数据解码
d2i_SM2_Ciphertext(standard_data: string): string {
let message: string = standard_data;
if (!message.startsWith(ASN1Util.SEQUENCE)) {
this.ciphertextErr();
}
message = message.slice(ASN1Util.SEQUENCE.length, message.length);
let sequence_lenHex: string = this.getLenHex(message);
message = message.slice(sequence_lenHex.length, message.length);
let sequence_len: number = this.lenHex2number(sequence_lenHex);
if (sequence_len != message.length / 2) {
this.ciphertextErr();
}
let sm2_sequence = new SM2_SEQUENCE();
message = this.readC1(sm2_sequence, message);
message = this.readC3(sm2_sequence, message);
message = this.readC2(sm2_sequence, message);
let primal_data: string = sm2_sequence.C1x + sm2_sequence.C1y + sm2_sequence.C3 + sm2_sequence.C2;
return primal_data;
}
// 生成传入内容的长度域
genLenHex(content: string): string {
let size: number = content.length / 2;
let lenHex: string;
if (size.toString(16).length % 2 == 1 ) {
lenHex= '0' + size.toString(16);
} else {
lenHex = size.toString(16);
}
if(size < 0x80){
return lenHex;
}
let lenHex_size: number = lenHex.length / 2;
return (lenHex_size | 0x80).toString(16) + lenHex;
}
// 提取长度域的Hex字符串
getLenHex(data: string): string {
let byte: number = Number.parseInt("0x" + data.slice(0, 2));
let len_size: number = byte > 127 ? byte - 0x80 + 1 : 1;
return data.slice(0, len_size * 2);
}
// 将长度域的Hex字符串转为整型
lenHex2number(lenHex: string): number {
if (lenHex.length == 2) {
return Number.parseInt("0x" + lenHex);
}
return Number.parseInt("0x" + lenHex.slice(2, lenHex.length));
}
ciphertextErr() {
hilog.error(0, "d2i_SM2_Ciphertext", "密文格式错误");
throw new Error("SM2 ciphertext error!")
}
readC1(sm2_sequence: SM2_SEQUENCE, data: string): string {
let xy: string[] = [];
for (let i = 0; i < 2; i++) {
if (data.startsWith("0220")) {
xy[i] = data.slice(4, 68);
data = data.slice(68, data.length);
} else if (data.startsWith("022100")) {
xy[i] = data.slice(6, 70);
data = data.slice(70, data.length);
} else {
this.ciphertextErr();
}
}
sm2_sequence.C1x = xy[0];
sm2_sequence.C1y = xy[1];
return data;
}
readC2(sm2_sequence: SM2_SEQUENCE, data: string): string {
if (data.startsWith(ASN1Util.OCTET_STRING)) {
data = data.slice(ASN1Util.OCTET_STRING.length, data.length);
let C2_lenHex = this.getLenHex(data);
data = data.slice(C2_lenHex.length, data.length)
if (this.lenHex2number(C2_lenHex) != data.length / 2) {
this.ciphertextErr()
}
sm2_sequence.C2 = data;
} else {
this.ciphertextErr();
}
return data;
}
readC3(sm2_sequence: SM2_SEQUENCE, data: string): string {
if (data.startsWith("0420")) {
sm2_sequence.C3 = data.slice(4, 68);
data = data.slice(68, data.length);
} else {
this.ciphertextErr();
}
return data;
}
/*
* 转鸿蒙签名后的数据
* */
d2i_SM2_SignText(standard_data: string): string {
let randNum:string = "";
let signText:string = "";
let message = standard_data.slice("30".length, standard_data.length);
let sequence_lenHex: string = this.getLenHex(message);
message = message.slice(sequence_lenHex.length, message.length);
try {
let randNum_len: string = message.slice(0, 4);
if(randNum_len == "0220"){
randNum = message.slice(4, 4+64);
message = message.slice(4+64, message.length);
} else {
randNum = message.slice(6, 6+64);
message = message.slice(6+64, message.length);
}
let signText_len: string = message.slice(0, 4);
if(signText_len == "0220"){
signText = message.slice(4, 4+64);
} else {
signText = message.slice(6, 6+64);
}
} catch (e) {
hilog.error(0x1, "d2i_SM2_SignText", "SignText format is err");
}
return randNum+signText
}
}
export class SM2_SEQUENCE{
private _C1x: string = "";
private _C1y: string = "";
private _C2: string = "";
private _C3: string = "";
public set C1x(value: string) {
this._C1x = value;
}
public get C1x(): string {
return this._C1x;
}
public set C1y(value: string) {
this._C1y = value;
}
public get C1y(): string {
return this._C1y;
}
public set C2(value: string) {
this._C2 = value;
}
public get C2(): string {
return this._C2;
}
public set C3(value: string) {
this._C3 = value;
}
public get C3(): string {
return this._C3;
}
public toString():string{
return JSON.stringify(this);
}
}
更多关于HarmonyOS鸿蒙Next ohos.security.cryptoFramework加解密框架使用使用的实战系列教程也可以访问 https://www.itying.com/category-93-b0.html
HarmonyOS鸿蒙Next中的ohos.security.cryptoFramework加解密框架提供了多种加密算法和功能,支持对称加密、非对称加密、摘要算法、密钥生成与管理等操作。
- 对称加密:支持AES、3DES等算法,适用于大数据量的加密和解密。
- 非对称加密:支持RSA、ECC等算法,适用于密钥交换和数字签名。
- 摘要算法:支持SHA-1、SHA-256等,用于生成数据的唯一哈希值。
- 密钥生成与管理:支持生成和存储对称密钥、非对称密钥对,并提供密钥的安全存储机制。
使用步骤:
- 初始化加密框架:通过
CryptoFramework类获取加解密实例。 - 创建密钥生成器:使用
KeyGenerator生成对称或非对称密钥。 - 创建加密/解密器:使用
Cipher类进行加密或解密操作。 - 执行加解密操作:调用
Cipher的init、update、doFinal方法完成加解密。
示例代码:
import cryptoFramework from '@ohos.security.cryptoFramework';
// 初始化加密框架
let cipher = cryptoFramework.createCipher('AES128|ECB|PKCS7');
// 生成密钥
let keyGenerator = cryptoFramework.createKeyGenerator('AES128');
let symKey = keyGenerator.generateKey();
// 初始化加密器
cipher.init(cryptoFramework.CryptoMode.ENCRYPT_MODE, symKey, null);
// 加密数据
let plainText = 'Hello, HarmonyOS!';
let encryptData = cipher.doFinal({ data: new Uint8Array(plainText) });
ohos.security.cryptoFramework适用于数据加密、安全通信等场景,确保数据的安全性和完整性。
HarmonyOS的ohos.security.cryptoFramework提供了丰富的加解密功能,支持对称加密、非对称加密、消息摘要等。使用时,首先通过CryptoFactory创建加密实例,然后配置密钥和算法,最后进行数据加解密操作。例如,使用AES对称加密时,需生成或导入密钥,调用cipher.init()初始化,再调用cipher.doFinal()完成加解密。开发者需根据业务需求选择合适的算法和密钥管理方式,确保数据安全。

