参考博文过多就不一一说明了,谢谢大家。
签名决定证书的唯一性,签名的信息越多,复杂程度越高,就越安全。
1,keyStore与trustStore的区别和联系
2,什么是自签名证书?自签名证书的生成过程?
3,CA证书为什么要收费?
4,CA收费证书是怎么加入到keyStore和trustStore的?
5,怎么从keyStore中导出证书和公钥密钥?
6,后缀为keyStore,jks,p12,crt,crs等的区别?
7,是公钥加密私钥解密吗?
8,双向验证与单向验证?
9,对称加密与非对称加密?
10,https工作流程图
11,浏览器和服务器证书信任概念理解
-------------------------------------------------------------------
1,keyStore与trustStore的区别和联系
trustStore是存储可信任的公钥,如6中红色字体中trustStore的生成过程就是把从keyStore导出的公钥证书导入到trustStore中。
KeyStore是服务器的密钥存储库,存服务器的公钥私钥证书
TrustStore是服务器的信任密钥存储库,存CA公钥,但有一部分人存的是客户端证书集合,这样并不合适
2,什么是自签名证书?自签名证书的生成过程?
自签名证书是使用jdk提供的keyTool工具生成的证书,但是这种生成的证书只有不是权威机构生成的,没有经过他认证,所以在访问或被访问时,不能别人认可,就会导致通讯失败。
生成过程:
keytool是jdk自带的一款ssl管理工具,jdk6和jdk7的keytool命令有些不同,jdk7的兼容jdk6的,
[root@localhost ~]# keytool -help
密钥和证书管理工具
命令:
-certreq 生成证书请求
-changealias 更改条目的别名
-delete 删除条目
-exportcert 导出证书
-genkeypair 生成密钥对
-genseckey 生成密钥
-gencert 根据证书请求生成证书
-importcert 导入证书或证书链
-importkeystore 从其他密钥库导入一个或所有条目
-keypasswd 更改条目的密钥口令
-list 列出密钥库中的条目
-printcert 打印证书内容
-printcertreq 打印证书请求的内容
-printcrl 打印 CRL 文件的内容
-storepasswd 更改密钥库的存储口令
使用 "keytool -command_name -help" 获取 command_name 的用法
生成自签名的证书
[root@localhost ~]# keytool -genkeypair -alias rootca -keyalg RSA
输入密钥库口令:
再次输入新口令:
您的名字与姓氏是什么?
[Unknown]: xx认证中心
您的组织单位名称是什么?
[Unknown]: xx认证中心
您的组织名称是什么?
[Unknown]: xxrenz^H^H^H^[[D
您所在的城市或区域名称是什么?
[Unknown]: zz
您所在的省/市/自治区名称是什么?
[Unknown]: gd
该单位的双字母国家/地区代码是什么?
[Unknown]: CN
CN=xx认证中心, OU=xx认证中心, O=xx, L=zz, ST=gd, C=CN是否正确?
[否]: Y
输入 的密钥口令
(如果和密钥库口令相同, 按回车):
[root@localhost ~]#
alias是别名,就是给某某证书取个名字,可以随便写,可以用changealias命令修改
keyalg是加密算法,有DSA,RSA,默认是DSA,因为DSA只能用于加密,不能用户证书签名,所以这里必须指定使用RSA算法
这里有两个密码:密钥库密码和密钥密码,密钥库是存储密钥的地方,他有密码;只有知道这个密码才可以访问这个密钥库;密钥密码用于生产密钥。
这样就生成了一个自签名的根证书
[root@localhost ~]# keytool -list -v
输入密钥库口令:
密钥库类型: JKS
密钥库提供方: SUN
您的密钥库包含 1 个条目
别名: rootca
创建日期: 2016-8-12
条目类型: PrivateKeyEntry
证书链长度: 1
证书[1]:
所有者: CN=xx认证中心, OU=xx认证中心, O=xx, L=zz, ST=gd, C=CN
发布者: CN=xx认证中心, OU=xx认证中心, O=xx, L=zz, ST=gd, C=CN
序列号: 7228c046
有效期开始日期: Fri Aug 12 15:02:13 CST 2016, 截止日期: Thu Nov 10 15:02:13 CST 2016
证书指纹:
MD5: 4D:C2:43:61:70:D8:B9:E8:C4:5E:04:0B:55:07:68:A3
SHA1: DF:E1:FE:D0:1E:CC:B6:21:C0:CB:97:DE:89:D6:19:06:AA:3D:C2:58
SHA256: 8E:9F:9C:1D:03:C6:CB:50:F6:6F:FD:99:B1:2C:BD:DA:F7:32:04:5A:0F:3A:7E:68:1D:75:1D:55:FF:6C:3B:63
签名算法名称: SHA256withRSA
版本: 3
扩展:
#1: ObjectId: 2.5.29.14 Criticality=false
SubjectKeyIdentifier [
KeyIdentifier [
0000: 93 FB 73 88 5C A1 5E 57 C5 9A 77 BB CC C7 A1 77 ..s.\.^W..w....w
0010: 8C C2 FA 8E ....
]
]
*******************************************
*******************************************
[root@localhost ~]#
可以看到这个证书的所有者和发布者都是xx认证中心,这就叫自签名.CA根证书都是自签名的
[root@localhost ~]# keytool -genkeypair -alias baidu -keyalg RSA
输入密钥库口令:
您的名字与姓氏是什么?
[Unknown]: www.baidu.com
您的组织单位名称是什么?
[Unknown]: 百度技术有限公司
您的组织名称是什么?
[Unknown]: 百度技术有限公司
您所在的城市或区域名称是什么?
[Unknown]: 背景
您所在的省/市/自治区名称是什么?
[Unknown]: 北京
该单位的双字母国家/地区代码是什么?
[Unknown]: CN
CN=www.baidu.com, OU=百度技术有限公司, O=百度技术有限公司, L=背景, ST=北京, C=CN是否正确?
[否]: Y
输入 的密钥口令
(如果和密钥库口令相同, 按回车):
[root@localhost ~]#
先通过这个自签名证书生成一个证书请求
[root@localhost ~]# keytool -certreq -alias baidu -file baidu.csr
输入密钥库口令:
[root@localhost ~]# ls
anaconda-ks.cfg gitdemo mcr
apache-tomcat-7.0.69.tar.gz install.log MCR_R2014a_glnxa64_installer.zip
baidu.csr install.log.syslog server-jre-7u79-linux-x64.tar.gz
datacenter.sql leptonica-1.73 tesseract-master
git leptonica-1.73.tar.gz tesseract-master.zip
[root@localhost ~]#
这样就生成了一个证书请求文件baidu.csr。然后我们拿着这个文件和钱去xx认证中心
[root@localhost ~]# keytool -gencert -alias rootca -infile baidu.csr -outfile baidu.cer
输入密钥库口令:
[root@localhost ~]# ls
anaconda-ks.cfg gitdemo MCR_R2014a_glnxa64_installer.zip
apache-tomcat-7.0.69.tar.gz install.log server-jre-7u79-linux-x64.tar.gz
baidu.cer install.log.syslog tesseract-master
baidu.csr leptonica-1.73 tesseract-master.zip
datacenter.sql leptonica-1.73.tar.gz
git mcr
[root@localhost ~]#
baidu.cer就是经过认证中心认证的证书了。百度拿着这个证书就回家了,然后把这个证书导入密钥库。证书的发布者就变成了xx认证中心
[root@localhost ~]# keytool -importcert -alias baidu -file baidu.cer
输入密钥库口令:
证书回复已安装在密钥库中
[root@localhost ~]# keytool -list -alias baidu -v
输入密钥库口令:
别名: baidu
创建日期: 2016-8-12
条目类型: PrivateKeyEntry
证书链长度: 2
证书[1]:
所有者: CN=www.baidu.com, OU=百度技术有限公司, O=百度技术有限公司, L=背景, ST=北京, C=CN
发布者: CN=xx认证中心, OU=xx认证中心, O=xx, L=zz, ST=gd, C=CN
序列号: 43c1823c
有效期开始日期: Fri Aug 12 15:40:29 CST 2016, 截止日期: Thu Nov 10 15:40:29 CST 2016
证书指纹:
MD5: 49:AF:7E:D8:CA:6C:96:76:A8:8E:FC:2C:46:A2:A3:B4
SHA1: 7F:73:80:E7:60:98:35:B0:BD:D8:B5:A2:E0:ED:0D:6B:48:49:31:F5
SHA256: D8:CF:AF:41:8F:82:CA:C5:D2:6E:CB:23:FF:18:38:B6:92:29:AA:55:00:82:40:62:39:5D:C8:C7:7C:39:97:0F
签名算法名称: SHA256withRSA
版本: 3
然后就可以参考5中方法一把认证后的cer证书导入到keyStore中。
3,CA证书为什么要收费?
这里在问题2中其实也说明了主要原因,因为自签名证书不被别人认可,所以只能使用大家都认可的一家平台做同一管理,既然管理了也就要收“物业费”喽。并且证书提供机构也提供证书的加密,签名,身份认证等技术服务。
CA公司的主要成本构成:审核 ,验证CSR成本,支持成本,法律成本(保险费用,担保费用)。全球信任度架高的HTTPS(SSL证书)签发机构不超过5家!所以信任度较高的证书,费用都是很高的。
要进入各个浏览器的根证书列表,CA公司每年必须过 WebTrust 年度审计,是很大的开销。
一些浏览器厂商还会对植入根证书列表的CA收费。
基础设施开销,CRL 和 OCSP 服务器成本。
验证CSR:就是提交证书申请后,CA要做多项验证,越是高级的证书(比如EV)验证越麻烦。不固定开销,有些要花费很多人力和时间来完成。
法律开销:CA公司得买保险,保险费跑不了。
CA链费用:新开的CA公司要等5-10年,才会被普遍信任,才能广泛进入根证书链。要想加快点,就得给别的大牌CA公司掏钱,买次级证书。
4,CA收费证书是怎么加入到keyStore和trustStore的?
以一种方式简单介绍先,使用keyTool生成自签名证书,通过这个自签名证书生成一个证书请求文件后缀是.csr,然后我们拿着这个文件和钱去xx认证中心,认证后就是就是经过认证中心认证的证书了,然后把这个证书导入密钥库。证书的发布者就变成了我们交钱的XX认证中心了。把认证好的cer导入到keyStore中,生成keyStore。导出公钥证书,把导出的公钥证书导入到trustStore中,就生成了trustStore
5,怎么从keyStore中导出证书和公钥密钥?
方法一:
检查一个keystore
keytool -list -v -keystore c:\server.jks
检查一个keystore的内容
keytool -list -v -keystore c:\server.jks
添加一个信任根证书到keystore文件
keytool -import -alias newroot -file root.cer -keystore server.jks
导入CA签署好的证书
keytool -import -keystore c:\server.jks -alias tomcat -file c:\cert.txt
从 KEYSTORE中导出一个证书文件
keytool -export -alias myssl -keystore server.jks -rfc -file server.cer
*备注: "-rfc" 表示以base64输出文件,否则以二进制输出。
从KEYSTORE中删除一个证书
keytool -delete -keystore server.jks -alias tomcat
*备注:删除了别名为tomcat的证书。
这里也要结合下面一起看,方便理解:
1.生成密钥库
keytool -keystore clientkeystore -genkey -alias client
这里clientkeystore可以是后缀为jks、keyStore的文件
2.生成证书请求文件
根据client密钥对生成证书请求文件,这个文件client.csr用于CA签名
keytool -keystore clientkeystore -certreq -alias client -keyalg rsa -file client.csr
这里们就拿着client.cer证书请求文件和money去证书认证中心认证。经过认证后的文件会由后缀为.csr变为cer文件,这里是CARoot.cer文件。如果带签名则是client.cer文件
3,把认证后的cer文件导入到clientkeyStore中。
keytool -import -keystore clientkeystore -file CARoot.cer -alias theCARoot
如果在ca机构认证的等级比较高(也是花的钱多),可能会有签名那么是如下命令:
keytool -import -keystore clientkeystore -file client.cer -alias client
4,导出公钥证书
keytool -export -alias icesslkey -keystore clientkeystore -rfc -file icecert.cer
其中icecert.cer是导出证书的名称,可以随便起个名字,clientkeystore 是2中生成的keystore 文件。
5,生成trustStore文件
把4生成的公钥证书icecert.cer导入到truststore中
keytool -import -alias icesslkey -file icecert.cer -keystore icetruststore.jks
icecert.cer是4导出的公钥证书,icetruststore.jks可以随便起,是生成的truststore的文件名。这条命令首先会生成一个truststore,然后导入4生成的公钥证书icecert.cer。
6,验证trustStore
验证5生成的truststore文件
keytool -list -v -keystore icetruststore.jks
icetruststore.jks是5生成的truststore文件名。
方法二:
import java.io.File;
import java.io.FileInputStream;
import java.io.FileWriter;
import java.security.Key;
import java.security.KeyPair;
import java.security.KeyStore;
import java.security.KeyStoreException;
import java.security.NoSuchAlgorithmException;
import java.security.PrivateKey;
import java.security.PublicKey;
import java.security.UnrecoverableKeyException;
import java.security.cert.Certificate;
import sun.misc.BASE64Encoder;
/**
* 导出证书(base64),导出私钥,导出公钥
* @author happyqing
*/
public class ExportCert {
//导出证书 base64格式
public static void exportCert(KeyStore keystore, String alias, String exportFile) throws Exception {
Certificate cert = keystore.getCertificate(alias);
BASE64Encoder encoder = new BASE64Encoder();
String encoded = encoder.encode(cert.getEncoded());
FileWriter fw = new FileWriter(exportFile);
fw.write("-----BEGIN CERTIFICATE-----\r\n"); //非必须
fw.write(encoded);
fw.write("\r\n-----END CERTIFICATE-----"); //非必须
fw.close();
}
//得到KeyPair
public static KeyPair getKeyPair(KeyStore keystore, String alias,char[] password) {
try {
Key key = keystore.getKey(alias, password);
if (key instanceof PrivateKey) {
Certificate cert = keystore.getCertificate(alias);
PublicKey publicKey = cert.getPublicKey();
return new KeyPair(publicKey, (PrivateKey) key);
}
} catch (UnrecoverableKeyException e) {
} catch (NoSuchAlgorithmException e) {
} catch (KeyStoreException e) {
}
return null;
}
//导出私钥
public static void exportPrivateKey(PrivateKey privateKey,String exportFile) throws Exception {
BASE64Encoder encoder = new BASE64Encoder();
String encoded = encoder.encode(privateKey.getEncoded());
FileWriter fw = new FileWriter(exportFile);
fw.write("—–BEGIN PRIVATE KEY—–\r\n"); //非必须
fw.write(encoded);
fw.write("\r\n—–END PRIVATE KEY—–"); //非必须
fw.close();
}
//导出公钥
public static void exportPublicKey(PublicKey publicKey,String exportFile) throws Exception {
BASE64Encoder encoder = new BASE64Encoder();
String encoded = encoder.encode(publicKey.getEncoded());
FileWriter fw = new FileWriter(exportFile);
fw.write("—–BEGIN PUBLIC KEY—–\r\n"); //非必须
fw.write(encoded);
fw.write("\r\n—–END PUBLIC KEY—–"); //非必须
fw.close();
}
public static void main(String args[]) throws Exception {
String keyStoreType = "JKS";
//String keystoreFile = "C:/mykeystore";
String keystoreFile = "C:/Documents and Settings/zhao/.keystore";
String password = "123456";
KeyStore keystore = KeyStore.getInstance(keyStoreType);
keystore.load(new FileInputStream(new File(keystoreFile)), password.toCharArray());
String alias = "cms";
String exportCertFile = "C:/Documents and Settings/zhao/cms.cer";
String exportPrivateFile = "C:/Documents and Settings/zhao/cmsPrivateKey.txt";
String exportPublicFile = "C:/Documents and Settings/zhao/cmsPublicKey.txt";
ExportCert.exportCert(keystore, alias, exportCertFile);
KeyPair keyPair = ExportCert.getKeyPair(keystore, alias, password.toCharArray());
ExportCert.exportPrivateKey(keyPair.getPrivate(), exportPrivateFile);
ExportCert.exportPublicKey(keyPair.getPublic(), exportPublicFile);
System.out.println("OK");
}
}
6,后缀为keyStore,jks,PKCS12,crt,crs等的区别?
jks:java用的存储密钥的容器。可以同时容纳n个公钥或私钥,后缀一般是.jks或者.keystore或.truststore等,千奇百怪。不管什么后缀,它就是一个容器,各个公司或机构叫法不同而已。比如把只包含"受信任的公钥"的容器存成.truststore文件等。
用jdk\bin目录下的keytool.exe对其进行查看,导入,导出,删除,修改密码等各种操作。可以对jks容器加密码,输入正确才可以操作此容器中密钥。还有一个密码的概念与上者不同,是jks中存储着的私钥的密码,通常是绝密的
7,是公钥加密私钥解密吗?
这个不是绝对的,不过通常是对请求内容是公钥加密,私钥解密;签名是私钥加密公钥解密。
举例:
公钥加密
假设一下,我找了两个数字,一个是1,一个是2。我喜欢2这个数字,就保留起来,不告诉你们(私钥),然后我告诉大家,1是我的公钥。
我有一个文件,不能让别人看,我就用1加密了。别人找到了这个文件,但是他不知道2就是解密的私钥啊,所以他解不开,只有我可以用
数字2,就是我的私钥,来解密。这样我就可以保护数据了。
我的好朋友x用我的公钥1加密了字符a,加密后成了b,放在网上。别人偷到了这个文件,但是别人解不开,因为别人不知道2就是我的私钥,
只有我才能解密,解密后就得到a。这样,我们就可以传送加密的数据了。
私钥签名
如果我用私钥加密一段数据(当然只有我可以用私钥加密,因为只有我知道2是我的私钥),结果所有的人都看到我的内容了,因为他们都知
道我的公钥是1,那么这种加密有什么用处呢?
但是我的好朋友x说有人冒充我给他发信。怎么办呢?我把我要发的信,内容是c,用我的私钥2,加密,加密后的内容是d,发给x,再告诉他
解密看是不是c。他用我的公钥1解密,发现果然是c。
这个时候,他会想到,能够用我的公钥解密的数据,必然是用我的私钥加的密。只有我知道我得私钥,因此他就可以确认确实是我发的东西。
这样我们就能确认发送方身份了。这个过程叫做数字签名。当然具体的过程要稍微复杂一些。用私钥来加密数据,用途就是数字签名。
总结:公钥和私钥是成对的,它们互相解密。
公钥加密,私钥解密。
私钥数字签名,公钥验证。
8,双向验证与单向验证?
单向验证:
双向验证:
9,对称加密与非对称加密?
可以理解为服务端与客户端都有一个密钥,并且是相同的,这里就没有公钥密钥之说了(如果有两把也可以理解为公钥和私钥)。服务端与客户端都用这个密钥加密,可能有另外一个密钥用来解密,看实际情况。
我和朋友都有同样的密钥--一串密码,我如果想发送信息给朋友,先用这密钥来加密发送的信息,朋友收到消息后,用密钥来解密我发送的信息,就能看到原文。就算其它人想办法获取了我们之间的通讯内容,没有这串解密钥,也看不到原文,这样就能满足我们的需求了。
放在互联网的场景中,我们来看看这种解决方案是否有效。我有一台服务器,对外提供高考成绩查询服务。小明他们班都来我的站点上来查询成绩,为了安全,他们需要把发送过来的身份信息用我们给的密钥进行加密,这样就只有我们能看懂他们的身份信息了。但他们班有30多个人,也就是说有30多个人有这份密钥,并以自己的方式将这个关键的密钥存在了30份不同的地方。根据‘我就只跟你说,你不要跟其它人说’原理,我们的密钥根本就没有安全性可言,随时都有暴漏的风险。
有四把钥匙,并且都不一样,服务端和客户端各两个,分别是公钥和私钥。对请求内容是公钥加密,私钥解密。签名则是反过来。
10,https工作流程图
11,浏览器和服务器证书信任概念理解
证书分为两种:一种是证书,一种是根证书;证书是指颁发者信任被颁发者,根证书是被颁发者信任颁发者。
让我们举例来更详细的分析这两种证书的区别:
1. 如颁发证书的机构CSDN可以颁发这两种证书。
2. 当CSDN把证书颁给小李,说明小李是被CSDN所信任的;
3. 当CSDN把根证书颁给大李,说明大李是信任CSDN机构的;
4. 那么小李和大李彼此信任;
如,你用chrome的时候,经常会看到浏览器提示“此站点是否信任”,具体是否信任由用户来决定,可以提醒你如果是刻意盗用你账户用户密码的黑客网站的攻击。
那么我们搭建的服务器,我们知道可以信任,但是浏览器不知道啊,所以在每次访问我们的服务器的时候都会弹出这样的提示对话框,会觉得没有必要,那么就该前面说的证书上场了;
1. 我们可以创建两个证书,一个证书让服务器进行安装;
2. 一个根证书让浏览器进行安装;
3. 这样浏览器在访问服务器的时候,服务器首先会返回它的证书,浏览器会用自己的证书和服务器返回的证书进行匹配,如果是可信任的证书,那么就会直接通过,不会出现“此站点是否信任”的阻止对话框;
4. 但是,如果你的浏览器安装了证书,可以你访问服务器的时候用的是ip地址,但是服务器返回的证书用的是域名,浏览器会进行提示,你可以继续进行访问;所以,最好访问的host名字和证书的名字是一样的;