openssl 1.1.1+ 版本增加了对SM2 的支持,所以我们就能直接使用这些版本的opsnssl 生成 SM2的公私钥对
openssl 生成国密证书请求文件
查看openssl 版本
$ openssl version
查看是否支持sm2算法
$ openssl ecparam -list_curves | grep SM2
SM2 : SM2 curve over a 256 bit prime field
生成sm2私钥文件
$ openssl ecparam -genkey -name SM2 -out sign.key
$ cat sign.key
-----BEGIN EC PARAMETERS-----
BggqgRzPVQGCLQ==
-----END EC PARAMETERS-----
-----BEGIN EC PRIVATE KEY-----
MHcCAQEEIOisvcLOU0q23GUTwx+lC4HOQRBvRT7QrKIUnqf9Ns+toAoGCCqBHM9V
AYItoUQDQgAElYOHcUAailvi3C5Cg6nM/Z+N9HRbAnRFNsTPyCn6OU7yJDTNG2tk
7nOWc9qgXH12cNyDsZCQjIo3YSCe1o4hUw==
-----END EC PRIVATE KEY-----
BggqgRzPVQGCLQ==是椭圆曲线的关键参数,对应secp256k1标识,用secp256k1生成私钥每次私钥是不同的,但EC PARAMETERS都是相同的。
生成sm2公钥文件(可忽略)
$ openssl ec -in sign.key -pubout -out pub.key
read EC key
writing EC key
$ cat pub.key
-----BEGIN PUBLIC KEY-----
MFkwEwYHKoZIzj0CAQYIKoEcz1UBgi0DQgAElYOHcUAailvi3C5Cg6nM/Z+N9HRb
AnRFNsTPyCn6OU7yJDTNG2tk7nOWc9qgXH12cNyDsZCQjIo3YSCe1o4hUw==
-----END PUBLIC KEY-----
生成的是非压缩格式的公钥。
查看密钥对
openssl ec -in guomi/sign.key -text -noout
read EC key
Private-Key: (256 bit)
priv:
a4:61:94:16:49:da:b2:19:84:44:e1:0b:be:43:bf:
ec:99:0d:42:e4:73:25:9e:f4:93:29:82:5b:53:bd:
07:62
pub:
04:dd:81:1a:17:41:13:4b:8f:d5:df:81:1c:34:2b:
d8:2a:5d:f9:87:3d:7c:be:9f:f8:b7:5e:94:f7:f1:
28:bf:c4:13:bf:78:f0:9a:18:83:74:0a:7a:65:bd:
86:32:ba:b1:65:ec:cb:f2:5a:f2:16:27:a9:5e:06:
3a:e2:c1:3e:9a
ASN1 OID: SM2
生成p10请求文件(PKCS#10申请书(CSR))
openssl req -new -key sign.key -out sign.req
输入国家、城市、公司名称等
$ cat sign.req
-----BEGIN CERTIFICATE REQUEST-----
MIIBGzCBwgIBADBgMQswCQYDVQQGEwJDTjEQMA4GA1UECAwHQ0hORUdEVTEQMA4G
A1UEBwwHQ0hFTkdEVTEOMAwGA1UECgwFS0FZQUsxDjAMBgNVBAsMBUtBWUFLMQ0w
CwYDVQQDDARLQVlLMFkwEwYHKoZIzj0CAQYIKoEcz1UBgi0DQgAElYOHcUAailvi
3C5Cg6nM/Z+N9HRbAnRFNsTPyCn6OU7yJDTNG2tk7nOWc9qgXH12cNyDsZCQjIo3
YSCe1o4hU6AAMAoGCCqGSM49BAMCA0gAMEUCIHvaP7S0dQ4wWAmx1SraMCbvvVSB
8CT54EObnM2sVO9QAiEA2KmgUCO/oj5Q119Fqu3/Ig8TjbKSaJ8+zUxKsTn1k3I=
-----END CERTIFICATE REQUEST-----
CFCA获取两码
CA机构联系获取两码
申请测试证书发邮件到 support@cfca.com.cn 这个邮箱,邮件内容说明单位名称,所需证书类型,数量。CFCA相关负责人员收到邮件后会免费给发两码。
邮件发送内容:
单位名称:*******股份有限公司
所需证书类型:OCA31 国密双证 SM2
数量 1套
CFCA机构回复
证书DN ********************
序列号 405822****
授权码 4XYACU****
CFCA登录申请证书
普通SM2服务器测试证书下载
点击下一步 生成内容加签证书 加密证书 私钥
获取sm2加密私钥内容-借助天威诚信工具
通过天威诚信的工具获取机密私钥内容
1.签名证书私钥--对应sign.key内
-----BEGIN EC PRIVATE KEY-----
MHcCAQEEIOisvcLOU0q23GUTwx+lC4HOQRBvRT7QrKIUnqf9Ns+toAoGCCqBHM9V
AYItoUQDQgAElYOHcUAailvi3C5Cg6nM/Z+N9HRbAnRFNsTPyCn6OU7yJDTNG2tk
7nOWc9qgXH12cNyDsZCQjIo3YSCe1o4hUw==
-----END EC PRIVATE KEY-----
2.加密证书 ---对应cert.cer
-----BEGIN CERTIFICATE-----
MIIC8jCCApegAwIBAgIFQFgigRQwDAYIKoEcz1UBg3UFADBhMQswCQYDVQQGEwJD
TjEwMC4GA1UECgwnQ2hpbmEgRmluYW5jaWFsIENlcnRpZmljYXRpb24gQXV0aG9y
aXR5MSAwHgYDVQQDDBdDRkNBIEFDUyBURVNUIFNNMiBPQ0EzMTAeFw0yMzA3MTgw
NjA2MjZaFw0yMzEwMTgwNjA2MjZaMIGeMQswCQYDVQQGEwJDTjERMA8GA1UECgwI
T0NBMzFTTTIxFzAVBgNVBAsMDkxvY2FsIFJBIE9DQTMxMRkwFwYDVQQLDBBPcmdh
bml6YXRpb25hbC0yMUgwRgYDVQQDDD9DRkNBQOaxn+iLj+W4uOeGn+WGnOadkeWV
huS4mumTtuihjOiCoeS7veaciemZkOWFrOWPuEBaMTIzNDU2QDIwWTATBgcqhkjO
PQIBBggqgRzPVQGCLQNCAAS0ywNti6hAkh/NAMTsYEVhNOxbWUkUzQzqVP4uJLu8
HYPMchX5g/eCYRtcFPgKA1GNI9QMa618fHtCKWxhloeOo4H7MIH4MD8GCCsGAQUF
BwEBBDMwMTAvBggrBgEFBQcwAYYjaHR0cDovL29jc3B0ZXN0LmNmY2EuY29tLmNu
OjgwL29jc3AwHwYDVR0jBBgwFoAUBMe8+VkBaT6MNDYgYhg83ry1uwwwDAYDVR0T
AQH/BAIwADA4BgNVHR8EMTAvMC2gK6AphidodHRwOi8vMjEwLjc0LjQyLjMvT0NB
MzEvU00yL2NybDIyMC5jcmwwDgYDVR0PAQH/BAQDAgM4MB0GA1UdDgQWBBRlgMoK
1ZwBzzdRyPRIVpie1mE/BzAdBgNVHSUEFjAUBggrBgEFBQcDAgYIKwYBBQUHAwQw
DAYIKoEcz1UBg3UFAANHADBEAiBazncX4OI41e75Bs37MSFGE2k8qwoBXso5n+Vu
KbBVaQIgX6paf1HzCuIC0efy6/EGVwHRroHB99n5yrjBjS5AG94=
-----END CERTIFICATE-----
3.加密私钥密文 --生成的SM2加密私钥证书
-----BEGIN EC PRIVATE KEY-----
MIHuMAkGByqBHM9VAWgwegIhAORoB8gn26uOf93GhBSfvXxRVnKNx3n7a0+wpcimTFt+AiEA3YPUVyVb4ygnQkotqbMcWM0CJOzQJQDGNZGZZDbtGeMEILEP+DMebsZzsNeojT4v3ZivAQbqew5DmpZqX3lEHXUHBBDwzSc1heT2HQtFoQtjhzatA0IABLTLA22LqECSH80AxOxgRWE07FtZSRTNDOpU/i4ku7wdg8xyFfmD94JhG1wU+AoDUY0j1AxrrXx8e0IpbGGWh44DIQCsN4EHB39+NSdLknSVksgIWkpmaC0C222GawFF03sNWQ==
-----END EC PRIVATE KEY-----
ps:将证书签发邮件中的“以下是您的签名证书”代码的文本复制出来(包括“—–BEGIN CERTIFICATE—–”和“—–END CERTIFICATE—–”)粘贴到记事本等文本编辑器中。为保障服务器证书在客户端的兼容性,服务器证书需要安装中级CA证书。 在服务器证书代码文本结尾,回车换行不留空行,粘贴证书签发邮件中的“以下是您的中级CA证书”部分里的第一段CA证书和第二段的内容(包括“—–BEGIN CERTIFICATE—–”和“—–END CERTIFICATE—–”),每串证书代码之间均需要使用回车换行不留空行文章来源:https://www.toymoban.com/news/detail-758441.html
生成sm2私钥证书-sm2结尾
package com.dcep.demo;
import cfca.sadk.algorithm.sm2.SM2PrivateKey;
import cfca.sadk.asn1.pkcs.PKCS12_SM2;
import cfca.sadk.org.bouncycastle.asn1.ASN1Primitive;
import cfca.sadk.org.bouncycastle.asn1.ASN1Sequence;
import cfca.sadk.org.bouncycastle.asn1.DEROctetString;
import cfca.sadk.util.Base64;
import cfca.sadk.x509.certificate.X509Cert;
/**
* @version 1.0
* @Description :
* @date 2023/8/1
*/
public class CADemo {
private static final String PUBLIC = "PUBLIC";
public static String genSm2(String pwd,String priKeyBase64,String pubCertPath) throws Exception{
ASN1Sequence priKeySeq = (ASN1Sequence) ASN1Primitive.fromByteArray(Base64.decode(priKeyBase64));
byte[] d = ((DEROctetString)priKeySeq.getObjectAt(1)).getOctets();// sm2私钥d值
X509Cert signCert = new X509Cert(pubCertPath);
byte[] bytes = PKCS12_SM2.generateSM2Data(signCert, new SM2PrivateKey(d, null, null), pwd);// base64格式
String base64SM2P12Text = new String(bytes);
return formatCert(base64SM2P12Text,76,"");
}
/**
* 格式化证书
* @param certContent
* @param len
* @return
*/
private static String formatCert(String certContent, int len, String type) {
String tmp = "";
if (len < 0) {
return "";
}
if (certContent.length() < len) {
return certContent;
}
int rows = (certContent.length() + len - 1) / len;
for (int i = 0; i < rows; i++) {
if (i == rows - 1) {
tmp += certContent.substring(i * len);
} else {
tmp += certContent.substring(i * len, i * len + len) + "\r\n";
}
}
if (PUBLIC.equals(type)) {
tmp = String.format("-----BEGIN CERTIFICATE-----\r\n%s\r\n-----END CERTIFICATE-----", tmp);
}
return tmp;
}
public static void main(String[] args) throws Exception {
String priKey = "MHcCAQEEIOisvcLOU0q23GUTwx+lC4HOQRBvRT7QrKIUnqf9Ns+toAoGCCqBHM9VAYItoUQDQgAElYOHcUAailvi3C5Cg6nM/Z+N9HRbAnRFNsTPyCn6OU7yJDTNG2tk7nOWc9qgXH12cNyDsZCQjIo3YSCe1o4hUw==";
String pwd="123456";
String pubCertPath="conf/cert/psbc/bank_sign.cer";
String s = genSm2(pwd, priKey, pubCertPath);
System.out.println(s);
}
}
解密代码(解密出对称密钥,密钥文件需要sm1进行解密)
针对从cfca获取到的密钥文件进行解密获取对称密钥,仅做了解,可以通过硬件通过进行生成;文章来源地址https://www.toymoban.com/news/detail-758441.html
public class CADemo {
public static void main(String[] args) throws Exception {
String priKey = "MHcCAQEEIOisvcLOU0q23GUTwx+lC4HOQRBvRT7QrKIUnqf9Ns+toAoGCCqBHM9VAYItoUQDQgAElYOHcUAailvi3C5Cg6nM/Z+N9HRbAnRFNsTPyCn6OU7yJDTNG2tk7nOWc9qgXH12cNyDsZCQjIo3YSCe1o4hUw==";
String pubKey = "MFkwEwYHKoZIzj0CAQYIKoEcz1UBgi0DQgAElYOHcUAailvi3C5Cg6nM/Z+N9HRbAnRFNsTPyCn6OU7yJDTNG2tk7nOWc9qgXH12cNyDsZCQjIo3YSCe1o4hUw==";
X509Cert signCert = new X509Cert("conf/cert/psbc/bank_sign.cer");
ASN1Sequence priKeySeq = (ASN1Sequence) ASN1Primitive.fromByteArray(Base64.decode(priKey));
byte[] d = ((DEROctetString)priKeySeq.getObjectAt(1)).getOctets();// sm2私钥d值
ASN1Sequence pubKeySeq = (ASN1Sequence) ASN1Primitive.fromByteArray(Base64.decode(pubKey));
byte[] pubKeyByte = ((DERBitString)pubKeySeq.getObjectAt(1)).getBytes();// sm2公钥
if (pubKeyByte.length == 65) {
pubKeyByte = Arrays.copyOfRange(pubKeyByte, 1, pubKeyByte.length); // sm2公钥
}
String encfca = "MIHuMAkGByqBHM9VAWgwegIhAORoB8gn26uOf93GhBSfvXxRVnKNx3n7a0+wpcimTFt+AiEA3YPUVyVb4ygnQkotqbMcWM0CJOzQJQDGNZGZZDbtGeMEILEP+DMebsZzsNeojT4v3ZivAQbqew5DmpZqX3lEHXUHBBDwzSc1heT2HQtFoQtjhzatA0IABLTLA22LqECSH80AxOxgRWE07FtZSRTNDOpU/i4ku7wdg8xyFfmD94JhG1wU+AoDUY0j1AxrrXx8e0IpbGGWh44DIQCsN4EHB39+NSdLknSVksgIWkpmaC0C222GawFF03sNWQ==";
byte[] encfcaByte = Base64.decode(encfca);
ASN1Sequence seq = (ASN1Sequence) ASN1Primitive.fromByteArray(encfcaByte);
ASN1Sequence objectAt = (ASN1Sequence) seq.getObjectAt(1);
byte[] X = ((ASN1Integer)objectAt.getObjectAt(0)).getValue().toByteArray();
if (X.length == 33) {
X = Arrays.copyOfRange(X, 1, X.length); // X值
}
byte[] Y = ((ASN1Integer)objectAt.getObjectAt(1)).getValue().toByteArray();
if (Y.length == 33) {
Y = Arrays.copyOfRange(Y, 1, Y.length); // Y值
}
byte[] hash = ((DEROctetString)objectAt.getObjectAt(2)).getOctets(); // sm2加密机构中的Hash
byte[] cipher = ((DEROctetString)objectAt.getObjectAt(3)).getOctets();// sm2加密结构中的c值
byte[] bcFormat = new byte[1 + X.length + Y.length + hash.length + cipher.length];
System.arraycopy(Hex.decode("04"), 0, bcFormat, 0, 1);
System.arraycopy(X, 0, bcFormat, 1, X.length);
System.arraycopy(Y, 0, bcFormat, 1 + X.length, Y.length);
System.arraycopy(hash, 0, bcFormat, 1 + X.length + Y.length, hash.length);
System.arraycopy(cipher, 0, bcFormat, 1 + X.length + Y.length + hash.length, cipher.length);
byte[] enPub = ((DERBitString) seq.getObjectAt(2)).getBytes();// 加密公钥信息
byte[] priCipher = ((DERBitString) seq.getObjectAt(3)).getBytes();// 加密私钥密信息
SM2 sm2 = new SM2(d, null, null);//创建SM2
byte[] symmetricKeyByte = sm2.decrypt(bcFormat, KeyType.PrivateKey);
System.out.println(HexUtil.encodeHexStr(symmetricKeyByte));// 2de4e6b1bbc95eb47ed79a02fd415f17
}
}
到了这里,关于通过openssl实现自签国密双证书详细教程的文章就介绍完了。如果您还想了解更多内容,请在右上角搜索TOY模板网以前的文章或继续浏览下面的相关文章,希望大家以后多多支持TOY模板网!