理解密钥与数字证书
2019-05-18 22:39:29 阿炯

证书与密钥

证书也叫CA(Certification Authority)证书,比较标准全称为“公开密钥认证”;密钥就是用来加解密用的文件或者字符串。

公开密钥认证(英语:Public key certificate),又称公开密钥证书、公钥证书、数字证书(digital certificate)、数字认证、身份证书(identity certificate)、电子证书或安全证书,是用于公开密钥基础建设的电子文件,用来证明公开密钥拥有者的身份。此文件包含了公钥信息、拥有者身份信息(主体)、以及数字证书认证机构(发行者)对这份文件的数字签名,以保证这个文件的整体内容正确无误。拥有者凭着此文件,可向计算机系统或其他用户表明身份,从而对方获得信任并授权访问或使用某些敏感的计算机服务。计算机系统或其他用户可以透过一定的程序核实证书上的内容,包括证书有否过期、数字签名是否有效,如果你信任签发的机构,就可以信任证书上的密钥,凭公钥加密与拥有者进行可靠的通信。

密钥

在密码学中,密钥(key,又常称金钥)是指某个用来完成加密、解密、完整性验证等密码学应用的秘密信息。在对称密码学(或称密钥密码学)中,加密和解密用的是同一个钥匙,因此钥匙需要保密。而在公钥密码学(或称非对称密码学)中,加密和解密用的钥匙不同:通常一个是公开的,称为公钥;另一个保密,称为私钥。

密钥在非对称加密的领域里指的是私钥和公钥,他们总是成对出现,其主要作用是加密和解密,具体原理可以参考RSA加密算法。需要指出的是,WIKI中提到1999年,RSA-155 (512 bits)被成功分解,2009年12月12日,编号为RSA-768(768 bits, 232 digits)数也被成功分解,目前建议直接使用2048-bit或4086-bit的加密强度。

下面着重地介绍开源界中最为出名的密钥工具--openssl。

openssl EN文档
openssl 中文文档

在说私钥公钥之前需要先熟悉熟悉openssl命令行工具,openssl是一个强大的加密、解密工具,由开源组织维护。利用openssl工具,我们可以实现一些常见的摘要算法,如Linux下简单计算md5,base64,sha1,sha2。

# 帮助信息

Standard(标准) commands
asn1parse      ca             ciphers        crl            crl2pkcs7
dgst           dh             dhparam        dsa            dsaparam
ec             ecparam        enc            engine         errstr
gendh          gendsa         genrsa         nseq           ocsp
passwd         pkcs12         pkcs7          pkcs8          prime
rand           req            rsa            rsautl         s_client
s_server       s_time         sess_id        smime          speed
spkac          verify         version        x509

Message Digest(信息摘要) commands (see the 'dgst' command for more details)
md2            md4            md5            mdc2           rmd160
sha            sha1

Cipher(加密) commands (see the 'enc' command for more details)
aes-128-cbc    aes-128-ecb    aes-192-cbc    aes-192-ecb    aes-256-cbc
aes-256-ecb    base64         bf             bf-cbc         bf-cfb
bf-ecb         bf-ofb         cast           cast-cbc       cast5-cbc
cast5-cfb      cast5-ecb      cast5-ofb      des            des-cbc
des-cfb        des-ecb        des-ede        des-ede-cbc    des-ede-cfb
des-ede-ofb    des-ede3       des-ede3-cbc   des-ede3-cfb   des-ede3-ofb
des-ofb        des3           desx           rc2            rc2-40-cbc
rc2-64-cbc     rc2-cbc        rc2-cfb        rc2-ecb        rc2-ofb
rc4            rc4-40         seed           seed-cbc       seed-cfb
seed-ecb       seed-ofb

