在前面说到。消息摘要用于验证数据完整性,对称与非对称加密用于保证数据保密性,数据签名用于数据的抗否认性,于是集这些安全手段于一身的终极武器--数字证书出现了。数字证书具备了加密/解密的必要信息。包括签名算法,可用于网络数据加密/解密交互。标识网络用户(计算机)身份。数据证书为公布公钥提供了一种简便途径,成为加密算法以及公钥的载体。

数字证书有多种文件编码格式,主要包括CER编码、DER编码等:

a.CER(Canonical Encoding Rules。规范编码格式)。是数字证书的一种编码格式。它是BER(Basic Encoding Rules,基本编码格式)的一个变种,比BER规定得更加严格。

b.DER(Distinguished Encoding Rule, 卓越编码格式),相同是BER的一个变种,与CER不的同之处在于:DER使用定长模式。而CER使用变长模式。

c.PKCS(Public-Key Cryptography Standards,公钥加密标准),由RSA实验室和其他安全系统开发商为促进公钥password发展而制定的一系列标准。

当中CER、DER格式证书都符合公钥基础设施(PKI)制定的X509国际标准(X.509标准),统称为X509格式证书。PKCS至今共公布过15个标准。经常使用标准包括PKCS#7、PKCS#10和PKCS#12。PKCS#7为password消息语法标准,文件名称后缀一般为:.p7b、.p7c、.spc;PKCS10#为证书请求语法标准,故证书请求文件採用该格式,文件名称后缀一般为:.p10、.csr;PKCS#12为个人信息交换语法标准。故个人信息证书採用该格式,文件名称后缀一般为:.p12、.pfx。

值得一提的是尽管PKCS#12为一种证书格式。但在Java中,个人更认为是一种KeyStore格式。由于PKCS#12格式文件里既能够存储证书,还能够存储私钥,而一般意义说来,证书是不包括私钥信息的。

一、数字证书详细包括了哪些信息,我们以12306的数字证书为例:

从上面的截图能够看到,一张数字证书中包括了非常多信息,主要有,版本、序列号、签名算法、签名哈希算法、颁发者、有效期、使用者、公钥、指纹算法、指纹以及一些数字证书的扩展属性信息。



二、证书怎样获取

假如你的公司要上线一个购物站点。那么肯定会使用到https协议,也就肯定会使用到数字证书,那么数字证书从哪里来?是自己生成吗?当然不是,正确的做法是。公司生成一个证书请求文件,再把证书请求文件提交给证书认证机构。然后证书认证机构使用其根证书再依据证书请求文件里的信息为您生成受信任证书。也就是颁发证书,当然要让证书认证机构为您公司颁发证书这是须要money的。可是有些时候也能够自己创建证书。仅仅只是这时候的证书颁者是你自己,仅仅是别人信息你自己的根证书,证书也能够照常使用。

三、证书是否合法(受信任)

说到证书是否受信任的问题就得先知道一条规则:受信任的证书所颁发的证书也是受信任的。那么先有鸡还是先有蛋的问题来了,第一个受信任的证书是从哪里来的。为了解决问题就引出了根证书,根证书是自己颁发给自己的证书,仅仅要信任了根证书,这样由根证书颁发的证书也就能够被信任。所以证书颁发事实上是一种树形结构,根证书能够颁发一级证书。一级证书在同意的情况下也能够为其他用户颁发二级证书。以Windows, IE为例(IE共用Windows系统中的证书),在Windows安装好后,系统就已经信任了一些权威证书认证机构的根证书,当然你也能够导入你自己制作的根证书。



四、何为证书颁发

证书颁发是个专业术语,事实上就是使用证书颁发者的私钥对证书使用者的证书进行签名。并设置使用者证书的颁发者,证书普通情况下须要由权威的证书认证机构颁发。其原就是对证书进行签名使用的是私钥,私钥仅仅有颁发机构才有。

以下就看看在Java中是怎样完毕对证书的各种操作的:

package com.xtayfjpk.security.certificate;

