1. X.509证书简介

X.509是密码学里公钥证书的格式标准。X.509证书己应用在包括TLS/SSL(WWW万维网安全浏览的基石)在内的众多Internet协议里。同时它也用在很多非在线应用场景里,比如电子签名服务。X.509证书里含有公钥、身份信息(比如网络主机名,组织的名称或个体名称等)和签名信息(可以是证书签发机构CA的签名,也可以是自签名)。对于一份经由可信的证书签发机构签名或者可以通过其它方式验证的证书,证书的拥有者就可以用证书及相应的私钥来创建安全的通信,对文档进行数字签名。-百度百科

所有的X.509证书包含以下数据:

①X.509版本号:指出该证书使用了哪种版本的X.509标准,版本号会影响证书中的一些特定信息。目前的版本是3。

②证书持有人的公钥:包括证书持有人的公钥、算法(指明密钥属于哪种密码系统)的标识符和其他相关的密钥参数。

③证书的序列号:由CA给予每一个证书分配的唯一的数字型编号,当证书被取消时,实际上是将此证书序列号放入由CA签发的CRL(Certificate Revocation List证书作废表,或证书黑名单表)中。这也是序列号唯一的原因。

④主题信息:证书持有人唯一的标识符(或称DN-distinguished name)这个名字在 Internet上应该是唯一的。DN由许多部分组成,看起来象这样:

CN=Bob Allen

OU=Total Network Security Division

O=Network Associates, Inc.

C=US

这些信息指出该科目的通用名、组织单位、组织和国家或者证书持有人的姓名、服务处所等信息。

⑤证书的有效期:证书起始日期和时间以及终止日期和时间;指明证书在这两个时间内有效。

⑥认证机构:证书发布者,是签发该证书的实体唯一的CA的X.509名字。使用该证书意味着信任签发证书的实体。(注意:在某些情况下,比如根或顶级CA证书,发布者自己签发证书)

⑦发布者的数字签名:这是使用发布者私钥生成的签名,以确保这个证书在发放之后没有被撰改过。

⑧签名算法标识符:用来指定CA签署证书时所使用的签名算法。算法标识符用来指定CA签发证书时所使用的公开密钥算法和HASH算法。

证书主题属性

属性类型名称 含义 简写
Common Name 通用名称 CN
Organizational Unit name 机构单元名称 OU
Organization name 机构名 O
Locality 地理位置 L
State or province name 州/省名 S
Country 国名 C

此外还有一些有效期,颁发者,证书颁发对象,用途等。详情参考

2.java操作X.509证书

java对x509有自己的一套实现可以选择sun公司自己的实现类,但是有些复杂的操作sun自带的做不了,所以我们一般使用bouncycastle这个java开源加密包。

需要注意的是:jdk自带的aes加密只支持到128位,更高的256位的加密,需要到oracle官网下载jce包,替换java自带的加密包。一般对称和非对称加密都是混合使用的,这也是为了在安全性和效率上取得平衡,这也是业内目前普遍采用的方法。

需要引入的包:

    <dependencies><!--bouncycastle加密包--><dependency><groupId>org.bouncycastle</groupId><artifactId>bcpkix-jdk15on</artifactId><version>1.64</version></dependency><dependency><groupId>org.bouncycastle</groupId><artifactId>bcprov-jdk15on</artifactId><version>1.64</version></dependency><dependency><groupId>org.bouncycastle</groupId><artifactId>bcmail-jdk15</artifactId><version>1.46</version></dependency><!--StringUtils等都在这个包下--><dependency><groupId>commons-lang</groupId><artifactId>commons-lang</artifactId><version>2.6</version></dependency></dependencies>

X509接口

import java.math.BigInteger;
import java.security.PrivateKey;
import java.security.PublicKey;
import java.util.Date;public interface X509Dao {/*** 制作证书* @param issuer 发布者* @param notBefore 使用日期* @param notAfter 到期* @param certDestPath 生成证书地址* @param serial 证书序列号* @param keyPassword 证书密码* @param alias 证书别名* @throws Exception*/void createCert(String issuer, Date notBefore, Date notAfter, String certDestPath, BigInteger serial,String keyPassword, String alias) throws Exception;/*** 输出证书信息* @param certPath 证书地址* @param keyPassword 证书密码* @throws Exception*/void printCert(String certPath, String keyPassword) throws Exception;/*** 返回公钥* @param certPath* @param keyPassword* @return* @throws Exception*/PublicKey getPublicKey(String certPath, String keyPassword) throws Exception;/*** 返回私钥* @param certPath* @param keyPassword* @return* @throws Exception*/PrivateKey getPrivateKey(String certPath, String keyPassword) throws Exception;/*** 证书延期(未实现)* @param endTime* @param certPath* @param keyPassword* @throws Exception*/void certDelayTo(Date endTime, String certPath, String keyPassword) throws Exception;/*** 修改密码* @param certPath* @param oldPwd* @param newPwd* @throws Exception*/void changePassword(String certPath, String oldPwd, String newPwd) throws Exception;/*** 删除证书* @param certPath* @param keyPassword* @param alias* @param entry* @throws Exception*/void deleteAlias(String certPath, String keyPassword, String alias, String entry) throws Exception;}

