# 密钥分配

## 对称密钥的分配

对称密钥分配存在以下两个问题：

1. 如果 n 个人中的每一个需要和其他 n – 1 个人通信，就需要 n(n - 1) 个密钥。但每两人共享一个密钥，因此密钥数是 n(n - 1)/2。如果 n 是个很大的数，所需要的密钥数量就非常大。
2. 通信的双方怎样才能安全地得到共享的密钥呢？正是因为网络不安全，所以才需要使用加密技术。但密钥又需要怎样传送呢？

目前常用的密钥分配方式是设立密钥分配中心 **KDC（Key Distribution Center）**。KDC 是大家都信任的机构，其任务就是**给需要进行秘密通信的用户临时分配一个会话密钥（仅使用一次）**。

<figure><img src="https://2360649912-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2F3c4d4G2SmdXooqcxZXXU%2Fuploads%2FfzRAAKV4vHmqh0RFkVeX%2Fimage.png?alt=media&#x26;token=1bb307df-2f51-42f2-9844-622b4b4d1ecb" alt=""><figcaption></figcaption></figure>

在图中假定用户 A 和 B 都是 KDC 的登记用户。A 和 B 在 KDC 登记时就已经在 KDC 的服务器上安装了各自和 KDC 进行通信的主密钥 $$K\_A$$ 和  $$K\_B$$。密钥分配分为三个步骤：

1. 用户 A 向密钥分配中心 KDC 发送时用明文，说明想和用户 B 通信。在明文中给出 A 和 B 在KDC登记的身份。
2. KDC 用随机数产生“一次一密”的会话密钥 $$K\_{AB}$$ 供 A 和 B 的这次会话使用，然后向 A 发送回答报文。这个回答报文用 A 的密钥 $$K\_A$$ 加密。这个报文中包含这次会话使用的密钥 $$K\_{AB}$$ 和请 A 转给 B 的一个票据（ticket），该票据包括 A 和 B 在 KDC 登记的身份，以及这次会话将要使用的密钥 $$K\_{AB}$$。票据用 B 的密钥 $$K\_B$$ 加密，A 无法知道此票据的内容，因为 A 没有 B 的密钥 $$K\_B$$，当然 A 也不需要知道此票据的内容。
3. 当 B 收到 A 转来的票据并使用自己的密钥 $$K\_B$$ 解密后，就知道 A 要和他通信，同时也知道 KDC 为这次和 A 通信所分配的会话密钥 $$K\_{AB}$$。

此后，A 和 B就可使用会话密钥 $$K\_{AB}$$ 进行这次通信了。

> KDC 还可在报文中加入时间戳，以防止报文的截取者利用以前已记录下的报文进行重放攻击。
>
> 会话密钥 $$K\_{AB}$$ 是一次性的，因此保密性较高。而 KDC 分配给用户的密钥 $$K\_{A}$$ 和 $$K\_{B}$$，都应定期更换，以减少攻击者破译密钥的机会。

> **目前最出名的密钥分配协议是 Kerberos V5。**

## 公钥的分配

设想用户 A 要欺骗用户 B，A 可以向 B 发送一份伪造是 C 发送的报文，A 用自己的私钥进行数字签名，并附上 A 自己的公钥，谎称这公钥是 C 的。B 如何知道这个公钥不是 C 的呢？

显然，这需要有一个值得信赖的机构来将公钥与其对应的实体（人或机器）进行绑定（binding）。这样的机构就叫做<mark style="color:blue;">**认证中心 CA（Certification Authority）**</mark>。每个实体都有 CA 发来的证书（certificate），里面有公钥及其拥有者的标识信息（人名或 IP 地址）。此证书被 CA 进行了数字签名。
