鸿蒙系统开发【ASN.1密文转换】安全

ASN.1密文转换

介绍

本示例对使用@kit.CryptoArchitectureKit加密后的密文格式进行转换。@kit.CryptoArchitectureKit加密后的密文格式默认为以base64显示的ASN.1格式问题,通过对密文进行base64变换后得到字符数组,以16进制数字显示,再此基础上进行密文格式转换,从ASN.1格式转换为c1c3c2格式的裸密文,再以c1c3c2格式的裸密文进行解密,以验证密文转换的正确性。

效果预览

使用说明

  1. 点击主页面加密 按钮,对原始数据使用SM2国密算法进行加密,其内容显示在加密数据 文本框中, 此时解密 按钮和base64转换按钮使能
  2. 点击主页面base64转换 按钮,对原始密文进行base64转换,在加密数据 文本框中显示转换后的密文 此时asn.1转换按钮使能
  3. 点击主页面asn.1转换 按钮,对密文进行asn.1转换,在加密数据 文本框中显示转换后的密文 此时加密 按钮和base64转换按钮去使能
  4. 点击主页面解密 按钮,对密文进行解密,在解密数据 文本框中显示解密后的文本 此时解密按钮去使能

具体实现

  • 对文本加密:在[SM2.ets] 点击加密按钮,调用加密函数实现对文本内容进行加密。点击解密按钮,调用解密函数实现对文本内容进行解密. 对消息加密的过程中采用cryptoFramework.Cipher完成加解密操作。

    import { cryptoFramework } from '@kit.CryptoArchitectureKit';
    import { print } from '@kit.BasicServicesKit';
    import { buffer, util } from '@kit.ArkTS';
    import { SM2CipherText } from './SM2CipherText';

    async function genECCPubKey(key: string) {
    let mode: number = 1;
    let pk: cryptoFramework.Point = {
    x: BigInt(""),
    y: BigInt(""),
    };
    if ((mode & 0x01) != 0 && key != null) {
    pk = {
    x: BigInt("0x" + key.substring(0, 64)),
    y: BigInt("0x" + key.substring(64, 128)),
    }
    }
    let keyPairGenerator: cryptoFramework.AsyKeyGeneratorBySpec;
    let pubKeySpec: cryptoFramework.ECCPubKeySpec = {
    params: genSM2CommonSpec(),
    pk: pk,
    algName: "ECC",
    specType: cryptoFramework.AsyKeySpecType.PUBLIC_KEY_SPEC
    };
    keyPairGenerator = cryptoFramework.createAsyKeyGeneratorBySpec(pubKeySpec);
    return await keyPairGenerator.generatePubKey();
    }

    async function genECCPriKey(key: string) {
    let mode: number = 2;
    let sk: bigint = BigInt("");
    if ((mode & 0x02) != 0) {
    sk = BigInt("0x" + key);
    }
    let keyPairGenerator: cryptoFramework.AsyKeyGeneratorBySpec;
    let priKey: cryptoFramework.ECCPriKeySpec = {
    params: genSM2CommonSpec(),
    sk: sk,
    algName: "ECC",
    specType: cryptoFramework.AsyKeySpecType.PRIVATE_KEY_SPEC
    };
    keyPairGenerator = cryptoFramework.createAsyKeyGeneratorBySpec(priKey);
    return await keyPairGenerator.generatePriKey();
    }

    export function genSM2CommonSpec(): cryptoFramework.ECCCommonParamsSpec {
    let fieldFp: cryptoFramework.ECFieldFp = {
    fieldType: "Fp",
    p: BigInt("0xFFFFFFFEFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF00000000FFFFFFFFFFFFFFFF")
    }

    let G: cryptoFramework.Point = {
      x: BigInt("0x32C4AE2C1F1981195F9904466A39C9948FE30BBFF2660BE1715A4589334C74C7"),
      y: BigInt("0xBC3736A2F4F6779C59BDCEE36B692153D0A9877CC62A474002DF32E52139F0A0")
    }
    
    let SM2CommonSpec: cryptoFramework.ECCCommonParamsSpec = {
      algName: "ECC",
      specType: cryptoFramework.AsyKeySpecType.COMMON_PARAMS_SPEC,
      field: fieldFp,
      a: BigInt("0xFFFFFFFEFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF00000000FFFFFFFFFFFFFFFC"),
      b: BigInt("0x28E9FA9E9D9F5E344D5A9E4BCF6509A7F39789F515AB8F92DDBCBD414D940E93"),
      g: G,
      n: BigInt("0xFFFFFFFEFFFFFFFFFFFFFFFFFFFFFFFF7203DF6B21C6052B53BBF40939D54123"),
      h: 1
    }
    return SM2CommonSpec;
    

    }

    export async function genSM2Key(pubKey: cryptoFramework.DataBlob | null, priKey: cryptoFramework.DataBlob | null): Promise<cryptoFramework.KeyPair> {
    let generator = cryptoFramework.createAsyKeyGenerator("SM2_256");
    return await generator.convertKey(pubKey, priKey)
    }

    async function encryptByPrimalKey(message: string, key: string): Promise<string> {
    let base64Helper = new util.Base64Helper();
    console.log(key len: ${key.length});
    let pubKey = await genECCPubKey(key);
    let keyPair = await genSM2Key(pubKey.getEncoded(), null);
    let cipher = cryptoFramework.createCipher("SM2_256|SM3");
    await cipher.init(cryptoFramework.CryptoMode.ENCRYPT_MODE, keyPair.pubKey, null);
    let plainTextBlob: cryptoFramework.DataBlob = { data: new Uint8Array(buffer.from(message, 'utf-8').buffer) };
    let encryptBlob = await cipher.doFinal(plainTextBlob);
    return base64Helper.encodeToStringSync(encryptBlob.data);
    }

    export async function encryptSM2(message: string) {
    let pubKey: string = "5A033A9DBEF84C0784C897D070E6608C5AEED39B806DF82853D64E2A686A3794" + "F9233D20DD878F642D61C2B0344988AE284646226767A1631BBB0DBB6DF40D07"
    return encryptByPrimalKey(message, pubKey);
    }

    async function decryptByPrimalKeyArray(messageArray: Uint8Array, key: string): Promise<string> {
    let priKey = await genECCPriKey(key);
    let keyPair = await genSM2Key(null, priKey.getEncoded());
    let cipher = cryptoFramework.createCipher("SM2_256|SM3");
    await cipher.init(cryptoFramework.CryptoMode.DECRYPT_MODE, keyPair.priKey, null);
    let plainTextBlob: cryptoFramework.DataBlob = { data: messageArray };
    let decryptBlob = await cipher.doFinal(plainTextBlob);
    return buffer.from(decryptBlob.data).toString('utf-8');
    }

    export async function decryptSM2(encryptedStr: string, isc1c3c2: Boolean = false): Promise<string> {
    let priKey: string = "3629EFF03FBC86711F6695CBF5590F0F2FCAAA3C269A1CA9BD64FB4C70DF9C9F"

    if (isc1c3c2) {
      let hexStr = new SM2CipherText().i2dSM2CipherText(encryptedStr);
      let encryptedArray = new Uint8Array(buffer.from(hexStr, 'hex').buffer);
      return decryptByPrimalKeyArray(encryptedArray, priKey);
    }
    else {
      let base64Helper = new util.Base64Helper;
      let message = base64Helper.decodeSync(encryptedStr);
      return decryptByPrimalKeyArray(message, priKey);
    }
    

    }

  • 对密文格式进行转换:在[SM2CipherText.ets]点击asn.1按钮,调用密文转换函数实现对密文内容进行转换。 完成密文转换操作。

    import { SM2Sequence } from './SM2Sequence';
    import { hilog } from '@kit.PerformanceAnalysisKit';

    export class ASN1Util {
    static readonly BOOLEAN: string = "01";
    static readonly INTEGER: string = "02";
    static readonly BIT_STRING: string = "03";
    static readonly OCTEN_STRING: string = "04";
    static readonly NULL: string = "05";
    static readonly REAL: string = "09";
    static readonly ENUMERATED: string = "0a";
    static readonly SEQUENCE: string = "30";
    static readonly SET: string = "31";
    }

    export class SM2CipherText {
    i2dSM2CipherText(primal_data: string): string {
    let sm2_sequence = new SM2Sequence();
    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;
    }
    
    d2iSM2CipherText(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_lexHex: string = this.getLenHex(message);
      message = message.slice(sequence_lexHex.length, message.length);
      let sequence_len: number = this.lenHex2number(sequence_lexHex);
      if (sequence_len != message.length / 2) {
        this.ciphertextErr();
      }
    
      let sm2_sequence = new SM2Sequence();
      message = this.readC1(sm2_sequence, message);
      message = this.readC3(sm2_sequence, message);
      message = this.readC2(sm2_sequence, message);
      console.log(sm2_sequence.toString());
    
      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;
    }
    
    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);
    }
    
    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: SM2Sequence, 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: SM2Sequence, data:string): string {
      if (data.startsWith(ASN1Util.OCTEN_STRING)) {
        data = data.slice(ASN1Util.OCTEN_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: SM2Sequence, 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;
    }
    

    }

以上就是本篇文章所带来的鸿蒙开发中一小部分技术讲解;想要学习完整的鸿蒙全栈技术。可以在结尾找我可全部拿到!

下面是鸿蒙的完整学习路线 ,展示如下:

除此之外,根据这个学习鸿蒙全栈学习路线,也附带一整套完整的学习【文档+视频】,内容包含如下

内容包含了:(ArkTS、ArkUI、Stage模型、多端部署、分布式应用开发、音频、视频、WebGL、OpenHarmony多媒体技术、Napi组件、OpenHarmony内核、鸿蒙南向开发、鸿蒙项目实战)等技术知识点。帮助大家在学习鸿蒙路上快速成长!

鸿蒙【北向应用开发+南向系统层开发】文档

鸿蒙【基础+实战项目】视频

鸿蒙面经

为了避免大家在学习过程中产生更多的时间成本,对比我把以上内容全部放在了↓↓↓想要的可以自拿喔!谢谢大家观看!

相关推荐
真真-真真22 分钟前
WebXR
linux·运维·服务器
hao_wujing25 分钟前
网络安全攻防演练中的常见计策
安全·web安全
轩辰~1 小时前
网络协议入门
linux·服务器·开发语言·网络·arm开发·c++·网络协议
SuperHeroWu71 小时前
【HarmonyOS】HarmonyOS和React Native混合开发 (一)之环境安装
react native·harmonyos·鸿蒙·开发环境·环境安装·rn·混合开发
燕雀安知鸿鹄之志哉.1 小时前
攻防世界 web ics-06
网络·经验分享·安全·web安全·网络安全
轻口味1 小时前
【每日学点鸿蒙知识】AVCodec、SmartPerf工具、web组件加载、监听键盘的显示隐藏、Asset Store Kit
前端·华为·harmonyos
无处安放的波澜1 小时前
【HarmonyOS 5.0】第十二篇-ArkUI公共属性(一)
华为·harmonyos·arkts·鸿蒙·鸿蒙系统
wanhengidc1 小时前
短视频运营行业该如何选择服务器?
运维·服务器
ProcessOn官方账号2 小时前
如何绘制网络拓扑图?附详细分类解说和用户案例!
网络·职场和发展·流程图·拓扑学
李洋-蛟龙腾飞公司2 小时前
HarmonyOS Next 应用元服务开发-分布式数据对象迁移数据文件资产迁移
分布式·华为·harmonyos