import java.io.ByteArrayOutputStream;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.ObjectInputStream;
import java.io.ObjectOutputStream;
import java.math.BigInteger;
import java.security.Key;
import java.security.KeyFactory;
import java.security.KeyPair;
import java.security.KeyPairGenerator;
import java.security.PrivateKey;
import java.security.Provider;
import java.security.PublicKey;
import java.security.Security;
import java.security.Signature;
import java.security.cert.CertificateFactory;
import java.security.cert.X509Certificate;
import java.security.spec.RSAPublicKeySpec;
import java.util.Date;
import java.util.HashMap;
import java.util.Map; import javax.security.auth.x500.X500Principal; import org.bouncycastle.asn1.DERBMPString;
import org.bouncycastle.asn1.pkcs.PKCSObjectIdentifiers;
import org.bouncycastle.asn1.x500.X500Name;
import org.bouncycastle.asn1.x509.AlgorithmIdentifier;
import org.bouncycastle.asn1.x509.Certificate;
import org.bouncycastle.asn1.x509.SubjectPublicKeyInfo;
import org.bouncycastle.cert.X509CertificateHolder;
import org.bouncycastle.cert.X509v3CertificateBuilder;
import org.bouncycastle.crypto.params.AsymmetricKeyParameter;
import org.bouncycastle.crypto.params.RSAKeyParameters;
import org.bouncycastle.crypto.util.PrivateKeyFactory;
import org.bouncycastle.crypto.util.PublicKeyFactory;
import org.bouncycastle.crypto.util.SubjectPublicKeyInfoFactory;
import org.bouncycastle.jce.interfaces.PKCS12BagAttributeCarrier;
import org.bouncycastle.jce.provider.BouncyCastleProvider;
import org.bouncycastle.operator.ContentSigner;
import org.bouncycastle.operator.DefaultDigestAlgorithmIdentifierFinder;
import org.bouncycastle.operator.DefaultSignatureAlgorithmIdentifierFinder;
import org.bouncycastle.operator.bc.BcRSAContentSignerBuilder;
import org.bouncycastle.pkcs.PKCS10CertificationRequest;
import org.bouncycastle.pkcs.PKCS10CertificationRequestBuilder;
import org.bouncycastle.x509.X509V3CertificateGenerator;
import org.junit.Before;
import org.junit.Test; /**
* issuer 证书颁发者
* subject 证书使用者
*
* DN:Distinguish Name
* 格式:CN=姓名,OU=组织单位名称,O=组织名称,L=城市或区域名称,ST=省/市/自治区名称,C=国家双字母
*
*/
@SuppressWarnings("deprecation")
public class CertifacateGenerateTest { private static final String KEY_PAIR_ALG = "RSA";
private static final String SIG_ALG = "SHA1withRSA";
private static final String DN_ZHANGSAN = "CN=zhangsan,OU=development,O=Huawei,L=ShenZhen,ST=GuangDong,C=CN";
private static final String DN_CA = "CN=Kingyea,OU=Kingyea,O=Kingyea,L=GuangZou,ST=GuangDong,C=CN";
private static Map<String, String> algorithmMap = new HashMap<>(); static {
/**
* 算法名称与算法标识符映射
*/
algorithmMap.put("1.2.840.113549.1.1.5", SIG_ALG);
algorithmMap.put("1.2.840.113549.1.1.1", KEY_PAIR_ALG);
} @Before
public void before() {
//注冊BC Provider,由于有些关于证书的操作使用到了BouncyCastle这个第三方库就顺便注冊上了,事实上不注冊也行
Provider provider = new BouncyCastleProvider();
Security.addProvider(provider);
} /**
* 生成根证书公钥与私钥对
*/
@Test
public void testGenRootKeyPair() throws Exception {
KeyPairGenerator keyPairGenerator = KeyPairGenerator.getInstance(KEY_PAIR_ALG);
keyPairGenerator.initialize(2048);
KeyPair keyPair = keyPairGenerator.generateKeyPair();
writeObject("H:/certtest/Kingyea.public", keyPair.getPublic());
writeObject("H:/certtest/Kingyea.private", keyPair.getPrivate());
} /**
* 生成用户证书公钥与私钥对
* @throws Exception
*/
@Test
public void testZhangsanKeyPair() throws Exception {
KeyPairGenerator keyPairGenerator = KeyPairGenerator.getInstance(KEY_PAIR_ALG);
keyPairGenerator.initialize(2048);
KeyPair keyPair = keyPairGenerator.generateKeyPair();
writeObject("H:/certtest/zhangsan.public", keyPair.getPublic());
writeObject("H:/certtest/zhangsan.private", keyPair.getPrivate());
} /**
* 生成根证书(被BC废弃,但能够使用)
*/
@Test
public void testGenRootCert() throws Exception {
X509V3CertificateGenerator certGen = new X509V3CertificateGenerator();
//设置证书颁发者
certGen.setIssuerDN(new X500Principal(DN_CA));
//设置证书有效期
certGen.setNotAfter(new Date(System.currentTimeMillis()+ 100 * 24 * 60 * 60 * 1000));
certGen.setNotBefore(new Date());
//设置证书公钥
certGen.setPublicKey(getRootPublicKey());
//设置证书序列号
certGen.setSerialNumber(BigInteger.TEN);
//设置签名算法
certGen.setSignatureAlgorithm(SIG_ALG);
//设置证书使用者
certGen.setSubjectDN(new X500Principal(DN_CA));
//使用私钥生成证书。主要是为了进行签名操作
X509Certificate certificate = certGen.generate(getRootPrivateKey());
PKCS12BagAttributeCarrier bagAttr = (PKCS12BagAttributeCarrier)certificate;
bagAttr.setBagAttribute(
PKCSObjectIdentifiers.pkcs_9_at_friendlyName,
new DERBMPString("Kingyea Coperation Certificate"));
writeFile("H:/certtest/ca.cer", certificate.getEncoded());
} /**
* 生成根证书的第二种方式
* @throws Exception
*/
@Test
public void testGenRootCertWithBuilder() throws Exception {
final AlgorithmIdentifier sigAlgId = new DefaultSignatureAlgorithmIdentifierFinder().find(SIG_ALG);
final AlgorithmIdentifier digAlgId = new DefaultDigestAlgorithmIdentifierFinder().find(sigAlgId); PublicKey publicKey = getRootPublicKey();
PrivateKey privateKey = getRootPrivateKey(); X500Name issuer = new X500Name(DN_CA);
BigInteger serial = BigInteger.TEN;
Date notBefore = new Date();
Date notAfter = new Date(System.currentTimeMillis()+ 100 * 24 * 60 * 60 * 1000);
X500Name subject = new X500Name(DN_CA); AlgorithmIdentifier algId = AlgorithmIdentifier.getInstance(PKCSObjectIdentifiers.rsaEncryption.toString());
System.out.println(algId.getAlgorithm());
AsymmetricKeyParameter publicKeyParameter = PublicKeyFactory.createKey(publicKey.getEncoded());
SubjectPublicKeyInfo publicKeyInfo = SubjectPublicKeyInfoFactory.createSubjectPublicKeyInfo(publicKeyParameter);
//此种方式不行,生成证书不完整
//SubjectPublicKeyInfo publicKeyInfo = new SubjectPublicKeyInfo(algId, publicKey.getEncoded());
X509v3CertificateBuilder x509v3CertificateBuilder = new X509v3CertificateBuilder(issuer, serial, notBefore, notAfter, subject, publicKeyInfo); BcRSAContentSignerBuilder contentSignerBuilder = new BcRSAContentSignerBuilder(sigAlgId, digAlgId);
AsymmetricKeyParameter privateKeyParameter = PrivateKeyFactory.createKey(privateKey.getEncoded());
ContentSigner contentSigner = contentSignerBuilder.build(privateKeyParameter); X509CertificateHolder certificateHolder = x509v3CertificateBuilder.build(contentSigner);
Certificate certificate = certificateHolder.toASN1Structure();
writeFile("H:/certtest/ca.cer", certificate.getEncoded());
} /**
* 生成用户证书
*/
@Test
public void testGenZhangsanCert() throws Exception {
X509V3CertificateGenerator certGen = new X509V3CertificateGenerator();
certGen.setIssuerDN(new X500Principal(DN_CA));
certGen.setNotAfter(new Date(System.currentTimeMillis()+ 100 * 24 * 60 * 60 * 1000));
certGen.setNotBefore(new Date());
certGen.setPublicKey(getZhangsanPublicKey());
certGen.setSerialNumber(BigInteger.TEN);
certGen.setSignatureAlgorithm(SIG_ALG);
certGen.setSubjectDN(new X500Principal(DN_ZHANGSAN));
X509Certificate certificate = certGen.generate(getRootPrivateKey()); writeFile("H:/certtest/zhangsan.cer", certificate.getEncoded());
} /**
* 验证根证书签名
*/
@Test
public void testVerifyRootCert() throws Exception {
CertificateFactory certificateFactory = CertificateFactory.getInstance("X.509");
FileInputStream inStream = new FileInputStream("H:/certtest/ca.cer");
X509Certificate certificate = (X509Certificate) certificateFactory.generateCertificate(inStream);
System.out.println(certificate);
Signature signature = Signature.getInstance(certificate.getSigAlgName());
signature.initVerify(certificate);
signature.update(certificate.getTBSCertificate());
boolean legal = signature.verify(certificate.getSignature());
System.out.println(legal);
} /**
* 验证用户证书签名
*/
@Test
public void testVerifyZhangsanCert() throws Exception {
CertificateFactory certificateFactory = CertificateFactory.getInstance("X.509");
FileInputStream inStream = new FileInputStream("H:/certtest/zhangsan.cer");
X509Certificate certificate = (X509Certificate) certificateFactory.generateCertificate(inStream);
System.out.println(certificate.getPublicKey().getClass());
Signature signature = Signature.getInstance(certificate.getSigAlgName());
signature.initVerify(getRootPublicKey());
signature.update(certificate.getTBSCertificate());
boolean legal = signature.verify(certificate.getSignature());
System.out.println(legal);
} /**
* 生成证书请求文件
*/
@Test
public void testGenCSR() throws Exception {
X500Name subject = new X500Name(DN_ZHANGSAN);
AsymmetricKeyParameter keyParameter = PrivateKeyFactory.createKey(getZhangsanPrivateKey().getEncoded());
SubjectPublicKeyInfo publicKeyInfo = SubjectPublicKeyInfoFactory.createSubjectPublicKeyInfo(keyParameter);
PKCS10CertificationRequestBuilder certificationRequestBuilder = new PKCS10CertificationRequestBuilder(subject, publicKeyInfo);
final AlgorithmIdentifier sigAlgId = new DefaultSignatureAlgorithmIdentifierFinder().find(SIG_ALG);
final AlgorithmIdentifier digAlgId = new DefaultDigestAlgorithmIdentifierFinder().find(sigAlgId);
BcRSAContentSignerBuilder contentSignerBuilder = new BcRSAContentSignerBuilder(sigAlgId, digAlgId);
PKCS10CertificationRequest certificationRequest = certificationRequestBuilder.build(contentSignerBuilder.build(keyParameter));
System.out.println(certificationRequest);
writeFile("H:/certtest/zhangsan.csr", certificationRequest.getEncoded());
} /**
* 依据证书请求文件生成用户证书,事实上主要是使用根证书私钥为其签名
*/
@Test
public void testZhangsanCertWithCSR() throws Exception {
byte[] encoded = readFile("H:/certtest/zhangsan.csr");
PKCS10CertificationRequest certificationRequest = new PKCS10CertificationRequest(encoded); RSAKeyParameters parameter = (RSAKeyParameters) PublicKeyFactory.createKey(certificationRequest.getSubjectPublicKeyInfo());
RSAPublicKeySpec keySpec = new RSAPublicKeySpec(parameter.getModulus(), parameter.getExponent());
String algorithm = algorithmMap.get(certificationRequest.getSubjectPublicKeyInfo().getAlgorithm().getAlgorithm().toString());
PublicKey publicKey = KeyFactory.getInstance(algorithm).generatePublic(keySpec);
System.out.println(certificationRequest.getSubject());
X509V3CertificateGenerator certGen = new X509V3CertificateGenerator();
certGen.setIssuerDN(new X500Principal(DN_CA));
certGen.setNotAfter(new Date(System.currentTimeMillis()+ 100 * 24 * 60 * 60 * 1000));
certGen.setNotBefore(new Date()); certGen.setPublicKey(publicKey);
certGen.setSerialNumber(BigInteger.TEN);
certGen.setSignatureAlgorithm(algorithmMap.get(certificationRequest.getSignatureAlgorithm().getAlgorithm().toString()));
certGen.setSubjectDN(new X500Principal(certificationRequest.getSubject().toString()));
X509Certificate certificate = certGen.generate(getRootPrivateKey()); writeFile("H:/certtest/zhangsan.cer", certificate.getEncoded()); } public PrivateKey getRootPrivateKey() throws Exception {
return PrivateKey.class.cast(readKey("H:/certtest/Kingyea.private"));
}
public PublicKey getRootPublicKey() throws Exception {
return PublicKey.class.cast(readKey("H:/certtest/Kingyea.public"));
} public PrivateKey getZhangsanPrivateKey() throws Exception {
return PrivateKey.class.cast(readKey("H:/certtest/zhangsan.private"));
}
public PublicKey getZhangsanPublicKey() throws Exception {
return PublicKey.class.cast(readKey("H:/certtest/zhangsan.public"));
} public byte[] readFile(String path) throws Exception {
FileInputStream cntInput = new FileInputStream(path);
ByteArrayOutputStream baos = new ByteArrayOutputStream();
int b = -1;
while((b=cntInput.read())!=-1) {
baos.write(b);
}
cntInput.close();
byte[] contents = baos.toByteArray();
baos.close();
return contents;
} public void writeFile(String path, byte[] content) throws Exception {
FileOutputStream fos = new FileOutputStream(path);
fos.write(content);
fos.close();
} public void writeObject(String path, Object object) throws Exception {
ObjectOutputStream oos = new ObjectOutputStream(new FileOutputStream(path));
oos.writeObject(object);
oos.close();
} public Object readObject(String path) throws Exception {
ObjectInputStream ois = new ObjectInputStream(new FileInputStream(path));
Object obj = ois.readObject();
ois.close();
return obj;
} public Key readKey(String path) throws Exception {
ObjectInputStream ois = new ObjectInputStream(new FileInputStream(path));
Key key = Key.class.cast(ois.readObject());
ois.close();
return key;
}
}

