const { sm2 } = require('sm-crypto');

/**
 * 国密2帮助类
 * 
 * 基于[ sm-crypto ](https://www.npmjs.com/package/sm-crypto)开发
 * 
 * Asn1 在线解析
 * 
 * https://the-x.cn/encodings/Asn1.aspx
 * 
 * http://lapo.it/asn1js/#
 */
export class Sm2Util {
    /**
     * 签名
     * 
     * 注：
     * 1.传入公钥的话，可以去掉sm3杂凑中推导公钥的过程，速度会比纯签名 + 生成椭圆曲线点 + sm3杂凑快
     * 2.如果没有公钥，传入 pointPool: [sm2.getPoint(), sm2.getPoint(), sm2.getPoint(), sm2.getPoint()],稍微快点
     * @param data 
     * @param privateKey 私钥，需传最终参与签名的16进制字符串，例：fd89d3ebd38097f5a5350c7df9033bfc75d911b7a17254d49d5ca2b4ba2dbcf1
     * @param opts pointPool: [sm2.getPoint(), sm2.getPoint(), sm2.getPoint(), sm2.getPoint()],
     * @returns 
     */
    static sign(data: string, privateKey: string, opts?: { pointPool?:any, der?: boolean, hash?: boolean, publicKey:string }) {
        let sign = sm2.doSignature(data, privateKey, {
            pointPool: opts.pointPool,
            der: opts?.der,
            hash: opts?.hash,
            publicKey: opts.publicKey
        });

        return Buffer.from(sign, 'hex').toString('base64');
    }

    /**
     * 验签
     * 
     * @param sign 签名结果(base64)
     * @param publicKey 公钥，需传最终参与验签的16进制字符串，例：047d4398d82a2565021d682b6fd7b1d9c0f194a8ceddeb3ad1bcb8b45cd4c9f377872b748dd29d6a3b2f6081a280cf931076bc8908ac2259512b015660e6c6fab8
     */
    static verifySign(data: string, sign: string, publicKey: string, opt?: { der?: boolean, hash?: boolean }) {
        return sm2.doVerifySignature(data,
            Buffer.from(sign, 'base64').toString('hex'),
            publicKey, {
            der: opt?.der,
            hash: opt?.hash,
        });
    }

    /**
     * 加密
     * 
     * @param publicKey 公钥，需传最终参与加密的16进制字符串，例：047d4398d82a2565021d682b6fd7b1d9c0f194a8ceddeb3ad1bcb8b45cd4c9f377872b748dd29d6a3b2f6081a280cf931076bc8908ac2259512b015660e6c6fab8
     * @param cipherMode 0 - C1C2C3,1 - C1C3C2，默认为1
     */
    static encrypt(data: string, publicKey: string, cipherMode?: 0 | 1) {
        let encrypted = sm2.doEncrypt(data, publicKey, cipherMode);
        //给JAVA解密需加04
        return Buffer.from('04' + encrypted, 'hex').toString('base64');
    }

    /**
     * 解密
     * 
     * @param data 待解密的字符串(base64)
     * @param privateKey 私钥，需传最终参与签名的16进制字符串，例：fd89d3ebd38097f5a5350c7df9033bfc75d911b7a17254d49d5ca2b4ba2dbcf1
     * @param cipherMode 0 - C1C2C3,1 - C1C3C2，默认为1
     */
    static decrypt(data: string, privateKey:string, cipherMode?: 0 | 1) {
        //JAVA密文需要去04再解密
        let decrypted = sm2.doDecrypt(Buffer.from(data, 'base64').toString('hex').substring(2), privateKey, cipherMode);
        return decrypted;
    }
}