# 加密的相关命令
options are
-in <file>     input file
-out <file>    output file
-pass <arg>    pass phrase source
-e             encrypt
-d             decrypt
-a/-base64     base64 encode/decode, depending on encryption flag
-k             passphrase is the next argument
-kfile         passphrase is the first line of the file argument
-md            the next argument is the md to use to create a key from a passphrase.  One of md2, md5, sha or sha1
-K/-iv         key/iv in hex is the next argument
-[pP]          print the iv/key (then exit if -P)
-bufsize <n>   buffer size
-engine e      use engine e, possibly a hardware device.

处理数据

信息摘要
# base64
echo -n "none" | openssl base64
# 解密 -d == decrypt
echo "cGhwZ2Fv" | openssl base64 -d
# 对一个文件计算摘要,下同
openssl base64 -in nginx.conf
# md5
echo -n "none" | openssl md5
# sha128
echo -n "none" | openssl sha1

加密解密
# 使用rc4算法加密php字符串,使用密钥none,输出使用base64编码
echo -n "php" | openssl rc4 -k none -base64

# 使用rc4算法解密字符串,使用密钥none,输入使用base64编码
echo U2FsdGVkX18f3qEoEhVf+hsNOg== | openssl rc4 -d -k none -base64

密钥相关操作

# 生成私钥
# genrsa 指使用rsa算法生成密钥文件
# -des3 指的是给私钥加密的算法(可选)
openssl genrsa -des3 -out key_rsa 4096
openssl genrsa -out key_rsa 4096
# 移除已经存在的密码(先做一下备份)
cp key_rsa old.key
openssl rsa -in old.key -out key_rsa

# 根据刚才创建的私钥创建公钥
openssl rsa -in key_rsa -pubout -out key_rsa.pub

# 使用公钥加密数据
# -in 输入文件
echo -n "none" | openssl rsautl -encrypt -pubin -inkey key_rsa.pub -out a.txt

# 使用私钥解密数据
openssl rsautl -decrypt -inkey key_rsa -in a.txt

# 查看密钥信息
openssl rsa -in key_rsa -text -noout
openssl rsa -pubin -in key_rsa.pub -text -noout

# 检查私钥
openssl rsa -check -in key_rsa
# 检查一个CSR文件
openssl req -text -noout -verify -in domain.csr
# 检查证书信息
openssl x509 -text -noout -in domain.crt


关于密钥的格式

密钥的格式有很多种,我们在使用的时候需要注意。我们刚才使用openssl生成的密钥格式叫PKCS#1,不同的程序可能需要不同格式的密钥,不同格式的密钥是可以转换的。

