Skip to content

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

@newCodingPeasant

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();
}

}

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