本示例对使用@kit.CryptoArchitectureKit加密后的密文格式进行转换。@kit.CryptoArchitectureKit加密后的密文格式默认为以base64显示的ASN.1格式问题,通过对密文进行base64变换后得到字符数组,以16进制数字显示,再此基础上进行密文格式转换,从ASN.1格式转换为c1c3c2格式的裸密文,再以c1c3c2格式的裸密文进行解密,以验证密文转换的正确性。
使用说明
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 { let generator = cryptoFramework.createAsyKeyGenerator("SM2_256"); return await generator.convertKey(pubKey, priKey) } async function encryptByPrimalKey(message: string, key: string): Promise { 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 { 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 { 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); } }
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内核、鸿蒙南向开发、鸿蒙项目实战)等技术知识点。帮助大家在学习鸿蒙路上快速成长!
为了避免大家在学习过程中产生更多的时间成本,对比我把以上内容全部放在了↓↓↓想要的可以自拿喔!谢谢大家观看!