数字证书应用综合揭秘(包括证书生成、加密、解密、签名、验签)

引言

创新互联建站是一家专业提供五台企业网站建设,专注与网站制作、做网站、H5建站、小程序制作等业务。10年已为五台众多企业、政府机构等服务。创新互联专业网络公司优惠进行中。

数字证书是一个经证书授权中心数字签名的包含公开密钥拥有者信息以及公开密钥的文件。为现实网络安全化标准如今大部分的 B2B、B2C、P2P、O2O 等商业网站含有重要企业资料个人资料的信息资信网站政府机构金融机构等服务网站大部分都使用了数字证书来加强网络的安全性。
数字证书一般由经过国家认证的权威机构颁发即CA例如中国各地方的CA公司中心签发的证书也可以由企业级CA系统进行签发例如Symantec、ResellerClub、数安时代等。开发人员也可以通过工具自动生成证书进行开发但不经过认证的证书将被视为无效证书不保安全保护但仍可正常运行。
在这篇文章里将为大家介绍数字证书的生成使用过程以及对数据进行加密、解密、签名、验签的使用方式。
希望能对各位的学习研究有所帮助当中有所错漏的地方敬请点评。

 

 

目录

一、数字证书介绍

二、加密算法介绍

三、生成数字证书的方式

四、获取公钥与私钥

五、数字证书加密与解密

六、数字证书签名与验签

 

 

 

一、数字证书介绍

 

1.1 什么是数字证书

数字证书就是互联网通讯中标志通讯各方身份信息的一串数字提供了一种在Internet上验证通信实体身份的方式数字证书不是数字×××而是身份认证机构盖在数字×××上的一个章或印或者说加在数字×××上的一个签名。它是由权威机构——CA机构又称为证书授权Certificate Authority中心发行的人们可以在网上用它来识别对方的身份。

最简单的证书包含密钥、名称以及证书授权中心的数字签名。数字证书还有一个重要的特征就是只在特定的时间段内有效。数字证书是一种权威性的电子文档可以由权威公正的第三方机构即CA例如中国各地方的CA公司中心签发的证书也可以由企业级CA系统进行签发。

 

数字证书应用综合揭秘(包括证书生成、加密、解密、签名、验签)

图 V.1.1

1.2 数字证书的分类

从数字签名使用对象的角度分目前的数字证书类型主要包括个人×××书、企业或机构×××书、支付网关证书、服务器证书、安全电子邮件证书、个人代码签名证书这些数字证书特点各有不同。

  • 个人×××书

符合 X.509 标准的数字安全证书证书中包含个人身份信息和个人的公钥用于标识证书持有人的个人身份。数字安全证书和对应的私钥存储于 E-key  中用于个人在网上进行合同签定、定单、录入审核、操作权限、支付信息等活动中标明身份。 

  • 企业或机构×××书

符合 X.509 标准的数字安全证书证书中包含企业信息和企业的公钥用于标识证书持有企业的身份。数字安全证书和对应的私钥存储于 E-key 或 IC 卡中可以用于企业在电子商务方面的对外活动如合同签定、网上证券交易、交易支付信息等方面。 

  • 支付网关证书

支付网关证书是证书签发中心针对支付网关签发的数字证书是支付网关实现数据加解密的主要工具用于数字签名和信息加密。支付网关证书仅用于支付网关提供的服务Internet 上各种安全协议与银行现有网络数据格式的转换。支付网关证书只能在有效状态下使用。支付网关证书不可被申请者转让。 

  • 服务器证书

符合 X.509 标准的数字安全证书证书中包含服务器信息和服务器的公钥在网络通讯中用于标识和验证服务器的身份。数字安全证书和对应的私钥存储于 E-key 中。服务器软件利用证书机制保证与其他服务器或客户端通信时双方身份的真实性、安全性、可信任度等。 

  • 企业或机构代码签名证书

代码签名证书是 CA 中心签发给软件提供商的数字证书包含软件提供商的身份信息、公钥及 CA 的签名。软件提供商使用代码签名证书对软件进行签名后放到 Internet 上当用户在 Internet 上下载该软件时将会得到提示从而可以确信软件的来源软件自签名后到下载前没有遭到修改或破坏。代码签名证书可以对 32-bit .exe 、 .cab 、 .ocx 、 .class 等程序和文件 进行签名。 

  • 安全电子邮件证书

符合 X.509 标准的数字安全证书通过 IE 或 Netscape 申请用 IE 申请的证书存储于 WINDOWS 的注册表中用 NETSCAPE  申请的存储于个人用户目录下的文件中。用于安全电子邮件或向需要客户验证的 WEB 服务器(https 服务) 表明身份。

  • 个人代码签名证书

个人代码签名证书是 CA 中心签发给软件提供人的数字证书包含软件提供个人的身份信息、公钥及 CA 的签名。软件提供人使用代码签名证书对软件进行签名后放到 Internet 上当用户在 Internet 上下载该软件时将会得到提示从而可以确信软件的来源软件自签名后到下载前没有遭到修改或破坏。代码签名证书可以对 32-bit .exe 、 .cab 、 .ocx 、 .class 等程序和文件进行签名。

从数字证书的技术角度分CA中心发放的证书分为两类SSL证书和SET证书。一般地说SSL 证书安全套接层是服务于银行对企业或企业对企业的电子商务活动的而SET安全电子交易证书则服务于持卡消费、网上购物。虽然它们都是用于识别身份和数字签名的证书但它们的信任体系完全不同而且所符合的标准也不一样。

 

1.3 数字证书的格式