在根证书生成后双击打开。Windows会提示:该CA根证书不受信任。要启用信任,将该证书安装到”受信任的根证书颁发机构“存储区。将自己生成的根证书安装到受信任的根证书颁发机构后,你会发现其颁发的用户证书也受信任了。

Java安全之数字证书的更多相关文章

  1. JAVA对数字证书的常用操作(转载)

    一:需要包含的包 import java.security. * ; import java.io. * ; import java.util. * ; import java.security. * ...

  2. 数字证书简介及Java编码实现

    1.数字证书简介 数字证书具备常规加密解密必要的信息,包含签名算法,可用于网络数据加密解密交互,标识网络用户(计算机)身份.数字证书为发布公钥提供了一种简便的途径,其数字证书则成为加密算法以及公钥的载 ...

  3. Java加密解密与数字证书的操作

    1 keytool命令总结 一.创建数字证书 交互模式 使用默认的密钥库.keystore(文件夹是c: Documents and Settingusername)和算法(DSA) keytool  ...

  4. Java使用数字证书加密通信(加解密/加签验签)

    本文中使用的Base64Utils.java可参考:http://www.cnblogs.com/shindo/p/6346618.html 证书制作方法可参考:http://www.cnblogs. ...

  5. java中的数据加密5 数字证书

    数字证书 A用私钥加密了,那么B接受到消息后,用A提供的公钥解密:那么现在有个讨厌的C,他把消息拦截了,然后用自己的私钥加密,同时把自己的公钥发给B,并告诉B,那是A的公钥,结果....,这时候就需要 ...

  6. 数字签名、数字证书的原理以及证书的获得java版

    数字签名原理简介(附数字证书) 首先要了解什么叫对称加密和非对称加密,消息摘要这些知识. 1. 非对称加密 在通信双方,如果使用非对称加密,一般遵从这样的原则:公钥加密,私钥解密.同时,一般一个密钥加 ...

  7. 如何利用java程序实现加密所需的公钥、密钥、数字证书

    本篇的主要目的在于实现pdf的数字签名问题,只是作为我学习知识的总结. 1.数字签名算法的概述 本部分主要参考于:https://blog.csdn.net/lovelichao12/article/ ...

  8. 【Java】Java与数字证书

    Java与数字证书 Java与数字证书 证书的签发和应用 证书的内容和意义 其它 证书(Certificate,也称public-key certificate)是用某种签名算法对某些内容(比如公钥) ...

  9. Java加密技术(八)——数字证书

    原文:http://snowolf.iteye.com/blog/391931 请大家在阅读本篇内容时先阅读 Java加密技术(四),预先了解RSA加密算法. 在构建Java代码实现前,我们需要完成证 ...

