文章目录
- 一、简介
- 二、生成随机密钥对
- 三、加密方法
- 四、解密方法
一、简介
SM2是国密加解密方法,在官方文档中有介绍,因使用中发现系统的方法有对应的格式,在这里对使用方法做出说明。
二、生成随机密钥对
因生成的密钥对,数据前方有格式头描述,所以从26位开始截取,这里是密钥的数据。
/** 生成SM2临时密钥对 */public generateSM2Key(): string {if (this.pubKey != undefined) {return this.pubKey;}// 创建一个AsyKeyGenerator实例let sm2Generator = cryptoFramework.createAsyKeyGenerator('SM2_256');// 使用密钥生成器随机生成非对称密钥对let keyPair = sm2Generator.generateKeyPairSync();let pubKey = keyPair.pubKey;this.priKey = keyPair.priKey;// 获取非对称密钥对的二进制数据let pkBlob = pubKey.getEncoded();let skBlob = this.priKey.getEncoded();DKLogger.info("生成的临时密钥" + buffer.from(pkBlob.data).toString('hex'));DKLogger.info("生成的临时密钥" + buffer.from(skBlob.data).toString('hex'));let base64 = new util.Base64Helper();let base64Str = base64.encodeToStringSync(pkBlob.data.slice(26));this.pubKey = base64Str;return base64Str;}
三、加密方法
···
/** 加密方法 */
public encryptSM2(publicKey: cryptoFramework.PubKey, plainText: cryptoFramework.DataBlob): string | undefined {
let cipher = cryptoFramework.createCipher(‘SM2_256|SM3’);
cipher.initSync(cryptoFramework.CryptoMode.ENCRYPT_MODE, publicKey, null);
let encryptData = cipher.doFinalSync(plainText);
let base64 = new util.Base64Helper();
let base64Str = base64.encodeToStringSync(encryptData.data);
return base64Str;
}
···
四、解密方法
/** 解密方法 */public decryptSM2(cipherText: string): Uint8Array| undefined {let base64 = new util.Base64Helper();let cipherData = base64.decodeSync(cipherText)// DKLogger.info("密文" + buffer.from(cipherData).toString('hex'))// 用于将SM2裸密文数据序列化let hexStr = this.i2d_SM2_Ciphertext(buffer.from(cipherData).toString('hex'))// hex转Uint8Arraylet encryptedArray = hexStr2Uint8Array(hexStr)// DKLogger.info("密文" + hexStr)let decoder = cryptoFramework.createCipher('SM2_256|SM3');decoder.initSync(cryptoFramework.CryptoMode.DECRYPT_MODE, this.priKey, null);let specData: cryptoFramework.DataBlob = { data: encryptedArray};try {let decryptData = decoder.doFinalSync(specData);return decryptData.data;} catch (err) {DKLogger.error("errCode:" + err.code + ",errMessage:" + err.message);return undefined}}
因为Java加密的结果是普通数据没有前缀描述,这里做了一下转换
/*** 用于将SM2裸密文数据序列化* @param primal_data SM2裸密文数据,长度为96+明文长度(字节),输入格式为C1C3C2的Hex字符串* @returns 返回序列化后的标准密文数据,输出格式为Hex字符串*/private i2d_SM2_Ciphertext(primal_data: string): string {let sm2_sequence = new SM2_SEQUENCE();sm2_sequence.C1x = primal_data.slice(2, 66);primal_data = primal_data.slice(66, 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;}
// 生成传入内容的长度域private 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;}
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);}}