<
groupId
>
org.bouncycastle
<
/groupId
>
<
artifactId
>
bcprov-jdk15on
<
/artifactId
>
<
version
>
1.6
.
8
<
/version
>
<
/dependency
>
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;
import org.bouncycastle.asn1.gm.GMNamedCurves;
import org.bouncycastle.asn1.x9.X9ECParameters;
import org.bouncycastle.jcajce.provider.asymmetric.ec.BCECPrivateKey;
import org.bouncycastle.jcajce.provider.asymmetric.ec.BCECPublicKey;
import org.bouncycastle.jce.provider.BouncyCastleProvider;
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 org.bouncycastle.util.encoders.Hex;
import javax.crypto.Cipher;
import java.math.BigInteger;
import java.security.InvalidAlgorithmParameterException;
import java.security.KeyFactory;
import java.security.KeyPair;
import java.security.KeyPairGenerator;
import java.security.NoSuchAlgorithmException;
import java.security.SecureRandom;
import java.security.spec.ECGenParameterSpec;
import java.util.Base64;
import java.util.HashMap;
import java.util.Map;
* SM2加密
* @author hcf
* @date 2021/9/1 14:31
@Slf4j
public class SM2Utils {
* SM2 生成公私钥
* @return 公私钥
public static Map<String, String> generateKeyPair() {
Map<String, String> resultMap = new HashMap<>(2);
try {
BouncyCastleProvider provider = new BouncyCastleProvider();
ECGenParameterSpec genParameterSpec = new ECGenParameterSpec("sm2p256v1");
KeyPairGenerator keyPairGenerator = KeyPairGenerator.getInstance("EC", provider);
keyPairGenerator.initialize(genParameterSpec, new SecureRandom());
KeyPair keyPair = keyPairGenerator.generateKeyPair();
BCECPrivateKey exPrivateKey = (BCECPrivateKey) keyPair.getPrivate();
BCECPublicKey ecPublicKey = (BCECPublicKey) keyPair.getPublic();
BigInteger privateKey = exPrivateKey.getD();
ECPoint publicKey = ecPublicKey.getQ();
resultMap.put("privateKey", privateKey.toString(16));
resultMap.put("publicKey", new String(Hex.encode(publicKey.getEncoded(true))));
} catch (NoSuchAlgorithmException | InvalidAlgorithmParameterException e) {
log.info("NoSuchAlgorithmException | InvalidAlgorithmParameterException {}", e.getMessage(), e);
return resultMap;
* sm2 加密
* @param publicKey 公钥
* @param content 内容
* @return 密文
public static String encrypt(String publicKey, String content) {
String contentEncrypt = StringUtils.EMPTY;
try {
BouncyCastleProvider provider = new BouncyCastleProvider();
X9ECParameters parameters = GMNamedCurves.getByName("sm2p256v1");
ECParameterSpec ecParameterSpec = new ECParameterSpec(parameters.getCurve(), parameters.getG(), parameters.getN(), parameters.getH());
ECPoint ecPoint = parameters.getCurve().decodePoint(Hex.decode(publicKey));
KeyFactory keyFactory = KeyFactory.getInstance("EC", provider);
BCECPublicKey bcecPublicKey = (BCECPublicKey) keyFactory.generatePublic(new ECPublicKeySpec(ecPoint, ecParameterSpec));
Cipher cipher = Cipher.getInstance("SM2", provider);
cipher.init(Cipher.ENCRYPT_MODE, bcecPublicKey);
contentEncrypt = Base64.getEncoder().encodeToString(cipher.doFinal(content.getBytes()));
} catch (Exception e) {
log.info("SM2Utils.encrypt(java.lang.String, java.lang.String) error {}", e.getMessage(), e);
return contentEncrypt;
* sm2 加密
* @param publicKey 公钥
* @param content 内容
* @return 密文
public static String encrypt(String publicKey, byte[] content) {
return encrypt(publicKey, new String(content));
* sm2 加密
* @param privateKey 私钥
* @param contentDecrypt 密文
* @return 明文
public static String decrypt(String privateKey, String contentDecrypt) {
String content = StringUtils.EMPTY;
try {
BouncyCastleProvider provider = new BouncyCastleProvider();
X9ECParameters parameters = GMNamedCurves.getByName("sm2p256v1");
ECParameterSpec ecParameterSpec = new ECParameterSpec(parameters.getCurve(), parameters.getG(), parameters.getN(), parameters.getH());
BigInteger bigInteger = new BigInteger(privateKey, 16);
KeyFactory keyFactory = KeyFactory.getInstance("EC", provider);
BCECPrivateKey bcecPrivateKey = (BCECPrivateKey) keyFactory.generatePrivate(new ECPrivateKeySpec(bigInteger, ecParameterSpec));
Cipher cipher = Cipher.getInstance("SM2", provider);
cipher.init(Cipher.DECRYPT_MODE, bcecPrivateKey);
content = new String(cipher.doFinal(Base64.getDecoder().decode(contentDecrypt)));
} catch (Exception e) {
log.info("SM2Utils.encrypt(java.lang.String, java.lang.String) error {}", e.getMessage(), e);
return content;
* sm2 加密
* @param privateKey 私钥
* @param contentDecrypt 密文
* @return 明文
public static String decrypt(String privateKey, byte[] contentDecrypt) {
return decrypt(privateKey, new String(contentDecrypt));
public static void main(String[] args) {
String privateKey = "dbd874c60c8c7432052c7f881ae23f5939d841b12a105bb38ab97129ed02f92d";
String publicKey = "033e5250957110884657948ce04507833731e7f88a18569f57f16b7e2abe3a79ad";
System.out.println(encrypt(publicKey, "content"));
String contentDecrypt = "BP4DukeJwLi9Xfp97HZ39GvfAsJ+u+1Rr8zK5TXd+b95YkwDuZnwFpCtSWkvfxfpXP5DmuIbRBQW0JUgcZ7SXbi+vGM9TDD3LNEVIlvQ1Z5Z8TcotgYsryL6J0eSwtdmoVbhdBEehRw=";
System.out.println(decrypt(privateKey, contentDecrypt));
参考:
https://blog.csdn.net/RisenMyth/article/details/107212156
开箱即用首先引入包<dependency> <groupId>org.bouncycastle</groupId> <artifactId>bcprov-jdk15on</artifactId> <version>1.6.8</version></dependency>import lombok.extern.slf4j.Slf4j;import org.apache.commons.lang3
SM2是国家密码管理局于2010年12月17日发布的椭圆曲线公钥密码算法。
SM2 算法和 RSA 算法都是公钥密码算法,SM2 算法是一种更先进安全的算法,在我们国家商用密码体系中被用来替换 RSA 算法。
随着密码技术和计算机技术的发展,目前常用的 1024 位 RSA 算法面临严重的安全威胁,我们国家密码管理部门经过研究,决定采用 SM2 椭圆曲线算法替换RSA算法。
SM2算法和RSA算法比较
SM2性能更优更安全:密码复杂度高、处理速度快、机器性能消耗更小
最近因为工作需要,项目中需要采用国密加密,最后根据需求采用了SM2加密。这里简单总结一下用法和踩的坑,供分享和交流。
1.依赖引入
后端依赖引入(Maven,pom.xml):
<dependency>
<groupId>org.bouncycastle</groupId>
<artifactId>bcprov-jdk15on</artifactId>
<version>1.70&
最近与一个外部公司对接接口,对方要求使用SM2非对称加密对报文进行签名,防止篡改。约定了各个参数和秘钥后,我发现加解密时在本地IDEA和Eclipse上没有问题,但是打完jar包部署到环境上就会报错,报错内容如下:
java.security.spec.InvalidKeySpecException: encoded key spec not recognised
at org.bouncycastle.jcajce.provider.asymmetric.util.BaseKeyFactoryS...
1、为什么要使用BouncyCastle?
我们平常都使用jdk自带的加密包对数据进行加密,加密方式也都是使用的默认的,如果我们想选择别的加密方式,发现会报错,比如如下代码:
Cipher cipher = Cipher.getInstance("AES/ECB/PKCS7Padding");
cipher.init(Cipher.ENCRYPT_MODE, new SecretKeySp
国密即国家密码局认定的国产密码算法。常用的主要有SM2,SM3,SM4。
SM2:椭圆曲线公钥密码算法是我国自主设计的公钥密码算法,为非对称加密,基于ECC。该算法已公开。由于该算法基于ECC,故其签名速度与秘钥生成速度都快于RSA。
SM3:消息摘要。可以用MD5作为对比理解。该算法已公开。校验结果为256位。
SM4:对称加密,密钥长度和分组长度均为128位。
由于国际环境(与美国的关系),我们在加密领域也基本切换为国密算法。
在有些项目中,没有使用HTTPS的时候,登录的口令(用户名/密码)
<groupId>org.bouncycastle</groupId>
<artifactId>bcprov-jdk15on</artifactId>
<version>1.60</version>
</dependency>
<dependency>
using Org.BouncyCastle.Asn1.X9;
using Org.BouncyCastle.Asn1.GM;
using Org.BouncyCastle.Crypto.Parameters;
using Org.BouncyCastle.Crypto;
using Org.BouncyCastle.Security;
加密后内容
可自行验证是否是你需要的sm2加密算法
私钥:BF1F907B4E0487F798DC80AFD7BC2A6201E8514233002272EA3BE2FC6F797843
公钥:前缀04+x坐标+y坐标
042DBA45E7B03394F603CADAFCDDEC854D3E01A4E9C52CD799B85B1A14BDB970137AE58BA553D79F058604DC1CD4B77DE5408BA3308E767584100C2B6
SM2算法是国密算法, 是一种非对称加密算法, 主要用于数字签名和加密。
在Java中,可以使用Bouncy Castle库来实现SM2算法。
下面是一个简单的示例代码,用于生成SM2公钥和私钥,并使用它们进行加密和解密:
import org.bouncycastle.jce.provider.BouncyCastleProvider;
import org.bouncycastle.pqc.m...
国密SM2算法是中国自主研发的非对称加密算法,可以用于数字签名、密钥交换等场景。要用C语言实现国密SM2加密算法,需要掌握C语言的基础知识和加密算法的原理。
具体实现过程包括以下步骤:
1. 密钥生成:使用C语言的随机数生成函数生成一对公私钥对。
2. 明文编码:将明文按照国密SM2算法要求进行编码,可以使用C语言的字符编码转换函数实现。
3. 加密操作:使用C语言的加法、减法、乘法、除法等基本运算实现SM2算法中的椭圆曲线点的加减运算、点的倍乘运算等操作。
4. 密文格式:按照国密SM2算法的要求生成密文格式,可以使用C语言的结构体定义和位运算等操作实现。
5. 密文输出:将生成的密文输出。
需要注意的是,实现国密SM2算法需要处理的数据类型和运算较为复杂,需要掌握一定的数学和编程基础。同时,由于加密算法的安全性对于实际应用非常重要,因此需要谨慎实现和测试,以确保实现的算法具有可靠的安全性和正确性。