HarmonyOS鸿蒙Next中是否有现成的国密加密工具类可以使用?
HarmonyOS鸿蒙Next中是否有现成的国密加密工具类可以使用?
请问有没有现成的国密加密工具类可以使用
现在的三方库里的加密都有点问题
5 回复
参考以下代码:
// 加密消息
async function encryptMessagePromise(publicKey: cryptoFramework.PubKey, plainText: cryptoFramework.DataBlob) {
//密钥类型为SM2_256、摘要算法为SM3的Cipher
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()
}
// SM2 main代码
async function main() {
//十六进制的公私钥
let pubKeyStr = "0453402B95F3584F36B9A7129A6B5C6109F2DBC7C94BE7858DB66C48AF38CB5C3B76883EE4BF18E270607191E233EAC0A95ECFB8EF6FE80C5F782DE24F018DEB5F"
let priKeyStr = "5B9270E0ADF86A101167610FCCD375A6549DC14E9225951EF3A4640F26D6CD9C"
//安卓加密后的密文
let a = "53ce193ad865c6d97742da78b18a21d0ca66200fe080284d774d5500915be2425cea2f310c9a423bc2d08ce5c1e78a75cfd66d88688a0e2076a45614307e4372aa10b514841cfe7bff08fc82d96bdf35754696571e5fbedd552d1ab7c54bff796a0e3fd72902";
//根据密钥参数生成对应的公私钥
let pubKey = await convertStrToPubKey(pubKeyStr)
let priKey = await convertStrToPriKey(priKeyStr)
// 此处为明文
let message = 'This is a test';
// 把字符串按utf-8解码为Uint8Array
let plainText: cryptoFramework.DataBlob = { data: new Uint8Array(buffer.from(message, 'utf-8').buffer) };
let encryptText = await encryptMessagePromise(pubKey, plainText);
console.log("encryptText=======>" + buffer.from(encryptText.data).toString('hex'))
//将加密的密文数据解码转换为安卓可用数据(用于鸿蒙和安卓的交接)
let b = new SM2_Ciphertext().d2i_SM2_Ciphertext(buffer.from(encryptText.data).toString('hex'))
console.log("解码后数据=======>" + b)
//解密得到结果
let res = await decryptMessagePromise(priKey, encryptText)
console.log("a=======>" + buffer.from(res.data).toString('utf-8'))
//针对安卓的密文处理,转成鸿蒙可用uint8Array数组数据
let c = new Uint8Array(buffer.from(new SM2_Ciphertext().i2d_SM2_Ciphertext(a), 'hex').buffer)
//对安卓生成的的密文进行解密
let resa = await decryptMessagePromise(priKey, { data: c })
console.log("安卓的密文解码数据=======>" + buffer.from(resa.data).toString('utf-8'))
}
import hilog from '@ohos.hilog';
import { SM2_SEQUENCE } from './sm2Sequence';
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裸密文数据序列化
@param primal_data SM2裸密钥数据,长度为96+明文长度(字节),输入格式为C1C3C2的Hex字符串
@returns 返回序列化后的标准密文数据,输出格式为Hex字符串
*/
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密文数据解码
@param standard_data 标准SM2密文数据,符合ASN.1编码标准,输入格式为Hex字符串
@returns 返回ASN.1解码后的SM2密文数据
*/
d2i_SM2_Ciphertext(standard_data: string): string {
let message: string = standard_data;
// 起始标识为03
if (!message.startsWith(ASN1Util.SEQUENCE)) {
this.ciphertextErr();
}
message = message.slice(ASN1Util.SEQUENCE.length, message.length);
// SM2 sequence
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 = ("00" + size.toString(16)).slice(-2);
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;
}
}
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中是否有现成的国密加密工具类可以使用?的实战系列教程也可以访问 https://www.itying.com/category-93-b0.html
鸿蒙自带的加密库有基础的国密加密
在HarmonyOS鸿蒙Next中,确实提供了现成的国密加密工具类。鸿蒙系统内置了对国密算法的支持,包括SM2、SM3、SM4等。具体来说,开发者可以通过ohos.security.crypto模块中的相关API来实现国密加密功能。例如,SM2用于非对称加密,SM3用于哈希算法,SM4用于对称加密。这些工具类可以直接在鸿蒙应用中使用,无需额外引入第三方库。开发者可以通过查阅鸿蒙官方文档获取详细的API使用方法和示例代码。


