当前位置:   article > 正文

java网络学习之 PKCS标准 X.509标准 证书等概念 的汇总(16)_x509和pkcs

x509和pkcs

一、文件编码格式(pem,der)

PEM (Privacy Enhancement Message),定义见 RFC1421
是一种基于 base64 的编码格式,常见于 linux/unix 下的证书编码

结构组成 == {header} body {tail}
示例

  1. -----BEGIN PUBLIC KEY-----
  2. MIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQDMYfnvWtC8Id5bPKae5yXSxQTt
  3. +Zpul6AnnZWfI2TtIarvjHBFUtXRo96y7hoL4VWOPKGCsRqMFDkrbeUjRrx8iL91
  4. 4/srnyf6sh9c8Zk04xEOpK1ypvBz+Ks4uZObtjnnitf0NBGdjMKxveTq+VE7BWUI
  5. yQjtQ8mbDOsiLLvh7wIDAQAB
  6. -----END PUBLIC KEY-----

DER (Distinguished Encoding Rules) , 定义见维基百科-ASN.1.DER
是来自ASN.1 体系的一种二进制编码格式,常用于 windows/mac 的证书编码

编码方式 == DER uses a pattern of type-length-value triplets

二、PKCS公钥标准

PKCS (Public Key Cryptography Standards),定义见维基百科-PKCS
是一套公钥密码学标准,其定义范围涵盖了证书签名、加密算法、填充模式及校验流程等。

常见PKCS标准

版本里程碑
PKCS#1RFC8017,定义了公钥私钥的编码格式(ASN.1编码),包括基础算法及编码/填充模式、签名校验,openssl的默认标准格式
PKCS#3DiffieHellman Key Agreement,定义了DH 密钥交换标准
PKCS#5RFC8018,基于密码的加密标准,定义了PBKDF2算法
PKCS#7RFC2315,定义密钥信息语法标准,PKI体系下的信息签名及加密标准,是S/MIME的一部分
PKCS#8RFC5958,定义私钥信息语法标准,用于描述证书密钥对的通用格式(不限RSA)
PKCS#11定义了密钥 Token接口,常用于单点登录/公钥算法/磁盘加密系统.(硬件加密)
PKCS#12RFC7292,个人信息交换语法标准,定义了私钥和公钥证书的存储方式(支持密码),常用PFX简称,Java Key Store的编码格式

三、RSA 密钥(RSA公钥和rsa私钥的内容在文件中存储结构介绍)

RSA 公钥编码(pkcs1-pem,pkcs1-der,pkcs8-pem,pkcs8-der)

PublicKey-PKCS#1-PEM

  1. -----BEGIN RSA PUBLIC KEY-----
  2. BASE64 ENCODED DATA
  3. -----END RSA PUBLIC KEY-----

PublicKey-PKCS#1-DER

  1. RSAPublicKey ::= SEQUENCE {
  2. modulus INTEGER, -- n
  3. publicExponent INTEGER -- e
  4. }

PublicKey-PKCS#8-PEM

  1. -----BEGIN PUBLIC KEY-----
  2. BASE64 ENCODED DATA
  3. -----END PUBLIC KEY-----

PublicKey-PKCS#8-DER

  1. PublicKeyInfo ::= SEQUENCE {
  2. algorithm AlgorithmIdentifier,
  3. PublicKey BIT STRING
  4. }
  5. AlgorithmIdentifier ::= SEQUENCE {
  6. algorithm OBJECT IDENTIFIER,
  7. parameters ANY DEFINED BY algorithm OPTIONAL
  8. }

 

RSA 私钥编码(pkcs1-pem,pkcs1-der,pkcs8-pem,pkcs8-der)

PrivateKey-PKCS#1-PEM

  1. -----BEGIN RSA PRIVATE KEY-----
  2. BASE64 ENCODED DATA
  3. -----END RSA PRIVATE KEY-----

PrivateKey-PKCS#1-DER

  1. RSAPrivateKey ::= SEQUENCE {
  2. version Version,
  3. modulus INTEGER, -- n
  4. publicExponent INTEGER, -- e
  5. privateExponent INTEGER, -- d
  6. prime1 INTEGER, -- p
  7. prime2 INTEGER, -- q
  8. exponent1 INTEGER, -- d mod (p-1)
  9. exponent2 INTEGER, -- d mod (q-1)
  10. coefficient INTEGER, -- (inverse of q) mod p
  11. otherPrimeInfos OtherPrimeInfos OPTIONAL
  12. }

PrivateKey-PKCS#8-PEM

  1. -----BEGIN PRIVATE KEY-----
  2. BASE64 ENCODED DATA
  3. -----END PRIVATE KEY-----

PrivateKey-PKCS#8-DER

  1. PrivateKeyInfo ::= SEQUENCE {
  2. version Version,
  3. algorithm AlgorithmIdentifier,
  4. PrivateKey OCTET STRING
  5. }
  6. AlgorithmIdentifier ::= SEQUENCE {
  7. algorithm OBJECT IDENTIFIER,
  8. parameters ANY DEFINED BY algorithm OPTIONAL
  9. }

私钥文件可采用加密方式存储,加密后的格式:
EncryptedPrivateKey-PKCS#8-PEM

  1. -----BEGIN ENCRYPTED PRIVATE KEY-----
  2. BASE64 ENCODED DATA
  3. -----END ENCRYPTED PRIVATE KEY-----

Encrypted-PrivateKey-PKCS#8-DER

  1. EncryptedPrivateKeyInfo ::= SEQUENCE {
  2. encryptionAlgorithm EncryptionAlgorithmIdentifier,
  3. encryptedData EncryptedData
  4. }
  5. EncryptionAlgorithmIdentifier ::= AlgorithmIdentifier
  6. EncryptedData ::= OCTET STRING

RSA 密钥 文件如何读取?

公钥文件 都可以在获取二进制字节数组后,用 X509EncodedKeySpec 初始化,使用KeyFactory 转化成 publickey 对象

  1. //入参为base64 编码的公钥字符串,这个字符串可以是从公钥文件里获取的,也可以是直接手动拼接的
  2. public static PublicKey getPublicKey(String publicKeyStr)
  3. throws GeneralSecurityException {
  4. KeyFactory keyFactory = KeyFactory.getInstance("RSA");//
  5. byte[] encodedKey = Base64.decodeBase64(publicKeyStr);
  6. return keyFactory.generatePublic(new X509EncodedKeySpec(encodedKey));
  7. }

私钥文件都可以在获取二进制字节数组后,用PKCS8EncodedKeySpec初始化,然后使用KeyFactory转化成 privateKey对象。

  1. /**
  2. * 获取私钥
  3. * 入参出的私钥字符串,可以是自己生成的,也可以是从文件里读取的,总之通过私钥字符串生成私钥就可以这样用
  4. * @param privateKeyStr
  5. * @return
  6. * @throws NoSuchAlgorithmException
  7. * @throws InvalidKeySpecException
  8. */
  9. public static PrivateKey getPrivateKey(String privateKeyStr)
  10. throws GeneralSecurityException {
  11. PKCS8EncodedKeySpec priPKCS8 = new PKCS8EncodedKeySpec(
  12. Base64.decodeBase64(privateKeyStr));
  13. KeyFactory keyf = KeyFactory.getInstance("RSA");
  14. return keyf.generatePrivate(priPKCS8);
  15. }

 

四、证书

X.509 证书,维基百科-X.509,是目前流行的公钥证书标准。
一个 X.509 证书包含了一个公钥和对应的实体名(hostname/organization/individual);证书通常由证书认证机构签名或自签名;当证书持有者被另外一方信任时(通过公钥签名验证),两者便可以基于公钥算法建立安全传输通道。

证书结构

  1. Certificate
  2. Version Number
  3. Serial Number
  4. Signature Algorithm ID
  5. Issuer Name
  6. Validity period
  7. Not Before
  8. Not After
  9. Subject name
  10. Subject Public Key Info
  11. Public Key Algorithm
  12. Subject Public Key
  13. Issuer Unique Identifier (optional)
  14. Subject Unique Identifier (optional)
  15. Extensions (optional)
  16. ...
  17. Certificate Signature Algorithm
  18. Certificate Signature

主要字段

字段描述
版本号指出该证书使用了哪种版本的X.509标准(版本1、版本2或是版本3),版本号会影响证书中的一些特定信息
序列号标识证书的唯一整数,由证书颁发者分配的本证书的唯一标识符
签名算法标识符用于签证书的算法标识,由对象标识符加上相关的参数组成,用于说明本证书所用的数字签名算法。例如,SHA-1-RSA
颁发者名称证书颁发者的可识别名(DN),是签发该证书的实体唯一的CA的X.500名字
有效期限证书起始日期和时间以及终止日期和时间
主体名证书持有人的唯一标识符(或称DN-distinguished name)
公钥信息包括证书持有人的公钥、算法
颁发者唯一标识符标识符—证书颁发者的唯一标识符,仅在版本2和版本3中有要求,属于可选项
主体唯一标识符标识符—证书颁发者的唯一标识符,仅在版本2和版本3中有要求,属于可选项
颁发者的数字签名这是使用颁发者私钥生成的签名,以确保这个证书在发放之后没有被撰改过
扩展信息..

扩展字段

字段描述
发行者密钥标识符证书所含密钥的唯一标识符,用来区分同一证书拥有者的多对密钥
密钥使用一个比特串,指明(限定)证书的公钥可以完成的功能或服务,如:证书签名、数据加密等。如果某一证书将 KeyUsage 扩展标记为“极重要”,而且设置为“keyCertSign”,则在 SSL 通信期间该证书出现时将被拒绝,因为该证书扩展表示相关私钥应只用于签写证书,而不应该用于 SSL
CRL分布点指明CRL的分布地点
私钥的使用期指明证书中与公钥相联系的私钥的使用期限,它也有Not Before和Not After组成。若此项不存在时,公私钥的使用期是一样的
证书策略由对象标识符和限定符组成,这些对象标识符说明证书的颁发和使用策略有关
策略映射表明两个CA域之间的一个或多个策略对象标识符的等价关系,仅在CA证书里存在
主体别名指出证书拥有者的别名,如电子邮件地址、IP地址等,别名是和DN绑定在一起的
颁发者别名指出证书颁发者的别名,如电子邮件地址、IP地址等,但颁发者的DN必须出现在证书的颁发者字段
主体目录属性指出证书拥有者的一系列属性。可以使用这一项来传递访问控制信息