X509实现类

package testx509;import org.apache.commons.lang.time.DateUtils;
import org.bouncycastle.asn1.ASN1InputStream;
import org.bouncycastle.asn1.x500.X500Name;
import org.bouncycastle.asn1.x509.SubjectPublicKeyInfo;
import org.bouncycastle.cert.X509CertificateHolder;
import org.bouncycastle.cert.X509v3CertificateBuilder;
import org.bouncycastle.jce.provider.BouncyCastleProvider;
import org.bouncycastle.operator.ContentSigner;
import org.bouncycastle.operator.jcajce.JcaContentSignerBuilder;import java.io.ByteArrayInputStream;
import java.io.FileInputStream;
import java.io.FileOutputStream;
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.ArrayList;
import java.util.Calendar;
import java.util.Date;
import java.util.Enumeration;public class X509CertDaoImpl implements X509Dao{public static final String Default_keyType = "PKCS12";//存储证书keyStore类型public static final String Default_KeyPairGenerator = "RSA";//非对称加密算法public static final String Default_Signature = "SHA1withRSA";//签名算法:RSA签名,用MD5哈希算法摘要public static final String cert_type = "X509";//证书类型public static final Integer Default_KeySize = 2048;static {//系统添加BC加密算法,以后系统中调用的算法都是BC的算法Security.addProvider(new BouncyCastleProvider());}@Overridepublic void createCert(String issuer, Date notBefore, Date notAfter, String certDestPath, BigInteger serial, String keyPassword, String alias) throws Exception {//产生公私钥对KeyPairGenerator kpg = KeyPairGenerator.getInstance(Default_KeyPairGenerator);kpg.initialize(Default_KeySize);KeyPair keyPair = kpg.generateKeyPair();PublicKey publicKey = keyPair.getPublic();PrivateKey privateKey = keyPair.getPrivate();//组装证书X500Name issueDn = new X500Name(issuer);X500Name subjectDn = new X500Name(issuer);//组装公钥信息SubjectPublicKeyInfo subjectPublicKeyInfo = SubjectPublicKeyInfo.getInstance(new ASN1InputStream(publicKey.getEncoded()).readObject());X509v3CertificateBuilder builder = new X509v3CertificateBuilder(issueDn, serial, notBefore, notAfter, subjectDn, subjectPublicKeyInfo);//证书签名数据ContentSigner signGen = new JcaContentSignerBuilder(Default_Signature).build(privateKey);X509CertificateHolder holder = builder.build(signGen);byte[] certBuf = holder.getEncoded();X509Certificate certificate = (X509Certificate) CertificateFactory.getInstance(cert_type).generateCertificate(new ByteArrayInputStream(certBuf));//创建KeyStore,存储证书KeyStore store = KeyStore.getInstance(Default_keyType);store.load(null, null);store.setKeyEntry(alias, keyPair.getPrivate(), keyPassword.toCharArray(), new Certificate[]{certificate});FileOutputStream fout = new FileOutputStream(certDestPath);store.store(fout, keyPassword.toCharArray());fout.close();}@Overridepublic void printCert(String certPath, String keyPassword) throws Exception {//char[] charArray = keyPassword.toCharArray();//KeyStore ks = KeyStore.getInstance(Default_keyType);//FileInputStream fis = new FileInputStream(certPath);//ks.load(fis, charArray);//fis.close();//System.out.println("keystore type=" + ks.getType());//Enumeration enumas = ks.aliases();//String keyAlias = null;//if (enumas.hasMoreElements()) {//    keyAlias = (String) enumas.nextElement();//    System.out.println("alias=[" + keyAlias + "]");//}//System.out.println("is key entry="+ks.isKeyEntry(keyAlias));//PrivateKey prikey = (PrivateKey) ks.getKey(keyAlias, charArray);//Certificate cert = ks.getCertificate(keyAlias);//PublicKey pubkey = cert.getPublicKey();//System.out.println("cert class = "+ cert.getClass().getName());//System.out.println("cert= "+cert);//System.out.println("public key = "+pubkey);//System.out.println("private key = "+prikey);char[] charArray = keyPassword.toCharArray();KeyStore ks = KeyStore.getInstance(Default_keyType);FileInputStream fis = new FileInputStream(certPath);ks.load(fis, charArray);fis.close();System.out.println("keystore type=" + ks.getType());Enumeration enumas = ks.aliases();String keyAlias = null;while (enumas.hasMoreElements()) {keyAlias = (String) enumas.nextElement();System.out.println("alias=[" + keyAlias + "]");System.out.println("is key entry="+ks.isKeyEntry(keyAlias));PrivateKey prikey = (PrivateKey) ks.getKey(keyAlias, charArray);Certificate cert = ks.getCertificate(keyAlias);PublicKey pubkey = cert.getPublicKey();System.out.println("cert class = "+ cert.getClass().getName());System.out.println("cert= "+cert);System.out.println("public key = "+pubkey);System.out.println("private key = "+prikey);}}@Overridepublic PublicKey getPublicKey(String certPath, String keyPassword) throws Exception {char[] charArray = keyPassword.toCharArray();KeyStore ks = KeyStore.getInstance(Default_keyType);FileInputStream fis = new FileInputStream(certPath);ks.load(fis, charArray);fis.close();Enumeration enumas = ks.aliases();String keyAlias = null;if (enumas.hasMoreElements()) {keyAlias = (String) enumas.nextElement();return ks.getCertificate(keyAlias).getPublicKey();}return null;}@Overridepublic PrivateKey getPrivateKey(String certPath, String keyPassword) throws Exception {char[] charArray = keyPassword.toCharArray();KeyStore ks = KeyStore.getInstance(Default_keyType);FileInputStream fis = new FileInputStream(certPath);ks.load(fis, charArray);fis.close();Enumeration enumas = ks.aliases();String keyAlias = null;if (enumas.hasMoreElements()) {keyAlias = (String) enumas.nextElement();return  (PrivateKey) ks.getKey(keyAlias, charArray);}return null;}@Overridepublic void certDelayTo(Date endTime, String certPath, String keyPassword) throws Exception {}@Overridepublic void changePassword(String certPath, String oldPwd, String newPwd) throws Exception {KeyStore ks = KeyStore.getInstance(Default_keyType);FileInputStream fis = new FileInputStream(certPath);ks.load(fis, oldPwd.toCharArray());fis.close();FileOutputStream fout = new FileOutputStream(certPath);ks.store(fout,newPwd.toCharArray());fout.close();}@Overridepublic void deleteAlias(String certPath, String keyPassword, String alias, String entry) throws Exception {char[] charArray = keyPassword.toCharArray();KeyStore ks = KeyStore.getInstance(Default_keyType);FileInputStream fis = new FileInputStream(certPath);ks.load(fis, charArray);fis.close();if (ks.containsAlias(alias)){ks.deleteEntry(entry);FileOutputStream fout = new FileOutputStream(certPath);ks.store(fout,keyPassword.toCharArray());fout.close();}else {throw new Exception("该证书未包含别名------->"+alias);}}public static void main(String[] args) throws Exception {//1.创建证书//X509CertDaoImpl impl = new X509CertDaoImpl();//String issuer="C=CN,ST=BJ,L=Beijing,O=testserver,OU=testserver,CN=testserver";//String certDestPath="E:\\iotest\\test2.p12";//BigInteger serial=BigInteger.valueOf(System.currentTimeMillis());//String keyPassword="123456";//String alias="test2";////Calendar calendar = Calendar.getInstance();//calendar.add(Calendar.YEAR,5);////impl.createCert(issuer,new Date(),calendar.getTime(),certDestPath,serial,keyPassword,alias);//System.out.println("创建证书成功");//2.遍历打印证书信息X509CertDaoImpl impl = new X509CertDaoImpl();impl.printCert("E:\\iotest\\cert\\test.p12","123456");//3.DateUtils的使用//Date date = DateUtils.parseDate("2021-11-12 09:50:00", new String[]{"yyyy-MM-dd HH:mm:ss"});//System.out.println(date.toLocaleString());//4.枚举的遍历问题//char[] charArray = "123456".toCharArray();//KeyStore ks = KeyStore.getInstance(Default_keyType);//FileInputStream fis = new FileInputStream("E:\\iotest\\cert\\test.p12");//ks.load(fis, charArray);//fis.close();//System.out.println("keystore type=" + ks.getType());//Enumeration enumas = ks.aliases();//ArrayList<String> aliasList = new ArrayList<>();//String [] keyAlias = null;//while (enumas.hasMoreElements()) {//    String alias = (String) enumas.nextElement();//    aliasList.add(alias);//}//System.out.println(aliasList);}
}

