BouncyCastle
Posted 20201221曾思源
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了BouncyCastle相关的知识,希望对你有一定的参考价值。
任务详情
在openEuler(推荐)或Ubuntu或Windows(不推荐)中完成下面任务
参考附件内容完成 SM2 加解密的内容,提交运行结果截图(10‘)
完成 SM3,SM4 算法的调用,提交运行结果截图和代码(15’, 选做)
jar包下载
官网:https://www.bouncycastle.org/latest_releases.html
bcprov-ext-jdk15to18-1.73.jar
bcprov-jdk15to18-1.73.jar
代码
demo.java
import org.bouncycastle.jce.provider.BouncyCastleProvider;
import java.security.*;
import java.security.spec.ECGenParameterSpec;
import java.util.Arrays;
public class demo
private static String M = "zsy20201221";
public static void main(String[] args) throws Exception
SM2Util sm2 = new SM2Util();
final ECGenParameterSpec sm2Spec = new ECGenParameterSpec("sm2p256v1");
// 获取一个椭圆曲线类型的密钥对生成器
final KeyPairGenerator kpg = KeyPairGenerator.getInstance("EC", new BouncyCastleProvider());
// 使用SM2参数初始化生成器
kpg.initialize(sm2Spec);
// 获取密钥对
KeyPair keyPair = kpg.generateKeyPair();
PublicKey publicKey = keyPair.getPublic();
PrivateKey privateKey = keyPair.getPrivate();
System.out.println("数据:" + M);
String data = sm2.encrypt(publicKey, M);
System.out.println("公钥加密:" + data);
String text = sm2.decrypt(privateKey, data);
System.out.println("私钥解密:" + text);
SM3Util sm3 = new SM3Util();
byte[] digest = sm3.digest(M);
System.out.println("SM3摘要:" + Arrays.toString(digest));
SM4Util sm4 = new SM4Util();
byte[] key1 = SM4Key.generateKey();
byte[] iv = null;
byte[] sm4data = sm4.encrypt(digest, key1, SM4ModeAndPaddingEnum.SM4_ECB_NoPadding, iv);
System.out.println("SM4加密:" + Arrays.toString(sm4data));
byte[] sm4text = sm4.decrypt(sm4data, key1, SM4ModeAndPaddingEnum.SM4_ECB_NoPadding, iv);
System.out.println("SM4解密:" + Arrays.toString(sm4text));
SM2Util.java
import org.bouncycastle.crypto.engines.SM2Engine;
import org.bouncycastle.crypto.params.*;
import org.bouncycastle.jcajce.provider.asymmetric.ec.BCECPrivateKey;
import org.bouncycastle.jcajce.provider.asymmetric.ec.BCECPublicKey;
import org.bouncycastle.jce.spec.ECParameterSpec;
import org.bouncycastle.util.encoders.Hex;
import java.nio.charset.StandardCharsets;
import java.security.PrivateKey;
import java.security.PublicKey;
import java.security.SecureRandom;
public class SM2Util
/**
* SM2加密算法
*
* @param publicKey 公钥
* @param data 明文数据
* @return
**/
public String encrypt(PublicKey publicKey, String data)
ECPublicKeyParameters ecPublicKeyParameters = null;
if (publicKey instanceof BCECPublicKey)
BCECPublicKey bcecPublicKey = (BCECPublicKey) publicKey;
ECParameterSpec ecParameterSpec = bcecPublicKey.getParameters();
ECDomainParameters ecDomainParameters = new ECDomainParameters(ecParameterSpec.getCurve(),
ecParameterSpec.getG(), ecParameterSpec.getN());
ecPublicKeyParameters = new ECPublicKeyParameters(bcecPublicKey.getQ(), ecDomainParameters);
SM2Engine sm2Engine = new SM2Engine();
sm2Engine.init(true, new ParametersWithRandom(ecPublicKeyParameters, new SecureRandom()));
byte[] arrayOfBytes = null;
try
byte[] in = data.getBytes(StandardCharsets.UTF_8);
arrayOfBytes = sm2Engine.processBlock(in, 0, in.length);
catch (Exception e)
System.out.println("SM2加密时出现异常:");
return Hex.toHexString(arrayOfBytes);
/**
* SM2解密算法
*
* @param privateKey 私钥
* @param cipherData 密文数据
* @return
**/
public String decrypt(PrivateKey privateKey, String cipherData)
byte[] cipherDataByte = Hex.decode(cipherData);
BCECPrivateKey bcecPrivateKey = (BCECPrivateKey) privateKey;
ECParameterSpec ecParameterSpec = bcecPrivateKey.getParameters();
ECDomainParameters ecDomainParameters = new ECDomainParameters(ecParameterSpec.getCurve(),
ecParameterSpec.getG(), ecParameterSpec.getN());
ECPrivateKeyParameters ecPrivateKeyParameters = new ECPrivateKeyParameters(bcecPrivateKey.getD(),
ecDomainParameters);
SM2Engine sm2Engine = new SM2Engine();
sm2Engine.init(false, ecPrivateKeyParameters);
String result = null;
try
byte[] arrayOfBytes = sm2Engine.processBlock(cipherDataByte, 0, cipherDataByte.length);
return new String(arrayOfBytes, StandardCharsets.UTF_8);
catch (Exception e)
System.out.println("SM2解密时出现异常");
return result;
SM3Util.java
import org.bouncycastle.crypto.digests.SM3Digest;
import org.bouncycastle.jce.provider.BouncyCastleProvider;
import java.security.Security;
/**
* @Description: 国密SM3摘要算法帮助类
* @Author: wucheng
* @CreateDate: 2020/2/16 16:36
*/
public class SM3Util
static
Security.addProvider(new BouncyCastleProvider());
public byte[] digest(String input)
SM3Digest sm3Digest = new SM3Digest();
int length = input.length();
byte[] data = input.getBytes();
sm3Digest.update(data, 0, length);
byte[] ret = new byte[sm3Digest.getDigestSize()];
sm3Digest.doFinal(ret, 0);
return ret;
SM4Key.java
import org.bouncycastle.jce.provider.BouncyCastleProvider;
import javax.crypto.KeyGenerator;
import java.security.SecureRandom;
import java.security.Security;
/**
* @Description:
* @Author: wucheng
* @CreateDate: 2020/2/16 16:51
*/
public class SM4Key
static
Security.addProvider(new BouncyCastleProvider());
public static byte[] generateKey() throws Exception
KeyGenerator kg = KeyGenerator.getInstance("SM4", BouncyCastleProvider.PROVIDER_NAME);
kg.init(128, new SecureRandom());
return kg.generateKey().getEncoded();
SM4Util.java
import org.bouncycastle.jce.provider.BouncyCastleProvider;
import javax.crypto.Cipher;
import javax.crypto.spec.IvParameterSpec;
import javax.crypto.spec.SecretKeySpec;
import java.security.Security;
/**
* @Description: 国密SM4对称加解密算法帮助类
* @Author: wucheng
* @CreateDate: 2020/2/16 16:38
*/
public class SM4Util
static
Security.addProvider(new BouncyCastleProvider());
/**
* SM4 加密
*
* @param input 明文数据
* @param key 密钥
* @param sm4ModeAndPaddingEnum 加密模式和padding模式
* @param iv 初始向量(ECB模式下传NULL)
* @return
* @throws Exception
*/
public byte[] encrypt(byte[] input, byte[] key, SM4ModeAndPaddingEnum sm4ModeAndPaddingEnum, byte[] iv)
throws Exception
return sm4(input, key, sm4ModeAndPaddingEnum, iv, Cipher.ENCRYPT_MODE);
/**
* SM4 解密
*
* @param input 密文数据
* @param key 密钥
* @param sm4ModeAndPaddingEnum 加密模式和padding模式
* @param iv 初始向量(ECB模式下传NULL)
* @return
* @throws Exception
*/
public byte[] decrypt(byte[] input, byte[] key, SM4ModeAndPaddingEnum sm4ModeAndPaddingEnum, byte[] iv)
throws Exception
return sm4(input, key, sm4ModeAndPaddingEnum, iv, Cipher.DECRYPT_MODE);
private static byte[] sm4(byte[] input, byte[] key, SM4ModeAndPaddingEnum sm4ModeAndPaddingEnum, byte[] iv,
int mode) throws Exception
IvParameterSpec ivParameterSpec = null;
if (iv != null)
ivParameterSpec = new IvParameterSpec(iv);
SecretKeySpec sm4Key = new SecretKeySpec(key, "SM4");
Cipher cipher = Cipher.getInstance(sm4ModeAndPaddingEnum.getName(), BouncyCastleProvider.PROVIDER_NAME);
if (ivParameterSpec == null)
cipher.init(mode, sm4Key);
else
cipher.init(mode, sm4Key, ivParameterSpec);
return cipher.doFinal(input);
SM4ModeAndPaddingEnum.java
/**
* @Description: SM4对称加解密算法中的模式和padding方式枚举类
* @Author: wucheng
* @CreateDate: 2020/2/16 16:39
*/
public enum SM4ModeAndPaddingEnum
SM4_ECB_NoPadding("SM4/ECB/NoPadding"), SM4_ECB_PKCS5Padding("SM4/ECB/PKCS5Padding"),
SM4_ECB_PKCS7Padding("SM4/ECB/PKCS7Padding"), SM4_CBC_NoPadding("SM4/CBC/NoPadding"),
SM4_CBC_PKCS5Padding("SM4/CBC/PKCS5Padding"), SM4_CBC_PKCS7Padding("SM4/CBC/PKCS7Padding");
private String name;
SM4ModeAndPaddingEnum(String name)
this.name = name;
public String getName()
return name;
结果:
为 RSACryptoProvider 和 BouncyCastle 生成密钥/加密/解密
【中文标题】为 RSACryptoProvider 和 BouncyCastle 生成密钥/加密/解密【英文标题】:Generate key/Encryption/Decryption for RSACryptoProvider and BouncyCastle 【发布时间】:2018-12-11 13:31:24 【问题描述】:通过 RSACryptoProvider 生成的密钥适用于 BouncyCastle 加密(使用公钥)/解密(使用私钥)?
using (RSACryptoServiceProvider rsa = new RSACryptoServiceProvider())
var pu = rsa.ToXmlString(false);
var pr = rsa.ToXmlString(true);
另外,如何使用 BouncyCastle 生成密钥?
【问题讨论】:
【参考方案1】:回答第一个问题,是的,RSA 是一种标准,它不依赖于所使用的库。
其次,试试这个:
public static void GetRsaKeyPair(out string privateXml, out string publicXml)
CryptoApiRandomGenerator randomGenerator = new CryptoApiRandomGenerator();
SecureRandom secureRandom = new SecureRandom(randomGenerator);
var keyGenerationParameters = new KeyGenerationParameters(secureRandom, 1024);
var rsaKeyPairGenerator = new RsaKeyPairGenerator();
rsaKeyPairGenerator.Init(keyGenerationParameters);
AsymmetricCipherKeyPair rsaKeyPair = rsaKeyPairGenerator.GenerateKeyPair();
var privateRsaParameters = DotNetUtilities.ToRSAParameters((RsaPrivateCrtKeyParameters)rsaKeyPair.Private);
using (RSACryptoServiceProvider rsaProvider = new RSACryptoServiceProvider())
rsaProvider.ImportParameters(privateRsaParameters);
privateXml = rsaProvider.ToXmlString(true);
publicXml = rsaProvider.ToXmlString(false);
【讨论】:
以上是关于BouncyCastle的主要内容,如果未能解决你的问题,请参考以下文章
使用 Bouncycastle 存储 PKCS#12 容器 (pfx)
在 fuse esb 中添加 bouncycastle 提供程序
找不到类 org.bouncycastle.cms.CMSSignedData
为 RSACryptoProvider 和 BouncyCastle 生成密钥/加密/解密