样例-维基百科证书

  1. Certificate:
  2. Data:
  3. Version: 3 (0x2)
  4. Serial Number:
  5. 10:e6:fc:62:b7:41:8a:d5:00:5e:45:b6
  6. Signature Algorithm: sha256WithRSAEncryption
  7. Issuer: C=BE, O=GlobalSign nv-sa, CN=GlobalSign Organization Validation CA - SHA256 - G2
  8. Validity
  9. Not Before: Nov 21 08:00:00 2016 GMT
  10. Not After : Nov 22 07:59:59 2017 GMT
  11. Subject: C=US, ST=California, L=San Francisco, O=Wikimedia Foundation, Inc., CN=*.wikipedia.org
  12. Subject Public Key Info:
  13. Public Key Algorithm: id-ecPublicKey
  14. Public-Key: (256 bit)
  15. pub:
  16. 04:c9:22:69:31:8a:d6:6c:ea:da:c3:7f:2c:ac:a5:
  17. af:c0:02:ea:81:cb:65:b9:fd:0c:6d:46:5b:c9:1e:
  18. ed:b2:ac:2a:1b:4a:ec:80:7b:e7:1a:51:e0:df:f7:
  19. c7:4a:20:7b:91:4b:20:07:21:ce:cf:68:65:8c:c6:
  20. 9d:3b:ef:d5:c1
  21. ASN1 OID: prime256v1
  22. X509v3 extensions:
  23. X509v3 Key Usage: critical
  24. Digital Signature, Key Agreement
  25. Authority Information Access:
  26. CA Issuers - URI:http://secure.globalsign.com/cacert/gsorganizationvalsha2g2r1.crt
  27. OCSP - URI:http://ocsp2.globalsign.com/gsorganizationvalsha2g2
  28. X509v3 Certificate Policies:
  29. Policy: 1.3.6.1.4.1.4146.1.20
  30. CPS: https://www.globalsign.com/repository/
  31. Policy: 2.23.140.1.2.2
  32. X509v3 Basic Constraints:
  33. CA:FALSE
  34. X509v3 CRL Distribution Points:
  35. Full Name:
  36. URI:http://crl.globalsign.com/gs/gsorganizationvalsha2g2.crl
  37. X509v3 Subject Alternative Name:
  38. DNS:*.wikipedia.org, DNS:*.m.mediawiki.org, DNS:*.m.wikibooks.org, DNS:*.m.wikidata.org, DNS:*.m.wikimedia.org, DNS:*.m.wikimediafoundation.org, DNS:*.m.wikinews.org, DNS:*.m.wikipedia.org, DNS:*.m.wikiquote.org, DNS:*.m.wikisource.org, DNS:*.m.wikiversity.org, DNS:*.m.wikivoyage.org, DNS:*.m.wiktionary.org, DNS:*.mediawiki.org, DNS:*.planet.wikimedia.org, DNS:*.wikibooks.org, DNS:*.wikidata.org, DNS:*.wikimedia.org, DNS:*.wikimediafoundation.org, DNS:*.wikinews.org, DNS:*.wikiquote.org, DNS:*.wikisource.org, DNS:*.wikiversity.org, DNS:*.wikivoyage.org, DNS:*.wiktionary.org, DNS:*.wmfusercontent.org, DNS:*.zero.wikipedia.org, DNS:mediawiki.org, DNS:w.wiki, DNS:wikibooks.org, DNS:wikidata.org, DNS:wikimedia.org, DNS:wikimediafoundation.org, DNS:wikinews.org, DNS:wikiquote.org, DNS:wikisource.org, DNS:wikiversity.org, DNS:wikivoyage.org, DNS:wiktionary.org, DNS:wmfusercontent.org, DNS:wikipedia.org
  39. X509v3 Extended Key Usage:
  40. TLS Web Server Authentication, TLS Web Client Authentication
  41. X509v3 Subject Key Identifier:
  42. 28:2A:26:2A:57:8B:3B:CE:B4:D6:AB:54:EF:D7:38:21:2C:49:5C:36
  43. X509v3 Authority Key Identifier:
  44. keyid:96:DE:61:F1:BD:1C:16:29:53:1C:C0:CC:7D:3B:83:00:40:E6:1A:7C
  45. Signature Algorithm: sha256WithRSAEncryption
  46. 8b:c3:ed:d1:9d:39:6f:af:40:72:bd:1e:18:5e:30:54:23:35:
  47. 66:5e:62:d5:01:e2:63:47:70:cb:6d:1b:17:b0:f5:4d:11:e4:
  48. ad:94:51:c5:5e:72:03:b0:d5:ab:18:eb:b5:3a:08:a8:73:95:
  49. f3:7f:41:1a:28:7b:45:7c:83:2e:d3:14:95:d8:d5:d1:5f:99:
  50. 4b:0c:f4:c3:9b:0b:4f:e9:49:f4:2c:b5:ae:c3:1d:7d:2a:80:
  51. f6:70:29:4c:0c:e6:e0:cb:88:8a:8a:02:ee:a5:d1:73:c2:93:
  52. 58:24:ff:43:1b:e3:fd:7b:aa:f0:15:0c:60:52:8f:21:7d:87:
  53. 3a:14:fa:81:41:00:60:4f:96:9a:62:94:58:de:cb:15:5c:3c:
  54. f4:c1:4d:33:e3:ff:39:fe:28:fb:b0:41:3e:d2:8a:11:d1:06:
  55. 01:28:74:7d:71:d4:2a:ef:1f:e3:25:4b:2d:f0:66:ef:26:fb:
  56. 4c:f0:81:85:bb:1a:99:06:c9:37:87:de:8d:49:f7:00:91:a9:
  57. 42:31:4a:b9:40:a0:7d:4f:4f:a6:ea:d4:58:07:3c:01:e0:1a:
  58. 53:54:66:e1:a3:7e:30:cd:3b:f8:69:59:a3:48:92:48:e1:9e:
  59. 63:ab:08:70:91:f2:48:d2:83:4b:98:06:fa:fd:bc:99:02:da:
  60. 9c:98:b1:a3

基于x509 标准的证书的公钥读取方式如下