这是java相关的证书操作(证书延期没有做),关于java如何使用x509实现加密解密,签名验签等操作,可以阅读这篇文章。

3.证书文件扩展名

X.509有多种常用的扩展名。不过其中的一些还用于其它用途,就是说具有这个扩展名的文件可能并不是证书,比如说可能只是保存了私钥。

.pem:(隐私增强型电子邮件)DER编码的证书再进行Base64编码的数据存放在"-----BEGIN CERTIFICATE-----"和"-----END CERTIFICATE-----"之中。

.cer、.crt、.der:用于存放证书,通常是二进制格式,但Base64编码后也很常见,不含私钥。

.p7b、.p7c:PKCS#7SignedData structure without data, just certificate(s) orCRL(s)

.p12:PKCS#12格式,包含证书的同时可能还有带密码保护的私钥。

.pfx:PFX,PKCS#12之前的格式(通常用PKCS#12格式,比如那些由IIS产生的PFX文件)。

PKCS#7是签名或加密数据的格式标准,官方称之为容器。由于证书是可验真的签名数据,所以可以用SignedData结构表述。.P7C文件是退化的SignedData结构,没有包括签名的数据。

PKCS#12由PFX进化而来的用于交换公共的和私有的对象的标准格式,可以包含公钥证书及其私钥,也可包含整个证书链。

