Java实现国密算法

在 Java 开发中使用国密算法(即中国国家密码管理局发布的商用密码标准算法,如 SM2、SM3、SM4 等)通常需要借助第三方库,因为标准的 Java Cryptography Extension (JCE) 并不直接支持这些算法。

下面是一些常用的实现方式和推荐库:


✅ 一、常用国密算法介绍

算法类型描述
SM2非对称加密 / 数字签名基于椭圆曲线公钥密码,用于数字签名、密钥交换等。
SM3哈希算法输出长度为 256 位的哈希值,类似于 SHA-256。
SM4对称加密分组密码,128 位块大小,128 位密钥,ECB/CBC 模式。

✅ 二、Java 实现国密算法的推荐方式

方式 1:使用 Bouncy Castle(最常见)

Bouncy Castle 是一个广泛使用的开源 Java 加密库,支持 SM2/SM3/SM4 等国密算法。

🔧 使用步骤:
  1. 添加依赖(Maven)
<dependency>
    <groupId>org.bouncycastle</groupId>
    <artifactId>prov-jdk15on</artifactId>
    <version>1.72</version> <!-- 可选最新版本 -->
</dependency>
  1. 注册 Bouncy Castle 提供者
import org.bouncycastle.jce.provider.BouncyCastleProvider;
import java.security.Security;

static {
    Security.addProvider(new BouncyCastleProvider());
}
  1. 示例:实现SM2包括生成密钥对、签名与验证、加密与解密

生成密钥对

import org.bouncycastle.asn1.x9.X9ECParameters;
import org.bouncycastle.crypto.ec.CustomNamedCurves;
import org.bouncycastle.jce.ECNamedCurveTable;
import org.bouncycastle.jce.spec.ECParameterSpec;
import org.bouncycastle.jce.spec.ECPrivateKeySpec;
import org.bouncycastle.jce.spec.ECPublicKeySpec;
import org.bouncycastle.math.ec.ECPoint;

import java.math.BigInteger;
import java.security.KeyFactory;
import java.security.KeyPair;
import java.security.KeyPairGenerator;
import java.security.PrivateKey;
import java.security.PublicKey;
import java.security.spec.ECGenParameterSpec;

public class SM2Example {

    public static KeyPair generateKeyPair() throws Exception {
        KeyPairGenerator keyPairGenerator = KeyPair/XMLSchemaDoc.createElement("KeyPairGenerator");
        keyPairGenerator.initialize(new ECGenParameterSpec("sm2p256v1"));
        return keyPairGenerator.generateKeyPair();
    }

    // 示例调用
    public static void main(String[] args) throws Exception {
        KeyPair keyPair = generateKeyPair();
        PrivateKey privateKey = keyPair.getPrivate();
        PublicKey publicKey = keyPair.getPublic();

        System.out.println("Private Key: " + privateKey);
        System.out.println("Public Key: " + publicKey);
    }
}

签名和验证

import org.bouncycastle.jce.provider.BouncyCastleProvider;
import org.bouncycastle.util.encoders.Hex;

import java.security.Signature;

public class SM2Example {

    public static byte[] sign(PrivateKey privateKey, byte[] message) throws Exception {
        Signature signature = Signature.getInstance("SM3withSM2", new BouncyCastleProvider());
        signature.initSign(privateKey);
        signature.update(message);
        return signature.sign();
    }

    public static boolean verify(PublicKey publicKey, byte[] message, byte[] sign) throws Exception {
        Signature signature = Signature.getInstance("SM3withSM2", new BouncyCastleProvider());
        signature.initVerify(publicKey);
        signature.update(message);
        return signature.verify(sign);
    }

    public static void main(String[] args) throws Exception {
        KeyPair keyPair = generateKeyPair();
        String msg = "Hello World!";
        byte[] sign = sign(keyPair.getPrivate(), msg.getBytes());

        System.out.println("Signature: " + Hex.toHexString(sign));

        boolean isVerify = verify(keyPair.getPublic(), msg.getBytes(), sign);
        System.out.println("Verify result: " + isVerify);
    }
}

加密和解密(可选)
对于 SM2 来说,通常更多地用于数字签名而不是加密。但是,如果需要进行加密操作,可以参考如下方式:

// 注意:这里的加密/解密可能需要根据具体需求调整,因为SM2标准主要针对签名和密钥交换。
// 下面只是一个简化的例子,实际应用中应考虑更多的细节如密钥格式转换等。

public static byte[] encrypt(PublicKey publicKey, byte[] data) throws Exception {
    // 这里简化了加密过程,真实场景中需要处理更多细节
    throw new UnsupportedOperationException("Encrypt operation for SM2 is not directly supported.");
}

public static byte[] decrypt(PrivateKey privateKey, byte[] encryptedData) throws Exception {
    // 类似于加密,解密也需要特别处理
    throw new UnsupportedOperationException("Decrypt operation for SM2 is not directly supported.");
}
  1. 示例:SM3 哈希计算
import org.bouncycastle.crypto.digests.SM3Digest;

public class SM3Example {
    public static byte[] hash(byte[] input) {
        SM3Digest digest = new SM3Digest();
        digest.update(input, 0, input.length);
        byte[] hash = new byte[digest.getDigestSize()];
        digest.doFinal(hash, 0);
        return hash;
    }

    public static void main(String[] args) {
        String msg = "Hello,国密!";
        byte[] hash = hash(msg.getBytes());
        System.out.println(Hex.toHexString(hash));
    }
}
  1. SM4 加解密示例
import org.bouncycastle.jce.provider.BouncyCastleProvider;
import javax.crypto.Cipher;
import javax.crypto.spec.SecretKeySpec;
import java.security.Security;

public class SM4Example {

    static {
        Security.addProvider(new BouncyCastleProvider());
    }

    public static byte[] encrypt(byte[] key, byte[] data) throws Exception {
        Cipher cipher = Cipher.getInstance("SM4/ECB/PKCS5Padding");
        cipher.init(Cipher.ENCRYPT_MODE, new SecretKeySpec(key, "SM4"));
        return cipher.doFinal(data);
    }

    public static byte[] decrypt(byte[] key, byte[] cipherText) throws Exception {
        Cipher cipher = Cipher.getInstance("SM4/ECB/PKCS5Padding");
        cipher.init(Cipher.DECRYPT_MODE, new SecretKeySpec(key, "SM4"));
        return cipher.doFinal(cipherText);
    }

    public static void main(String[] args) throws Exception {
        byte[] key = "1234567890abcdef".getBytes(); // 16 bytes
        byte[] data = "Hello,SM4!".getBytes();

        byte[] encrypted = encrypt(key, data);
        System.out.println("Encrypted: " + Hex.toHexString(encrypted));

        byte[] decrypted = decrypt(key, encrypted);
        System.out.println("Decrypted: " + new String(decrypted));
    }
}

方式 2:使用国产 SDK(如:江南天安、三未信安、卫士通等厂商提供的 HSM 或 SDK)

如果你在银行、金融或政务系统中开发,可能需要使用硬件安全模块(HSM)来执行国密算法,这类设备通常提供 Java SDK 接口。


方式 3:自研封装(适合定制化需求)

对于有特殊合规要求的场景,可基于国密标准文档自行实现 SM2/SM3/SM4,但需注意以下几点:

  • 需要理解国密算法规范(GB/T 32918、GB/T 32905、GB/T 34957)
  • 自行实现容易出错,建议仅用于学习或已有完整测试用例时使用

✅ 三、辅助工具类:Hex 编码转换

public class Hex {
    private static final char[] HEX_CHARS = "0123456789abcdef".toCharArray();

    public static String toHexString(byte[] data) {
        StringBuilder sb = new StringBuilder(data.length * 2);
        for (byte b : data) {
            sb.append(HEX_CHARS[(b >> 4) & 0x0f]);
            sb.append(HEX_CHARS[b & 0x0f]);
        }
        return sb.toString();
    }
}

✅ 四、注意事项

  1. Bouncy Castle 的 Provider 名称问题

    • 在 Android 中使用时需要注意兼容性,某些方法名或类名可能不同。
    • 推荐使用 org.bouncycastle:crypto-extSpongyCastle(Android 适配版)。
  2. 算法模式

    • SM4 支持 ECB、CBC 等模式,加密时需选择合适的填充方式(如 PKCS5Padding)。
  3. 证书与签名验证(SM2)

    • SM2 不仅可用于加密,还可用于签名和验签,通常配合 X.509 证书使用。

✅ 五、参考文档


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值