1   从证书中获取公钥对象,然后从公钥对象获取base64编码公钥字符串的方法

  1. CertificateFactory cf = CertificateFactory.getInstance("X.509");
  2. X509Certificate cert = (X509Certificate)cf.generateCertificate(new FileInputStream("my.cer"));
  3. PublicKey publicKey = cert.getPublicKey();
  4. BASE64Encoder base64Encoder=new BASE64Encoder();
  5. String publicKeyString = base64Encoder.encode(publicKey.getEncoded());
  6. System.out.println("-----------------公钥--------------------");
  7. System.out.println(publicKeyString);
  8. System.out.println("-----------------公钥--------------------");
  9. ---------------------

或者 

  1. URL url = Demo.class.getClassLoader().getResource("C000024.crt"); //证书路径
  2. System.out.println("公钥所在路径:"+url.getFile());
  3. X509Certificate cert = X509Certificate.getInstance(new FileInputStream(url.getFile()));
  4. PublicKey publicKey = cert.getPublicKey();
  5. BASE64Encoder base64Encoder=new BASE64Encoder();
  6. String publicKeyString = base64Encoder.encode(publicKey.getEncoded());
  7. System.out.println("-----------------公钥--------------------");
  8. System.out.println(publicKeyString);
  9. System.out.println("-----------------公钥--------------------");

说明:因为只做示例,没有进行异常处理和流的释放,方式1的代码可能少点,方式2需要强转,美观上可能方式1更好看点,但方式1的实质还是调用的方式2,方式2内部有实现缓存策略.更多可以参考下api文档,文档上有提供示例.

 

证书格式

  • PKI ITU-T X509标准,传统标准(.der .pem .cer .crt),仅包含公钥
  • PKCS#7 加密消息语法标准(.p7b .p7c .spc .p7r),p7b/p7c/spc 包含了证书链,p7r是证书请求回复(非证书)
  • PKCS#10 证书请求标准(.p10),.p10是证书请求文件,与.csr文件类似
  • PKCS#12 个人信息交换标准(.pfx *.p12),包含公钥和私钥,需密码保护

编码形式

  • X.509 DER(Distinguished Encoding Rules)编码,后缀为:.der .cer .crt
  • X.509 BASE64编码(PEM格式),后缀为:.pem .cer .crt

X.509CRT-PEM

  1. -----BEGIN CERTIFICATE-----
  2. BASE64 ENCODED DATA
  3. -----END CERTIFICATE-----

关键特性

  • 编码形式:二进制还是ASCII
  • 是否包含公钥、私钥
  • 包含一个还是多个证书
  • 是否支持密码保护(针对当前证书)

 

最后说一下,如何从秘钥库中读取 公钥,私钥

1获取秘钥库

  1. public static KeyStore getKeyInfo(String pfxkeyfile, String keypwd,
  2. String type) throws IOException {
  3. LogUtil.writeLog("加载签名证书==>" + pfxkeyfile);
  4. FileInputStream fis = null;
  5. try {
  6. KeyStore ks = null;
  7. if ("JKS".equals(type)) {
  8. ks = KeyStore.getInstance(type);
  9. } else if ("PKCS12".equals(type)) {
  10. String jdkVendor = System.getProperty("java.vm.vendor");
  11. String javaVersion = System.getProperty("java.version");
  12. LogUtil.writeLog("java.vm.vendor=[" + jdkVendor + "]");
  13. LogUtil.writeLog("java.version=[" + javaVersion + "]");
  14. // Security.addProvider(new org.bouncycastle.jce.provider.BouncyCastleProvider());
  15. if (null != jdkVendor && jdkVendor.startsWith("IBM")) {
  16. // 如果使用IBMJDK,则强制设置BouncyCastleProvider的指定位置,解决使用IBMJDK时兼容性问题
  17. Security.insertProviderAt(
  18. new org.bouncycastle.jce.provider.BouncyCastleProvider(),
  19. 1);
  20. printSysInfo();
  21. }else{
  22. Security.addProvider(new org.bouncycastle.jce.provider.BouncyCastleProvider());
  23. }
  24. // ks = KeyStore.getInstance(type, "BC");
  25. ks = KeyStore.getInstance(type);
  26. }
  27. LogUtil.writeLog("Load RSA CertPath=[" + pfxkeyfile + "],Pwd=["
  28. + keypwd + "]");
  29. fis = new FileInputStream(pfxkeyfile);
  30. char[] nPassword = null;
  31. nPassword = null == keypwd || "".equals(keypwd.trim()) ? null
  32. : keypwd.toCharArray();
  33. if (null != ks) {
  34. ks.load(fis, nPassword);
  35. }
  36. return ks;
  37. } catch (Exception e) {
  38. if (Security.getProvider("BC") == null) {
  39. LogUtil.writeLog("BC Provider not installed.");
  40. }
  41. LogUtil.writeErrorLog("getKeyInfo Error", e);
  42. if ((e instanceof KeyStoreException) && "PKCS12".equals(type)) {
  43. Security.removeProvider("BC");
  44. }
  45. return null;
  46. }finally{
  47. if(null!=fis)
  48. fis.close();
  49. }
  50. }

