https通讯基础知识汇总

参考博文过多就不一一说明了,谢谢大家。

签名决定证书的唯一性,签名的信息越多,复杂程度越高,就越安全。

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 的用法

这是支持的命令,可以使用 keytool -command_name -help获得子命令的用法,如 keytool -genkeypair -help.

生成自签名的证书

[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根证书都是自签名的

再生产一个自签名的证书,后面用前面这个rootca来签名这个证书,这样这个证书就不是自签名的证书,而是得到xx认证中心认证的证书了

[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 ~]# 

现在假设我们是百度,我们需要申请一个证书,如上,我们生成了一个叫百度的自签名证书,但是百度的信用很差,广大网友不认可百度的信誉,所以百度的证书要到xx认证中心去认证。

先通过这个自签名证书生成一个证书请求

[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证书为什么要收费?

CA - certificate authority,身份认证

这里在问题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中存储着的私钥的密码,通常是绝密的

.crt 证书文件 ,可以是DER(二进制)编码的,也可以是PEM( ASCII (Base64) )编码的 ,在类unix系统中比较常见 
.cer 也是证书  常见于Windows系统  编码类型同样可以是DER或者PEM的,windows 下有工具可以转换crt到cer
.csr 证书签名请求   一般是生成请求以后发送给CA,然后CA会给你签名并发回证书
.key  一般公钥或者密钥都会用这种扩展名,可以是DER编码的或者是PEM编码的  查看DER编码的(公钥或者密钥)的文件的命令为 openssl rsa -inform DER  -noout -text -in  xxx.key  查看PEM编码的(公钥或者密钥)的文件的命令为 openssl rsa -inform PEM   -noout -text -in  xxx.key  
.p12 证书  包含一个X509证书和一个被密码保护的私钥

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,双向验证与单向验证?

单向验证:

https通讯基础知识汇总_第1张图片


双向验证:

https通讯基础知识汇总_第2张图片

9,对称加密与非对称加密?

对称加密

可以理解为服务端与客户端都有一个密钥,并且是相同的,这里就没有公钥密钥之说了(如果有两把也可以理解为公钥和私钥)。服务端与客户端都用这个密钥加密,可能有另外一个密钥用来解密,看实际情况。

我和朋友都有同样的密钥--一串密码,我如果想发送信息给朋友,先用这密钥来加密发送的信息,朋友收到消息后,用密钥来解密我发送的信息,就能看到原文。就算其它人想办法获取了我们之间的通讯内容,没有这串解密钥,也看不到原文,这样就能满足我们的需求了。

放在互联网的场景中,我们来看看这种解决方案是否有效。我有一台服务器,对外提供高考成绩查询服务。小明他们班都来我的站点上来查询成绩,为了安全,他们需要把发送过来的身份信息用我们给的密钥进行加密,这样就只有我们能看懂他们的身份信息了。但他们班有30多个人,也就是说有30多个人有这份密钥,并以自己的方式将这个关键的密钥存在了30份不同的地方。根据‘我就只跟你说,你不要跟其它人说’原理,我们的密钥根本就没有安全性可言,随时都有暴漏的风险。

非对称加密

有四把钥匙,并且都不一样,服务端和客户端各两个,分别是公钥和私钥。对请求内容是公钥加密,私钥解密。签名则是反过来。

如果说公钥的权力太大,那能不能把权限调整一下,哪怕你有公钥,但经过公钥加密的信息,哪怕你拿到了不属于你的公钥,但你还是打不开经过公钥加密后的信息,只有私钥可以打开。这也就是密码学领域里的“非对称加密”。可以理解为公钥和私钥的权力不对等--公钥加密的信息,自己没法解开,只有私钥可以解开;私钥加密的信息,公钥都可以解开。那么假设公钥被他人非法持有,并且同时很不幸,他们还获取了加密后的内容,但因为他们得到私钥的成本较大,我们一样可以认为这对他们并没有什么帮助,用户信息还是安全的。但真的是这样吗?

10,https工作流程图

11,浏览器和服务器证书信任概念理解

证书分为两种:一种是证书,一种是根证书;证书是指颁发者信任被颁发者,根证书是被颁发者信任颁发者。

让我们举例来更详细的分析这两种证书的区别:

1. 如颁发证书的机构CSDN可以颁发这两种证书。

2. 当CSDN把证书颁给小李,说明小李是被CSDN所信任的;

3. 当CSDN把证书颁给大李,说明大李是信任CSDN机构的;

4. 那么小李和大李彼此信任;

如,你用chrome的时候,经常会看到浏览器提示“此站点是否信任”,具体是否信任由用户来决定,可以提醒你如果是刻意盗用你账户用户密码的黑客网站的攻击。


那么我们搭建的服务器,我们知道可以信任,但是浏览器不知道啊,所以在每次访问我们的服务器的时候都会弹出这样的提示对话框,会觉得没有必要,那么就该前面说的证书上场了;

1. 我们可以创建两个证书,一个证书让服务器进行安装;

2. 一个根证书让浏览器进行安装;

3. 这样浏览器在访问服务器的时候,服务器首先会返回它的证书,浏览器会用自己的证书和服务器返回的证书进行匹配,如果是可信任的证书,那么就会直接通过,不会出现“此站点是否信任”的阻止对话框;


4. 但是,如果你的浏览器安装了证书,可以你访问服务器的时候用的是ip地址,但是服务器返回的证书用的是域名,浏览器会进行提示,你可以继续进行访问;所以,最好访问的host名字和证书的名字是一样的;



你可能感兴趣的:(java,java)