证书主要的文件类型和协议有: PEM、DER、PFX、JKS、KDB、CER、KEY、CSR、CRT、CRL 、OCSP、SCEP等。

1.3.1 PEM 格式

Openssl使用 PEM(Privacy Enhanced Mail)格式来存放各种信息,它是 openssl 默认采用的信息存放方式。Openssl 中的 PEM 文件一般包含如下信息:
内容类型:表明本文件存放的是什么信息内容,它的形式为“——-BEGIN XXXX ——”,与结尾的“——END XXXX——”对应。
头信息:表明数据是如果被处理后存放,openssl 中用的最多的是加密信息,比如加密算法以及初始化向量 iv。
信息体:为 BASE64 编码的数据。可以包括所有私钥RSA 和 DSA、公钥RSA 和 DSA和 (x509) 证书。它存储用 Base64 编码的 DER 格式数据用 ascii 报头包围因此适合系统之间的文本模式传输。
使用PEM格式存储的证书

-----BEGIN CERTIFICATE-----
MIIF6TCCBNGgAwIBAgIQSSOR8EYFvAGtG16qv0lZ4DANBgkqhkiG9w0BAQsFADBC
MQswCQYDVQQGEwJVUzEWMBQGA1UEChMNR2VvVHJ1c3QgSW5jLjEbMBkGA1UEAxMS
UmFwaWRTU0wgU0hBMjU2IENBMB4XDTE3MDQyNDAwMDAwMFoXDTE5MDQyNDIzNTk1
OVowITEfMB0GA1UEAwwWc2VjdXJpdHkucHVqaW53YW5nLmNvbTCCASIwDQYJKoZI
hvcNAQEBBQADggEPADCCAQoCggEBANrPWriCfyigreL9cVAyEPesYScRd176xhH0
.............
-----END CERTIFICATE-----


使用PEM格式存储的私钥

-----BEGIN RSA PRIVATE KEY-----
MIIF6TCCBNGgAwIBAgIQSSOR8EYFvAGtG16qv0lZ4DANBgkqhkiG9w0BAQsFADBC
MQswCQYDVQQGEwJVUzEWMBQGA1UEChMNR2VvVHJ1c3QgSW5jLjEbMBkGA1UEAxMS
UmFwaWRTU0wgU0hBMjU2IENBMB4XDTE3MDQyNDAwMDAwMFoXDTE5MDQyNDIzNTk1
OVowITEfMB0GA1UEAwwWc2VjdXJpdHkucHVqaW53YW5nLmNvbTCCASIwDQYJKoZI
hvcNAQEBBQADggEPADCCAQoCggEBANrPWriCfyigreL9cVAyEPesYScRd176xhH0
.............
-----END RSA PRIVATE KEY-----


使用PEM格式存储的证书请求文件

-----BEGIN CERTIFICATE REQUEST-----
MIIF6TCCBNGgAwIBAgIQSSOR8EYFvAGtG16qv0lZ4DANBgkqhkiG9w0BAQsFADBC
MQswCQYDVQQGEwJVUzEWMBQGA1UEChMNR2VvVHJ1c3QgSW5jLjEbMBkGA1UEAxMS
UmFwaWRTU0wgU0hBMjU2IENBMB4XDTE3MDQyNDAwMDAwMFoXDTE5MDQyNDIzNTk1
OVowITEfMB0GA1UEAwwWc2VjdXJpdHkucHVqaW53YW5nLmNvbTCCASIwDQYJKoZI
hvcNAQEBBQADggEPADCCAQoCggEBANrPWriCfyigreL9cVAyEPesYScRd176xhH0
.............
-----END&~bsp;KETIFICATE REQUEST-----


1.3.2 DER 格式

辨别编码规则 (DER) 可包含所有私钥、公钥和证书。它是大多数浏览器的缺省格式并按 ASN1 DER 格式存储。它是无报头的  PEM 是用文本报头包围的 DER。
PFX 或 P12 – 公钥加密标准 #12 (PKCS#12) 可包含所有私钥、公钥和证书。其以二进制格式存储也称为 PFX 文件。通常可以将Apache/OpenSSL使用的“KEY文件 + CRT文件”格式合并转换为标准的PFX文件你可以将PFX文件格式导入到微软IIS 5/6、微软ISA、微软Exchange Server等软件。转换时需要输入PFX文件的加密密码。

1.3.3 JKS格式

通常可以将Apache/OpenSSL使用的“KEY文件 + CRT文件”格式”转换为标准的Java Key Store(JKS)文件。JKS文件格式被广泛的应用在基于Java的WEB服务器、应用服务器、中间件。你可以将JKS文件导入到TOMCAT、 WEBLOGIC 等软件。

1.3.4 KDB格式

通常可以将Apache/OpenSSL使用的“KEY文件 + CRT文件”格式转换为标准的IBM KDB文件。KDB文件格式被广泛的应用在IBM的WEB服务器、应用服务器、中间件。你可以将KDB文件导入到IBM HTTP Server、IBM Websphere 等软件。

1.3.5 CSR 格式证书请求文件 Certificate Signing Request)

生成 X509 数字证书前,一般先由用户提交证书申请文件,然后由 CA 来签发证书。大致过程如下(X509 证书申请的格式标准为 pkcs#10 和 rfc2314):
用户生成自己的公私钥对;
构造自己的证书申请文件,符合 PKCS#10 标准。该文件主要包括了用户信息、公钥以及一些可选的属性信息,并用自己的私钥给该内容签名;
用户将证书申请文件提交给 CA;
CA 验证签名,提取用户信息,并加上其他信息(比如颁发者等信息),用 CA 的私钥签发数字证书;
说明:数字证书(如x.509)是将用户(或其他实体)身份与公钥绑定的信息载体。一个合法的数字证书不仅要符合 X509 格式规范,还必须有 CA的签名。用户不仅有自己的数字证书,还必须有对应的私钥。X509v3数字证书主要包含的内容有:证书版本、证书序列号、签名算法、颁发者信息、有效时间、持有者信息、公钥信息、颁发者 ID、持有者 ID 和扩展项。

1.3.6 OCSP格式在线证书状态协议 Online Certificate StatusProtocol,rfc2560)