随机推荐

  1. 【php】 php的注释问题,单行注释和多行注释与php结束符的关系

    单行注释仅仅注释到行末或者当前的 PHP 代码块,视乎哪个首先出现.这意味着在 // ... ?> 或者 # ... ?> 之后的 HTML 代码将被显示出来:?> 跳出了 PHP ...

  2. Luogu 2216 [HAOI2007]理想的正方形 (单调队列优化)

    题意: 给出一个 N×M 的矩阵,以及一个数值 K ,求在给定的矩阵中取出一个 K×K 的矩阵其中最大值减去最小值的最小值. 细节: 没有细节来发暴力走天下,20分也是分啊~~~ QAQ. 分析: 感 ...

  3. bs4--官文--修改文档树

    修改文档树 Beautiful Soup的强项是文档树的搜索,但同时也可以方便的修改文档树 修改tag的名称和属性 在 Attributes 的章节中已经介绍过这个功能,但是再看一遍也无妨. 重命名一 ...

  4. android sdk 下载

    不知道是因为最近kaihui还是怎么的,打开android sdk官方网站特别的慢,想下载最新版本的platform几乎变成不可能完成的任务,不知道为什么Google不像Apache那样在各国设立镜像 ...

  5. swift final关键字、?、!可选与非可选符

    ?符号: 可选型 在初始化时可以赋值为nil !符号:  隐形可选型 类型值不能为nil,如果解包后的可选类型为nil会报运行时错误,主要用在一个变量/常量在定义瞬间完成之后值一定会存在的情况.这主要 ...

  6. CF802D

    D. Marmots (easy) time limit per test 2 seconds memory limit per test 256 megabytes input standard i ...

  7. 总结搭建Oracle11g DG踩的坑

    此次的操作环境是Oracle11g 单实例,os为Linux,采用duplicate在线创建物理备库 primary上设置相关参数 ALTER SYSTEM SET LOG_ARCHIVE_CONFI ...

  8. scp命令(基于ssh上传文件等)

    (转:http://www.cnblogs.com/hitwtx/archive/2011/11/16/2251254.html) svn 删除所有的 .svn文件 find . -name .svn ...

  9. iOS学习笔记15-序列化、偏好设置和归档

    一.本地持久化 所谓的持久化,就是将数据保存到硬盘中,使得在应用程序或机器重启后可以继续访问之前保存的数据.在iOS开发中,有很多数据持久化的方案,接下来我将尝试着介绍一下5种方案: plist文件( ...

  10. 【2018.10.18】CXM笔记(动态规划)

    1.给你一棵树,让你修任意多条点不相交的铁路(每条铁路都是一根链),定义一个点的代价为它到根节点的路径中不在铁路上的边数,求一种设计方案代价最大的点最小. 铁路点不相交与 每个点连出去的铁路条数 $\ ...