Skip to content

使用BC库SM2加解密大数据的方式 #4

Description

@newCodingPeasant

博主你好,以下是使用BC库SM2加解密大数据的一种方式,看看有没有参考价值

import org.bouncycastle.crypto.InvalidCipherTextException;
import org.bouncycastle.crypto.digests.SM3Digest;
import org.bouncycastle.crypto.engines.SM2Engine;
import org.bouncycastle.crypto.params.ECDomainParameters;
import org.bouncycastle.crypto.params.ECPrivateKeyParameters;
import org.bouncycastle.crypto.params.ECPublicKeyParameters;
import org.bouncycastle.jce.provider.BouncyCastleProvider;
import org.bouncycastle.math.ec.ECCurve;
import org.bouncycastle.math.ec.ECPoint;
import org.bouncycastle.util.encoders.Hex;

import java.math.BigInteger;
import java.security.Security;
import java.util.Arrays;

public class SM2EncryptUtil {

static {
    // 添加 Bouncy Castle 提供商
    if (Security.getProvider(BouncyCastleProvider.PROVIDER_NAME) == null) {
        Security.addProvider(new BouncyCastleProvider());
    }
}

// SM2 曲线参数(国密标准)
private static final ECCurve curve = new ECCurve.Fp(
        new BigInteger("FFFFFFFEFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF00000000FFFFFFFFFFFFFFFF", 16),
        new BigInteger("FFFFFFFEFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF00000000FFFFFFFFFFFFFFFC", 16),
        new BigInteger("28E9FA9E9D9F5E344D5A9E4BCF6509A7F39789F515AB8F92DDBCBD414D940E93", 16)
);

private static final ECPoint G = curve.decodePoint(Hex.decode("04"
        + "32C4AE2C1F1981195F9904466A39C9948FE30BBFF2660BE1715A4589334C74C7"
        + "BC3736A2F4F6779C59BDCEE36B692153D0A9877CC62A474002DF32E52139F0A0"));

private static final BigInteger n = new BigInteger("FFFFFFFEFFFFFFFFFFFFFFFFFFFFFFFF7203DF6B21C6052B53BBF40939D54123", 16);
private static final ECDomainParameters domainParams = new ECDomainParameters(curve, G, n);

/**
 * SM2 加密(支持大数据分块)
 *
 * @param data      json明文数据
 * @param publicKey 公钥(Hex 格式)
 * @return 加密后的数据(Hex 格式)
 */
public static String sm2Encrypt(String data, String publicKey) throws InvalidCipherTextException {
    byte[] dataBytes = data.getBytes();
    // SM2 单次最大加密块大小
   /* int blockSize = 254;
    StringBuilder result = new StringBuilder();

    for (int i = 0; i < dataBytes.length; i += blockSize) {
        int length = Math.min(blockSize, dataBytes.length - i);
        byte[] block = Arrays.copyOfRange(dataBytes, i, i + length);
        String encryptedBlock = sm2EncryptBlock(block, publicKey);
        result.append(encryptedBlock);
    }*/


    // 添加 04 前缀表示未压缩格式
    return "04" + sm2EncryptBlock(dataBytes, publicKey);
}

/**
 * SM2 单块加密
 *
 * @param data      数据块
 * @param publicKey 公钥(Hex 格式)
 * @return 加密后的数据(Hex 格式)
 */
private static String sm2EncryptBlock(byte[] data, String publicKey) throws InvalidCipherTextException {
    ECPoint pubPoint = curve.decodePoint(Hex.decode(publicKey));
    ECPublicKeyParameters pubKeyParams = new ECPublicKeyParameters(pubPoint, domainParams);

    SM2Engine engine = new SM2Engine(SM2Engine.Mode.C1C3C2);
    engine.init(true, pubKeyParams);

    byte[] encrypted = engine.processBlock(data, 0, data.length);
    // 添加 04 前缀表示未压缩格式
    return "04" + Hex.toHexString(encrypted);
}

/**
 * SM2 解密(支持大数据分块)
 *
 * @param encryptedData 加密数据(Hex 格式)
 * @param privateKey    私钥(Hex 格式)
 * @return 解密后的明文数据
 */
public static String sm2Decrypt(String encryptedData, String privateKey) throws InvalidCipherTextException {
   // 04 前缀表示未压缩格式,解密的时候不能去掉,否则无法解析出C1曲线点
    /* if (encryptedData.startsWith("04")) {
        // 去除 04 前缀
        encryptedData = encryptedData.substring(2);
    }*/

    byte[] encryptedBytes = Hex.decode(encryptedData);
    // SM2 密文固定长度(C1+C3+C2)
    return sm2DecryptBlock(encryptedBytes, privateKey);
}

/**
 * SM2 单块解密
 *
 * @param encryptedData 加密数据块
 * @param privateKey    私钥(Hex 格式)
 * @return 解密后的数据
 */
private static String sm2DecryptBlock(byte[] encryptedData, String privateKey) throws InvalidCipherTextException {
    BigInteger d = new BigInteger(privateKey, 16);
    ECPrivateKeyParameters privKeyParams = new ECPrivateKeyParameters(d, domainParams);

    SM2Engine engine = new SM2Engine(SM2Engine.Mode.C1C3C2);
    engine.init(false, privKeyParams);

    byte[] decrypted = engine.processBlock(encryptedData, 0, encryptedData.length);
    return Hex.toHexString(decrypted);
}

/**
 * SM3 摘要计算
 *
 * @param data 输入数据
 * @return 摘要结果(Hex 格式)
 */
public static String sm3Digest(byte[] data) {
    SM3Digest digest = new SM3Digest();
    digest.update(data, 0, data.length);
    byte[] hash = new byte[digest.getDigestSize()];
    digest.doFinal(hash, 0);

    return Hex.toHexString(hash).toLowerCase();
}

}

Activity

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions