对于Java不同类型密钥库之PKCS12和JCEKS感兴趣的读者,本文将提供您所需要的所有信息,我们将详细讲解jks密钥库使用专用格式,并且为您提供关于.NETCoreRSA密钥的xml、pkcs1、
对于Java不同类型密钥库之PKCS12和JCEKS感兴趣的读者,本文将提供您所需要的所有信息,我们将详细讲解jks密钥库使用专用格式,并且为您提供关于.NET Core RSA密钥的xml、pkcs1、pkcs8格式转换和JavaScript、Java等语言进行对接、iOS:如何以编程方式在应用程序中从私钥和x509certificate创建PKCS12(P12)密钥库?、Java 9中的SunPKCS11提供程序、java PKCS12 证书生成的宝贵知识。
本文目录一览:- Java不同类型密钥库之PKCS12和JCEKS(jks密钥库使用专用格式)
- .NET Core RSA密钥的xml、pkcs1、pkcs8格式转换和JavaScript、Java等语言进行对接
- iOS:如何以编程方式在应用程序中从私钥和x509certificate创建PKCS12(P12)密钥库?
- Java 9中的SunPKCS11提供程序
- java PKCS12 证书生成
Java不同类型密钥库之PKCS12和JCEKS(jks密钥库使用专用格式)
摘要:密钥库是一个存放加密密钥和证书的存储设施,它们经常用于SSL通信来标明服务器和客户机的身份,本文所列的为Java密钥库中的PKCS12和JCEKS类型。介绍了其存储和加载密钥、证书所使用的代码片段。
编者注:密钥库是一个存放加密密钥和证书的存储设施,它们经常用于SSL通信来标明服务器和客户机的身份,一个密钥库可以是一份文件或硬件设备。Java中不同类型的密钥库包含:PrivateKey、SecretKey、JKS、PKCS12、JCEKS等。其中JKS的详细介绍可参考《Java不同密钥库类型之JKS》。本文所讲诉的为PKCS12和JCEKS的用法。
以下为译文:
JCEKS
JCEKS是Java平台的一个密钥库格式,将密钥存储在密钥库中以防止加密密钥的暴露。在JCEKS中存储和装载不同条目的过程类似于JKS,只需在调用KeyStore.getInstance()时更改相应的JCEKS密钥库类型。
存储密钥
密钥可以通过一下代码存储到JCEKS中:
try{
KeyStore keyStore = KeyStore.getInstance("JCEKS");
keyStore.load(null, null);
KeyGenerator keyGen = KeyGenerator.getInstance("DES");
keyGen.init(56);;
Key key = keyGen.generateKey();
keyStore.setKeyEntry("secret", key, "password".toCharArray(), null);
keyStore.store(new FileOutputStream("output.jceks"), "password".toCharArray());
} catch (Exception ex) {
ex.printStackTrace();
}
加载密钥
代码如下:
try{
KeyStore keyStore = KeyStore.getInstance("JCEKS");
keyStore.load(new FileInputStream("output.jceks"), "password".toCharArray());
Key key = keyStore.getKey("secret", "password".toCharArray());
System.out.println(key.toString());
} catch (Exception ex) {
ex.printStackTrace();
}
输出代码:
javax.crypto.spec.SecretKeySpec@fffe7b9b
PKCS12
PKCS12是公钥加密标准,它规定了可包含所有私钥、公钥和证书。其以二进制格式存储,也称为 PFX 文件,在windows中可以直接导入到密钥区。注意,PKCS12的密钥库保护密码同时也用于保护Key。
创建PKCS12密钥库
在把一个条目存入PKCS12之前必须先加载密钥库,这意味着我们必须首先创建一个密钥库。简单创建一个PKCS12密钥库的方式如下:
try{
KeyStore keyStore = KeyStore.getInstance("PKCS12");
keyStore.load(null, null);
keyStore.store(new FileOutputStream("output.p12"), "password".toCharArray());
} catch (Exception ex){
ex.printStackTrace();
}
需要注意的是,在调用keyStore.load(null, null)时,两个null是作为输入密钥流和密码传递的。这是因为我们没有可用的密钥库。运行这段代码后,当前工作目录中应该会输出一个名为output.p12的文件。
存储密钥
代码如下:
try{
KeyStore keyStore = KeyStore.getInstance("PKCS12");
keyStore.load(null, null);
KeyGenerator keyGen = KeyGenerator.getInstance("AES");
keyGen.init(128);
Key key = keyGen.generateKey();
keyStore.setKeyEntry("secret", key, "password".toCharArray(), null);
keyStore.store(new FileOutputStream("output.p12"), "password".toCharArray());
} catch (Exception ex){
ex.printStackTrace();
}
存储私钥
密钥库包含可用于网络上的SSL通信的私钥和证书:
try{
KeyStore keyStore = KeyStore.getInstance("PKCS12");
// keyStore.load(new FileInputStream("output.p12"),"password".toCharArray());
keyStore.load(null, null);;
CertAndKeyGen gen = new CertAndKeyGen("RSA","SHA1WithRSA");
gen.generate(1024);
Key key=gen.getPrivateKey();
X509Certificate cert=gen.getSelfCertificate(new X500Name("CN=ROOT"), (long)365*24*3600);
X509Certificate[] chain = new X509Certificate[1];
chain[0]=cert;
keyStore.setKeyEntry("private", key, "password".toCharArray(), chain);
keyStore.store(new FileOutputStream("output.p12"), "password".toCharArray());
}catch(Exception ex){
ex.printStackTrace();
}
别忘了调用keyStore.store()来保存密钥,否则条目在程序退出时会丢失。
存储证书
存储证书可以调用KeyStore.setCertificateEntry():
try{
KeyStore keyStore = KeyStore.getInstance("PKCS12");
// keyStore.load(new FileInputStream("output.p12"),"password".toCharArray());
keyStore.load(null, null);;
CertAndKeyGen gen = new CertAndKeyGen("RSA","SHA1WithRSA");
gen.generate(1024);
X509Certificate cert=gen.getSelfCertificate(new X500Name("CN=ROOT"), (long)365*24*3600);
keyStore.setCertificateEntry("cert", cert);
keyStore.store(new FileOutputStream("output.p12"), "password".toCharArray());
}catch(Exception ex){
ex.printStackTrace();
}
存储的证书可以通过调用提供别名的KeyStore.getCertificate() 来提取,例如:
Certificate cert = keyStore.getCertificate("cert");
加载私钥
try{
KeyStore keyStore = KeyStore.getInstance("PKCS12");
keyStore.load(new FileInputStream("output.p12"), "password".toCharArray());
Key pvtKey = keyStore.getKey("private", "password".toCharArray());
System.out.println(pvtKey.toString());
} catch (Exception ex){
ex.printStackTrace();
}
代码输出:
sun.security.rsa.RSAPrivateCrtKeyImpl@ffff2466
加载证书链
如果一个证书链存在密钥库中,我们可以通过调用KeyStore.getCertificateChain()来加载:
try{
KeyStore keyStore = KeyStore.getInstance("PKCS12");
keyStore.load(new FileInputStream("output.p12"), "password".toCharArray());
Key pvtKey = keyStore.getKey("private", "password".toCharArray());
System.out.println(pvtKey.toString());
java.security.cert.Certificate[] chain = keyStore.getCertificateChain("private");
for(java.security.cert.Certificate cert:chain){
System.out.println(cert.toString());
}
} catch (Exception ex){
ex.printStackTrace();
}
输出:
[
[
Version: V3
Subject: CN=ROOT
Signature Algorithm: SHA1withRSA, OID = 1.2.840.113549.1.1.5
Key: Sun RSA public key, 1024 bits
modulus: 107262652552256813768678166856978781385254195794582600239703451044252881438814396239031781495369251659734172714120481593881055888193254336293673302267462500060447786562885955334870856482264000504019061160524587434562257067298291769329550807938162702640388267016365640782567817416484577163775446236245223552189
public exponent: 65537
Validity: [From: Mon Jan 05 13:03:29 SGT 2015,
To: Tue Jan 05 13:03:29 SGT 2016]
Issuer: CN=ROOT
SerialNumber: [ 5e5ca8a4]
]
Algorithm: [SHA1withRSA]
Signature:
0000: 22 21 BF 73 A6 6D 12 9B F7 49 6C 0E B3 50 6A 9D "!.s.m...Il..Pj.
0010: FA 30 43 22 32 FF 54 95 80 2E B3 8B 6F 59 D4 B5 .0C"2.T.....oY..
0020: 6C A6 AE 89 B7 18 9A A8 35 7D 65 37 BF ED A3 F4 l.......5.e7....
0030: E7 DB 5D 5F 9B DA 4B FA 39 04 9B 4D DB C2 3E FA ..]_..K.9..M..>.
0040: 3B C2 63 F8 1E BE 03 F3 BD 1C D4 8A 8E 3C 51 68 ;.c..........
注:如何在Java中创建证书链?可参考:点此进入
加载证书
加载证书可以通过调用KeyStore.getCertificate()来实现:
try{
KeyStore keyStore = KeyStore.getInstance("PKCS12");
keyStore.load(new FileInputStream("output.p12"), "password".toCharArray());
java.security.cert.Certificate cert = keyStore.getCertificate("private");
System.out.println(cert);
} catch (Exception ex){
ex.printStackTrace();
}
输出:
[
[
Version: V3
Subject: CN=ROOT
Signature Algorithm: SHA1withRSA, OID = 1.2.840.113549.1.1.5
Key: Sun RSA public key, 1024 bits
modulus: 107262652552256813768678166856978781385254195794582600239703451044252881438814396239031781495369251659734172714120481593881055888193254336293673302267462500060447786562885955334870856482264000504019061160524587434562257067298291769329550807938162702640388267016365640782567817416484577163775446236245223552189
public exponent: 65537
Validity: [From: Mon Jan 05 13:03:29 SGT 2015,
To: Tue Jan 05 13:03:29 SGT 2016]
Issuer: CN=ROOT
SerialNumber: [ 5e5ca8a4]
]
Algorithm: [SHA1withRSA]
Signature:
0000: 22 21 BF 73 A6 6D 12 9B F7 49 6C 0E B3 50 6A 9D "!.s.m...Il..Pj.
0010: FA 30 43 22 32 FF 54 95 80 2E B3 8B 6F 59 D4 B5 .0C"2.T.....oY..
0020: 6C A6 AE 89 B7 18 9A A8 35 7D 65 37 BF ED A3 F4 l.......5.e7....
0030: E7 DB 5D 5F 9B DA 4B FA 39 04 9B 4D DB C2 3E FA ..]_..K.9..M..>.
0040: 3B C2 63 F8 1E BE 03 F3 BD 1C D4 8A 8E 3C 51 68 ;.c..........
导入导出密钥和证书
PKCS12密钥库可以用于导入导出密钥和证书,下面的代码演示了从PKCS12导出一个私钥并导入到JKS密钥库中:
try{
KeyStore keyStore = KeyStore.getInstance("PKCS12");
keyStore.load(new FileInputStream("output.p12"), "password".toCharArray());
Key pvtKey = keyStore.getKey("private", "password".toCharArray());
java.security.cert.Certificate[] chain = keyStore.getCertificateChain("private");
KeyStore jksStore = KeyStore.getInstance("JKS");
jksStore.load(null, null);;
jksStore.setKeyEntry("jksPrivate", pvtKey, "newpassword".toCharArray(), chain);
jksStore.store(new FileOutputStream("output.jks"), "password".toCharArray());
} catch (Exception ex){
ex.printStackTrace();
本文分享自微信公众号 - JAVA乐园(happyhuangjinjin88)。
如有侵权,请联系 support@oschina.cn 删除。
本文参与“OSC源创计划”,欢迎正在阅读的你也加入,一起分享。
.NET Core RSA密钥的xml、pkcs1、pkcs8格式转换和JavaScript、Java等语言进行对接
众所周知在.NET下的RSA类所生成的密钥为Xml格式,而其他语言比如java一般使用pkcs8格式的密钥,JavaScript一般使用pkcs1格式。我们在开发过程中很可能遇到需要与其他语言开发的api进行对接,如果遇到RSA加密解密,我们肯定需要保证key是相同的,才能保证数据的正确处理,我们肯定需要对密钥进行转换,下面我将我自己的使用经验分享给大家。
pkcs1和pkcs8的操作借助了开源项目bouncycastle
RSAUtil 项目
RSAUtil 项目是.NET Core下RSA算法使用帮助工具,支持使用RSA算法对数据进行加密,解密,签名和验证签名,支持xml,pkcs1,pkcs8三种密钥格式,支持这三种格式的密钥相互转换。最后还支持pem格式化。
使用
生成密钥
使用“RsaKeyGenerator”类。返回的结果是一个有两个元素的字符串的列表,元素1是私钥,元素2是公钥。
格式:XML
var keyList = RsaKeyGenerator.XmlKey(2048);
var privateKey = keyList [0];
var publicKey = keyList [1];
格式:Pkcs1
var keyList = RsaKeyGenerator.Pkcs1Key(2048);
var privateKey = keyList [0];
var publicKey = keyList [1];
格式:Pkcs8
var keyList = RsaKeyGenerator.Pkcs8Key(2048);
var privateKey = keyList [0];
var publicKey = keyList [1];
RSA密钥转换
使用“RsaKeyConvert”类。它支持这三种格式的密钥转换,即:xml,pkcs1,pkcs8。
XML-> Pkcs1:
- 私钥:
RsaKeyConvert.PrivateKeyXmlToPkcs1()
- 公钥:
RsaKeyConvert.PublicKeyXmlToPem()
XML-> Pkcs8:
- 私钥:
RsaKeyConvert.PrivateKeyXmlToPkcs8()
- 公钥:
RsaKeyConvert.PublicKeyXmlToPem()
Pkcs1-> XML:
- 私钥:
RsaKeyConvert.PrivateKeyPkcs1ToXml()
- 公钥:
RsaKeyConvert.PublicKeyPemToXml()
Pkcs1-> Pkcs8:
- 私钥:
RsaKeyConvert.PrivateKeyPkcs1ToPkcs8()
- 公钥:不需要转换
Pkcs8-> XML:
- 私钥:
RsaKeyConvert.PrivateKeyPkcs8ToXml()
- 公钥:
RsaKeyConvert.PublicKeyPemToXml()
Pkcs8-> Pkcs1:
- 私钥:
RsaKeyConvert.PrivateKeyPkcs8ToPkcs1()
- 公钥:不需要转换
加密,解密,签名和验证签名
XML,Pkcs1,Pkcs8分别对应类:
RsaXmlUtil
,RsaPkcs1Util
,RsaPkcs8Util
。它们继承自抽象类RSAUtilBase
- 加密:
RSAUtilBase.Encrypt()
- 解密:
RSAUtilBase.Decrypt()
- Sign:
RSAUtilBase.SignData()
- 验证:
RSAUtilBase.VerifyData()
PEM格式化
使用类“RsaPemFormatHelper”。
- 格式化Pkcs1格式私钥:
RsaPemFormatHelper.Pkcs1PrivateKeyFormat()
- 删除Pkcs1格式私钥格式:
RsaPemFormatHelper.Pkcs1PrivateKeyFormatRemove()
- 格式化Pkcs8格式私钥:
RsaPemFormatHelper.Pkcs8PrivateKeyFormat()
- 删除Pkcs8格式的私钥格式:
RsaPemFormatHelper.Pkcs8PrivateKeyFormatRemove()
其他说明
本项目已开源,如果对您有帮助,欢迎来个star:https://github.com/stulzq/RSAUtil
为了方便使用已经上传Nuget:https://www.nuget.org/packages/XC.RSAUtil/
直接使用命令安装:
Install-Package XC.RSAUtil
iOS:如何以编程方式在应用程序中从私钥和x509certificate创建PKCS12(P12)密钥库?
在我们的应用程序(服务器,客户端)中,我们正在实现客户端身份验证(基于X509Certificate的SSL).我们已经有办法生成密钥对,创建PKCS10证书签名请求,由自签名CA签名并创建X509Certificate,然后发回.但是,要在SSL请求中使用此证书,必须将私钥和X509Certificate导出到PKCS12(P12)密钥库.
有没有人知道如何做到这一点,或者即使它可能?客户端必须生成P12文件(我们不想发出私钥),客户端正在运行iOS,并且是移动设备.该解决方案适用于Android使用BouncyCastle(spongycastle),但我们没有找到任何iOS.
编辑:在Java中,此导出由以下内容完成:
ByteArrayOutputStream bos = new ByteArrayOutputStream(); KeyStore ks = KeyStore.getInstance("PKCS12",BouncyCastleProvider.PROVIDER_NAME); ks.load(null); ks.setKeyEntry("key-alias",(Key) key,password.tochararray(),new java.security.cert.Certificate[] { x509Certificate }); ks.store(bos,password.tochararray()); bos.close(); return bos.toByteArray();
解决方法
您可以使用openssl生成密钥和证书:
EVP_PKEY * pkey; pkey = EVP_PKEY_new(); RSA * rsa; rsa = RSA_generate_key( 2048,/* number of bits for the key - 2048 is a sensible value */ RSA_F4,/* exponent - RSA_F4 is defined as 0x10001L */ NULL,/* callback - can be NULL if we aren't displaying progress */ NULL /* callback argument - not needed in this case */ ); EVP_PKEY_assign_RSA(pkey,rsa); X509 * x509; x509 = X509_new(); ASN1_INTEGER_set(X509_get_serialNumber(x509),1); X509_gmtime_adj(X509_get_notBefore(x509),0); X509_gmtime_adj(X509_get_notAfter(x509),31536000L); X509_set_pubkey(x509,pkey); X509_NAME * name; name = X509_get_subject_name(x509); X509_NAME_add_entry_by_txt(name,"C",MBSTRING_ASC,(unsigned char *)"CA",-1,0); X509_NAME_add_entry_by_txt(name,"O",(unsigned char *)"MyCompany Inc.","CN",(unsigned char *)"localhost",0); X509_set_issuer_name(x509,name); //X509_sign(x509,pkey,EVP_sha1()); const EVP_CIPHER *aConst = EVP_des_ede3_cbc();
你可以用这些函数把它写成pem格式:
PEM_write_PrivateKey(f,NULL,NULL); PEM_write_X509( f,/* write the certificate to the file we've opened */ x509 /* our certificate */ );
之后可以将这些文件写入p12文件,源自此处:
https://github.com/luvit/openssl/blob/master/openssl/demos/pkcs12/pkwrite.c
/* pkwrite.c */ #include <stdio.h> #include <stdlib.h> #include <openssl/pem.h> #include <openssl/err.h> #include <openssl/pkcs12.h> /* Simple PKCS#12 file creator */ int main(int argc,char **argv) { FILE *fp; EVP_PKEY *pkey; X509 *cert; PKCS12 *p12; if (argc != 5) { fprintf(stderr,"Usage: pkwrite infile password name p12file\n"); exit(1); } SSLeay_add_all_algorithms(); ERR_load_crypto_strings(); if (!(fp = fopen(argv[1],"r"))) { fprintf(stderr,"Error opening file %s\n",argv[1]); exit(1); } cert = PEM_read_X509(fp,NULL); rewind(fp); pkey = PEM_read_PrivateKey(fp,NULL); fclose(fp); p12 = PKCS12_create(argv[2],argv[3],cert,0); if(!p12) { fprintf(stderr,"Error creating PKCS#12 structure\n"); ERR_print_errors_fp(stderr); exit(1); } if (!(fp = fopen(argv[4],"wb"))) { fprintf(stderr,argv[1]); ERR_print_errors_fp(stderr); exit(1); } i2d_PKCS12_fp(fp,p12); PKCS12_free(p12); fclose(fp); return 0; }
Java 9中的SunPKCS11提供程序
在Java 8之前,SunPKCS11提供程序的加载方式如下:
Provider provider = new sun.security.pkcs11.SunPKCS11 (new ByteArrayInputStream (configFile.getBytes ()));
Security.addProvider (provider);
configFile
是带有配置参数的字符串。因此,如果应用程序需要使用多个连接的智能卡,则可以创建多个提供程序。要访问每个提供程序,使用的名称是“
SunPKCS11-”,后跟我们在配置中指示的名称。
在Java 8中,sun.security.pkcs11.SunPKCS11
该类已在JDK中删除。因此,我必须通过反射对上一个调用进行编程。
Java 9中的PKCS#11提供程序的操作似乎非常不同:
-
该
SunPKCS11
构造已更改为空单。配置是通过“ configure”方法加载的,因此必须将其保存在磁盘上的文件中,并且我无法再通过流将其加载到字符串中。 -
如果我们尝试使用反射,则会出现以下警告:
WARNING: An illegal reflective access operation has occurred WARNING: Illegal reflective access by PruebaTarjeta
(file:/C:/temp/pkcs11java9/classes/) to constructor
sun.security.pkcs11.SunPKCS11()
WARNING: Please consider reporting this to the maintainers of
PruebaTarjeta
WARNING: Use –illegal-access=warn to enable warnings of further illegal
reflective access operations
WARNING: All illegal access operations will be denied in a future
release
- 在Java 9中,将自动生成SunPKCS11提供程序,该程序位于加密提供程序的列表中。可以从列表中获取并进行配置。问题是您只能在列表中加载一个PKCS#11提供程序。在Java的9文档表明,我们可以得到的PKCS#11提供商,“SunPKCS11-”之后,我们在配置中指示的名字,但事实并非如此。如果我们查看提供商列表,则只有一个是“ SunPKCS11”,因此每个智能卡都不能有一个提供商。
别人也会这样吗?有什么办法吗?
java PKCS12 证书生成
<dependency> <groupId>org.bouncycastle</groupId> <artifactId>bcprov-jdk15on</artifactId> <version>1.49</version> </dependency> <dependency> <groupId>org.bouncycastle</groupId> <artifactId>bcpkix-jdk15on</artifactId> <version>1.49</version> </dependency>
直接上代码
package test; import org.bouncycastle.asn1.ASN1ObjectIdentifier; import org.bouncycastle.asn1.ASN1Primitive; import org.bouncycastle.asn1.x500.X500Name; import org.bouncycastle.asn1.x509.*; import org.bouncycastle.cert.X509CertificateHolder; import org.bouncycastle.cert.X509v3CertificateBuilder; import org.bouncycastle.cert.jcajce.JcaX509v3CertificateBuilder; import org.bouncycastle.jce.provider.BouncyCastleProvider; import org.bouncycastle.operator.ContentSigner; import org.bouncycastle.operator.jcajce.JcaContentSignerBuilder; import java.io.*; import java.math.BigInteger; import java.security.*; import java.security.cert.Certificate; import java.security.cert.CertificateFactory; import java.security.cert.X509Certificate; import java.text.SimpleDateFormat; import java.util.*; /** * 成都一方思致科技有限公司 * * @author 蒋昌宝 * @version 1.0 * @date 2019/8/23 9:26 * @description 证书生成工具类 * ========================================================================= * 变更履历: * ------------------------------------------------------------------------- * 变更编号 变更时间 变更人 变更原因 变更内容 * ------------------------------------------------------------------------- */
public class GenerateCertificateUtil {
private static KeyPair getKey() throws NoSuchAlgorithmException { // 密钥对 生成器,RSA算法 生成的 提供者是 BouncyCastle KeyPairGenerator generator = KeyPairGenerator.getInstance("RSA",new BouncyCastleProvider()); // 密钥长度 1024 generator.initialize(1024); // 证书中的密钥 公钥和私钥 KeyPair keyPair = generator.generateKeyPair(); return keyPair; } /** * @param password 密码 * @param issuerStr 颁发机构信息 * @param subjectStr 使用者信息 * @param certificateCRL 颁发地址 * @return */ public static Map<String,byte[]> createCert(String password,String issuerStr,String subjectStr,String certificateCRL) { Map<String,byte[]> result = new HashMap<String,byte[]>(); ByteArrayOutputStream out = null; try { // 生成JKS证书 // KeyStore keyStore = KeyStore.getInstance("JKS"); // 标志生成PKCS12证书 KeyStore keyStore = KeyStore.getInstance("PKCS12",new BouncyCastleProvider()); keyStore.load(null,null); KeyPair keyPair = getKey(); // issuer与 subject相同的证书就是CA证书 Certificate cert = generateCertificateV3(issuerStr,subjectStr,keyPair,result,certificateCRL,null); // cretkey随便写,标识别名 keyStore.setKeyEntry("cretkey",keyPair.getPrivate(),password.tochararray(),new Certificate[] { cert }); out = new ByteArrayOutputStream(); cert.verify(keyPair.getPublic()); keyStore.store(out,password.tochararray()); byte[] keyStoreData = out.toByteArray(); result.put("keyStoreData",keyStoreData); return result; } catch (Exception e) { e.printstacktrace(); } finally { if (out != null) { try { out.close(); } catch (IOException e) { } } } return result; } /** * @param issuerStr * @param subjectStr * @param keyPair * @param result * @param certificateCRL * @param extensions * @return */ public static Certificate generateCertificateV3(String issuerStr,KeyPair keyPair,Map<String,byte[]> result,String certificateCRL,List<Extension> extensions) { ByteArrayInputStream bout = null; X509Certificate cert = null; try { PublicKey publicKey = keyPair.getPublic(); PrivateKey privateKey = keyPair.getPrivate(); Date notBefore = new Date(); Calendar rightNow = Calendar.getInstance(); rightNow.setTime(notBefore); // 日期加1年 rightNow.add(Calendar.YEAR,1); Date notAfter = rightNow.getTime(); // 证书序列号 BigInteger serial = BigInteger.probablePrime(256,new Random()); X509v3CertificateBuilder builder = new JcaX509v3CertificateBuilder( new X500Name(issuerStr),serial,notBefore,notAfter,new X500Name(subjectStr),publicKey); JcaContentSignerBuilder jBuilder = new JcaContentSignerBuilder( "SHA1withRSA"); Secur删除eRandom secur删除eRandom = new Secur删除eRandom(); jBuilder.setSecur删除eRandom(secur删除eRandom); ContentSigner singer = jBuilder.setProvider( new BouncyCastleProvider()).build(privateKey); // 分发点 ASN1ObjectIdentifier cRLdistributionPoints = new ASN1ObjectIdentifier( "2.5.29.31"); GeneralName generalName = new GeneralName( GeneralName.uniformResourceIdentifier,certificateCRL); GeneralNames seneralNames = new GeneralNames(generalName); distributionPointName distributionPoint = new distributionPointName( seneralNames); distributionPoint[] points = new distributionPoint[1]; points[0] = new distributionPoint(distributionPoint,null,null); CRLdistPoint cRLdistPoint = new CRLdistPoint(points); builder.addExtension(cRLdistributionPoints,true,cRLdistPoint); // 用途 ASN1ObjectIdentifier keyUsage = new ASN1ObjectIdentifier( "2.5.29.15"); // | KeyUsage.nonRepudiation | KeyUsage.keyCertSign builder.addExtension(keyUsage,new KeyUsage( KeyUsage.digitalSignature | KeyUsage.keyEncipherment)); // 基本限制 X509Extension.java ASN1ObjectIdentifier basicConstraints = new ASN1ObjectIdentifier("2.5.29.19"); builder.addExtension(basicConstraints,new BasicConstraints(true)); // privKey:使用自己的私钥进行签名,CA证书 if (extensions != null){ for (Extension ext : extensions) { builder.addExtension( new ASN1ObjectIdentifier(ext.getoid()),ext.isCritical(),ASN1Primitive.fromByteArray(ext.getValue())); } } X509CertificateHolder holder = builder.build(singer); CertificateFactory cf = CertificateFactory.getInstance("X.509"); bout = new ByteArrayInputStream(holder.toASN1Structure() .getEncoded()); cert = (X509Certificate) cf.generateCertificate(bout); byte[] certBuf = holder.getEncoded(); SimpleDateFormat format = new SimpleDateFormat("yyyy-MM-dd"); // 证书数据 result.put("certificateData",certBuf); //公钥 result.put("publicKey",publicKey.getEncoded()); //私钥 result.put("privateKey",privateKey.getEncoded()); //证书有效开始时间 result.put("notBefore",format.format(notBefore).getBytes("utf-8")); //证书有效结束时间 result.put("notAfter",format.format(notAfter).getBytes("utf-8")); } catch (Exception e) { e.printstacktrace(); } finally { if (bout != null) { try { bout.close(); } catch (IOException e) { } } } return cert; } class Extension { private String oid; private boolean critical; private byte[] value; public String getoid() { return oid; } public void setoid(String oid) { this.oid = oid; } public boolean isCritical() { return critical; } public void setCritical(boolean critical) { this.critical = critical; } public byte[] getValue() { return value; } public void setValue(byte[] value) { this.value = value; } }
/**
- 测试证书生成
- @throws Exception
*/
public static void main(String[] args) throws Exception{
// CN: 名字与姓氏 OU : 组织单位名称
// O :组织名称 L : 城市或区域名称 E : 电子邮件
// ST: 州或省份名称 C: 单位的两字母国-家代码
String issuerStr = "CN=jcb凭证,OU=研发部,O=jcb有限公司,C=CN,[email protected],L=北京,ST=北京";
String subjectStr = "CN=jcb有限公司,OU=用户,O=test,[email protected],ST=北京";
String certificateCRL = "https://jcb.cn";
Map<String,byte[]> result = GenerateCertificateUtil.createCert("123456",issuerStr,certificateCRL);
// 生成.p12
FileOutputStream outPutStream = new FileOutputStream("d:/keystore_jcb.p12");
outPutStream.write(result.get("keyStoreData"));
outPutStream.flush();
outPutStream.close();
//生成.cer颁发给用户的证书
// FileOutputStream fos = new FileOutputStream(new File("d:/zheng.cer"));
// fos.write(result.get("certificateData"));
// fos.flush();
// fos.close();
}
}
关于Java不同类型密钥库之PKCS12和JCEKS和jks密钥库使用专用格式的问题就给大家分享到这里,感谢你花时间阅读本站内容,更多关于.NET Core RSA密钥的xml、pkcs1、pkcs8格式转换和JavaScript、Java等语言进行对接、iOS:如何以编程方式在应用程序中从私钥和x509certificate创建PKCS12(P12)密钥库?、Java 9中的SunPKCS11提供程序、java PKCS12 证书生成等相关知识的信息别忘了在本站进行查找喔。
本文标签: