PKI-DH 是密码学中的两个组合。其中 PKI 代表了公钥技术设施,DH 代表了 Diffie-Hellman 密钥交换算法。

DH 密钥交换

DH 密钥交换算法用于在不安全的信道上协商出对称密钥。

其数学原理如下:

Diagram

如图所示:

双方协定 p=23, g=5。

Alice 选中一个 秘密 整数 a;b 选中一个秘密整数 b,然后双方分别将计算得到的 A, B 发送给对方,对方在使用 A, B 计算出整数 K。得到密钥 K。数学保证了双方计算得到的 K 是相同的。

由于 a, b 是保密操作,因此无法算出 K。

劣势

尽管 DH 可以在不安全信道上工作。但是某实体位于通信链路中间,发起两次密钥协商,分别伪装成 Bob 和 Alice,就能够窃取信息(也就是中间人攻击)。针对此问题,可以使用 PKI 进行身份验证

ECDH

ECDH(Elliptic Curve Diffie-Hellman)是 DH 的一种变种。使用椭圆曲线算法进行密钥交换。相比于 DH,ECDH 更加安全,且速度更快。其基本步骤如下:

Diagram

PKI

PKI 全名为公钥基础设施。是建立在非对称加密上的一套体系。PKI 体系中包含了 CA 证书,数字证书,密钥等概念。相关规范为 X509。

在解释相关概念之前,首先解释非对称加密和证书之前的区别:

非对称加密分为两部分:公钥和私钥。其中公钥分发到网上,私钥自己持有。在这基础之上,衍生出了多种用法:

  • 数据加密:使用公钥/私钥加密,对方使用对应的内容进行解密。就可以实现数据加密。但是非堆成加密速度较慢,一般会配合 DH 协商出对称密钥,然后使用对称密钥进行加密。

  • 数字签名:使用私钥对数据进行签名,然后使用公钥进行验证。用于验证数据的完整性和身份。一般情况会现对数据进行处理生成一个消息摘要,以避免签名过长。

权威机构生成自己的公钥和密钥。然后公钥分发给用户。用户生成自己的证书,然后将公钥发送到权威机构进行签名,生成证书文件。也就是说,证书是附带了权威机构签名的公钥文件。权威机构的证书可以从网络获得,通过权威机构的公钥就可以验证证书的真实性。

单向认证

PKIDH 中最经典的为单向认证。单向认证主要用来验证服务器的身份。被广泛应用到 SSL 等传输协议中。下面以 SSL 为例,解释单向认证的过程:

Diagram

双向认证

某些情况下需要同时验证双方的身份。这种情况下一般为服务器和客户端身份不固定,或者是点对点网络。SSL 双向认证流程如下:

Diagram

MAC

MAC(Message Authentication Code) 和数字签名类似,但是数字签名使用非对称机密算法,而 MAC 使用对称加密算法。主要用于验证数据的完整性和权威性。MAC 一般使用 DH 密钥交换之后获得的 SharedSecret 来进行加密。

Hash, 数字签名, MAC 对比如下:

HashMAC数字签名

完整性

来源

不可否认

密钥类型

对称密钥

非对称密钥

  1. 完整性意为验证消息是否被篡改。

  2. 来源意为验证消息是否是可靠来源。

  3. 不可否认意为能够确信消息的发件人。

前向加密

前向机密是指当当前密钥泄露后依然能够保证历史数据不会被解密。PKIDH 中使用 DH 和 sessionKey 保证了此点。具体而言:

  • 每次新的 session 都会使用 DH 协商出一个新的密钥。

  • 即便是双方的密钥发生了泄露依然能够保证密钥是安全的(被动攻击)。

这就是为什么不在 Client 端生成密钥后直接发送给 Server 端的原因。由于 DH 只有中间人攻击才会导致信息泄露,而历史数据无法行使中间人攻击,因此 PKIDH 保证了前向加密。

自签名证书

下面介绍了通过 OpenSSL 自签名证书的步骤:

#!/bin/sh

set -xe

work_dir=$(cd $(dirname $0); pwd)
dir='certs'

dir=$work_dir/$dir

rm -rf $dir
mkdir $dir

cat > $dir/openssl.cnf <<EOF
[ v3_server ]
basicConstraints = critical,CA:false
keyUsage = nonRepudiation, digitalSignature
subjectKeyIdentifier = hash
authorityKeyIdentifier = keyid:always,issuer:always
subjectAltName = @alt_names

[ v3_client ]
basicConstraints = critical,CA:false
keyUsage = nonRepudiation, digitalSignature
extendedKeyUsage = critical, clientAuth
subjectKeyIdentifier = hash
authorityKeyIdentifier = keyid:always,issuer:always

[ alt_names ]
DNS.1 = testserver.com
DNS.2 = second.testserver.com
DNS.3 = localhost
EOF

# 生成根证书
openssl genrsa -out $dir/root.key 4096
openssl req -new -x509 -days 1000 -key $dir/root.key -out $dir/root.crt -subj "/CN=ponytown RSA CA"

# 生成私钥
openssl genrsa -out $dir/op1.key 2048
# 生成请求文件
openssl req -new -key $dir/op1.key -out $dir/op1.csr -config $dir/openssl.cnf -subj "/CN=testserver.com"
# 使用根证书签署请求文件以生成证书
openssl x509 -req -days 365 -CA $dir/root.crt -CAkey $dir/root.key -CAcreateserial -in $dir/op1.csr -out $dir/op1.crt -extensions v3_server -extfile $dir/openssl.cnf

# 生成第二个证书
openssl genrsa -out $dir/op2.key 2048
openssl req -new -key $dir/op2.key -out $dir/op2.csr -config $dir/openssl.cnf -subj "/CN=testserver.com"
openssl x509 -req -days 365 -CA $dir/root.crt -CAkey $dir/root.key -CAcreateserial -in $dir/op2.csr -out $dir/op2.crt -extensions v3_server -extfile $dir/openssl.cnf

rm $dir/*.csr
rm $dir/*.srl
rm $dir/openssl.cnf
Last moify: 2025-01-22 07:09:06
Build time:2025-07-18 09:41:42
Powered By asphinx