HPKE的运行机制

HPKE通过分层设计实现高效安全的加密传输,其核心流程分为三个阶段:

1. KEM(密钥封装机制)

使用非对称加密传递对称密钥种子。发送方通过接收方公钥加密生成:

● 临时共享密钥 shared_secret

● 封装结果 enc(包含临时公钥信息)

接收方用私钥解封装获得相同密钥

2. KDF(密钥派生函数)

采用HKDF将共享密钥扩展为三个核心参数:

key:对称加密密钥(如AES-GCM-256)

base_nonce:初始计数器

exporter_secret:扩展密钥

通过``saltinfo`参数增强随机性

3. AEAD(带认证的加密)

使用对称算法(如AES-GCM-256)加密数据

基于ECDH密钥交换模拟HPKE运行机制

本地密钥生成:

img

KEM实现:

img

img

HPKE 密钥协商:

img

加解密封装:

img

模拟 HPKE 的运行逻辑:

img

运行效果:

img

基于pyhpke库进行HPKE加密实践

导入pyhpke 包:

img

假设 alice 和 bob 基于 HPKE 进行加密通信,alice为发送方,bob 为接收方,在开始通信前做好数据准备:

img

生成 bob 接收方的公私钥:

img

发送方 alice 进行 KEM 生成预共享密钥:

img

发送方 alice 加密明文数据:

img

接收方 bob 接收密文并解密:

img

运行效果:

img

HPKE运行的几种模式

模式核心参数安全强度适用场景
Base模式仅接收方公钥★★★☆内部服务通信
PSK模式+ 预共享密钥psk★★★★IoT设备认证
Auth模式+ 发送方私钥sks★★★★☆跨服务认证
PSK+Authpsk+sks双参数★★★★★军事/政府通信

Base模式(基本模式):

○ 发送方:只需要接收方的公钥(pkr)和信息(info,可选)

○ 接收方:需要封装后的临时公钥(enc)、接收方的私钥(skr)和相同的信息(info)

○ 安全强度:提供前向安全性,但不提供发送方认证

PSK模式(预共享密钥模式):

○ 发送方:除了Base模式的参数外,还需要预共享密钥(psk)和预共享密钥标识(psk_id)

○ 接收方:同样需要enc, skr, info,以及相同的psk和psk_id

○ 安全强度:除了前向安全性,还通过预共享密钥提供了双向认证(双方都知道PSK),防止未知方发起通信

Auth模式(身份验证模式):

○ 发送方:需要接收方的公钥(pkr)、信息(info,可选)以及发送方的私钥(sks)用于身份验证

○ 接收方:需要enc, skr, info,以及发送方的公钥(pks)用于验证发送方身份

○ 安全强度:提供发送方身份认证,确保接收方知道消息的来源

Auth_PSK模式(认证+预共享密钥模式):

○ 发送方:需要pkr, info, psk, psk_id, 以及发送方的私钥(sks)

○ 接收方:需要enc, skr, info, psk, psk_id, 以及发送方的公钥(pks)

○ 安全强度:同时提供发送方身份认证和预共享密钥认证,安全强度最高

安全配置建议

• 敏感数据 :优先选择Auth或PSK+Auth模式

• 性能敏感场景 :Base模式+P-256曲线(比P-521快3倍)

• 密钥轮换 :通过info字段绑定密钥版本(如info=b"v2_key")

使用PSK+AUTH模式的实践示例

  1
  2
  3
  4
  5
  6
  7
  8
  9
 10
 11
 12
 13
 14
 15
 16
 17
 18
 19
 20
 21
 22
 23
 24
 25
 26
 27
 28
 29
 30
 31
 32
 33
 34
 35
 36
 37
 38
 39
 40
 41
 42
 43
 44
 45
 46
 47
 48
 49
 50
 51
 52
 53
 54
 55
 56
 57
 58
 59
 60
 61
 62
 63
 64
 65
 66
 67
 68
 69
 70
 71
 72
 73
 74
 75
 76
 77
 78
 79
 80
 81
 82
 83
 84
 85
 86
 87
 88
 89
 90
 91
 92
 93
 94
 95
 96
 97
 98
 99
100
101
102
103
104
# 假设 alice  bob 需要使用 HPKE 方式进行加密通信通信的内容就是 plaintext
# 假设 alice 是发送方(sender)bob 是接收方(recipient)
    plaintext ="Hello, HPKE! 这是一段用于测试 HPKE 的代码,用于理解 HPKE 的运算流程!".encode()
print(f'plain:{plaintext.decode()}')
print(f'plain hash:{hashlib.sha256(plaintext).hexdigest()}')

# 定义HPKE所需的附加信息
    aead_info =b"HPKE AEAD INFO"
    psk =b"HPKE PSK DATA"
    psk_id =b"HPKE PSK ID"
    aad_tag =b"HPKE AEAD TAG"

# 分割线
print('########################')
# 分割线

# 生成Bob的公私钥对
# Bob的公钥是公开的Alice可以获取到
    bob_ec_private_key , bob_ec_public_key = generate_key_pair()

# 生成 alice 的公钥
    alice_ec_private_key , alice_ec_pubic_key = generate_key_pair()
    alice_public_key_for_auth = KEMKey.from_pem(alice_ec_pubic_key.public_bytes(
            encoding = serialization.Encoding.PEM ,
format= serialization.PublicFormat.SubjectPublicKeyInfo ,
))
    alice_private_key_for_auth = KEMKey.from_pem(alice_ec_private_key.private_bytes(
            encoding = serialization.Encoding.PEM ,
format= serialization.PrivateFormat.PKCS8 ,
            encryption_algorithm = serialization.NoEncryption(),
))

# Alice和Bob约定的密钥规格
# 使用KEM_P521_HKDF_SHA512作为KEM算法
# 使用HKDF_SHA512作为KDF算法
# 使用AES256_GCM作为AEAD算法
    alice_cipher_suite = CipherSuite.new(
            kem_id = KEMId.DHKEM_P521_HKDF_SHA512 ,
            kdf_id = KDFId.HKDF_SHA512 ,
            aead_id = AEADId.AES256_GCM ,
)

# Alice解析Bob的公钥
# 将Bob的公钥转换为PEM格式并从中提取出KEMKey对象
    peer_public_key_from_bob = KEMKey.from_pem(bob_ec_public_key.public_bytes(
            encoding = serialization.Encoding.PEM ,
format= serialization.PublicFormat.SubjectPublicKeyInfo ,
))

# Alice基于Bob的公钥生成临时公钥和加密上下文
# KEM阶段Alice使用Bob的公钥生成一个共享密钥
# 返回临时公钥字节和发送者上下文
    alice_tmp_enc_public_key_bytes , alice_sender = alice_cipher_suite.create_sender_context(
            pkr = peer_public_key_from_bob ,
            info = aead_info ,
            psk = psk ,
            psk_id = psk_id ,
            sks = alice_private_key_for_auth ,# 发送者使用私钥做身份验证
)
print(f'alice_tmp_enc_public_key hash:{hashlib.sha256(alice_tmp_enc_public_key_bytes).hexdigest()}')
print(f'alice_tmp_enc_public_key_bytes length:{len(alice_tmp_enc_public_key_bytes)}')

# 发送方Alice加密数据
# AEAD阶段Alice使用生成的上下文对明文进行加密
    ciphertext = alice_sender.seal(pt = plaintext , aad = aad_tag)
print(f'ciphertext hash:{hashlib.sha256(ciphertext).hexdigest()}')

# 分割线
print('########################')
# 分割线

# Bob配置相同的CipherSuite
    bob_cipher_suite = CipherSuite.new(
            kem_id = KEMId.DHKEM_P521_HKDF_SHA512 ,
            kdf_id = KDFId.HKDF_SHA512 ,
            aead_id = AEADId.AES256_GCM ,
)

# Bob解析自己的私钥
# 将Bob的私钥转换为PEM格式并从中提取出KEMKey对象
    bob_private_key = KEMKey.from_pem(bob_ec_private_key.private_bytes(
            encoding = serialization.Encoding.PEM ,
format= serialization.PrivateFormat.PKCS8 ,
            encryption_algorithm = serialization.NoEncryption(),
))

# Bob创建接收者上下文
# KEM阶段Bob使用自己的私钥和Alice的临时公钥生成共享密钥
# 返回接收者上下文
    bob_as_receiver = bob_cipher_suite.create_recipient_context(
            enc = alice_tmp_enc_public_key_bytes ,
            skr = bob_private_key ,
            info = aead_info ,
            psk = psk ,
            psk_id = psk_id ,
            pks = alice_public_key_for_auth ,# 发送者的公钥
)

# 接收方Bob解密数据
# AEAD阶段Bob使用生成的上下文对密文进行解密
    decrypted = bob_as_receiver.open(ciphertext , aad = aad_tag)
print(f'decrypted hash:{hashlib.sha256(decrypted).hexdigest()}')
print(f'decrypted: {decrypted.decode()}')
print('解密成功:', decrypted == plaintext)

最核心的参数变化为:

img

img

运行效果:

img