2 获取公钥信息

  1. public static PublicKey getSignPublicKey() {
  2. try {
  3. Enumeration<String> aliasenum = keyStore.aliases();
  4. String keyAlias = null;
  5. if (aliasenum.hasMoreElements()) // we are readin just one
  6. // certificate.
  7. {
  8. keyAlias = (String) aliasenum.nextElement();
  9. }
  10. Certificate cert = keyStore.getCertificate(keyAlias);
  11. PublicKey pubkey = cert.getPublicKey();
  12. return pubkey;
  13. } catch (Exception e) {
  14. LogUtil.writeErrorLog(e.toString());
  15. return null;
  16. }
  17. }

3获取私钥信息

PrivateKey privateKey = (PrivateKey) keystore.getKey(keyAlias, certPwd.toCharArray());

 

理解服务器证书 CA&SSL

正规流程:去CA机构申请SSL证书

域名型https证书(DVSSL):信任等级一般,只需验证网站的真实性便可颁发证书保护网站;

 

企业型https证书(OVSSL):信任等级高,须要验证企业的身份,审核严格,安全性更强;

 

增强型https证书(EVSSL):信任等级最高,一般用于银行证券等金融机构,审核严格,安全性最好,同时可以激活绿色网址栏

 

1. CA证书理解?CA证书的作用?

CA证书顾名思义就是由CA(Certification Authority)机构发布的数字证书。要对CA证书完全理解及其作用,首先要理解SSL。SSL(security sockets layer,安全套接层)是为网络通信提供安全及数据完整性的一种安全协议。SSL3.0版本以后又被称为TLS。SSL位于TCP与各应用层之间,是操作系统向外提供的API。SSL如何保证网络通信的安全和数据的完整性呢?就是采用了两种手段:身份认证和数据加密。首先身份认证就需要用到CA证书了。先了解CA证书具体包括哪些内容:

颁发者 
使用者 
版本 
签名算法 
签名哈希算法 
使用者 
公钥 
指纹 
指纹算法 
…… 
上述中颁发者、使用者、版本等内容好理解,颁发者就是CA机构,下面会讲到。对于签名算法、签名哈希算法的理解,首先要先理解签名是什么东东?联系到实际情况,当我们向某机构提供报告时,往往在报告最后加上个人的名字,以表示该报告是我本人的。签名在网络通讯中的应用称为数字签名,当服务器向客户端发送信息时,会将报文生成报文摘要,同时对报文摘要进行hash计算,得到hash值,然后对hash值进行加密,然后将加密的hash值放置在报文后面,这个加密后的hash值就称为签名。服务器将报文、签名和数字证书一同发送给客户端。客户端收到这些信息后,会首先验证签名,利用签名算法对签名进行解密,得到报文摘要的hash值,然后将得到的报文生成报文摘要并利用签名hash算法生成新的hash值,通过对比这两个hash值是否一致,就能判断信息是否完整,是否是由真正的服务器发送的。可知签名有两个作用确认消息发送方可靠,确认消息完整准确。

上面提到了hash值的加密,我们还需要理解SSL的加密机制,在使用SSL的网络通讯过程中,消息在请求和响应中都是加密传送的。首先要知道加密算法分为两种:对称加密和非对称加密。对称加密就是发送双发使用相同的密钥对消息进行加解密,常见的对称加密为DES、3DES,AES等。非对称加密是发送双方各自拥有一对公钥私钥,其中公钥是公开的,私钥是保密的。当发送方向接收方发送消息时,发送方利用接收方的公钥对消息进行加密,接收方收到消息后,利用自己的私钥解密就能得到消息的明文。其中非对称加密方法有RSA、Elgamal、ECC等。此处只是简单了说明了这两种加密机制的过程,若要深入理解它们的原理、过程请搜索相应的资料,很容易搜索到。

好了,了解了签名原理和两种加密机制,我们继续理解网络通讯中是怎么利用CA证书进行身份认证的?客户端与服务端需要经过一个握手的过程才能完成身份认证,建立一个安全的连接。握手的过程如下:

  1. 客户端访问服务器(比如:https://www.12306.cn),发送ssl版本、客户端支持的加密算法、随机数等消息。
  2. 服务器向客户端发送ssl版本、随机数、加密算法、证书(证书出现了)等消息。
  3. 客户端收到消息后,判断证书是否可信(如何判断可信,看下文介绍),若可信,则继续通信,发送消息包括:向服务器发送一个随机数,从证书中获取服务器端的公钥,对随机数加密;编码改变通知,表示随后信息都将使用双方协定的加密方法和密钥发送;客户端握手结束通知。
  4. 服务器端对数据解密得到随机数,发送消息:编码改变通知,表示随后信息都将使用双方协定的加密方法和密钥发送。

以上就是整个握手的过程,在第三步实际上就完成了身份的认证,第四、五步是进行密钥的商定,因为非对称加密算法对数据加密非常慢,效率低,而对称加密加密效率很高,因此在整个握手过程要生成一个对称加密密钥,然后数据传输中使用对称加密算法对数据加密。可知ssl整个握手过程包括身份认证、密钥商定。上述讲述ssl的握手过程比较简单,想要深入理解ssl原理,下面这篇博文讲的不错: 
https://segmentfault.com/a/1190000002554673 
一定要看上面的博文,否则无法彻底理解证书使用的原理。

2.客户端是如何验证CA证书是可信任的?

一般来说,现在公共网站数据传输都是使用SSL,即通过https协议访问。Https就是http加SSL。在上面SSL握手过程中,客户端是如何验证服务器发送的CA证书呢?我们以12306网站为例进行说明,此时,客户端就是浏览器,如果我们是第一次访问12306网站,使用https://www.12306.cn地址访问,返回如下结果: 
这里写图片描述

提示此网站的安全证书有问题,说明证书不可信,如果我们忽略证书不可信,继续访问网站,打开12306网页,在首页提供一个根证书的下载,见下页面:

这里写图片描述

下载根证书,安装完毕,再次访问12036网站,就不会提示网站的安全证书有问题了。这是什么机制呢?

打开【工具】菜单(360浏览器为例),然后选择【内容】选项卡,点击【证书】按钮,打开证书窗口,选择【中级证书颁发机构】,会看到已经安装的12306的证书:

这里写图片描述

只要安装上12306证书,就说明证书是可信的。使用https协议访问时,服务器发送证书向浏览器时,首先查找该证书是否已在信任列表中,然后对证书进行校验,校验成功,那么就证明证书是可信的。另外,证书的认证是安装证书链执行的,证书链的意思是有一个证书机构A,A生成证书B,B也可以生成证书C,比如在证书窗口中有一个360证书,见下图:

这里写图片描述

360证书的颁发者是certification authority of wosign,在【受信任的根证书颁发机构】中,我们会看到该证书:见下图,

这里写图片描述

也就是说,certification authority of wosign生成360证书,360可以生成其它的证书。A证书或者certification authority of wosign证书在整个证书链上就被称为根证书,证书验证的机制是只要根证书是受信任的,那么它的子证书都是可信的。比如说,我们使用https协议访问了需要360证书的网站,即使我们不安装360证书,那么网站也不会提示证书不安全,因为,生成360证书的根证书certification authority of wosign证书,在受信任的证书列表中。如果一个证书的根证书是不可信的,那么这个证书肯定也是不可信任的。

由以上可知,根证书在证书验证中极其重要,而且,根证书是无条件信任的,只要我们将根证书安装上,就说明我们对根证书是信任的。比如我们安装12306的根证书,是出于我们对国家的信任,对网站的信任,我们才放心安装这个根证书。对于一些不安全的网站的证书,一定要慎重安装

另外需要知道的是,【受信任的根证书颁发机构】中的证书是windows预先安装的一些证书,都是国际上很有权威的证书机构,他们证书的生成都有很严格的流程,因此他们的证书被认为是安全,就像我们相信银行是安全,所以把钱存入到银行。

3.有哪些CA机构?

世界上较早的数字认证中心是美国的verisign公司,在windows的证书窗口中可以看到好多verisign公司生成的证书,见下图:

这里写图片描述

另外还有加拿大的ENTRUST公司,也是很著名的证书机构。中国的安全认证体系分为金融CA和非金融CA。在金融CA方面,根证书由中国人民银行管理,在非金融CA方面,由中国电信负责。中国CA又可分为行业性CA和区域性CA,行业性CA中影响最大是中国金融认证中心和中国电信认证中国;区域性CA主要是以政府为背景,以企业机制运行,其中广东CA中心和上海CA中影响最大。

4java 获取根证书列表

  1. import java.io.File;
  2. import java.io.FileInputStream;
  3. import java.io.IOException;
  4. import java.security.InvalidAlgorithmParameterException;
  5. import java.security.KeyStore;
  6. import java.security.KeyStoreException;
  7. import java.security.NoSuchAlgorithmException;
  8. import java.security.cert.CertificateException;
  9. import java.security.cert.PKIXParameters;
  10. import java.security.cert.TrustAnchor;
  11. import java.security.cert.X509Certificate;
  12. import java.util.Iterator;
  13. public class Main {
  14. public static void main(String[] args) {
  15. try {
  16. // Load the JDK's cacerts keystore file
  17. String filename = System.getProperty("java.home") + "/lib/security/cacerts".replace('/', File.separatorChar);
  18. FileInputStream is = new FileInputStream(filename);
  19. KeyStore keystore = KeyStore.getInstance(KeyStore.getDefaultType());
  20. String password = "changeit";
  21. keystore.load(is, password.toCharArray());
  22. // This class retrieves the most-trusted CAs from the keystore
  23. PKIXParameters params = new PKIXParameters(keystore);
  24. // Get the set of trust anchors, which contain the most-trusted CA certificates
  25. Iterator it = params.getTrustAnchors().iterator();
  26. while( it.hasNext() ) {
  27. TrustAnchor ta = (TrustAnchor)it.next();
  28. // Get certificate
  29. X509Certificate cert = ta.getTrustedCert();
  30. System.out.println(cert);
  31. }
  32. } catch (CertificateException e) {
  33. } catch (KeyStoreException e) {
  34. } catch (NoSuchAlgorithmException e) {
  35. } catch (InvalidAlgorithmParameterException e) {
  36. } catch (IOException e) {
  37. }
  38. }
  39. }

 

 

 

5.自签名证书的如何生成、安装?

有时候,我们在内部系统传输数据需要使用SSL协议,对数据加密,但是我们又不想花钱去申请CA,这个时候可以使用自签名CA,实现数据加密传输的功能。首先要明确一点就是自签名证书是不安全的,存在安全漏洞,具体看下面的博文介绍:

为什么”自签名SSL证书”不安全? 
https://www.wosign.com/FAQ/selfsigned_SSL_insecure.htm

自签名证书使用jdk中的keytool生成即可,看似神秘,但实际上比较简单,见下博文:

如何利用keytool工具生成数字证书 
https://jingyan.baidu.com/article/b0b63dbfe18eff4a483070f4.html

自签名证书的安装也很简单,见下博文:

添加自签发的 SSL 证书为受信任的根证书 
https://cnzhx.net/blog/self-signed-certificate-as-trusted-root-ca-in-windows/

在java编程中,使用socket网络编程,实现SSL协议,对服务器的证书需要导入到客户端的秘钥库中,这样才能完成自动认证,具体实现见下博文:

JAVA SSL SOCKET通信服务器端客户端证书双向认证 
http://blog.csdn.net/matt8/article/details/45071815

声明:本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有侵权的内容,请联系我们。转载请注明出处:【wpsshop博客】
推荐阅读
相关标签
  

闽ICP备14008679号