用于实时表明证书状态。OCSP 客户端通过查询 OCSP服务来确定一个证书的状态,可以提供给使用者一个或多个数字证书的有效性资料它建立一个可实时响应的机制让用户可以实时确认每一张证书的有效性解决由CRL引发的安全问题。。OCSP 可以通过 HTTP协议来实现。rfc2560 定义了 OCSP 客户端和服务端的消息格式。

1.3.7 CRL格式证书吊销列表 Certification Revocation List)

是一种包含撤销的证书列表的签名数据结构。CRL是证书撤销状态的公布形式,CRL 就像信用卡的黑名单,用于公布某些数字证书不再有效。CRL是一种离线的证书状态信息。它以一定的周期进行更新。CRL 可以分为完全 CRL和增量 CRL。在完全 CRL中包含了所有的被撤销证书信息,增量 CRL 由一系列的 CRL 来表明被撤销的证书信息,它每次发布的 CRL 是对前面发布 CRL的增量扩充。基本的 CRL 信息有:被撤销证书序列号、撤销时间、撤销原因、签名者以及 CRL 签名等信息。基于 CRL的验证是一种不严格的证书认证。CRL 能证明在 CRL 中被撤销的证书是无效的。但是,它不能给出不在 CRL中的证书的状态。如果执行严格的认证,需要采用在线方式进行认证,即 OCSP认证。一般是由CA签名的一组电子文档包括了被废除证书的唯一标识证书序列号CRL用来列出已经过期或废除的数字证书。它每隔一段时间就会更新因此必须定期下茇该轻祬才会取得最新信息。

1.3.8 SCEP 简单证书注册协议

基于文件的证书登记方式需要从您的本地计算机将文本文件复制和粘贴到证书发布中心和从证书发布中心复制和粘贴到您的本地计算机。 SCEP可以自动处理这个过程但是CRLs仍然需要手工的在本地计算机和CA发布中心之间进行复制和粘贴。

1.3.9 PKCS7 加密消息语法(pkcs7)

是各种消息存放的格式标准。这些消息包括:数据、签名数据、数字信封、签名数字信封、摘要数据和加密数据。