RSA Private Key (PKCS#1):

-----BEGIN RSA PRIVATE KEY-----
BASE64 ENCODED DATA
-----END RSA PRIVATE KEY-----

PKCS#1 RSA Public Key:

-----BEGIN RSA PUBLIC KEY-----
BASE64 ENCODED DATA
-----END RSA PUBLIC KEY-----

X.509 Public Key:

-----BEGIN PUBLIC KEY-----
BASE64 ENCODED DATA
-----END PUBLIC KEY-----

PKCS#8 Private Key:

-----BEGIN PRIVATE KEY-----
BASE64 ENCODED DATA
-----END PRIVATE KEY-----

PKCS#8 Encrypted Private Key:

-----BEGIN ENCRYPTED PRIVATE KEY-----
BASE64 ENCODED DATA
-----END ENCRYPTED PRIVATE KEY-----

SSH public key:

ssh-rsa AAAAB3NzaC1....... freeoa@local

参考Converting OpenSSH public keys,我们可以使用命令 ssh-keygen -f id_rsa.pub -e -m pem 将ssh-rsa格式转为PKCS#1 PEM格式。

更多格式(我们经常用到的没几个):
#define PEM_STRING_X509_OLD "X509 CERTIFICATE"
#define PEM_STRING_X509     "CERTIFICATE"
#define PEM_STRING_X509_PAIR    "CERTIFICATE PAIR"
#define PEM_STRING_X509_TRUSTED "TRUSTED CERTIFICATE"
#define PEM_STRING_X509_REQ_OLD "NEW CERTIFICATE REQUEST"
#define PEM_STRING_X509_REQ "CERTIFICATE REQUEST"
#define PEM_STRING_X509_CRL "X509 CRL"
#define PEM_STRING_EVP_PKEY "ANY PRIVATE KEY"
#define PEM_STRING_PUBLIC   "PUBLIC KEY"
#define PEM_STRING_RSA      "RSA PRIVATE KEY"
#define PEM_STRING_RSA_PUBLIC   "RSA PUBLIC KEY"
#define PEM_STRING_DSA      "DSA PRIVATE KEY"
#define PEM_STRING_DSA_PUBLIC   "DSA PUBLIC KEY"
#define PEM_STRING_PKCS7    "PKCS7"
#define PEM_STRING_PKCS7_SIGNED "PKCS #7 SIGNED DATA"
#define PEM_STRING_PKCS8    "ENCRYPTED PRIVATE KEY"
#define PEM_STRING_PKCS8INF "PRIVATE KEY"
#define PEM_STRING_DHPARAMS "DH PARAMETERS"
#define PEM_STRING_DHXPARAMS    "X9.42 DH PARAMETERS"
#define PEM_STRING_SSL_SESSION  "SSL SESSION PARAMETERS"
#define PEM_STRING_DSAPARAMS    "DSA PARAMETERS"
#define PEM_STRING_ECDSA_PUBLIC "ECDSA PUBLIC KEY"
#define PEM_STRING_ECPARAMETERS "EC PARAMETERS"
#define PEM_STRING_ECPRIVATEKEY "EC PRIVATE KEY"
#define PEM_STRING_PARAMETERS   "PARAMETERS"
#define PEM_STRING_CMS      "CMS"

列表来自what is the differences between "BEGIN RSA PRIVATE KEY" and "BEGIN PRIVATE KEY"


数字证书(digital certificate)


又称公开密钥认证(英语:Public key certificate)或身份证书(identity certificate)。是用于公开密钥基础建设的电子文件,用来证明公开密钥拥有者的身份。此文件包含了公钥信息、拥有者身份信息(主体)、以及数字证书认证机构(发行者)对这份文件的数字签名,以保证这个文件的整体内容正确无误。拥有者凭着此文件,可向电脑系统或其他用户表明身份,从而对方获得信任并授权访问或使用某些敏感的电脑服务。电脑系统或其他用户可以透过一定的程序核实证书上的内容,包括证书有否过期、数字签名是否有效,如果你信任签发的机构,就可以信任证书上的密钥,凭公钥加密与拥有者进行可靠的通信。

简而言之,认证机构用自己的私钥对需要认证的人(或组织机构)的公钥施加数字签名并生成证书,即证书的本质就是对公钥施加数字签名。

数字证书的其中一个最主要好处是在认证拥有者身份期间,拥有者的敏感个人资料(如出生日期、身份证号码等)并不会传输至索取资料者的电脑系统上。透过这种资料交换模式,拥有者既可证实自己的身份,亦不用过度披露个人资料,对保障电脑服务访问双方皆有好处。人们透过信任数字证书认证机构的根证书、及其使用公开密钥加密作数字签名核发的公开密钥认证,形成信任链架构,已在TLS实现并在万维网的HTTPS、在电子邮件的SMTPS和STARTTLS广泛应用。业界现行的标准是国际电信联盟电信标准化部门制定的X.509,并由IETF发行的RFC 5280详细述明。在不少国家/地区,都已立法承认使用数字证书所作的数字签名拥有等同亲笔签名的法律效力。


证书种类

根证书

根证书获得广泛认可,通常已预先安装在各种软件(包括操作系统、浏览器、电邮软件等),作为信任链的起点,来自于公认可靠的政府机关、软件公司(如Google、Let's Encrypt)、证书颁发机构公司(如VeriSign)等,与各大软件商透过严谨的核认程序才在不同的软件广泛部署。由于部署程序复杂费时,需要行政人员的授权及机构法人身份的核认,一张根证书有效期可能长达十年以上。在某些企业,也可能会在内部电脑自行安装企业自签的根证书,以支持内部网的企业级软件;但是这些证书可能未被广泛认可,只在企业内部适用。

中介证书

认证机构的一个重要任务就是为客户签发证书,虽然广泛认可的认证机构都已拥有根证书,相对应的私钥可用以签署其他证书,但因为密钥管理和行政考虑,一般会先行签发中介证书,才为客户作数字签署。中介证书的有效期会较根证书为短,并可能对不同类别的客户有不同的中介证书作分工。

授权证书

授权证书又称属性证书,本身没有公钥,必须依附在一张有效的数字证书上才有意义,其用处是赋予相关拥有人签发终端实体证书的权力;某些情况下,如果只在短期内授予证书机构签发权力,便可以不改变(缩短)该机构本身持有的证书的有效期。这种情况,类似于某人持有长达十年期的护照,而只透过签发短期入境签证,来个别赋予护照持有人额外权力。

终端实体证书

其他不会用作签发其他证书的,都可称为终端实体证书,在实际的软件中部署,以便创建加密通道时应用。

TLS服务器证书

服务器通常以域名形式在互联网上提供服务,服务器证书上主体的通用名称就会是相应的域名,相关机构名称则写在组织或单位一栏上。服务器证书(包括公钥)和私钥会安装于服务器(例如Apache),等待客户端连接时协议加密细节。客户端的软件(如浏览器)会运行认证路径验证算法以确保安全,如果未能肯定加密通道是否安全(例如证书上的主体名称不对应网站域名、服务器使用了自签证书、或加密算法不够强),可能会警告用户。

通配符证书

如果服务器证书上主体的通用名称(或主体别名)一栏以通配符前缀,则该证书可以用于旗下的所有子域名,特别适合较具规模、或设有多个子网站的机构一次过申领,套用于多个服务器上;即使未来创建新的子域名,也可以套用。但通配符不可用于扩展认证证书上。

TLS客户端证书

有时候,某些TLS服务器可能会在创建加密通道时,要求客户端提供客户端证书,以验证身份及控制访问权限。客户端证书包含电子邮件地址或个人姓名,而不是主机名。但客户端证书比较不常见,因为考虑到技术门槛及成本因素,通常都是由服务提供者验证客户身份,而不是依赖第三方认证机构。通常,需要使用到客户端证书的服务都是内部网的企业级软件,他们会设立自己的内部根证书,由企业的技术人员在企业内部的电脑安装相关客户端证书以便使用。在公开的互联网,大多数网站都是使用登录密码和Cookie来验证用户,而不是客户端证书。

客户端证书在RPC系统中更常见,用于验证连接设备的许可授权。一般遵从X.509格式规范的证书,会有以下的内容,它们以字段的方式表示:
版本:现行通用版本是 V3
序号:用以识别每一张证书,特别在撤消证书的时候有用
主体:拥有此证书的法人或自然人身份或机器,包括:
    国家(C,Country)
    州/省(S,State)
    地域/城市(L,Location)
    组织/单位(O,Organization)
    通用名称(CN,Common Name):在TLS应用上,此字段一般是网域
发行者:以数字签名形式签署此证书的数字证书认证机构
有效期开始时间:此证书的有效开始时间,在此前该证书并未生效
有效期结束时间:此证书的有效结束时间,在此后该证书作废
公开密钥用途:指定证书上公钥的用途,例如数字签名、服务器验证、客户端验证等
公开密钥
公开密钥指纹
数字签名
主体别名:例如一个网站可能会有多个网域(www.wikipedia.org, zh.wikipedia.org, zh.m.wikipedia.org 都是维基百科)、一个组织可能会有多个网站(*.wikipedia.org, *.wikibooks.org, *.wikidata.org 都是维基媒体基金会旗下的网域),不同的网域可以一并使用同一张证书,方便实现应用及管理。


公开密钥基础建设的弱点,在于人们必须循数字证书上的信任链找到根证书,并信任核发根证书的数字证书认证机构,一旦证书机构被黑客入侵,黑客可以在人们不知情下签发了伪冒他人身份的证书,以中间人攻击进行欺诈。业界已研发不同的防御方法,例如证书机构可以透过证书透明度公布新签发的电子证书,让大众检查手上收到的电子证书是否可能未被正式授权(中间人攻击不会“公布”他伪冒了别人签发了欺诈证书),网站管理员也可以定期检查是否有不明机构发出了未被授权的证书。另一方面,HTTPS网站可以使用HPKP指明其固定的公钥,让中间人的欺诈证书无法使用。另外,而OCSP和OCSP装订也在发展中,让用户软件可以透过第三方检查证书是否有效。在公钥基础设施以外,信任网络则采用去中心化的概念,取代了依赖数字证书认证机构的公钥基础设施,因为每一张电子证书在信任链中最终只由一个根证书授权信任,信任网络的公钥则可以累积多个用户的信任。



CA证书

证书与密钥不同,CA证书指的是权威机构给我们颁发的证书,我们的电脑或者电子设备中内置了根证书,我们的电脑信任根证书。

   +-----------------+                    +--------------------+
   |                 |                    |                    |
   |                 |                    |                    |
   |                 |                    |                    |
   |   browser/PC    |  ① GET / HTTP/1.0 |                    |
   |                 |-------------------->  sites over https  |
   |                 ① WAIT! Where is CA ?|                   |
   |                 +-------------------->                    |
   |                 |  ④ Anyway,give me |                    |
   +-----+----^------+   the code!        +--------------------+
         |    |
         |    |
         |    |③ He is good!
② Is's it|    |
a bad site?   |
         |    |    +----------------------+
         |    |    |                      |
         |    +----+                      |
         |         |                      |
         |         |         CA           |
         +--------->                      |
                   |                      |
                   |                      |
                   +----------------------+

证书原理

CA证书能够帮助我们鉴别某一个网站的合法性,简单的概括一下原理:

生成我的公钥
CA机构用自己的私钥加密我的公钥以及相关信息
客户信任CA,并拥有CA的公钥,客户就可以使用公钥解密加密后的证书,并从证书中得到我的公钥
如果能用CA的公钥解密出数据,说明我的证书是经过CA认证过的,客户就可以放心访问了,如果系统发现证书不是权威CA机构颁发的,会警告用户
客户使用我的公钥解密数据,然后进行信息交换

有一些需要注意的地方:

证书有有效期这一说
证书中的相关信息,需要包括改证书到根证书的信任链,如下图,bing.com的证书中,就能够顺藤摸瓜,找到根CA机构,所以在生成自己的证书后,一定要加入这个信任链才能让系统正确的识别到与证书相关的最终根CA。


必应(bing)的证书信息


证书格式

SSL使用X.509证书标准,编码格式有两种。

证书的编码格式

PEM(Privacy Enhanced Mail),通常用于数字证书认证机构(Certificate Authorities,CA),扩展名为.pem, .crt, .cer,.key。内容为Base64编码的ASCII码文件,有类似"-----BEGIN CERTIFICATE-----" 和 "-----END CERTIFICATE-----"的头尾标记。服务器认证证书,中级认证证书和私钥都可以储存为PEM格式(认证证书其实就是公钥)。Apache和nginx等类似的服务器使用PEM格式证书。

DER(Distinguished Encoding Rules),与PEM不同之处在于其使用二进制而不是Base64编码的ASCII。扩展名为.der,但也经常使用.cer用作扩展名,所有类型的认证证书和私钥都可以存储为DER格式。Java使其典型使用平台。

证书编码的转换

# PEM转为DER
openssl x509 -in cert.crt -outform der -out cert.der

# DER转为PEM
openssl x509 -in cert.crt -inform der -outform pem -out cert.pem

CSR

In public key infrastructure (PKI) systems, a certificate signing request (also CSR or certification request) is a message sent from an applicant to a certificate authority in order to apply for a digital identity certificate. The most common format for CSRs is the PKCS #10 specification and another is the Signed Public Key and Challenge Spkac format generated by some Web browsers. - Wiki of Certificate signing request

CSR(Certificate Signing Request),它是向CA机构申请数字身份证书时使用的请求文件,他最常见的格式是PKCS #10。在生成请求文件前,我们需要准备一对对称密钥。私钥信息自己保存,请求中会附上公钥信息以及国家,城市,域名,Email等信息,csr中还会附上签名信息。当我们准备好CSR文件后就可以提交给CA机构,等待他们给我们签名,签好名后我们会收到crt文件,即证书。

# 帮助
openssl req -h
# 生成CSR请求文件和私钥
openssl req -nodes -days 365 -newkey rsa:2048 -keyout key_rsa -out domain.csr
# 从已存在的私钥生生成CSR请求文件
openssl req -new -days 365 -key key_rsa -out domain.csr

# 信息可以直接写好
openssl req -new -days 3650 -key key_rsa -out domain.csr -subj \
"/C=CN/ST=Shanghai/L=Shanghai/O=Qihoo 360/OU=IT Dept/CN=blog.none.com/emailAddress=admin@none.com"

# 检查CSR文件信息
openssl req -text -noout -verify -in domain.csr

CRT

其实我们最终就需要一个私钥文件和证书文件,这一步骤我们会得到CRT文件。

自签名
当我们生成好CSR文件后,就可以开始签名了,是的,自己给自己签名!

openssl ca -h
# 先生成一个CA根证书
openssl req -x509 -nodes -days 36500 -newkey rsa:2048 -keyout key_ca_rsa -out ca.crt
# 使用CA的私钥签名
openssl ca -policy policy_anything -days 365 -cert ca.crt -keyfile key_rsa -in domain.csr -out domain.crt

# 可能会出错,因为缺少一些必要文件
mkdir -p demoCA/newCerts
touch demoCA/index.txt
echo -n "01" > demoCA/serial

直接生成证书
我们当然也可以直接生成CRT文件。

# 生成证书和私钥
openssl req -x509 -nodes -days 365 -newkey rsa:2048 -keyout key_rsa -out key.crt
# 从已存在的私钥生成生成证书
openssl req -x509 -new -days 365 -key domain.key -out domain.crt

# 检查证书信息
openssl x509 -text -noout -in domain.crt

补充信息
CSR所需要的信息

CN = Country Name (2 letter code)
ST = State or Province Name (full name)
L  = Locality Name (eg, city)
O  = Organization Name (eg, company)
OU = Organizational Unit Name
CN = Common Name (eg, your name or your server's hostname)

# 例子

Country Name (2 letter code) [AU]:CN
State or Province Name (full name) [Some-State]:Shanghai
Locality Name (eg, city) []:Shanghai
Organization Name (eg, company) [Internet Widgits Pty Ltd]:Qihoo 360
Organizational Unit Name (eg, section) []:IT Dept
Common Name (e.g. server FQDN or YOUR name) []:blog.none.com
Email Address []:admin@none.com

# 我们可以在需要输入以上信息的时候直接用下面的选项,就不用在一个一个输入了
-subj \
"/C=CN/ST=Shanghai/L=Shanghai/O=Qihoo 360/OU=IT Dept/CN=blog.none.com/emailAddress=admin@none.com"


RSA

RSA加密算法是一种非对称加密算法。在公开密钥加密和电子商业中RSA被广泛使用。RSA是1977年由罗纳德·李维斯特(Ron Rivest)、阿迪·萨莫尔(Adi Shamir)和伦纳德·阿德曼(Leonard Adleman)一起提出的。当时他们三人都在麻省理工学院工作。RSA就是他们三人姓氏开头字母拼在一起组成的。

对极大整数做因数分解的难度决定了RSA算法的可靠性。换言之,对一极大整数做因数分解愈困难,RSA算法愈可靠。假如有人找到一种快速因数分解的算法的话,那么用RSA加密的信息的可靠性就肯定会极度下降。但找到这样的算法的可能性是非常小的。今天只有短的RSA钥匙才可能被强力方式解破。到当前为止,世界上还没有任何可靠的攻击RSA算法的方式。只要其钥匙的长度足够长,用RSA加密的信息实际上是不能被解破的。


Diffie-Hellman

Diffie-Hellman加密算法的最终目的是为了完成通信双方对称秘钥的交互,但是它最了不起的地方是即使处在不安全的环境(有人侦听)也不会造成秘钥泄露,生成的时间会比较长,请耐心等待。

openssl dhparam -out /etc/ssl/certs/dhparam.pem 2048

使用方法:
ssl_dhparam /etc/ssl/certs/dhparam.pem;


数字签名与数字证书的一些小知识

在开始介绍前先提一些问题:

什么是数字签名,数字签名的作用是什么?
为什么要对数据的摘要进行签名,而不是直接计算原始数据的数字签名?
什么是数字证书,数字证书解决了什么问题?
非对称加密中公私钥都可以加密,那么什么时候用公钥加密,什么时候用私钥“加密” ?

加密就是对明文数据按某种特殊算法进行处理,使其成为不可读的一段代码,通常称为“密文”,密文通过“密钥”解密后还原出原来的明文,通过这样的途径可以达到保护数据不被非法人窃取、阅读的目的。

定义简单吧?那来看个题,考虑以下哪些属于加密方法:
AES、RSA、MD5、SM4

这几种都是日常开发中常用的数据编码技术,但是只有 AES、RSA、SM4 才能算是加密方法。一个区分的简单方法就是看编码后的数据是否还能还原,能还原的是加密。

MD5 实际上是对数据进行有损压缩,无论数据有多长,1KB、1Mb 还是 1G,都会生成固定 128 位的散列值,并且 MD5 理论上是不可能对编码后的数据进行还原的,即不可逆。MD5 因为其具有不可逆性、单向恒定性(相同的数据多次计算值不变)被广泛应用于文件完整性验证、口令加密以及接下来会讲到的数字签名中。


加密算法的分类

加密算法按照加解密使用的密钥是否相同,可分为:
对称加密(Symmetric Cryptography)
非对称加密(Asymmetric Cryptography)

1. 对称加密
对称加密是指加密和解密时使用同一个密钥。通信双方使用同一个密钥,不同算法工作。数据发送方使用密钥和加密算法对数据进行加密,数据接收方使用密钥和解密算法对密文进行解密,还原数据。基本模型如下图所示:


对称加密模型
常见对称加密算法DES、AES。
加密算法缺点:密钥需要数据发送方通过不可信网络传输给数据接受方,密钥存在泄漏风险。


2. 非对称加密
非对称加密是指加密和解密使用不同的密钥,这两个密钥分别叫做「公钥」、「私钥」。
公钥是可以公开给所有人的,而私钥需要自己保密的。
公钥加密的数据只能用私钥解密。同理,私钥“加密”的数据只能用公钥“解密”。
大家注意到没,这里对 私钥“加密” 这里打了引号,为什么呢?
因为私钥不是用来加密的,准确的说法应该是 「私钥签名,公钥验签」;这个问题很多人都存在误解,认为公私钥都可以用于加密。

通信双方使用不同的密钥,相同的算法工作。数据发送方持有公钥,数据接收方持有私钥。公钥由数据接收方通过网络发送给数据发送方。数据发送方通过加密算法和公钥对数据进行加密,数据接收方通过加密算法和私钥对密文进行解密,还原数据。基本模型如下图所示:


非对称加密模型

常见非对称加密算法 RSA、DSA。
非对称加密算法私钥由数据接收方持有,不会在网络上传递,保证了密钥的安全。
非对称加密算法通常比对称加密算法计算复杂,性能消耗高。
非对称加密算法可用于数字签名。


因为数字签名属于非对称加密,非对称加密依赖于复杂的数学运算,包括大数乘法、大数模等等,耗时比较久。如果数据量大的时候计算数字签名将会比较耗时,所以一般做法是先将原数据进行 Hash 运算,得到的 Hash 值就叫做「摘要」。「摘要」就像人的指纹一样,可以代表一个人,只要内容发生了改变,计算出来的摘要也应该变化。「摘要」最好是不可逆转的,一般使用开头提到的 MD5 作为 Hash 函数,MD5 输出的结果固定位 128 位。

可将数字证书叫做「公钥的数字签名」。

为什么呢?我们引入数字证书的目的是为了保证公钥不被篡改,即使被篡改了也能识别出来。而防篡改的方法就是数字签名,但是这个签名不能我们自己做,原因说过了,因为我们的公钥还没分发出去,别人无法验证。所以只能找可信的第三方来帮我们签名,即证书颁布机构(CA),CA 会将:证书的颁布机构、有效期、公钥、持有者(subject)等信息用 CA 的私钥进行签名。并且将签名结果和这些信息放在一起,这就叫做「数字证书」。


当然是使用 CA 的公钥进行验签。CA 的公钥也是需要使用证书来分发的,所以电脑里必须安装 CA 的证书,证书里包含了 CA 的公钥。

证书不可信?

那么什么情况下浏览器会提示 “证书不可信” 呢?根据我们上面的分析,下面是可能的原因:

证书不是权威 CA 颁发
有些企业为了贪图便宜使用盗版的证书,没有经过 CA 认证。也就是无法使用浏览器内置 CA 公钥进行验证。

证书过期
上面说了,证书里有一项就是有效期,一般就是一年或者两年的时间。如果证书过期,那么浏览器就会提示“证书不可信”

证书部署错误
可能是服务器证书部署出错,比如证书与域名不匹配,因为证书里有一项是持有人信息的。

3. 数字签名

数字签名是校验安装包是否被篡改、损坏的有效手段,数字签名采用了非对称加密 + Hash 两种技术。具体原理参见下图,主要是以下几步。


对原始数据进行 hash,得到数据摘要。
通过私钥和加密算法对数据摘要进行加密得到加密后的数据摘要。
将加密后的数据摘要附加在原始数据后,组合成签名后的数据,并发送个对方。
对方收到签名后的数据后,将原始数据和签名的摘要分开,同样通过 hash 原始数据得到一份数据摘要。
对加密后的数据摘要通过公钥解密,得到待验证的数据摘要。

对比两份数据摘要,只要完全一致则表明原始数据未被篡改或损坏。


现在我们来回答上面提出的一些问题:

非对称加密中公私钥都可以加密,那么什么时候用公钥加密,什么时候用私钥“加密” ?
加密场景,那么肯定希望只有我才能解密,别人只能加密。即公钥加密,私钥解密。
签名场景,既然是签名,就希望只能我才能签名,别人只能验证。即私钥签名,公钥验签

什么是数字签名,数字签名的作用是什么?
数字签名就是使用私钥对数据摘要进行签名,并附带和数据一起发送。可以起到防篡改、防伪装、防否认的作用。

为什么要对数据的摘要进行签名,而不是直接计算原始数据的数字签名?
数据可能比较大,签名是使用非对称加密算法,比较耗时
防止第三方使用公钥解开签名后,拿到原始数据

什么是数字证书,数字证书存在解决了什么问题?
数字证书就是由 CA 机构使用自己私钥,对证书申请者的公钥进行签名认证。
数字证书解决了如何安全分发公钥的问题,也奠定了信任链的基础。


SSL在线工具

SSL证书在线工具SSL Online Tools


参考来源:

证书,密钥,加密,rsa到底是啥