前几日做支付对接时, 被对方文档中的加密方式搞晕乎了一会. 意识到证书加密方面的理解不够深入, 事后查阅参考资料补习一波. 本文是根据期间的学习, 以及长期以来的实践做出的总结.
加密方式
密码学是涉及数学, 电子信息, 计算机等多学科的一门重要学科, 是现代互联网安全的基石, 也是目前如火如荼的区块链技术的安全保障. 概括来说, 加密方式可归结如下:
一, 不可逆加密
信息摘要 (Message Digest) 和安全散列 (Secure Hash) 算法属于此类, 常见的算法包括 MD5,SHA1,PBKDF2,bcrypt 等. 此类算法可将任意大小的原始数据变换成规定长度的输出, 即获取内容的数字指纹, 常用于校验原始内容是否被篡改. 这类算法的主要特点是:
不可逆性. 除非穷举等手段, 原则上不存在根据密文推断出原文的算法;
雪崩效应. 对输入数据敏感, 原始内容的极小改动会造成输出的大差异;
防碰撞性. 原则上很难找到两组相同的原文, 经过加密后密文相同.
左耳朵耗子的 "RSYNC 的核心算法 https://coolshell.cn/articles/7425.html" 介绍了 MD5 算法在 rsync 中的具体应用. MD5 和 SHA1 已经被证实不安全(王小云教授在 04 年找到 MD5 迅速碰撞方法, 谷歌在 17 年完成了 SHA1 的第一次碰撞), 实践中建议至少用 SHA-256 算法, 或采用对算力不敏感的 scrypt,Argon2 等算法.
哈希算法的一个变种是 HMAC(Hash-based Message Authentication Code)算法, 用于解决身份认证和防抵赖. HMAC 算法的输入为一个密钥 (通信双方共享), 一种哈希算法(常为经典哈希算法) 和原始数据, 输出的内容格式取决于所采用的哈希算法. 由于只有通信双方知晓密钥, 签名正确的情况下可确认信息就是由对方发出.
二, 可逆加密
哈希算法的签名可保证通信中的数据不被篡改, 可逆加密算法是还原出明文的关键. 可逆加密算法可分成三类:
基于算法的加密算法, 也被称为古典加密算法, 如 http 认证中的 base64, 比特币生成地址用的 base58(公开的算法也可称作编码方式). 这类算法主要对原始内容进行置换和替换得到密文, 安全性依赖于算法是否外泄;
对称加密算法, 加密和解密使用同一个密钥. 对称加密算法的出现标志密码学进入现代密码学阶段, 密文的安全性从依赖于算法转向依赖于密钥. 常见的对称加密算法有 DES,3DES,AES;
非对称加密算法, 加密和解密使用不同的密钥. 非对称加密算法开创了密码学的里程碑, 解决了对称加密过程中密钥分发的安全问题, 被认为现代密码学最伟大的发明. 常见的算法有 RSA,DH(Diffie-Hellman), 椭圆曲线算法(Elliptic curve cryptography,ECC).
非对称算法设计巧妙, 但实际中要结合对称加密使用. 原因是某些算法不能加解密(DH,DSA), 或者效率太低(RSA), 或者能处理的数据大小有限制(RSA). 而对称加密算法的有点是速度快, 加密强度高. 常用非对称算法获得共享密钥, 之后用对称加密处理数据.
本文的重点是非对称加密及其衍生概念, 下面逐一介绍.
公钥, 私钥和证书
除算法外, 非对称加密中另外两个重要的概念是公钥和私钥. 公钥对外公开, 任何人均可持有和使用; 私钥自行保管, 其安全性是通信安危的关键. 例如 OpenSSH 客户端默认会拒绝用权限开放的私钥连接服务器, 会出现如下提示:
- # 放开私钥权限
- chmod 644 ~/.ssh/id_ras
- # 连接服务器
- ssh server
- # openssh 客户端出现如下报错:
- Permissions 0644 for '/home/tlanyan/.ssh/id_rsa' are too open.
It is required that your private key files are NOT accessible by others.
This private key will be ignored.
Load key "/home/tlanyan/.ssh/id_rsa": bad permissions
Permission denied (publickey,gssapi-keyex,gssapi-with-mic).
私钥和公钥的作用一般分为两种:
公钥加密, 私钥解密, 主要用于通信;
私钥签名, 公钥验证, 主要用于签名.
本次做支付对接时, 对其算法疑虑的地方是需要用到私钥, 按理要用对方的公钥加密才对啊! 后来意识到是用作数据签名, 用客户端的私钥是正确的.
理论上有了公钥和密钥, 双方就可以安全无碍的通信, 那常说的证书是怎么回事?
证书, 顾名思义, 就是证明的文件. 例如浏览器和 tlanyan.me 服务器通信, 浏览器怎么知道对方就是 tlanyan.me 对应的服务器呢? 在不可信的网络下通信, 中立的第三方作用就显现出来了. 权威的第三方中立机构 (同常是 Certificate Authority, CA) 给 tlanyan.me 的持有者颁发证书, 证明其就是域名所有人. 服务器收到请求后将证书一起发送出去, 浏览器对证书进行检查, 并向第三方询问是否为真, 确认无误后, 就可以放心的通信了.
证书包含公钥, 所以拿到证书意味着就拿到了对方的公钥. 几乎所有的浏览器都会都证书进行校验, 以确保网页通信中的安全. 使用自签发的证书, 或者过期, 与请求主机不符合的证书, 都会导致浏览器发出安全警告, 提醒用户潜在的风险.
CURL 等第三方库一般不会对证书进行检查, 服务器交互时如何确保通信的对方是真李逵而非李鬼?
答案是客户端预先存一份服务器证书, 通信时校验服务端发来的证书与本地的是否一致. 如果不一致, 则说明遇到了中间人攻击, 或预设的通信方实体已经变更. 之前做微信支付的对接, 不理解微信的服务器证书的作用, 后来才理解其深意.
许多国外网站使用 https, 照样倒在国内伟大的防火墙之下. 根据 https 加密通信的特点, 同时 CA 加持, 原则上墙是不可能知道通信的内容. 那么在 https 通信时, 墙是怎么识别出来并阻断的? 个人认为有三个可切入的点:
DNS 污染, 返回错误的 IP 地址;
直接把域名的所有 IP 封掉;
根据 HTTPS 的交互流程, 客户端和服务器协商密钥阶段的数据均为明文, 获取密钥后才会加密数据(包括 URL). 协商阶段的证书必然出现网站主机名, 防火墙在这个阶段可识别进并阻断.
以上想法出自个人猜测.
总结: 通信的私钥应该总是被妥善保管, 在不可靠的网络环境下通信, 证书能避免中间人攻击.
CSR,PEM,keystore 等
苹果开发会接触到 CSR, 证书, 安卓开发会用到 keystore,web 开发会用到 pem, 密钥, 证书, jks 等. 这些都是什么?
CSR(Certificate Sign Request), 公钥, 密钥和证书归属为一类. CSR 用来获取证书, 包含申请人的公钥, 邮件等证明身份的信息. 证书颁发结构 (可以是自己) 收到 CSR 后签发证书, 生成的证书中包含公钥, 有效期, 持有人等信息. 私钥可单独生成, 也可在生成 CSR 的同时生成. 整个过程中, 私钥应当都要被妥善保管, 不能泄露.
keystore,pem,cer/crt,key 等文件存储格式可归为一类. Java KeyStore(文件后缀. keystore 或. jks)是 Java 常用的存储密钥和证书的文件格式, 需要设置文件密码, 别名和别名密码, 安卓打包和部署 Tomcat 时会用到; PEM(Privacy Enhanced Mail)以文本形式存放私钥和证书(链);cer/crt 和 key 分别用来存放证书和密钥; 另外一种常见的格式是 pfx 或者 p12, 同 jks 格式, 这类文件一般是二进制, 访问需要密码.
PKI(Public key infrastructure)体系构建在公钥加密基础之上, 主要解决证书的颁发和管理问题. 证书管理中应用广泛的两个标准是 X509 和 PKCS. 遵循 X509 标准的证书文件结尾多为 pem,der,crt 等; 遵循 PKCS 标准的证书常用后缀名是 pfx,p12 等.
OpenSSL
OpenSSL 是通用的加密库, openssl 是基于其的命令行工具, 上文提到的内容基本都在其功能范围内. 另一个与 openssl 类似的工具是 GPG(GNU Privacy Guard), 区别是 OpenSSL 遵循 X509 标准, GPG 遵循 OpenPGP 标准. 两者加密的文件在格式上有所差异, 无法解开对方加密过的文件. OpenSSL 和 GPG 内置在大多数 * nix 系统中, 可直接使用. 以下的示例基于 OpenSSL,gpg 的用法可查看文中最后的参考文献.
openssl 命令的 man 页面描述了其能力范围:
The openssl program is a command line tool for using the various cryptography functions of
OpenSSL's crypto library from the shell. It can be used for
o Creation and management of private keys, public keys and parameters
o Public key cryptographic operations
o Creation of X.509 certificates, CSRs and CRLs
o Calculation of Message Digests
o Encryption and Decryption with Ciphers
o SSL/TLS Client and Server Tests
o Handling of S/MIME signed or encrypted mail
o Time Stamp requests, generation and verification
接下来看一些简单的 openssl 使用示例:
- md5:
- echo tlanyan | openssl md5
- ## 结果与下条命令相同
- echo tlanyan | md5sum
aes 加解密:
- # 用法
- # openssl aes-128-cbc -e -in 加密文件 -out 解密文件 -pass pass: 密码
- # 例如
- echo tlanyan> input
- openssl aes-128-cbc -e -in input -out output -pass pass:1234567890abcdef
- # 加密的内容在 output 中
- # 解密
openssl aes-128-cbc -d -in output -o origin -pass pass:1234567890abcdef
生成 CSR, 签发证书:
- # 先生成 csr 和私钥
- # 注意使用 - nodes 选项, 否则私钥会有密码, 用在 nginx 启动时需要手动输入
openssl req -new -out tlanyan.csr -newkey rsa:2048 -nodes -keyout tlanyan.priv.key
- # 接下来的交互里填入一些基本信息, 完毕后会生成 tlanyan.csr 和 tlanyan.priv.key 两个文件
- # csr 的格式如下:
- # -----BEGIN CERTIFICATE REQUEST-----
- # xxxx
- # -----END CERTIFICATE REQUEST-----
- # 密钥文件的格式类似
- # 有了 csr, 接下来为自己签发证书
openssl req -x509 -sha256 -nodes -days 365 -in tlanyan.csr -key tlanyan.priv.key -out tlanyan.crt
- # 命令结束后, 目录中出现 tlanyan.crt 的证书文件
- # 校验密钥
- openssl rsa -in tlanyan.priv.key --check
- # 校验 csr
openssl req -in tlanyan.csr -verify
# 校验证书
openssl x509 -in tlanyan.crt -text -noout
转换各种不同格式的证书:
# 将 pem 格式转换成 pfx/p12 格式
openssl pkcs12 -export -out tlanyan.pfx -inkey tlanyan.priv.key -in tlanyan.crt
# 将 pfx 格式转换成 pem 格式
openssl pkcs12 -in tlanyan.pfx -out tlanyan.cer -nodes
# 生成的 tlanyan.cer 文件包含了证书和公钥, 对应导入前的 tlanyan.crt 和 tlanyan.priv.key 两个文件
pem 和 jks 的格式转换太过复杂, 具体请看 Oracle 的文档.
以上演示了 openssl 工具包中的极小一部分命令. 更多的用法请参考官方文档.
总结
本文介绍了非对称加密和证书的相关概念, 并演示了 openssl 命令的一些用法. 文章涉及内容较多, 理解上稍显难度. 另外本文参考了不少文章, 理解上的不到之处敬请指正.
- https://coolshell.cn/articles/7425.html
- http://www.tldp.org/HOWTO/SSL-Certificates-HOWTO/x64.html
- https://legacy.gitbook.com/book/yeasy/blockchain_guide/details
- https://www.integralist.co.uk/posts/security-basics/
- https://rakhesh.com/infrastructure/notes-on-cryptography-ciphers-rsa-dsa-aes-rc4-ecc-ecdsa-sha-and-so-on/
- https://www.sslshopper.com/what-is-a-csr-certificate-signing-request.html
- http://www.cnblogs.com/jeremy-blog/p/5291296.html
- https://www.sslshopper.com/ssl-converter.html
- https://docs.oracle.com/cd/E35976_01/server.740/es_admin/src/tadm_ssl_convert_pem_to_jks.html
来源: https://juejin.im/post/5b004133f265da0ba17cc7ab