1.3.10 PKCS12 (个人数字证书标准Public Key Cryptography Standards #12)

包含了公钥和私钥的二进制格式的证书形式一般以 pfx 作为证书文件后缀名。用于存放用户证书、crl、用户私钥以及证书链pkcs12 中的私钥J羌用湸娴诺摹

1.3.11 CER   一般指使用DER格式的证书

CER 证书一般是以 DER 二进制编码的证书证书中没有私钥以 *.cer 作为证书文件后缀名。证书可以以 BASE64 编码输出以Base64 编码的证书证书中没有私钥BASE64 编码格式的证书文件也是以 *.cer 作为证书文件后缀名。

1.3.12 CRT    证书文件可以是PEM格式

1.3.13 KEY   一般指PEM格式的私钥文件

回到目录

 

二、加密算法介绍

在生成数据证书是用户可选择不同的加密方式对数据进行加密常见的加密算法可以分成三类对称加密算法非对称加密算法和Hash算法。

2.1 对称加密

在对称加密算法中加密使用的密钥和解密使用的密钥是相同的。也就是说加密和解密都是使用的同一个密钥。因此对称加密算法要保证安全性的话密钥要做好保密只能让使用的人知道不能对外公开。在对称加密算法中加密和解密都是使用同一个密钥不区分公钥和私钥。

对称加密算法的优点在于加解密的高速度和使用长密钥时的难破解性。假设两个用户需要使用对称加密方法加密然后交换数据则用户最少需要2个密钥并交换使用如果企业内用户有n个则整个企业共需要n×(n-1) 个密钥密钥的生成和分发将成为企业信息部门的恶梦。对称加密算法的安全性取决于加密密钥的保存情况但要求企业中每一个持有密钥的人都保守秘密是不可能的他们通常会有意无意的把密钥泄漏出去——如果一个用户使用的密钥被***者所获得***者便可以读取该用户密钥加密的所有文档如果整个企业共用一个加密密钥那整个企业文档的保密性便无从谈起。

常见的对称加密算法DES、3DES、DESX、Blowfish、IDEA、RC4、RC5、RC6和AES。
DES是一种分组数据加密技术先将数据分成固定长度的小数据块之后进行加密速度较快适用于大量数据加密而3DES是一种基于DES的加密算法使用3个不同密匙对同一个分组数据块进行3次加密如此以使得密文强度更高。
相较于DES和3DES算法而言AES算法有着更高的速度和资源使用效率安全级别也较之更高了被称为下一代加密标准。

2.2 非对称加密

在非对称加密算法中加密使用的密钥和解密使用的密钥是不相同的也称为公私钥加密也就是说加密使用的密钥和解密使用的密钥不同。

假设两个用户要加密交换数据双方交换公钥使用时一方用对方的公钥加密另一方即可用自己的私钥解密。如果企业中有n个用户企业需要生成n对密钥并分发n个公钥。由于公钥是可以公开的用户只要保管好自己的私钥即可因此加密密钥的分发将变得十分简单。同时由于每个用户的私钥是唯一的其他用户除了可以可以通过信息发送者的公钥来验证信息的来源是否真实还可以确保发送者无法否认曾发送过该信息。非对称加密的缺点是加解密速度要远远慢于对称加密在某些极端情况下甚至能比非对称加密慢上1000倍。

常见的非对称加密算法RSA、ECC移动设备用、Diffie-Hellman、El Gamal、DSA数字签名用。
RSA和DSA的安全性及其它各方面性能都差不多而ECC较之则有着很多的性能优越包括处理速度带宽要求存储空间等等。

2.3 Hash算法

Hash算法特别的地方在于它是一种单向算法用户可以通过Hash算法对目标信息生成一段特定长度的唯一的Hash值却不能通过这个Hash值重新获得目标信息。因此Hash算法常用在不可还原的密码存储、信息完整性校验等。

常见的Hash算法MD2、MD4、MD5、HAVAL、SHA、SHA-1、HMAC、HMAC-MD5、HMAC-SHA1。
这几种算法只生成一串不可逆的密文经常用其效验数据传输过程中是否经过修改因为相同的生成算法对于同一明文只会生成唯一的密文若相同算法生成的密文不同则证明传输数据进行过了修改。通常在数据传说过程前使用MD5和SHA1算法均需要发送和接收数据双方在数据传送之前就知道密匙生成算法而HMAC与之不同的是需要生成一个密匙发送方用此密匙对数据进行摘要处理生成密文接收方再利用此密匙对接收到的数据进行摘要处理再判断生成的密文是否相同。
加密算法的效能通常可以按照算法本身的复杂程度、密钥长度密钥越长越安全、加解密速度等来衡量。上述的算法中除了DES密钥长度不够、MD2速度较慢已逐渐被淘汰外其他算法仍在目前的加密系统产品中使用。

 

回到目录

三、生成数字证书的方式

数字证书可以通过在线工具脚本代码KEYTOOL工具OPEN SSL工具等多种方式生成。下面以常用的RSA非对称加密为例子向大家介绍几种常用的数字证书生成方式。

3.1 利用KEYTOOL工具生成数字证书

KEYTOOL 是个密钥和证书管理工具可以在 JAVA 环境下管理安全钥匙与证书的生成与安装。它还是一个有效的安全钥匙和证书的管理工具使用户能够管理自己的公钥/私钥对及相关证书。它管理一个存储了私有钥匙和验证相应公共钥匙的与它们相关联的X.509 证书链的keystore(相当一个数据库里面可存放多个X.509标准的证书)。能够使用户使用数字签名来管理他们自己的私有/公共钥匙对,管理用来作自我鉴定的相关的证书,管理数据完整性和鉴冬服务‖能使用户在通信时缓存它们的公共钥匙。

3.1.1 KEYTOOL命令介绍

KEYTOOL通是以keytool开关当中常用命令有: 

keytool -genkey -alias casserver -keypass cas123 -keyalg RSA -keystore casserver.keystore -validity 365
keytool -export -alias casserver -storepass cas123 -file casserver.cer -keystore casserver.keystore
keytool -import -trustcacerts -alias casserver -storepass cas123 -file casserver.cer –keystore cacerts
  • -genkey      在用户主目录中创建一个默认文件".keystore",还会产生一个mykey的别名mykey中包含用户的公钥、私钥和证书
    在没有指定生成位置的情况下,keystore会存在用户系统默认目录如对于window xp系统会生成在系统的C:/Documents and Settings/UserName/文件名为“.keystore”

  • -alias       产生别名  -keystore 指定密钥库的名称(产生的各类信息将不在.keystore文件中)  -keyalg  指定密钥的算法 (如 RSA  DSA如果不指定默认采用DSA)

  • -validity    指定创建的证书有效期多少天-keysize     指定密钥长度

  • -storepass   指定密钥库的密码(获取keystore信息所需的密码)

  • -keypass     指定别名条目的密码(私钥的密码)

  • -dname       指定证书拥有者信息 
    例如  "CN=名字与姓氏,OU=组织单位名称,O=组织名称,L=城市或区域名称,ST=州或省份名称,C=单位的两字母国家代码"

  • -list        显示密钥库中的证书信息      
    例如 keytool -list -v -keystore 是指定 keystore -storepass 密码 -v 显示密钥库中的证书详细信息

  • -export      将别名指定的证书导出到文件  
    例如keytool -export -alias 需要导出的别名 -keystore 指定keystore -file 指定导出的证书位置及证书名称 -storepass 密码

  • -file            参数指定导出到文件的文件名

  • -delete       删除密钥库中某条目    
    例如keytool -delete -alias 指定需删除的别  -keystore 指定keystore  -storepass 密码

  • -printcert   查看导出的证书信息     
    例如keytool -printcert -file leslie.crt

  • -keypasswd   修改密钥库中指定条目口令    
    例如keytool -keypasswd -alias 需修改的别名 -keypass 旧密码 -new  新密码  -storepass keystore密码  -keystore sage

  • -storepasswd 修改keystore口令      
    例如keytool -storepasswd -keystore c:/leslie.keystore(需修改口令的keystore) -storepass 123456(原始密码) -new 888888(新密码)

  • -import      将已签名数字证书导入密钥库 
    理萭 keytool -import -alias 指定导入条目的别名 -keystore 指定keystore -file 需导入的证书

3.1.2 生成 *.keystore 文件流程

首先执行以下命令分别输入密钥库口令、姓名单位组织城市省份国家等信息经确认后生成对应的 leslie.keystore 文件。注意 *.keystore 文件相当于一个资源库后面的公钥、私钥、证书等都依赖于它生成必须谨慎保管。

keytool -genkey -alias everygold -keypass 123456 -keyalg RSA -keystore leslie.keystore -validity 365

提示  -alias指定别名为 everygold -keyalg 指定 RSA 算法-keypass 指定私钥密码为123456
             -keystore 指定密钥文件名称为 leslie.keystore-validity指定有效期为365天。

数字证书应用综合揭秘(包括证书生成、加密、解密、签名、验签)

 

3.1.3 生成数字证书

根据上述生成的 leslie.keystore 文件执行以下命令就可以生成数字证书 leslie.cer

keytool -export -alias everygold -storepass 123456 -file leslie.cer -keystore leslie.keystore

提示  -alias 指定别名为 everygold -storepass 指定私钥为 123456
            -file 指定导出证书的文件名为 leslie.cer-keystore 指定之前生成的密钥文件的文件名

注意 -alias 和- storepass 必须为生成 leslie.keystore 密钥文件时所指定的别名和密码一致否则证书导出失败

生成证书 

数字证书应用综合揭秘(包括证书生成、加密、解密、签名、验签)

若需要获取 BASE64 或 DER 证书可以使用导出功能在图片上按 “复制到文件”选择文件格式即可。

数字证书应用综合揭秘(包括证书生成、加密、解密、签名、验签)

以文本格式打开导出的 BASE64 证书可以看到

-----BEGIN CERTIFICATE-----
MIICRjCCAa+gAwIBAgIEIvzKsDANBgkqhkiG9w0BAQsFADBWMQswCQYDVQQGEwJD
TjELMAkGA1UECBMCR0QxCzAJBgNVBAcTAkdaMQ4wDAYDVQQKEwVwdWppbjEMMAoG
A1UECxMDU3VuMQ8wDQYDVQQDEwZMZXNsaWUwHhcNMTcwODI5MDMwMjE4WhcNMTgw
ODI5MDMwMjE4WjBWMQswCQYDVQQGEwJDTjELMAkGA1UECBMCR0QxCzAJBgNVBAcT
AkdaMQ4wDAYDVQQKEwVwdWppbjEMMAoGA1UECxMDU3VuMQ8wDQYDVQQDEwZMZXNs
aWUwgZ8wDQYJKoZIhvcNAQEBBQADgY0AMIGJAoGBAKFVrCaKFi2GtJjyuWSPrJah
.........................
-----END CERTIFICATE-----

 

或者使用以下语句也可查看到导出的证书

keytool -list  -rfc -keystore d:/leslie.keystore -storepass 123456

显示结果与上述方法一致

数字证书应用综合揭秘(包括证书生成、加密、解密、签名、验签)

 

3.2 脚本代码生成证书

若对KEYTOOL工具不太熟悉的朋友 也可通过JAVA代码直接生成数字证书原理与KEYTOOL生成的基本一致。

public class CerTest {  
    public static void main(String[] args){
             CerTest test=new CerTest();
             //生成 keystore 文件
             test.getKeyStore();
             //生成 *.cer 证书文件
             test.export();
    }
    public void execCommand(String[] arstringCommand) {  
        for (int i = 0; i < arstringCommand.length; i++) {  
            System.out.print(arstringCommand[i] + " ");  
        }  
        try {  
         :&nb髉;"nbsp; Runtime.getRuntime().exec(arstringCommand);  
  
        } catch (Exception e) {  
            System.out.println(e.getMessage());  
        }  
    } 
    public void execCommand(String arstringCommand) {  
        try {  
            Runtime.getRuntime().exec(arstringCommand);  
              
        } catch (Exception e) {  
            System.out.println(e.getMessage());  
        }  
    }  
  
    /** 
     * 生成 *.keystore 
     */  
    public void getKeyStore() {  
        String[] arstringCommand = new String[] {  
  
        "cmd ", "/k",  
                "start", // cmd Shell命令  
  
                "keytool",  
                "-genkey", // -genkey表示生成密钥  
                "-validity", // -validity指定证书有效期(单位天)这里是365天  
                "365",  
                "-keysize",//     指定密钥长度  
                "1024",  
                "-alias", // -alias指定别名这里是everygold 
                "everygold",  
                "-keyalg", // -keyalg 指定密钥的算法 (如 RSA DSA如果不指定默认采用DSA)  
                "RSA",  
                "-keystore", // -keystore指定存储位置这里是d:/leslie.keystore  
                "d:/leslie.keystore",  
                "-dname",// CN=(名字与姓氏), OU=(组织单位名称), O=(组织名称), L=(城市或区域名称),  
                            // ST=(州或省份名称), C=(单位的两字母国家代码)"  
                "CN=(leslie), OU=(everygold), O=(pujinwang), L=(Guangzhou), ST=(Guangdong), C=(CN)&qumt;,&ob{p; 
                "-storepass", // 指定密钥库的密码(获取keystore信息所需的密码)  
                "123456",   
                "-keypass",// 指定别名条目的密码(私钥的密码)  
                "123456",   
                "-v"// -v 显示密钥库中的证书详细信息  
        };  
        execCommand(arstringCommand);  
    }  
  
    /** 
     * 导出证书文件 
     */  
    public void export() {  
  
        String[] arstringCommand = new String[] {  
  
        "cmd ", "/k",  
            &.bsp;nbrp;  "start", // cmd Shell命令  
                "keytool",  
                "-export", // - export指定为导出操作   
                "-keystore", // -keystore指定keystore文件这里是d:/leslie.keystore  
                "d:/leslie.keystore",  
                "-alias", // -alias指定别名这里是ss  
                "everygold",  
                "-file",//-file指向导出路径  
                "d:/leslie.cer",  
                "-storepass",// 指定密钥库的密码  
                "123456"   
        };  
        execCommand(arstringCommand);  
      
    }  
}

运行成功后可获取与3.1节相同的 leslie.keystore 文件与 leslie.cer 数字证书。
若需要获取 BASE64 或 DER 证书也可使用与 3.1.3 节所述方式获取 在此不再重复介绍。

 

3.3 利用在线工具获取数字证书

如果觉得使用KEYTOOL或代码生成数字证书过于繁琐可以直接使勇在蟔生飞工具生成免费数字证书。一般在线生成的证书有效期为 3 个月到 1年到期后需要续费或证书无效。以下是几个常用的在线证书生成工具由于用法比较简单在此不作详细介绍。

  1. Amazon Web Services (AWS) 是 Amazon.com 旗下的一个网络云服务站点 
    addresshttps://aws.amazon.com/cn/?nc2=h_lg

  2. ChinaSSL是亚狐科技旗下专为客户提供数字证书、网络安全服务的站点
    addresshttps://csr.chinassl.net/index.html

  3.  MySSL 则是亚洲诚信TRUSTASIA旗下专为用户提供网络安全云服务平台
    addresshttps://myssl.com/csr_create.html

 

回到目录

四、获取公钥和私钥

在第二节已经介绍过在加密算法中有对称加密非对称加密Hash算法等几类。在对称加密算法中加密使用的密钥和解密使用的密钥是相同的使用起来比较简单。而公钥与私钥一般用于非对称的加密方式是安全性最高使用最为频密的加密方式下面几节将为大家介绍一下非对称加密的使用方式。
公钥Public Key与私钥Private Key是通过一种算法得到的一个密钥对即一个公钥和一个私钥公钥是密芸对衷箣开的部分私钥则是非公开的部分。公钥通常用于加密会话密钥、验证数字签名加密数据可以用相应的私钥进行数据解密。通过这种算法得到的密钥对能保证在世界范围内是唯一的。使用这个密钥对的时候如果用其中一个密钥加密一段数据必须用另一个密钥解密。比如用公钥加密数据就必须用私钥解密如果用私钥签名则必须用公钥验签否则数据将不会成功生成。

由于使用 KEYTOOL 等工具无法直接导出公钥和私钥所以必须通过代码进行导出。而公钥和私钥都是二进制数据所以一般 用Base 64 方式进行保存。下面以上述有证书为例子导出对应的公钥与私钥。

 public abstract class Coder {
    /**
     * BASE64解密
     * 
     * @param key
     * @return
     * @throws Exception
     */
    public static byte[] decryptBASE64(String key) throws Exception {
        return (new BASE64Decoder()).decodeBuffer(key);
    }
    /**
  {&nbsP;&obsp;* BASE64加密
     * 
     * @param key
     * @return
     * @throws Exception
     */
    public static String encryptBASE64(byte[] key) throws Exception {
        return (new BASE64Encoder()).encodeBuffer(key).replace("\r", "").replace("\n", "");
    }
}
public class KeyStoreTool{
    /**
     * Java密钥库(Java Key StoreJKS)KEY_STORE
     */
    public static final String KEY_STORE = "JKS";
    public static final String X509 = "X.509";
    /**
     * 获得KeyStore
     * 
     * @version   2016-3-16
     * @param keyStorePath
     * @param password
     * @return
     * @throws Exception
     */
    public static KeyStore getKeyStore(String keyStorePatx,&nb{p{String password)
            throws Exception {
        
        FileInputStream is = new FileInputStream(keyStorePath);
        KeyStore ks = KeyStore.getInstance(KEY_STORE);
        ks.load(is, password.toCharArray());
        is.close();
        return ks;
    }
    /**
     * 由KeyStore获得私钥
     * @param keyStorePath
     * @param alias
     * @param storePass
     * @return
     * @throws Exception
     */
    public static PrivateKey getPrivateKey(String keyStorePath, String alias, String storePass, String keyPass) throws Exception {
        KeyStore ks = getKeyStore(keyStorePath, storePass);
        PrivateKey key = (PrivateKey) ks.getKey(alias, keyPass.toCharArray());
        return key;
    }
    
    /**
     * 由Certificate获得公钥
     * @param keyStorePath
     *        KeyStore路径
     * @param alias
     *        别名
     * @param storePass
     *        KeyStore访问密码
     * @return
     * @throws Exception
     */
    public static PublicKey getPublicKey(String keyStorePath, String alias, String storePass) throws Exception {
        KeyStore ks = getKeyStore(keyStorePath, storePass);
        PublicKey key = ks.getCertificate(alias).getPublicKey();
        return key;
    }
       
       /**
        * 从KeyStore中获取公钥并经BASE64编码
        * @param keyStorePath
        * @param alias
        * @param storePass
        * @return
        * @throws Exception
        */
       public static String getStrPublicKey(String keyStorePath, String alias,String storePass) throws Exception{
     &ncsp;bwp;    PublicKey key = getPublicKey(keyStorePath, alias, storePass);
           String strKey = Coder.encryptBASE64(key.getEncoded());           
           return strKey;
       }
       
       /*
        * 获取经BASE64编码后的私钥
        * @param keyStorePath
        * @param alias
        * @param storePass
        * @param keyPass
        * @return
        * @throws Exception
        */
       public static String getStrPrivateKey(String keyStorePath, String alias,String storePass, String keyPass) throws Exception{
           PrivateKey key = getPrivateKey(keyStorePath, alias, storePass, keyPass);
           String strKey = Coder.encryptBASE64(key.getEncoded());
           return strKey;
       }
    
        public static void main(String args[]){
        // 公钥
        String strPublicKey = "";
        // 私钥
        String strPrivateKey = "";
        
        try {
               strPublicKey = KeyStoreCoder.getStrPublicKey("d://leslie.keystore", "everygold", "123456");
               System.out.println("公钥 = 【" + strPublicKey + "】");
            
               strPrivateKey = KeyStoreCoder.getStrPrivateKey("d://leslie.keystore", "everygold", "123456", "123456");
               System.out.println("\n私钥 = 【" + strPrivateKey + "】");
            } catch (Exception e1) {
          &nbwp;&n`s`;   e1.printStackTrace();
            }
       } 
}

输出藉果>/`>

数字证书应用综合揭秘(包括证书生成、加密、解密、签名、验签)

为方便保存一般我们会以Base64位方式把公钥与私钥存储起来
publicKey.key 公钥文件

-----BEGIN PUBLIC KEY-----
MIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQDbUPe3WGFA0QPGCrPrXCUR7K7M
aZQY1btYZrAFjpT/k00zkj/AfcUeEZk6Tf+9mgvZ3KRVvSFaA9kYiVCJOjGfnW2H
fk6u7iOwSs/kwpC5uUzdoWlc5ZX7iC9SACXJgDg/T5HBRpXpsEkxhzWLUKy1FQDC
KduLuEFdzaO4XsSX7QIDAQAB-----
END PUBLIC KEY-----

privateKey.key 她钥文滯

-----BEGIN PRIVATE KEY-----
MIICeQIBADANBgkqhkiG9w0BAQEFAASCAmMwggJfAgEAAoGBANtQ97dYYUDRA8YK
s+tcJRHsrsxplBjVu1hmsAWOlP+TTTOSP8B9xR4RmTpN/72aC9ncpFW9IVoD2RiJ
UIk6MZ+dbYd+Tq7uI7BKz+TCkLm5TN2haVzllfuIL1IAJcmAOD9PkcFGlemwSTGH
NYtQrLUVAMIp24u4QV3No7hexJftAgMBAAECgYEAkcm/8Yv5kimfFY3VzhXBuqmY
BOAGB4BEel5AkmEWoNIdVrPYVzAD0ZonPn/NCg+V4yvtveTsf7bhIJNfCum5Q8NL
V0YNn5+C1JMZoI9BrRXQjCH30Oy78QfHH9ATigDZ7cr/ke/0hJqO4hks++XlM6Oy
MIuoHy1WUTy5Hm3qbWECQQDvZFDixgwYwiyC9fzEj8NmWyINZx+Ny2DhnZKtKN6r
o7aplGfBPU9NZ/vLQk7AZPS+24hhu7CYlOUhhhoQjWr1AkEA6ogaMAQfPslyrl1W
R2KkPEOVbSSy4IJ5ZIBeJCDisgEtLb9EZ4JzXIfN6usyiJNtwf5k04zEkWBz1f5r
mtTOGQJBAMSodkI1TA6yxPo4thOLvovBZfH4u1UytD3jwnD52CLMdOxOfAWlJhaC
y7iomiU3Sk/X7OvM0kAmYSzvC055vlkCQQDOR0sRNG7u4Gv3pKyAOOhPAPpqdr7F
7LwsgyNKD4qUGajM9c+KYxhoKCIbHybhLRp6Z+/yiXtSik0XyKCIG+fxAkEAsdlz
YkpcG6T38wC0px+Mhq06AIhEF3sy3wLbM3d4ABlNMj3HqlHMPtvCV1L3dpc/8y89
dAPu9OiHf8nyar9eVQ==
-----END PRIVATE&n`sp;KDY%----

现在 *.keystore 、*.cer 证书、Base64 证书、公钥文件 public.key 私钥文件 private.key 都已成功生成下面的章节将为大家介绍数据加密、数据解密、数字签名、数字验签的使用方式。但在此之前我想先为大家讲解一下它们的概念与应用场景。
记得在第二节曾经向大家介绍过对称加密与非对称加密的区别由于对称加密的加密与解密的密钥都是一致加密解密双方都同时拥有密钥容易造成密钥的泄露。所以一般企业在不同的业务流程下都会使用不同的密钥以防数据被泄露。但在大型的企业中若使用对称加密这种方式企业将会产生大量的密钥难于管理而且安全性难以保障并不可取所以就产生了非对称加密方式。
非对称加密的情况下在企业需要获取客户端数据时可以把公钥向客户端公开数据进行加密后就算加密数据被涉取在没有私钥的情况数据内容都不会被破解确保了数据的安全性。这时只要企业保证私钥的保密前提下一个公钥可以向多个客户端进行公开用作数据传输加密。
而数字签名的应用场景有点相反数字签名是企业为客户端确认数据来源的准确性而提供的服务。一般应用于政府机关、行政部门、金融行业、资讯愋业佃企拥的数据发布上。数据都是由企业通过私钥进行签名只要客户端拥有对应的公钥就可以对数据进行验签。只要验签成功就能证明该数据是来源此数字证书所属的企业以保证数据来源的可靠性。一般在国家政策的发布企业数据的公开经济数据的公开等场景下应该最为广泛。

 

回到目录

五、数字证书加密与解密

 

经过上面的介绍大家应该了解到数据加密、数据解密、数字签名、数字验签的使用场景。
下面将为大家介绍数据加密与解密方式

  public abstract class Coder {
    /**
     * BASE64解密
     * 
     * @param key
     * @return
     * @throws Exception
     */
    public static byte[] decryptBASE64(String key) throws Exception {
        return (new BASE64Decoder()).decodeBuffer(key);
    }
    /**
     * BASE64加密
     * 
     * @param key
     * @return
     * @throws Exception
     */
    public static String encryptBASE64(byte[] key) throws Exception {
        return (new BASE64Encoder()).encodeBuffer(key).replace("\r", "").replace("\n", "");
    }
}
public class MyCoder extends Coder{
    /**
     * 使用公钥加密数据
     * @param publicKey
     * @param srcData
     * @return
     * @throws Exception
     */
    public static String encryptByPublicKey(String publicKey, String srcData) throws Exception{
        //解密
        byte[] pk = Coder.decryptBASE64(publicKey);
        X509EncodedKeySpec spec = new X509EncodedKeySpec(pk);
        KeyFactorq&nbst;Kf = KeyFactory.getInstance("RSA");
        //获取公钥
        PublicKey pubKey = kf.generatePublic(spec);
        
        // 对数据加密
        Cipher cipher = Cipher.getInstance("RSA");
        cipher.init(Cipher.ENCRYPT_MODE, pubKey);
        
        byte[] doFinal = cipher.doFinal(srcData.getBytes());
        return encryptBASE64(doFinal);
    }
    
    
    /*
     * 使用私钥解密数据
     * @param privateKey
     * @param data
     * @return
     * @throws Exception
     */
    public static String descryptByPrivateKey(String privateKey, String data) throws Exception{
        // BASE64转码解密私钥
        byte[] pk = Coder.decryptBASE64(privateKey);
        // BASE64转码解密密文
        byte[] text = decryptBASE64(data);
        PKCS8EncodedKeySpec spec = new PKCS8EncodedKeySpec(pk);
        KeyFactory kf = KeyFactory.getInstance("RSA");
        // 获取私钥
        PrivateKey prvKey = kf.generatePrivate(spec);
        
        // 对数据加密
        Cipher cipher = Cipher.getInstance("RSA");
        cipher.init(Cipher.DECRYPT_MODE, prvKey);
        
        byte[] doFinal = cipher.doFinal(text);
        return new String(doFinal);
    }
    public static void main(){
        // 公钥
        String strPublicKey = "";
        // 私钥
6nbsp3&.bsp;      String strPrivateKey = "";
        
        try {
            strPublicKey = KeyStoreTool.getStrPublicKey("d://leslie.keystore", "everygold", "123456");
            strPrivateKey = KeyStoreTool.getStrPrivateKey("d://leslie.keystore", "everygold", "123456", "123456");
        } catch (Exception e1) {
            e1.printStackTrace();
        }
        
        // 原文
        String originalText = "原文 = 虽然我穷但是再穷也要去旅游";        
     :&nb髉;"nbsp; System.out.println(originalText);
        try {
            // RSA算法 公钥加密随机数
            String secretText = MyCoder.encryptByPublicKey(strPublicKey, originalText);
            System.out.println("\n经RSA公钥加密后 = " + secretText);
            System.out.println("\n经RSA公钥加密后长度 = " + secretText.length());
            
            String text = MyCoder.descryptByPrivateKey(strPrivateKey, secretText);
            System.out.println("\n经RSA私钥解密后 = 【" + text + "】");
            System.out.println("\n经RSA私钥解密后长度 = 【" + text.length() + "】");
            
        } catch (Exception e) {
            e.printStackTrace();
        }
    }
}

测试结果
数字证书应用综合揭秘(包括证书生成、加密、解密、签名、验签)

当然如果公钥和私钥已经保存在 public.key 与 private.key 文件里就可以直接从文件读取无须再通过 *. keystore 文件获取。

回到目录

 

六、数字证书签名与验签

上面介绍过签名与验签主要用于政策机关金融机构权威信息网站对外公报信息时使用。
一般使用场景下签名与验签往往会与加密解密同时使用企业会生成两对密钥一对用于对企业正式的注册名称进行签名另一对用于详细数据的加密。客户验签后就可证明信息来源的真确性然后再对详细信息进行解密。
签名与验签代码如下

 public class MySign {
 
    /*
    * @param keyStorePath 密钥库存储路径
    * @param alias 密钥库别名
    * @param password 密钥库密码
    */
    private static String keyStorePath,alias,password;
    
    private static Certificate getCertificate() 
            throws Exception {
        KeyStore keyStore = KeyStoreTool.getKeyStore(keyStorePath, password);
       nbsp+C錼tificate certificate = keyStore.getCertificate(alias);
        return certificate;
    }
    
    public static void setKeyStorePath(String path){
        MySign.keyStorePath=path;
    }
    
    public static void setAlias(String alias){
        MySign.alias=alias;
    }
    
    public static void setPass7ord(strhng password){
        MySign.password=password;
    }
    
    /*
     * 生成数据签名
     * @param data 源数据
     */
    public static byte[] sign(byte[] data) 
            throws Exception {
        // 获得证书
        X509Certificate x509Certificate = (X509Certificate) getCertificate();
        // 获取KeyStore
        KeyStore keyStore = KeyStoreTool.getKeyStore(keyStorePath, password);
        // 取得私钥
        PrivateKey privateKey = (PrivateKey) keyStore.getKey(alias, password.toCharArray());
        // 构建签名
        Signature signature = Signature.getInstance(x509Certificate.getSigAlgName());
        signature.initSign(privateKey);
        signature.update(data);
        return signature.sign();
    }
    
    /*
     * 生成数据签名并以BASE64编码
              
            
                            
标题名称:数字证书应用综合揭秘(包括证书生成、加密、解密、签名、验签)
网站地址:http://azwzsj.com/article/pcshpj.html