SM2加密和MD5

385 阅读4分钟

SM2加解密 + MD5验签

1.SM2加密

概念:

SM2(国密椭圆曲线密码算法)是由中国国家密码管理局制定的椭圆曲线公钥密码算法标准。它包含了数字签名、加密、密钥协商等多个功能。以下是SM2加解密的基本介绍:

SM2加密(公钥加密):
  1. 生成密钥对: 首先,需要生成一对公私钥对。这对密钥是基于椭圆曲线的数学问题生成的,分别用于加密和解密。

  2. 加密数据: 加密方使用接收方的公钥对数据进行加密。具体步骤如下:

    • 随机生成对称密钥(比如AES密钥),用于对称加密数据。
    • 使用接收方的公钥对对称密钥进行非对称加密。
    • 使用对称密钥对原始数据进行对称加密。
  3. 发送密文: 发送方将加密后的对称密钥和加密后的数据一起发送给接收方。

SM2解密(私钥解密):
  1. 获取密文: 接收方收到密文后,使用自己的私钥对对称密钥进行解密,得到原始的对称密钥。

  2. 解密数据: 使用解密得到的对称密钥对密文进行对称解密,得到原始的数据。

SM2的特点:
  • 安全性: SM2基于椭圆曲线离散对数问题,具有较高的安全性,能够抵抗传统的公钥密码体制中的大多数攻击。

  • 效率: 相比RSA,SM2在相同安全性水平下使用较短的密钥长度,加密解密效率更高。

  • 国密标准: SM2是中国国家密码管理局发布的密码算法标准,广泛应用于中国的各种信息安全领域,包括数字证书、电子身份证等。

特点: 公钥加密,私钥解密。此时公司不会将公钥私钥进行传输,而是将其存储在本地配置文件中,只需传输加密数据即可。

//数据加密
//入参: 字节数组 公钥 + 数据
//返参: 字符串
public static String encrypt(byte[] publicKey, byte[] data) throws IOException {
        if (publicKey == null || publicKey.length == 0) {
            return null;
        }
        if (data == null || data.length == 0) {
            return null;
        }
        byte[] source = new byte[data.length];
        System.arraycopy(data, 0, source, 0, data.length);
        Cipher cipher = new Cipher();
        SM2 sm2 = SM2.Instance();
        ECPoint userKey = sm2.ecc_curve.decodePoint(publicKey);
        ECPoint c1 = cipher.Init_enc(sm2, userKey);
        cipher.Encrypt(source);
        byte[] c3 = new byte[32];
        cipher.Dofinal(c3);
        return new StringBuffer(Util.byteToHex(c1.getEncoded())).append(Util.byteToHex(c3)).append(Util.byteToHex(source)).toString();
    }
    // 数据解密1
	//入参:私钥 + 字符串加密数据   返参:字符串
    public static String decrypt(String privateKey, String encryptedData) throws IOException {
        return decrypt(privateKey, encryptedData, "UTF-8");
    }
	//数据解密2
	//入参:私钥 + 字符串加密数据 + 编码设置  返参:字符串
    public static String decrypt(String privateKey, String encryptedData, String character) throws IOException {
        if (privateKey == null || privateKey.equals("")) {
            return null;
        }
        if (encryptedData == null || encryptedData.equals("")) {
            return null;
        }
        byte[] data = Util.hexToByte(encryptedData);
        byte[] privateK = Util.hexToByte(privateKey);
        // 加密字节数组转换为十六进制的字符串 长度变为encryptedData.length * 2
        byte[] c1Bytes = Util.hexToByte(encryptedData.substring(0, 130));
        int c2Len = data.length - 97;
        byte[] c3 = Util.hexToByte(encryptedData.substring(130, 130 + 64));
        byte[] c2 = Util.hexToByte(encryptedData.substring(194, 194 + 2 * c2Len));

        SM2 sm2 = SM2.Instance();
        BigInteger userD = new BigInteger(1, privateK);
        // 通过C1实体字节来生成ECPoint
        ECPoint c1 = sm2.ecc_curve.decodePoint(c1Bytes);
        Cipher cipher = new Cipher();
        cipher.Init_dec(userD, c1);
        cipher.Decrypt(c2);
        cipher.Dofinal(c3);
        // 返回解密结果
        return new String(c2,character);
    }

2.MD5验签

概念:

MD5 验签是一种基于 MD5(Message Digest Algorithm 5)哈希算法的数据验证方法,用于验证数据的完整性和真实性。通常,MD5 验签是在数字签名和摘要的场景下应用的一种技术。

MD5 验签的步骤:
  1. 数据签名: 发送方使用私钥对原始数据进行数字签名,生成数字签名值。
  2. 数据传输: 发送方将原始数据数字签名值一起传输给接收方。
  3. 数据验签: 接收方使用相同的哈希算法,对接收到的原始数据进行哈希运算,生成一个散列值。然后,接收方使用发送方数字签名值进行验证。
  4. 比对散列值: 接收方比对计算得到的散列值和数字签名值是否匹配。如果匹配,说明数据未被篡改,验证通过。

举例:

//1.转换为字节数组
byte[] md5 = json.toString().getBytes();
//2.字节数组转换为其十六进制表示的散列值
String Contentmd5 = DigestUtils.md5DigestAsHex(md5);
//3.将header中的散列值与计算的散列值比较
Contentmd5.equals(headers)