跳到主要内容

5.1 Creating the Encryption Context (创建加密上下文)

5.1 Creating the Encryption Context (创建加密上下文)

本文档中定义的 HPKE 变体共享一个通用的密钥调度 (key schedule), 该调度将协议输入转换为加密上下文.密钥调度输入如下:

  • mode: 一个单字节值, 指示 HPKE 模式, 在表1中定义.

  • shared_secret: 为此事务生成的 KEM 共享秘密.

  • info: 应用程序提供的信息 (可选; 默认值为 "").

  • psk: 发送者和接收者都持有的预共享密钥 (PSK) (可选; 默认值为 "").

  • psk_id: PSK 的标识符 (可选; 默认值为 "").

发送者和接收者必须按照 7.1 节中的描述验证 KEM 输入和输出.

psk 和 psk_id 字段必须一起出现或完全不出现.也就是说, 如果为其中一个提供了非默认值, 则另一个也必须设置为非默认值.此要求在下面的 VerifyPSKInputs() 中编码.

psk, psk_id 和 info 字段具有最大长度, 这些长度取决于 KDF 本身, LabeledExtract() 的定义以及与它们一起使用的常量标签.有关这些长度的精确限制, 请参见 7.2.1 节.

密钥调度计算的 key, base_nonce 和 exporter_secret 具有以下属性: 它们仅为接收者私钥的持有者以及使用 KEM 生成 shared_secret 和 enc 的实体所知.

在 Auth 和 AuthPSK 模式中, 接收者可以确信发送者持有私钥 skS.对于本文档中定义的 DHKEM 变体, 由于密钥妥协冒充 (key-compromise impersonation), 此保证受到限制, 如 4.1 节和 9.1 节所述.在 PSK 和 AuthPSK 模式中, 如果按要求提供了 psk 和 psk_id 参数, 则接收者可以确信发送者持有相应的预共享密钥.有关更多详细信息, 请参见 9.1 节.

HPKE 算法标识符, 即 KEM kem_id, KDF kdf_id 和 AEAD aead_id 的 2 字节代码点, 分别在表 2, 3 和 5 中定义, 假定从实现中隐式获得, 而不作为参数传递.在 LabeledExtract 和 LabeledExpand 中使用的隐式 suite_id 值基于它们定义如下:

suite_id = concat(
"HPKE",
I2OSP(kem_id, 2),
I2OSP(kdf_id, 2),
I2OSP(aead_id, 2)
)

default_psk = ""
default_psk_id = ""

def VerifyPSKInputs(mode, psk, psk_id):
got_psk = (psk != default_psk)
got_psk_id = (psk_id != default_psk_id)
if got_psk != got_psk_id:
raise Exception("Inconsistent PSK inputs")

if got_psk and (mode in [mode_base, mode_auth]):
raise Exception("PSK input provided when not needed")
if (not got_psk) and (mode in [mode_psk, mode_auth_psk]):
raise Exception("Missing required PSK input")

def KeySchedule<ROLE>(mode, shared_secret, info, psk, psk_id):
VerifyPSKInputs(mode, psk, psk_id)

psk_id_hash = LabeledExtract("", "psk_id_hash", psk_id)
info_hash = LabeledExtract("", "info_hash", info)
key_schedule_context = concat(mode, psk_id_hash, info_hash)

secret = LabeledExtract(shared_secret, "secret", psk)

key = LabeledExpand(secret, "key", key_schedule_context, Nk)
base_nonce = LabeledExpand(secret, "base_nonce",
key_schedule_context, Nn)
exporter_secret = LabeledExpand(secret, "exp",
key_schedule_context, Nh)

return Context<ROLE>(key, base_nonce, 0, exporter_secret)

ROLE 模板参数是 S 或 R, 分别取决于发送者或接收者的角色.有关密钥调度输出 (包括特定于角色的 Context 结构及其 API) 的讨论, 请参见 5.2 节.

请注意, KeySchedule() 中的 key_schedule_context 构造等效于在 TLS 表示语法中序列化以下形式的结构:

struct {
uint8 mode;
opaque psk_id_hash[Nh];
opaque info_hash[Nh];
} KeyScheduleContext;