4.证书管理工具keytool

Java自带的keytool工具是个密钥和证书管理工具。它使用户能够管理自己的公钥/私钥对及相关证书,用于(通过数字签名)自我认证(用户向别的用户/服务认证自己)或数据完整性以及认证服务。它还允许用户储存他们的通信对等者的公钥(以证书形式)。

keytool将密钥和证书储存在一个所谓的密钥仓库(keystore)中。缺省的密钥仓库实现将密钥仓库实现为一个文件。它用口令来保护私钥。

Java KeyStore的类型

JKS和JCEKS是Java密钥库(KeyStore)的两种比较常见类型(还有JKS、JCEKS、PKCS12、BKS、UBER)。

JKS的Provider是SUN,在每个版本的JDK中都有,JCEKS的Provider是SUNJCE,1.4后我们都能够直接使用它。

JCEKS在安全级别上要比JKS强,使用的Provider是JCEKS(推荐),尤其在保护KeyStore中的私钥上(使用TripleDes)。

PKCS#12是公钥加密标准,它规定了可包含所有私钥、公钥和证书。其以二进制格式存储,也称为PFX文件,在windows中可以直接导入到密钥区,注意,PKCS#12的密钥库保护密码同时也用于保护Key。

BKS来自BouncyCastle Provider,它使用的也是TripleDES来保护密钥库中的Key,它能够防止证书库被不小心修改(Keystore的keyentry改掉1个bit都会产生错误),BKS能够跟JKS互操作。

UBER比较特别,当密码是通过命令行提供的时候,它只能跟keytool交互。整个keystore是通过PBE/SHA1/Twofish加密,因此keystore能够防止被误改、察看以及校验。以前,Sun JDK(提供者为SUN)允许你在不提供密码的情况下直接加载一个Keystore,类似cacerts,UBER不允许这种情况。

从.p12中提出为.cer证书

使用上述的java代码,生成了test2.p12,alias为test2。使用keytool操作命令如下:

keytool -export -alias test2 -keystore test2.p12 -storetype PKCS12 -rfc -file test2.cer

将.cer证书放入.p12中

使用上述的java代码,生成了test.p12,alias为test。将上面的test2.cer放入到test.p12中:

keytool -import -alias test2 -trustcacerts -file test2.cer -keystore test.p12

这样在test.p12中就存在了两个别名的证书test和test2。

参考文献:

原文链接:https://blog.csdn.net/do_bset_yourself/article/details/78159697

https://www.cnblogs.com/testlife007/p/6888191.html

