openssl 1.1.1+ 版本增加了對(duì)SM2 的支持,所以我們就能直接使用這些版本的opsnssl 生成 SM2的公私鑰對(duì)
openssl 生成國(guó)密證書(shū)請(qǐng)求文件
查看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==是橢圓曲線的關(guān)鍵參數(shù),對(duì)應(yīng)secp256k1標(biāo)識(shí),用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-----
生成的是非壓縮格式的公鑰。
查看密鑰對(duì)
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請(qǐng)求文件(PKCS#10申請(qǐng)書(shū)(CSR))
openssl req -new -key sign.key -out sign.req
輸入國(guó)家、城市、公司名稱(chēng)等
$ cat sign.req
-----BEGIN CERTIFICATE REQUEST-----
MIIBGzCBwgIBADBgMQswCQYDVQQGEwJDTjEQMA4GA1UECAwHQ0hORUdEVTEQMA4G
A1UEBwwHQ0hFTkdEVTEOMAwGA1UECgwFS0FZQUsxDjAMBgNVBAsMBUtBWUFLMQ0w
CwYDVQQDDARLQVlLMFkwEwYHKoZIzj0CAQYIKoEcz1UBgi0DQgAElYOHcUAailvi
3C5Cg6nM/Z+N9HRbAnRFNsTPyCn6OU7yJDTNG2tk7nOWc9qgXH12cNyDsZCQjIo3
YSCe1o4hU6AAMAoGCCqGSM49BAMCA0gAMEUCIHvaP7S0dQ4wWAmx1SraMCbvvVSB
8CT54EObnM2sVO9QAiEA2KmgUCO/oj5Q119Fqu3/Ig8TjbKSaJ8+zUxKsTn1k3I=
-----END CERTIFICATE REQUEST-----
CFCA獲取兩碼
CA機(jī)構(gòu)聯(lián)系獲取兩碼
申請(qǐng)測(cè)試證書(shū)發(fā)郵件到 support@cfca.com.cn 這個(gè)郵箱,郵件內(nèi)容說(shuō)明單位名稱(chēng),所需證書(shū)類(lèi)型,數(shù)量。CFCA相關(guān)負(fù)責(zé)人員收到郵件后會(huì)免費(fèi)給發(fā)兩碼。
郵件發(fā)送內(nèi)容:
單位名稱(chēng):*******股份有限公司
所需證書(shū)類(lèi)型:OCA31 國(guó)密雙證 SM2
數(shù)量 1套
CFCA機(jī)構(gòu)回復(fù)
證書(shū)DN ********************
序列號(hào) 405822****
授權(quán)碼 4XYACU****
CFCA登錄申請(qǐng)證書(shū)
普通SM2服務(wù)器測(cè)試證書(shū)下載
點(diǎn)擊下一步 生成內(nèi)容加簽證書(shū) 加密證書(shū) 私鑰
獲取sm2加密私鑰內(nèi)容-借助天威誠(chéng)信工具
通過(guò)天威誠(chéng)信的工具獲取機(jī)密私鑰內(nèi)容
1.簽名證書(shū)私鑰--對(duì)應(yīng)sign.key內(nèi)
-----BEGIN EC PRIVATE KEY-----
MHcCAQEEIOisvcLOU0q23GUTwx+lC4HOQRBvRT7QrKIUnqf9Ns+toAoGCCqBHM9V
AYItoUQDQgAElYOHcUAailvi3C5Cg6nM/Z+N9HRbAnRFNsTPyCn6OU7yJDTNG2tk
7nOWc9qgXH12cNyDsZCQjIo3YSCe1o4hUw==
-----END EC PRIVATE KEY-----
2.加密證書(shū) ---對(duì)應(yīng)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加密私鑰證書(shū)
-----BEGIN EC PRIVATE KEY-----
MIHuMAkGByqBHM9VAWgwegIhAORoB8gn26uOf93GhBSfvXxRVnKNx3n7a0+wpcimTFt+AiEA3YPUVyVb4ygnQkotqbMcWM0CJOzQJQDGNZGZZDbtGeMEILEP+DMebsZzsNeojT4v3ZivAQbqew5DmpZqX3lEHXUHBBDwzSc1heT2HQtFoQtjhzatA0IABLTLA22LqECSH80AxOxgRWE07FtZSRTNDOpU/i4ku7wdg8xyFfmD94JhG1wU+AoDUY0j1AxrrXx8e0IpbGGWh44DIQCsN4EHB39+NSdLknSVksgIWkpmaC0C222GawFF03sNWQ==
-----END EC PRIVATE KEY-----
ps:將證書(shū)簽發(fā)郵件中的“以下是您的簽名證書(shū)”代碼的文本復(fù)制出來(lái)(包括“—–BEGIN CERTIFICATE—–”和“—–END CERTIFICATE—–”)粘貼到記事本等文本編輯器中。為保障服務(wù)器證書(shū)在客戶端的兼容性,服務(wù)器證書(shū)需要安裝中級(jí)CA證書(shū)。 在服務(wù)器證書(shū)代碼文本結(jié)尾,回車(chē)換行不留空行,粘貼證書(shū)簽發(fā)郵件中的“以下是您的中級(jí)CA證書(shū)”部分里的第一段CA證書(shū)和第二段的內(nèi)容(包括“—–BEGIN CERTIFICATE—–”和“—–END CERTIFICATE—–”),每串證書(shū)代碼之間均需要使用回車(chē)換行不留空行文章來(lái)源:http://www.zghlxwxcb.cn/news/detail-758441.html
生成sm2私鑰證書(shū)-sm2結(jié)尾
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,"");
}
/**
* 格式化證書(shū)
* @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);
}
}
解密代碼(解密出對(duì)稱(chēng)密鑰,密鑰文件需要sm1進(jìn)行解密)
針對(duì)從cfca獲取到的密鑰文件進(jìn)行解密獲取對(duì)稱(chēng)密鑰,僅做了解,可以通過(guò)硬件通過(guò)進(jìn)行生成;文章來(lái)源地址http://www.zghlxwxcb.cn/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加密機(jī)構(gòu)中的Hash
byte[] cipher = ((DEROctetString)objectAt.getObjectAt(3)).getOctets();// sm2加密結(jié)構(gòu)中的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);//創(chuàng)建SM2
byte[] symmetricKeyByte = sm2.decrypt(bcFormat, KeyType.PrivateKey);
System.out.println(HexUtil.encodeHexStr(symmetricKeyByte));// 2de4e6b1bbc95eb47ed79a02fd415f17
}
}
到了這里,關(guān)于通過(guò)openssl實(shí)現(xiàn)自簽國(guó)密雙證書(shū)詳細(xì)教程的文章就介紹完了。如果您還想了解更多內(nèi)容,請(qǐng)?jiān)谟疑辖撬阉鱐OY模板網(wǎng)以前的文章或繼續(xù)瀏覽下面的相關(guān)文章,希望大家以后多多支持TOY模板網(wǎng)!