JuneAndGreen / sm-crypto

国密算法js版
MIT License
963 stars 257 forks source link

Sm2使用hutool工具进行加解密的解决方案 #72

Open musicguoke opened 2 years ago

musicguoke commented 2 years ago

问题的原因

通常由于网上找的js端提供的 SM2代码实现的方案, 都是直接使用的私钥的d值和公钥的q值直接进行的加解密 所以后端口返回的最好是从公钥里面提取的q值,以q值做为js端的加密公钥

前端使用publicKey加密步骤

GunhouWong commented 2 years ago

非常感谢,搞了半天看到您的方案终于解决了。👍

关于 hexStr 可以简化成以下的方法调用:

String hexStr = HexUtil.encodeHexStr(sm2.getQ(false));

longshihui commented 1 year ago

后端解密的时候还是用的原始私钥进行解密吗?按照上面的方法,后端目前一直解码出错

Tyler-Rabbit commented 1 year ago

后端解密的时候还是用的原始私钥进行解密吗?按照上面的方法,后端目前一直解码出错

SM2 sm2 = SmUtil.sm2(privateKey, null); String requestBody = sm2.decryptStr("04" + requestBody, KeyType.PrivateKey); 可以用生成的Base64编码的私钥构造sm2对象来解密,需要在密文前加上04前缀

herodotus-ecosystem commented 2 months ago

使用 SM2 和 SM4 实现的数字信封前后端数据传输加解密。

SM2 部分实现,如下。详情参见:代码

前端

class SM2Utilities {
  private static instance = new SM2Utilities();
  private cipherMode = 1; // 1 - C1C3C2,0 - C1C2C3

  private constructor() {}

  public static getInstance(): SM2Utilities {
    return this.instance;
  }

  public createKeyPair() {
    return sm2.generateKeyPairHex();
  }

  public encrypt(content: string, publicKey: string) {
    return '04' + sm2.doEncrypt(content, publicKey, this.cipherMode);
  }

  public decrypt(content: string, privateKey: string) {
    let data = content.substring(2).toLocaleLowerCase();
    return sm2.doDecrypt(data, privateKey, this.cipherMode);
  }
}

后端

    @Override
    public SecretKey createSecretKey() {
        // 随机生成秘钥
        SM2 sm2 = SmUtil.sm2();
        // sm2的加解密时有两种方式即 C1C2C3、 C1C3C2,
        sm2.setMode(SM2Engine.Mode.C1C3C2);
        // 生成私钥
        String privateKey = HexUtil.encodeStr(ECKeyUtil.encodeECPrivateKey(sm2.getPrivateKey()));
        // 生成公钥
        String publicKey = HexUtil.encodeStr(((BCECPublicKey) sm2.getPublicKey()).getQ().getEncoded(false));

        SecretKey secretKey = new SecretKey();
        secretKey.setPrivateKey(privateKey);
        secretKey.setPublicKey(publicKey);
        return secretKey;
    }

    @Override
    public String decrypt(String content, String privateKey) {
        // 可用的 Hutool SM2 解密
        SM2 sm2 = SmUtil.sm2(privateKey, null);
        sm2.setMode(SM2Engine.Mode.C1C3C2);

        String result = StrUtil.utf8Str(sm2.decrypt(content, KeyType.PrivateKey));
        log.trace("[Herodotus] |- SM2 crypto decrypt data, value is : [{}]", result);

        return result;
    }

    @Override
    public String encrypt(String content, String publicKey) {
        SM2 sm2 = SmUtil.sm2(null, publicKey);

        String result = sm2.encryptHex(content, KeyType.PublicKey);
        log.trace("[Herodotus] |- SM2 crypto encrypt data, value is : [{}]", result);
        return result;
    }