X.509证书与java相关推荐

  1. java xca,keytool 错误: java.lang.Exception: 所输入的不是 X.509 证书

    假设:你的服务器是用https部署的,有一天网管给你一个服务器的证书名为:server.cer的证书,需要客户端做一个验证,而在android平台下,这个cer文件是不能应用的,所以需要转换成andr ...

  2. ROOT证书、CA证书和使用CA签发的X.509证书

    简介 日常开发中,我们程序员不怎么会接触证书相关的问题,对信息安全领域相关的内容知之甚少.因为平时主要实现的业务很少要直接面向底层的通信,也就很少关注这证书这样的知识.在一般情况下,我们仅仅只是在使用 ...

  3. X.509证书的介绍

    目录 1.X.509简介 2.证书组成结构 3.证书文件扩展名 4.生成一个自签名证书的示例 5.生成签名请求及CA 签名 1.X.509简介 X.509是密码学里公钥证书的格式标准.X.509证书已 ...

  4. 【转】x.509证书在WCF中的应用(CS篇)

    [转自]x.509证书在WCF中的应用(CS篇) 为什么要用x.509证书? WCF的服务端和客户端之间,如 果不作任何安全处理(即服务端的<security mode="None&q ...

  5. DTLS协议中的509证书和密钥如何传输

    DTLS协议 在openssl中,创建DTLS环境都已经被封装好了 ssl_ctx = SSL_CTX_new(DTLS_method()); 接下去我们编程的时候有两种方式去使用DTLS,1 是直接 ...

  6. WCF服务运行找不到X.509证书解决方案

    异常: 无法使用以下搜索标准找到 X.509 证书: StoreName"My".StoreLocation"LocalMachine".FindType&qu ...

  7. WCF---关于无法使用以下搜索标准找到 X.509 证书的问题

    在上篇中的证书验证,我在测试过程中发现这样的问题,"无法使用以下搜索标准找到 X.509 证书的问题" 搜索后解决 1.先将本机证书导出. 运行certmgr.msc. 到处一个. ...

  8. 【ssl认证、证书】java中的ssl语法API说明(SSLContext)、与keytool 工具的联系

    文章目录 1. 前言 java中的ssl语法与keytool 工具的联系 2. SSLContext的体系 2.1 KeyStore 2.1.1 通过证书库文件创建: 2.1.2 随机生成自签名证书库 ...

  9. 给出x.509证书的实例并分析其工作方式

    本篇文章对x.509的结构进行了详细的分析,对x.509证书的工作原理的描述有所不足,仅供参考,希望能对大家有所帮助! x.509证书: Certificate: Data: Version: 1 ( ...

  10. X.509证书DN之详解

    X.509使用DN(Distinct Name)来唯一标识一个实体,其功能类似我们平常使用的ID,不过不同的是,DN不再是类似 123456 这样得数字标识,而是采用多个字段来标识一个实体,例如&qu ...

最新文章

  1. 图片提取文字功能很神奇?Java几行代码搞定它!
  2. python从菜鸟到高手电子书下载_PYTHON从菜鸟到高手 清华大学出版社
  3. SAP IDoc Post不成功,报错 - Conventional invoice verification no longer maintained as of Release 4.6-
  4. IT职场常见疾病之“脂肪肝”
  5. C#人爱学不学9[C#5.0异步实例+WPF自己的MVVM Async应用 1/12]
  6. [core]-ARM A76学习笔记
  7. [error] MFC错误不能将参数1从const char [3]转换为const wchar_t *
  8. 配对交易方法_COVID下的自适应配对交易,一种强化学习方法
  9. 石油大学c语言考试答案,中石油华东2012春《C语言》在线答案
  10. 51Nod-2149 字符串出现位置【水题】
  11. ES6新特性 - const let var
  12. 又看了半天的pdf格式的js方面的书,感觉受益匪浅啊,只会一点操作的我,要学好理论...
  13. 模拟tcp_TCP 半连接队列和全连接队列满了会发生什么?又该如何应对?
  14. Idea导入jar包的两种方法
  15. 《21天学通C语言》总结(2)
  16. android 悬浮窗口透明,基于popupWindow实现悬浮半透明效果
  17. c语言precede函数怎么构造,数据结构——栈的应用(表达式求值)(C语言)
  18. 自然语言处理 | (4)英文文本处理与NLTK
  19. 怎么设置织梦栏目html结尾,dedecms网站栏目地址url优化成.html结尾的而不是文件夹形式结尾的。请大家来帮忙。...
  20. win10使用markdownpad2报错 An error occurred with the HTML rendering component. This issue may be fixed b

热门文章

  1. matlab分布函数逆函数,正态分布函数的反函数求导 matlab
  2. 愿世间所有美好都恰逢其时
  3. 深入了解智能手机常见感应器
  4. Generative Image Inpainting with Contextual Attention
  5. 【MySQL学习笔记(十六)】之redo日志超详细讲解
  6. 蒟蒻自推——稳定匹配
  7. iMeta | 北大陈峰/陈智滨等发表口腔微生物组研究中各部位取样的实验方法(Protocol)...
  8. 软件工程(速成)——第四章 总体设计
  9. 开源OA办公平台教程:手机APP指纹认证的配置
  10. 丹佛机场行李系统案例分析