HarmonyOS 有没有现成的国密加密工具类可以使用

HarmonyOS
2天前
浏览
收藏 0
回答 1
待解决
回答 1
按赞同
/
按时间
zbw_apple

sm2 加解密 为十六进制字符串生成HarmonyOS密钥对 对铭文加解密的demo案例如下

// 加密消息
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'))
  //针对密文处理,转成HarmonyOS可用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'))
}

sm2Ciphertext.ets

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(&#34;0x&#34; + sm2_sequence.C1x.slice(0, 2)) &gt; 127) ? &#34;022100&#34; : &#34;0220&#34;;
    let C1y_title: string = (Number.parseInt(&#34;0x&#34; + sm2_sequence.C1y.slice(0, 2)) &gt; 127) ? &#34;022100&#34; : &#34;0220&#34;;
    let C3_title: string = &#34;0420&#34;;
    let C2_title: string = &#34;04&#34; + 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 = &#34;30&#34; + 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 &#20869;&#23481;&#30340;&#38271;&#24230;
    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.leng

分享
微博
QQ
微信
回复
2天前
相关问题
HarmonyOS 算法API
432浏览 • 0回复 待解决
鸿蒙-有没有缓存工具
5962浏览 • 1回复 待解决
HarmonyOS 标准方案
204浏览 • 1回复 待解决
HarmonyOS有没有通用工具样例Demo
382浏览 • 1回复 待解决
HarmonyOS SM2,SM4加解密使用demo
283浏览 • 1回复 待解决
如何使用SM2算法进行加解密
4302浏览 • 1回复 待解决
HarmonyOS 有没有类似gradle打包工具
93浏览 • 1回复 待解决
ArkTS有没有读取ini
268浏览 • 1回复 待解决