[translate]设计一个认证系统


=Start=

缘由:

最近在学习 Kerberos 协议的时候仔细看了一下由 Bill Bryant 写于 1988 年的文章 Designing an Authentication System: a Dialogue in Four Scenes,该文章通过4场对话将设计一个认证系统中需要面临的典型问题都提了出来,并针对其中的大部分问题提供了可行的解决方案和思路。虽然文章写的早,当时也主要是为了让人们更容易理解 Kerberos 协议(V4版本)做的描述,但按照文章整理人的说法——其中体现出的核心思想和V5版本基本一致,除了少量区别之外。

通过跟着文中 Athena 的思路逐步深入,会更容易理解 Kerberos 等身份认证协议的作用和设计原理,对不了解底层逻辑的人来说帮助很大,值得花时间思考和学习。

正文:

参考解答:
精简总结:

# Scene I - 场景一

>>> 格子间里的第一次相遇,Athena 向 Euripides 抱怨分时系统的缺陷(如果当前已登录的人数满了,新的用户就无法登录,也就无法正常工作从而影响效率),同时提出一个她的愿景——每个人都能有自己的工作站,同时打印/邮件/文件存储等公用功能由专职服务器来承担。Euripides 指出 Athena 想法不成熟的地方——没有认证系统,导致网络上的服务器不能知道谁是谁,因此能够冒用身份做一些不可控的恶意行为。(Athena会回去思考新的方案来解决对话中提到的各种设计缺陷,直到能基本满足要求)

# Scene II - 场景二

>>> Athena 回去之后更新了一下她的设计,其中包含几个特点:

1. 用户向服务发起请求以实现特定功能并不是由用户直接发起,而是由一个agent代理发起,这个agent代理是这个服务的客户端,专门用来做此项工作的;
2. 在这个认证系统中,不仅用户有密码,服务也有密码,而认证系统 Charon 知道所有的密码,密码存储在单个集中式数据库中;
3. 认证系统流程概述:当你要使用某个服务A时,先向 Charon 提供你的账号密码,然后它在内部进行匹配,若能匹配成功,则认为你的身份得到了证实,并给你发送一个票证 ticketA(enc{username}) ,里面包含使用服务A的密码加密的用户名;然后你拿着刚颁发的票证 ticketA 向服务A发起请求,服务A接收到 ticketA 之后尝试用自己的密码进行解密,若解密成功且 username 和发起请求的为同一个账号,则会按照需求正常提供服务;

4. 经建议,在票证 ticket 中添加一个 servicename 会有助于服务判断是否解密成功,即 ticket(enc{username,servicename}) ;
5. 经建议,再添加一个 ip_address 信息可以支持和请求发起人的 ip_address 信息做比对,防止票证被盗用,即 ticket(enc{username,ip_address,servicename}) ;
6. 除此之外还有一些问题没有解决,比如每次想用一个新服务时都需要重复输入账号密码,这种方式不安全,用户体验也很差。

>>> 上面的这个设计已经和现在常规的账号密码认证方式很像了,相比而言有其优点(类似SSO的多服务复用同一密码)也有缺点(每次都输入密码,票证容易被盗用),整体比较简单和初级。

# Scene III - 场景三

>>> 场景三比前两个场景进行了更多的讨论,设计也随着讨论的深入进行了更多的更改:

>>> Athena 将之前 Euripides 提到的几个问题转换成了一些系统的基本要求:

>>> 1. 用户只需在工作站会话开始时输入一次密码——这是通过新发明一个 ticket-granting 服务来实现的,它会向通过身份认证的用户发放一个 TGT(ticket-granting ticket,票证授予票证),这个新服务其实是 Charon 的一部分,它可以让你后面使用 TGT 而不是密码来证实自己的身份;

>>> 2. 密码不应以明文形式通过网络发送——当你使用 kinit 程序获取 TGT-票证授予票证 时,kinit 不会将你的密码发送到 Charon 服务器,kinit 只会发送你的用户名,然后 Charon 使用接收到的用户名来查找密码,找到了之后会用你的密码对票证信息进行加密然后将内容返回,接收到返回之后 kinit 提示你输入你的密码,输入之后 kinit 尝试用你输入的密码解密 TGT-票证授予票证,若解密成功,则你已成功向 Charon 证明自己。但是接下来如何用 TGT 来生成 ST 没有细说,应该是复用上面场景二中的部分逻辑。

>>> 到现在这个阶段,用户体验已经很好了——你只需要正确输入一次用户名密码(且密码还不会通过网络传输),就能借助新设计的 ticket-granting 服务生成 TGT 来实现后续的免密访问。但是这样的安全风险也很大,因为现在的设计中服务票据(ST,service ticket)是能够重复使用的,如果服务票据被窃取了,那你在这些服务中的身份也就被窃取了。所以需要给服务票据添加一些额外信息来限制服务票据的有效期。现在服务票据的格式是 enc{username:ip_address:servicename:lifespan:timestamp} 。但即便是这样也有一些问题,比如有效期内的重放攻击等。

# Scene IV - 场景四

>>> 在上一幕的讨论结束时有一个明确的遗留问题——服务票据(ST)在有效期内的重放攻击,对这个问题 Athena 将问题归结为——服务如何判断使用票据的人与真实票据所有人是同一个?(实际上这并不能解决重放攻击的问题,解决重放需要增加一个计数器,让相关authenticator不能重复使用)

>>> Athena 回溯了一下身份认证的过程,试图从中找到解决思路,客户端和服务端交互时发送的内容为 username,ip_address,ticket(enc{username:ip_address:servicename:lifespan:timestamp}) 这里面ticket是用服务的密码进行加密生成的内容,也就只有服务能解开。服务接到ticket之后正常解开可以拿到用户名、网络地址、服务名称和有效期做比对,这些校验做完之后最多只能说明ticket是 Charon 签发的,但说明不了票是不是真的来自于票的实际拥有人,因为客户端和服务端之间当前没有更多互相共享的信息了。解决的办法就是增加一个只有它们两者才知道的会话密钥(sessionkey)。

>>> 但是 Charon 如何将会话密钥分发给用户和服务是个问题。一开始 Athena 想的是——直接在 Charon 给用户的回复中同时提供会话密钥和票证 enc_by_userkey{sessionkey:ticket} 内容通过用户密码进行加密;给服务分发会话密钥是通过把会话密钥包含在加密的票证里面 ticket=enc_by_servicekey{sessionkey:username:ip_address:servicename:lifespan:timestamp} ,用户可以在用自己的密码解密返回的内容之后拿到 sessionkey ,然后将 ticket 在后面的请求中直接转发给服务,服务拿自己的密码解密之后可以看到和用户一样的 sessionkey ,这样就完成了只有用户和服务才知道的 sessionkey 的分发。

>>> 当你想获得一项服务时,客户端会先构建一个 AUTHENTICATOR-身份验证器 ,它里面包含用户名和网络地址,并使用上面的会话密钥加密 enc_by_sessionkey{username:ip_address} ,然后将其和刚才解密提取出的 ticket 一起发送到服务端,该服务一开始还无法解密身份验证器,因为它没有会话密钥。该会话密钥在票证ticket中,因此服务首先解密票证ticket。解密票证之后,若票证还在有效期内,才会用刚才得到的会话密钥来解密身份验证器。如果解密顺利进行,则服务会拿到其中的用户名和网络地址。服务会根据票证中的姓名和地址以及发送票证的人的姓名和地址以及从身份验证器中提取的信息来进行验证。如果一切都匹配,则服务已确定票证发送者确实是票证的真正所有者。

>>> 但即便是上面这种设计也无法完全解决重放的问题,因为攻击者可以同时监听窃取 ticket 和 authenticator ,然后再针对性的修改它的 username+ip_address 就可以在票证的有效期内完成重放攻击。即便是给 authenticator-身份验证器 里面添加过期时间等信息,也只是降低了被重放攻击的可能但并没有从源头上解决问题。真正有效的办法是增加一个检查,让身份验证器只可使用一次而不能被重复使用(不过对话中最后并没有采用,这个问题在 Kerberos V5 中得到了解决)。

I'll state the problem by way of contrast. Without session keys and authenticators, Charon can protect its servers from false users, but it cannot protect its users from false servers. The system needs a way for client programs to authenticate the server before sending sensitive information to the service. The system must allow for mutual authentication.
如果没有 会话密钥-sessionkey 和 身份验证器-authenticator ,Charon 只能保护服务免受虚假用户的干扰,但它没法保护用户被虚假服务欺骗,认证系统需要一个方法能让client在发送敏感信息到服务之前验证服务身份的能力,也即让 client 和 service 互相能进行双向认证。

会话密钥-sessionkey 解决了这个问题(如果设计得当的话),client 用 sessionkey 对要发送给 service 的内容进行加密,合法的 service 才有 sessionkey 能正确解密请求(通过这一步service验证了client的身份,因为它有sessionkey);然后 service 用 sessionkey 将要返回的信息进行加密,client 拿到加密信息之后可以用 sessionkey 解密,这时可以证明 service 也是合法的,从而完成了双向认证。
# 摘要

这段对话虚构了一个名为“Charon”的开放网络身份验证系统的设计。随着对话的进行,Athena和Euripides发现了开放网络环境中固有的安全问题。每个问题都必须在Charon的设计中得到解决,设计也得到相应地发展。Athena和Euripides直到对话结束才完成他们的工作(不过在防重放攻击的问题上还是存在缺陷,不过在当时而言已经基本够用了)。

当他们完成系统的设计后,Athena将系统的名称更改为“Kerberos”,非常巧合的是,这个名称是在MIT的Athena项目中设计和实现的认证系统的名称。对话中的“Kerberos”系统与在1988年德克萨斯州达拉斯冬季USENIX大会上介绍的 Kerberos: An Authentication Service for Open Network Systems 中描述的系统惊人地相似。

# 人物介绍

Athena    一个有前途的系统开发人员(an up and coming system developer.)
Euripides    一个经验丰富的开发人员和常驻怪人(a seasoned developer and resident crank.)

# Scene I - 场景一

>>> 格子间里的第一次相遇,Athena 向 Euripides 抱怨分时系统的缺陷(如果当前已登录的人数满了,新的用户就无法登录),同时提出一个她的愿景——每个人都能有自己的工作站,同时打印/邮件/文件存储等公用功能由专职服务器来承担。Euripides 指出 Athena 想法不成熟的地方——没有认证系统,导致网络上的服务器不能知道谁是谁,因此能够冒用身份做一些不可控的恶意行为。(Athena会回去思考新的方案来解决对话中提到的各种设计缺陷,直到能基本满足要求)

格子间里,Athena 和 Euripides 正在相邻的工位工作。

Athena:    嘿,大哥,这个分时系统真是个累赘。我什么工作都干不了,因为其他人都已登录了。
Euripides: 不要向我抱怨。我只在这里工作。

Athena:    你知道我们需要什么吗?我们需要为每个人提供自己的工作站,这样他们就不必担心共享计算周期。同时我们将使用网络连接所有工作站,这样人们就可以相互交流。 You know what we need? We need to give everyone their own workstation so they don't have to worry about sharing computer cycles. And we'll use a network to connect all the workstations so folks can communicate with one another.
Euripides:    美好的愿望。那么我们需要什么,大约一千个工作站?Fine. So what do we need, about a thousand workstations?

Athena:    差不多吧。More or less.
Euripides:    你见过典型工作站磁盘驱动器的大小吗?分时机器上甚至都没有足够的空间来装下所有的软件。 Have you seen the size of a typical workstation's disk drive? There isn't enough room for all the software that you have on a timesharing machine.

Athena:    我已经想过了。我们可以在各种服务器上保留系统软件的副本。当你登录到工作站时,工作站通过与其中一台服务器建立网络连接来访问系统软件。这种设置让一大群工作站使用相同的系统软件副本,并且使软件更新变得方便。你不必四处走动到每个工作站。只需修改系统软件服务器。 I figured that out already. We can keep copies of the system software on various server machines. When you login to a workstation, the workstation accesses the system software by making a network connection with one of the servers. This setup lets a whole bunch of workstations use the same copy of the system software, and it makes software updates convenient. You don't have to trundle around to each workstation. Just modify the system software servers.
Euripides:    好的。你打算怎么处理个人文件?使用分时系统,我可以从任何连接到系统的终端登录并访问我的文件。我可以走到任何工作站并自动获取我的文件吗?还是我必须像 PC 用户一样将文件保存在软盘上?我希望不是这样。 All right. What are you going to do about personal files? With a timesharing system I can login and get to my files from any terminal that is connected to the system. Will I be able to walk up to any workstation and automatically get to my files? Or do I have to make like a PC user and keep my files on diskette? I hope not.

Athena:    我认为我们可以使用其他机器来提供个人文件存储。你可以登录到任何工作站并访问你的文件。 I think we can use other machines to provide personal file storage. You can login to any workstation and get to your files.
Euripides:    打印呢?每个工作站都需要有自己的打印机吗?你准备用谁的钱来这么办?还有电子邮件呢?你准备怎么将邮件分发到所有这些工作站? What about printing? Does every workstation have its own printer? Whose money are you spending anyway? And what about electronic mail? How are you going to distribute mail to all these workstations?

Athena:    嗯……很明显,我们没有足够的钱给每个人分配一台打印机,但我们可以有专门用于打印服务的机器,你将作业发送到打印服务器,它会为你打印。邮件收发也一样,安排一台专门用于邮件服务的机器。你想要你的邮件,你联系邮件服务器然后它会把你的邮件发给你。 Ah . . . Well obviously we don't have the cash to give everyone a printer, but we could have machines dedicated to print service. You send a job to a print server, and it prints it for you. You could do sort of the same thing with mail. Have a machine dedicated to mail service. You want your mail, you contact the mail server and pick up your mail.
Euripides:    你的工作站系统听起来很不错。当我拿到我的邮件,你知道接下来我要做什么吗?我会找出你的用户名,让我的工作站认为我是你。然后我再联系邮件服务器获取你的邮件。我将联系你的文件服务器并删除你的文件,以及一系列的操作…… Your workstation system sounds really good Tina. When I get mine, you know what I'm going to do? I'm going to find out your username, and get my workstation to think that I am you. Then I'm going to contact the mail server and pick up your mail. I'm going to contact your file server and remove your files, and--

Athena:    你能做到吗? Can you do that?
Euripides:    当然!这些网络服务器怎么知道我不是你? Sure! How are these network servers going to know that I'm not you?

Athena:    哎,我不知道。我想我需要做一些思考。 Gee, I don't know. I guess I need to do some thinking.
Euripides:    听起来是这样,当你想清楚了告诉我。 Sounds like it. Let me know when you figure it out.


# Scene II - 场景二

>>> Athena 想出了一个设计,其中包含几个特点:
>>> 1. 用户向服务发起请求以实现特定功能并不是由用户直接发起,而是由一个agent代理发起,这个agent代理是这个服务的客户端,专门用来做此项工作的;
>>> 2. 不仅用户有密码,服务也有密码,而认证系统 Charon 知道所有的密码,密码存储在单个集中式数据库中;
>>> 3. 系统流程概述:当你要使用某个服务A时,先向 Charon 提供你的账号密码,然后它在内部进行匹配,若能匹配成功,则认为你的身份得到了证实,并给你发送一个票证 ticketA(enc{username}) ,里面包含使用服务A的密码加密的用户名,服务A接到票证 ticketA 之后用自己的密码进行解密,若解密成功且 username 和发起请求的为同一个账号,则会按照需求正常提供服务;
>>> 4. 经建议,在票证 ticket 中添加一个 service name 会有助于服务判断是否解密成功,即 ticket(enc{username,servicename}) ;
>>> 5. 经建议,再添加一个 ip_address 信息可以支持和请求发起人的 ip_address 信息做比对,防止票证被盗用,即 ticket(enc{username,ip_address,servicename}) ;
>>> 6. 除此之外还有一些问题没有解决,比如每次想用一个新服务时都需要重复输入账号密码,这种方式不安全,用户体验也很差。
>>> 上面的这个设计已经和现在常规的账号密码认证方式很像了,相比而言有其优点(类似SSO的多服务复用同一密码)也有缺点(每次都输入密码),比较简单和初级。


第二天早晨在 Euripides 的办公室里,Euripides 正坐在书桌前看他的信件。Athena 敲了敲门。

Athena:    我已经想到了该如何保护一个开放的网络环境(的方法),这样像你这样不道德的人就不能以其他人的名义使用网络服务。 Well I've figured out how to secure an open network environment so that unscrupulous folks like you cannot use network services in other people's names.
Euripides:    真的吗?让我们坐下来聊一聊。 Is that so? Have a seat.

Athena 坐了下来。

Athena:    在我进行描述之前,我可以为这个讨论制定一个基本规则吗? Before I describe it, can I lay down one ground rule about this discussion?
Euripides:    你的规则是什么? What's your rule?

Athena:    假设当我说:“我想要我的电子邮件,所以我联系邮件服务器并要求它将邮件发送到我的工作站。”实际上,我不是直接联系邮件服务器的实体,而是使用一个程序来联系邮件服务器并检索我的邮件,该程序是邮件服务程序的客户端。但是我不想每次提到用户和网络服务器之间的事务时都说“客户端做某事”。我只想说“我做某事”,当然要记住客户端程序正在代表我做事。这样你觉得可以吗?
Well suppose I say something like the following: "I want my electronic mail, so I contact the mail server and ask it to send the mail to my workstation." In reality I'm not the entity that contacts the mail server. I'm using a program to contact the mail server and retrieve my mail, a program that is a CLIENT of the mail service program.

But I don't want to say "the client does such-and-such" every time I refer to a transaction between the user and a network server. I'd just as soon say "I do such-and-such," keeping in mind of course that a client program is doing things on my behalf. Is that okay with you?

Euripides:    可以,没问题。 Sure. No problem.

Athena:    好的。我将首先说明我已解决的问题。在开放的网络环境中,提供服务的机器必须能够确认请求服务的人的身份。如果我联系邮件服务器并索要我的邮件,服务程序必须能够验证我是我声称的那个人,对吗? Good. All right, I'll begin by stating the problem I have solved. In an open network environment, machines that provide services must be able to confirm the identities of people who request service. If I contact the mail server and ask for my mail, the service program must be able to verify that I am who I claim to be, right?
Euripides:    是的。 Right.

Athena:    你可以通过要求邮件服务器在我使用它之前要求输入密码来笨拙地解决这个问题。我通过向服务器提供我的密码来证明我是谁。 You could solve the problem clumsily by requiring the mail server to ask for a password before I could use it. I prove who I am to the server by giving it my password.
Euripides:    这样做很笨拙。在这样的系统中,每个服务器都必须知道你的密码。如果网络有一千个用户,每台服务器必须知道一千个密码。如果你想更改密码,你必须联系所有服务器并通知他们更改。我认为你的系统没有这么愚蠢。 That's clumsy all right. In a system like that, every server has to know your password. If the network has one thousand users, each server has to know one thousand passwords. If you want to change your password, you have to contact all servers and notify them of the change. I take it your system isn't this stupid.

Athena:    我的系统并不愚蠢。它的工作原理是这样的:不仅人有密码,服务也有密码。每个用户都知道她或他的密码,每个服务程序都知道自己的密码,并且有一个 AUTHENTICATION SERVICE 知道所有密码——每个用户的密码,以及每个服务的密码。身份验证服务将密码存储在单个集中式数据库中。 My system isn't stupid. It works like this: Not only do people have passwords, services have passwords too. Each user knows her or his password, each service program knows its password, and there's an AUTHENTICATION SERVICE that knows ALL passwords--each user's password, and each service's password. The authentication service stores the passwords in a single, centralized database.
Euripides:    这个身份验证服务有名字吗? Do you have a name for this authentication service?

Athena:    我还没有想到。你有什么想法吗? I haven't thought of one yet. Do you have any ideas?
Euripides:    那个运送死者过冥河的家伙叫什么名字? What's the name of that fellow who ferries the dead across the River Styx?

Athena:    Charon?
Euripides:    对,就是他。除非你能证明你的身份,否则他不会带你过河。 Yeah, that's him. He won't take you across the river unless you can prove your identity.

Athena:    去你的,你在尝试改写希腊神话。Charon 并不在乎你的身份。他只是想确定你已经死了。 There you go Rip, trying to rewrite Greek mythology again. Charon doesn't care about your identity. He just wants to make sure that you're dead.
Euripides:    你有更好的名字吗? Have you got a better name?

Pause.
Athena:    没,还没有。 No, not really.
Euripides:    那让我们将身份验证服务称为“Charon”吧。 Then let's call the authentication service "Charon."

Athena:    
好的。我想我应该具体描述一下系统的工作原理,对吧? Okay. I guess I should describe the system, huh?

假设你想使用邮件服务,在我的系统设计中,除非 Charon 告诉服务你就是你声称的那个人否则你就无法使用该服务。除非你向 Charon 证明了自己的身份,否则你无法获得使用服务的许可。当你向 Charon 请求身份验证时,你必须告诉 Charon 你想要的服务。如果你想使用邮件服务器,你必须明确告诉 Charon。
Let's say you want to use a service, the mail service. In my system you cannot use a service unless, ah, Charon tells the service that you are who you claim to be. And you can't get the okay to use a service unless you have authenticated yourself to Charon. When you request authentication from Charon, you have to tell Charon the service for which you want the okay. If you want to use the mail server, you've got to tell Charon.

Charon 要求你证明你的身份。你可以通过提供你的密码来做到这一点。Charon 获取你的密码并将其与在 Charon 数据库中为你注册的密码进行比较。如果两个密码匹配,Charon 认为你的身份已得到证实。
Charon asks you to prove your identity. You do so by providing your secret password. Charon takes your password and compares it to the one that is registered for you in the Charon database. If the two passwords match, Charon considers your identity proven.

Charon 现在必须让邮件服务器相信你就是你所说的那个人。由于 Charon 知道所有服务密码,它知道邮件服务的密码。可以想象,Charon 可以给你密码,你可以将其转发到邮件服务,作为你已向 Charon 验证自己的证明。
Charon now has to convince the mail server that you are who you say you are. Since Charon knows all service passwords, it knows the mail service's password. It's conceivable that Charon could give you the password, which you could forward to the mail service as proof that you have authenticated yourself to Charon.

问题是,Charon 不能直接给你密码,因为那样你就知道了。下次你想要邮件时,你可以绕过 Charon 直接使用邮件服务器,而无需证明你是谁。你甚至可以伪装成其他人,并以其他人的名义使用邮件服务器。
The problem is, Charon cannot give you the password directly, because then you would know it. The next time you wanted mail, you could circumvent Charon and use the mail server without correctly identifying yourself. You could even pretend to be someone else, and use the mail server in that other person's name.

因此,Charon 不会给你邮件服务器的密码,而是给你一个邮件服务 TICKET。此票证包含已使用邮件服务器的密码加密的用户名信息。
So instead of giving you the mail server's password, Charon gives you a mail service TICKET. This ticket contains a version of your username that has been ENCRYPTED USING the MAIL SERVER'S PASSWORD.

拿到票后,你现在可以向邮件服务索要你的邮件。你通过告诉邮件服务器你是谁来提出你的请求,并用票来证明你就是你所说的那个人。
Ticket in hand, you can now ask the mail service for your mail. You make your request by telling the mail server who you are, and furnishing the ticket that proves you are who you say you are.

服务器使用它自己的密码解密票证,如果票证正确解密,则服务器以 Charon 放置在票证中的用户名结束。
The server uses its password to decrypt the ticket, and if the ticket decrypts properly, the server ends up with the username that Charon placed in the ticket.

该服务将此用户名与你随票证发送的用户名进行比较。如果两者匹配,邮件服务器会认为你的身份已得到证实并继续向你提供邮件。
The service compares this name with the name you sent along with the ticket. If the names match, the mail server considers your identity proven and proceeds to give you your mail.

你认为这个办法怎么样?
What do you think of those apples?

Euripides:    我有一些问题。 I've got some questions.

Athena:    猜到就会这样,你说吧。 I figured. Well go ahead.
Euripides:    当服务程序解密票证时,它如何知道它已正确解密票证? When a service program decrypts a ticket, how does it know that it has decrypted the ticket properly?

Athena:    我不知道。 I don't know.
Euripides:    也许你应该在票证中包含服务的名称。这样,当服务解密票证时,它可以根据是否能在解密票证中找到其名称来衡量其成功与否。 Maybe you should include the service's name in the ticket. That way when a service decrypts a ticket, it can gauge its success on whether or not it can find its name in the decrypted ticket.

Athena:    
听起来不错。所以票看起来像这样(至少包含{username:servicename}):
That sounds good to me. So the ticket looks something like this:
(She scrawls the following on a pad of paper:)
   TICKET -  {username:servicename}
Euripides:    所以票证只包含用户名和服务名称? So the service ticket contains just your username and the servicename?

Athena:    用服务的密码进行加密。 Encrypted with the service's password.
Euripides:    我认为这些信息不足以确保票证安全。 I don't think that's enough information to make the ticket secure.

Athena:    那你的意思是? What do you mean?
Euripides:    假设你向 Charon 申请邮件服务器的票证。Charon 准备好了票证——其中包含你的用户名“tina”。现在假设我复制那张票,因为它在从 Charon 到你的网络中飞驰而过。假设我让不安全的工作站相信我的用户名是“tina”。我工作站上的邮件客户端程序认为我是你。程序以你的名义将被盗的票证转发到邮件服务器。服务器解密票证并看到它是有效的。票证中的用户名与发送票证的用户名相匹配,然后邮件服务器把你的邮件发给了我……
Let's suppose you ask Charon for a mail server ticket. Charon prepares that ticket so that it has your username "tina" in it. Suppose I copy that ticket as it wizzes by on its way across the network from Charon to you. Suppose I convince my insecure workstation that my username is "tina." The mail client program on my workstation thinks I am you. In your name, the program forwards the stolen ticket to the mail server. The server decrypts the ticket and sees that it is valid. The username in the ticket matches the name of the user who sent the ticket. The mail server gives me your mail . . .

Athena:    哦!好吧,那不是很好。 Oh! Well that's not so good.
Euripides:    

但我想我知道解决这个问题的方法,或者至少对其提供部分修复。我认为 Charon 应该在它生成的服务票据中包含更多信息——除了用户名之外,票证还应包括用户向 Charon 申请票证的网络地址。这为你提供了额外的安全级别。
But I think I know a way to fix this problem. Or to at least provide a partial fix to it. I think Charon should include more information in the service tickets it produces. In addition to the username, the ticket should also include the NETWORK ADDRESS from which the user asked Charon for the ticket. That gives you an additional level of security.

举例来说,假设我现在偷了你的票证。票证中有你工作站的网络地址,而此地址与我的工作站地址不匹配。以你的名义,我将被盗的票转发到邮件服务器。服务器程序从票证中提取用户名和网络地址,并尝试将该信息与发送票证的实体的用户名和网络地址进行匹配。用户名匹配,但网络地址不匹配。服务器拒绝该票,因为它显然是被盗的。
I'll illustrate. Suppose I steal your mail ticket now. The ticket has your workstation's network address in it, and this address does not match my workstation's address. In your name I forward the purloined ticket to the mail server. The server program extracts the username and network address from the ticket and attempts to match that information against the username and network address of the entity that sent the ticket. The username matches, but the network address does not. The server rejects the ticket because obviously it was stolen.

Athena:    真棒,真棒!我真希望我能想到这一点。 Bravo, bravo! I wish I had thought of that.
Euripides:    这就是我在这的意义。 Well that's what I'm around for.

Athena:    
所以修改后的票证设计是这样的{username:ip_address:servicename}:
So the revised ticket design looks like this:

She scrawls the following on a chalkboard:
  TICKET -   {username:ws_address:servicename}

Athena:    现在我真的很兴奋。让我们建立一个 Charon 系统来看它是否真的有效! Now I'm really excited. Let's build a Charon system and see if it works!
Euripides:    没那么快。我对你的系统还有其他一些问题。 Not so fast. I have some other questions about your system.

Athena:    好吧,请继续。 All right. (Athena leans forward in her chair) Shoot.
Euripides:    听起来我每次想使用服务时都必须获得一张新票。如果我要投入一天的工作,我可能会想要不止一次地收到我的邮件。每次我想收到我的邮件时,我都必须获得一张新票吗?如果这是真的,我不喜欢你的系统。 Sounds like I've got to get a new ticket every time I want to use a service. If I'm putting in a full day's work, I'll probably want to get my mail more than once. Do I have to get a new ticket every time I want to get my mail? If that's true, I don't like your system.

Athena:    呃……好吧,我不明白为什么票不能重复使用。如果你得到了邮件服务器的票,你应该可以一次又一次地使用它。例如,当邮件客户端程序以你的名义请求服务时,它会将票证的副本转发到邮件服务器。 Ah . . . Well I don't see why tickets can't be reusable. If you get a ticket for the mail server, you ought to be able to use it again and again. For instance, when the mail client program makes a request for service in your name, it forwards a COPY of the ticket to the mail server.
Euripides:    这样好一些了。但我仍然有问题。你似乎暗示每次我想使用我还没有票的服务时,我都必须给 Charon 我的密码。我登录并想访问我的文件。我向 Charon 发出了正确票证的请求,这意味着我必须使用我的密码。然后我想阅读我的邮件。向 Charon 发起另一个请求,我必须再次输入我的密码。现在假设我想将我的一封邮件发送到打印服务器。又要再向 Charon 发一个请求,你明白我的意思吗? That's better. But I still have problems. You seem to imply that I have to give Charon my password every time I want to use a service for which I don't have a ticket. I login and want to access my files. I fire off a request to Charon for the proper ticket and this means that I've had to use my password. Then I want to read my mail. Another request to Charon, I have to enter my password again. Now suppose I want to send one of my mail messages to the print server. Another Charon request and, well you get the picture.

Athena:    嗯,是的,我理解了。 Uh, yeah, I do.
Euripides:    如果你觉得这还不够糟糕,请考虑一下:听起来当你向 Charon 验证自己的身份时,你会通过网络以明文形式发送你的密码。像你这样聪明的人真的可以监控网络并窃取人们的密码副本。如果我有你的密码,我可以使用你名下的任何服务。Athena 叹了口气。 And if that weren't bad enough, consider this: it sounds like when you authenticate yourself to Charon, you send your secret password over the network in cleartext. Clever people like yours truly can monitor the network and steal copies of people's passwords. If I've got your password, I can use any service in your name. Athena sighs.

Athena:    这些都是很严重的问题。我想我需要回去再好好想想。 These are serious problems. Guess I need to go back to the drawing board.


# Scene III - 场景三

>>> 场景三比前2个场景进行了更多的讨论,设计也随着讨论的深入需要进行更多的修改:

>>> Athena 将之前 Euripides 提到的几个问题转换成了一些系统的基本要求:

>>> 1. 用户只需在工作站会话开始时输入一次密码——这是通过新发明一个 ticket-granting 服务来实现的,它会向通过身份认证的用户发放一个 TGT(ticket-granting ticket, 票证授予票证),这个新服务其实是 Charon 的一部分,它可以让你后面使用TGT而不是密码来证实自己的身份;

>>> 2. 密码不应以明文形式通过网络发送——当你使用 kinit 程序获取 TGT票证授予票证 时,kinit 不会将你的密码发送到 Charon 服务器,kinit 只会发送你的用户名,然后 Charon 使用用户名来查找你的密码,找到了之后会用你的密码对票证信息进行加密然后将内容返回,接收到返回之后 kinit 提示你输入你的密码,输入之后 kinit 尝试使用你输入的密码解密票证,若解密成功,则你已成功向 Charon 证明自己。但是接下来如何用 TGT 来生成 ST 好像没有细说?

>>> 到现在这个阶段,用户体验已经很好了——你只需要正确输入一次用户名密码(且密码还不会通过网络传输),就能借助新设计的 ticket-granting 服务生成 TGT 来实现后续的免密访问。但是这样的安全风险也很大,因为现在的设计中服务票据(ST,service ticket)是能够重复使用的,如果服务票据被窃取了,那你在这些服务中的身份也就被窃取了。所以需要给服务票据添加一些额外信息来限制服务票据的有效期。现在服务票据的格式是 enc{username:ip_address:servicename:lifespan:timestamp} 。但即便是这样也有一些问题,比如有效期内的重放攻击等。


第二天早晨,Athena 在咖啡区找到了 Euripides 。Athena 在 Euripides 倒咖啡的时候拍了拍 Euripides 的肩膀。然后两人共同走向咖啡机。

Athena:    我又设计了一个新版本的 Charon 可以解决我们的问题。 I've got a new version of Charon that solves our problems.
Euripides:    真的吗?这么快就解决了? Really? That was quick.

Athena:    嗯,你知道,这种性质的问题让我彻夜难眠。 Well, you know, problems of this nature keep me up all night.
Euripides:    一定是你的心虚。我们要不要移到那个小会议室? Must be your guilty conscience. Shall we repair to yon small conference room?

Athena:    为什么不呢? Why not?
两人搬到小会议室。 The two move to the small conference room.

Athena:    我将再次先复述之前问题,但这次我会将它们转换成为系统的要求。 I'll begin by stating the problems again, but I'll invert them so that they become requirements of the system.
Athena 清了清嗓子。 Athena clears her throat.
Athena:    第一个要求:用户只需在工作站会话开始时输入一次密码。此要求意味着你不必在每次需要新服务票证时都输入密码。第二个要求:密码不应以明文形式通过网络发送。 The first requirement: Users only have to enter their passwords once, at the beginning of their workstation sessions. This requirement implies that you shouldn't have to enter your password every time you need a new service ticket. The second requirement: passwords should not be sent over the network in clear text.
Euripides:    好的。 Okay.

Athena:    
我将从第一个要求开始:你应该只需要使用一次密码。我通过发明一种新的网络服务来满足这个要求。它被称为“ticket-granting”服务,该服务向已经向 Charon 证明其身份的用户发放 Charon 门票。如果你有票证,你可以使用此票证授予服务,即票证授予票证。
I'll start with the first requirement: you should only have to use your password once. I've met this requirement by inventing a new network service. It's called the "ticket-granting" service, a service that issues Charon tickets to users who have already proven their identity to Charon. You can use this ticket-granting service if you have a ticket for it, a ticket-granting ticket.

票证授予服务实际上只是 Charon 的一个版本,因为它可以访问 Charon 数据库。它是 Charon 的一部分,可让你使用票证而不是密码来验证自己。
The ticket-granting service is really just a version of Charon in as much as it has access to the Charon database. It's a part of Charon that lets you authenticate yourself with a ticket instead of a password.

无论如何,验证系统现在的工作方式如下:你登录到工作站并使用名为 kinit 的程序联系 Charon 服务器。你向 Charon 证明你的身份,然后 kinit 程序会为你提供一张票据授权票据。
Anyhow, the authentication system now works as follows: you login to a workstation and use a program called kinit to contact the Charon server. You prove your identity to Charon, and the kinit program gets you a ticket-granting ticket.

现在假设你想从邮件服务器获取你的邮件。你还没有邮件服务器票证,因此你使用“ticket-granting”票证为你获取邮件服务器票证。你无需使用密码即可获得新票。
Now say you want to get your mail from the mail server. You don't have a mail server ticket yet, so you use the "ticket-granting" ticket to get the mail server ticket for you. You don't have to use your password to get the new ticket.

Euripides:    每次我需要访问另一个网络服务时,我是否必须获得新的“授予票证”票证? Do I have to get a new "ticket-granting" ticket every time I need to get to another network service?.

Athena:    不,请记住,我们上次同意票可以重复使用。一旦你已经获得了授予票证的票证,你就无需再获得另一个授予票证的票证。你使用授予票证的票证来获取你需要的其他票证。 No. Remember, we agreed last time that tickets can be reused. Once you have acquired a ticket-granting ticket, you don't need to get another. You use the ticket-granting ticket to get the other tickets you need.
Euripides:    好吧,这是有道理的。而且由于你可以重复使用票证,一旦票证授予服务为你提供了特定服务的票证,你就无需再次获得该特定票证。 Okay, that makes sense. And since you can reuse tickets, once the ticket-granting service has given you a ticket for a particular service, you don't need to get that particular ticket again.

Athena:    是啊,这样做是不是很优雅? Yeah, isn't that elegant?
Euripides:    好的,目前为止我都理解了……只要你在获得票证授予票证时不必通过网络以明文形式发送密码。 Okay, I buy it so far . . . As long as you didn't have to send your password in cleartext over the network when you got the ticket-granting ticket.

Athena:    
就像我说的,我也解决了这个问题。问题是,当我说你必须联系 Charon 以获得票证授予票时,听起来好像你必须通过网络以明文形式将密码发送到 Charon 服务器。但实际情况不一定是这样。 Like I said, I've solved that problem as well. The thing is, when I say you have to contact Charon to get the ticket-granting ticket, I make it sound as though you have to send your password in cleartext over the network to the Charon Server. But it doesn't have to be that way.

这就是真正发生的事情。当你使用 kinit 程序获取票证授予票证时,kinit 不会将你的密码发送到 Charon 服务器,kinit 只会发送你的用户名。
Here's really what happens. When you use the kinit program to get the ticket-granting ticket, kinit doesn't send your password to the Charon server, kinit sends only your username.

Euripides:    挺好。 Fine.

Athena:    
Charon 使用用户名来查找你的密码。新的 Charon 构建了一个数据包,其中包含授予票证的票证。在向你发送数据包之前,Charon 会使用你的密码来加密数据包的内容。
Charon uses the username to look up your password. Next Charon builds a packet of data that contains the ticket-granting ticket. Before it sends you the packet, Charon uses your password to encrypt the packet's contents.

你的工作站收到票证数据包。你输入你的密码。 kinit 尝试使用你输入的密码解密票证。如果 kinit 成功,则你已成功向 Charon 证明自己。你现在拥有一张授予票证的票证,该票证可以为你提供所需的其他票证。
Your workstation receives the ticket packet. You enter your password. Kinit attempts to decrypt the ticket with the password you entered. If kinit succeeds, you have successfully authenticated yourself to Charon. You now possess a ticket-granting ticket, and that ticket can get you the other tickets you require.

整个新奇的想法怎么样?
How's that for some fancy thinking?

Euripides:    我不知道……我还在努力思考。你知道,我认为你刚才描述的系统部分工作得很好。你的系统要求我只证明自己一次。此后,Charon 可以在我不知道的情况下向我签发服务票。天衣无缝,在这方面天衣无缝。但不知何故,服务票的设计有些让我烦恼。这与门票可重复使用的事实有关。现在我同意它们必须是可重复使用的,但可重复使用的票据就其性质而言是非常危险的。 I don't know . . . I'm trying to think myself. You know, I think the parts of the system that you just described work pretty well. Your system requires me to authenticate myself only once. Thereafter Charon can issue me service tickets without my being aware of it. Seamless, seamless in that regard. But there's something about the design of the service ticket that troubles me somehow. It has to do with the fact that tickets are reusable. Now I agree that they have to be reusable, but reusable tickets are, by their nature, very dangerous.

Athena:    你的意思是? What do you mean?
Euripides:    

这样看。假设你使用的是不安全的工作站。在你的登录会话过程中,你将获得一张邮件服务票、一张打印服务票和一张文件服务票。假设你在注销时无意中将这些票据留在了工作站上。
Look at it this way. Suppose you are using an insecure workstation. In the course of your login session you acquire a mail service ticket, a printing service ticket, and a file service ticket. Suppose you inadvertantly leave these tickets on the workstation when you logout.

现在假设我登录到工作站并找到那些票。我感觉要惹麻烦,所以我让工作站认为我是你。由于票是以你的名义开出的,我可以使用邮件客户端程序访问你的邮件,我可以使用文件服务客户端访问和删除你的文件,我可以用你的名义来使用打印服务。这一切都是因为这些门票不小心被遗弃了。
Now suppose I login to the workstation and find those tickets. I'm feeling like causing trouble, so I make the workstation think that I am you. Since the tickets are made out in your name, I can use the mail client program to access your mail, I can use the file service client to access and remove your files, and I can use the printing command to run up huge bills on your account. All because these tickets have been accidentally left lying around.

并且没有什么能阻止我把这些票复制到我自己的任何地方。我可以永远使用它们。
And nothing can keep me from copying these tickets to a place of my own. I can continue to use them for all eternity.

Athena:    
这很容易解决。我们只需编写一个程序,在每次登录会话后销毁用户的票证。你不能使用已销毁的门票。
But that's an easy fix. We just write a program that destroys a user's tickets after each login session. You can't use tickets that have been destroyed.

Euripides:    

很明显你的系统必须要有一个票据销毁程序,但是让用户依赖这样的东西是愚蠢的。你不能指望用户在每次完成工作站会话时都记得销毁他们的票证。即使你依靠你的用户销毁他们的票证,也请考虑以下情况。
Well obviously your system must have a ticket-destroying program, but it's foolish to make users rely on such a thing. You can't count on users to remember to destroy their tickets every time they finish a workstation session. And even if you rely upon your users to destroy their tickets, consider the following scenario.

我有一个程序可以监视网络并在服务票通过网络时复制它们。假设我想伤害你。我等你开始一个工作站会话,我打开我的程序并复制你的一堆票。
I've got a program that watches the network and copies service tickets as they zip accross the network. Suppose I feel like victimizing you. I wait for you to begin a workstation session, I turn on my program and copy a bunch of your tickets.

我等你完成你的会话,最后你退出并离开。我摆弄我的工作站的网络软件并更改它的地址,以便它与你在获得我复制的票证时使用的工作站的地址相匹配。我让我的工作站相信我就是你。我有你的票、你的用户名和正确的网络地址。我可以重放这些票并以你的名义使用服务。
I wait for you to finish your session, and eventually you logout and leave. I fiddle with my workstation's network software and change its address so that it matches the address of the workstation you were using when you acquired the tickets I copied. I make my workstation believe that I am you. I have your tickets, your username, and the correct network address. I can REPLAY these tickets and use services in your name.

在结束工作站会话之前销毁票证并不重要。我偷的票只要我愿意使用就一直有效,因为你当前的票设计并没有限制你可以重复使用票的次数或票的有效期。
It doesn't matter that you destroyed your tickets before you ended your workstation session. The tickets I have stolen are valid for as long as I care to use them, because your current ticket design does not place a limit on the number of times you can reuse a ticket, or on how long a ticket remains valid.

Athena:    哦,我明白你的意思了!门票不可能永远有效,因为它们会构成巨大的安全风险。我们必须限制一张票可以使用的时间长度,也许给每张票一个有效期。 Oh I see what you're saying! Tickets can't be valid forever because they would then constitute a huge security risk. We have to restrict the length of time for which a ticket can be used, perhaps give each ticket some kind of expiration date.
Euripides:    确切地说,我认为每张票需要有两个额外的信息:一个表示票有效时间长度的生命周期,以及一个表示 Charon 签发票的日期和时间的时间戳。所以一张票看起来像这样: Exactly. I think each ticket needs to have two additional pieces of information: a lifespan that indicates the length of time for which the ticket is valid, and a timestamp that indicates the date and time at which Charon issued the ticket. So a ticket would look something like this:

Euripides goes to the chalkboard and scrawls the following:
   TICKET   {username:address:servicename:lifespan:timestamp}

Euripides:    现在,当服务解密票证时,它会检查票证中包含的用户名和地址与发送票证的人的姓名和地址,并使用时间戳和生命周期信息来查看票证是否已过期。 Now when a service decrypts tickets, it checks the ticket's username and address against the name and address of the person sending the ticket, and it uses the timestamp and lifespan information to see if the ticket has expired.

Athena:    好的。那典型的服务票证应该有什么样的生命周期? All right. What kind of lifetime should the typical service ticket have?
Euripides:    我也不知道。可能是典型工作站会话的长度——八小时。 I don't know. Probably the length of a typical workstation session. Say eight hours.

Athena:    因此,如果我在工作站上坐了超过 8 个小时,我的所有票都会过期。这包括我授予票证的票证。所以我必须在八小时后重新向 Charon 申请身份验证。 So if I sit at my workstation for more than eight hours, all my tickets expire. That includes my ticket-granting ticket. So I have to reauthenticate myself to Charon after eight hours.
Euripides:    这不无道理吧? That's not unreasonable is it?

Athena:    我猜不是。所以我们确定了——门票在八小时后到期。现在我有一个问题要问你。假设我从网络上复制了你的票—— I guess not. So we're settled -- tickets expire after eight hours. Now I've got a question for you. Suppose I have copied YOUR tickets from the network--
Euripides:    (眼睛闪烁)噢,Tina!你不会真的那么做吧?(Eyes twinkling) Aw, Tina! You wouldn't really do that would you?

Athena:    
这只是为了争论。我已经复制了你的票。现在我等你注销。假设你有一个医生预约或要参加一个课程,因此你在几个小时后结束你的工作站会话。你是一个聪明人,并且在退出之前已经销毁了你的门票副本。
This is just for the sake of argument. I've copied your tickets. Now I wait for you to logout. Suppose you have a doctor's appointment or a class to attend, so you end your workstation session after a couple of hours. You are a smart boots and have destroyed your copies of the tickets before logging out.

但是我已经偷了你的票,它们大约可以放六个小时。这给了我充足的时间来掠夺你的文件并以你的名义打印一千份。
But I've stolen your tickets, and they are good for about six hours. That gives me ample time to pillage your files and print one thousand copies of whatever in your name.

看,如果票证窃贼选择在票证过期后重播票证,生命周期时间戳业务可以正常工作。但如果小偷在有效期到期之前重打之前的罚单……
See, the lifetime-timestamp business works fine in the event that a ticket thief chooses to replay the ticket after the ticket has expired. If the thief can replay the ticket before that . . .

Euripides:    嗯,你是对的。 Uh, well . . . Of course you are right.

Athena:    我认为我们遇到了一个大问题。(她叹了口气。) I think we have run into a major problem. (She sighs.)
暂停。 Pause.

Euripides:    我想这意味着你今晚会很忙。想要更多的咖啡吗? I guess that means you'll be busy tonight. Want more coffee?
Athena:    为什么不呢。 Why not.


# Scene IV - 场景四

>>> 在上一幕的讨论结束时有一个明确的遗留问题——服务票据(ST)在有效期内的重放攻击,对这个问题 Athena 将问题归结为——服务如何判断使用票据的人与真实票据所有人是同一个?

>>> Athena 回溯了一下身份认证的过程,试图从中找到解决思路,客户端和服务端交互时发送的内容为 username,ip_address,ticket(enc{username:ip_address:servicename:lifespan:timestamp}) 这里面ticket是用服务的密码进行加密生成的内容,也就只有服务能解开。服务接到ticket之后正常解开可以拿到用户名、网络地址、服务名称和有效期做比对,这些校验做完之后最多只能说明ticket是 Charon 签发的,username,ip_address 这些都能对的上且是否在有效期内。说明不了票是不是真的来自于票的实际拥有人,因为客户端和服务端之间也没有更多已共享的信息了。解决的办法就是增加一个只有它们两者才知道的会话密钥(session key)。

>>> 但是 Charon 如何将会话密钥分发给用户和服务是个问题。一开始 Athena 想的是——直接在 Charon 给用户的回复中同时提供会话密钥和票证 sessionkey|ticket ;给服务分发会话密钥是通过把会话密钥包含在加密的票证里面 ticket(enc{sessionkey:username:address:servicename:lifespan:timestamp}) 。

>>> 当你想获得一项服务时,客户端会先构建一个 AUTHENTICATOR-身份验证器 ,它包含用户名和网络地址,并使用上面的会话密钥加密 sessionkey_enc{username:address} ,然后将其发送到服务端,该服务还无法解密身份验证器,因为它没有会话密钥。该密钥在票证中,因此服务首先解密票证。解密票证之后,若票证还在有效期内,再去用得到的会话密钥来解密身份验证器。如果解密顺利进行,则服务会拿到其中的用户名和网络地址。该服务会根据票证中的姓名和地址以及发送票证的人的姓名和地址以及身份验证器来进行校验。如果一切都匹配,则服务已确定票证发送者确实是票证的真正所有者。

>>> 即便是上面这种设计也无法解决重放的问题,因为攻击者可以监听获取 Charon 直接明文返回给用户的会话密钥,拿到了会话密钥之后我一样可以通过伪造数据包来绕过数据合法性校验,真正有效的办法是增加一个检查让身份验证器只可使用一次不能被重复使用。

>>> 如果直接按照上面这个思路来理解,其实设计还是有问题的,不过 Athena 后来又按照她的说法讲了一遍,才理解实际流程:

client->Charon: username
Charon->client: userpass_enc{sessionkey,tgt}
Charon->server: servicepass_enc{sessionkey:username:address:servicename:lifespan:timestamp}
client 成功解密 Charon 返回的数据包,可以拿到 sessionkey,tgt 信息,tgt的内容是加密的{sessionkey:username:address:servicename:lifespan:timestamp};

client->TGS: sessionkey_enc{authenticator(username:address)}, tgt, username,address,servicename

TGS->client: sessionkey2
TGS->server: sessionkey2
...

上面的方案通过“一次一密”解决了信息传输泄漏的问题,让 client 和 TGS 以及 service 分别具有了 2对 会话密钥(sessionkey),从而加强了认证的安全性。但是还存在虚假服务器的可能,所以需要双向验证。上面的流程中,服务端验证了客户端的真实性,但是客户端并没有验证服务端。所以再加一个流程,客户端发送额外的一个加密请求,若服务端可以正常解密,则客户端也就验证了服务端,完成了双向验证。



第二天早晨在 Euripides 的办公室里。Athena 敲了敲门。

Euripides:    你都有黑眼圈了。 You've got rings under your eyes this morning.

Athena:    嗯,你知道的。又是一个漫长的夜晚。 Well, you know. Another one of those long nights.
Euripides:    你解决重放的问题了吗? Have you solved the replay problem?

Athena:    我认为是的。 I think so.
Euripides:    请坐。 Have a seat.

She does.
Athena:    像往常一样,我得再次重申上次遗留的问题——门票可以在有限的时间跨度内重复使用,比如八小时。如果有人窃取了你的门票并选择在门票到期前重放,我们将无法阻止他们。 As usual, I feel compelled to restate the problem. Tickets are reusable within a limited timespan, say eight hours. If someone steals your tickets and chooses to replay them before they expire, we can't do anything to stop them.
Euripides:    这就是问题所在。 That's the problem.

Athena:    如果我们将票设计成不能重复使用,就可以解决这个问题。 We could beat the problem if we designed the tickets so they couldn't be reusable.
Euripides:    但是这样的话每次你想使用网络服务时,你都必须获得一张新票。 But then you would have to get a new ticket every time you wanted to use a network service.

Athena:    
是的,这充其量是一个笨拙的解决方案。呃,我该如何继续我们的讨论呢?
Right. That is a clumsy solution at best. (Pause.) Ah, how do I proceed with my argument? (She ponders for a moment.)

那好,我再重申一下这个问题,这次是以需求的形式,网络服务必须能够证明使用票的人与签发票的人是同一个人。
All right, I'm going to restate the problem again, this time in the form of a requirement. A network service must be able to prove that the person using a ticket is the same person to whom that ticket was issued.

让我再次跟踪身份验证过程,看看是否可以找出一种适当的方式来说明我对这个问题的解决方案。
Let me trace the authentication process again and see if I can tease out an appropriate way to illustrate my solution to this problem.

我想使用某个网络服务。我通过在我的工作站上启动客户端程序来访问该服务。客户端向服务机器发送三样东西——我的账号、我工作站的网络地址和适当的服务票证。
I want to use a certain network service. I access that service by starting a client program on my workstation. The client sends three things to the service machine-- my name, my workstation's network address, and the appropriate service ticket.

票证包含签发给的人的账号以及该人在获得票证时所使用的工作站的地址,它还包含生命周期形式的到期时间和时间戳。所有这些信息都使用已在 Charon 中的服务密码进行加密。
The ticket contains the name of the person it was issued to and the address of the workstation that person was using when he or she acquired the ticket. It also contains an expiration date in the form of a lifespan and a timestamp. All this information has been encrypted in the service's Charon password.

我们当前的身份验证方案依赖于以下测试:
Our current authentication scheme relies on the following tests:

该服务可以解密票证吗? Can the service decrypt the ticket?
票证过期了吗? Has the ticket expired?
票证中指定的姓名和工作站地址是否与发送票证的人的姓名和地址一致? Do the name and workstation address specified in the ticket match the name and address of the person who sent the ticket?

这些测试证明了什么?第一个测试可以证明这张票是不是来自 Charon 。如果票证无法解密,则它并非来自 Charon 。因为 Charon 会使用服务的密码对票证进行加密。Charon 和服务是唯一知道服务密码的两个实体。如果票证解密成功,服务就知道它来自真正的 Charon。这个测试可以防止人们制造假的 Charon 票证。
What do these tests prove? The first test proves that the ticket either did or did not come from Charon. If the ticket cannot be decrypted, it did not come from the real Charon. The real Charon would have encrypted the ticket with the service's password. Charon and the service are the only two entities that know the service's password. If the ticket decrypts successfully, the service knows that it came from the real Charon. This test prevents folks from building fake Charon tickets.

第二个测试检查票证的生命周期和时间戳。如果它已过期,服务将拒绝该票证。这个测试阻止人们使用旧票证,它可能是被盗的票证。
The second test checks the ticket's lifespan and timestamp. If it has expired, the service rejects the ticket. This test stops people from using old tickets, tickets that perhaps were stolen.

第三个测试检查票证用户的姓名和地址与票中指定的人的姓名和地址。如果测试失败,则提交票证的用户(可能是偷偷摸摸地)获得了另一个人的票证。这个票证当然被拒绝了。
The third test checks the ticket-user's name and address against the name and address of the person specified in the ticket. If the test fails, the ticket-user has obtained (perhaps surreptitiously) another person's ticket. The ticket is of course rejected.

如果姓名和地址确实匹配,那测试证明了什么?什么也没有证明。Scallywags 可以从网络上窃取票证,适当地更改他们的工作站地址和用户名,并掠夺其他人的资源。正如我昨天指出的,门票可以在没有过期的情况下被重放。它们可以重放,因为服务无法确定发送票证的人是否是票证的合法所有者。
If the names and addresses do match, what has the test proved? Nothing. Scallywags can steal tickets from the network, change their workstation addresses and usernames appropriately, and rifle other folks resources. As I pointed out yesterday, tickets can be replayed as long as they haven't expired. They can be replayed because a service cannot determine that the person sending the ticket is actually the ticket's legitimate owner.

服务本身无法做出此决定,因为它不与用户共享密码。这样看。如果我在 Elsinore 守望,你知道这是 Hamlet 中的城堡,你应该接替我,但除非你能提供正确的密码,否则我不应该让你代替我的位置。这就是我们两个共享密码的情况。这可能是其他人为所有守望的人编造的密码。
The service cannot make this determination because it does not share a secret with the user. Look at it this way. If I'm on watch at Elsinore, you know, the castle in Hamlet, and you are supposed to relieve me, I'm not supposed to let you take my place unless you can provide the correct password. That's the case where the two of us share a secret. And it's probably a secret that someone else made up for everyone who stands on watch.

所以我昨晚在想,为什么不让 Charon 为合法的票据拥有者编一个密码来与服务共享呢?Charon 将此会话密钥的副本提供给服务,也同时提供给用户。当服务收到用户的票时,它可以使用会话密钥来测试用户的身份。
So I was thinking last night, why not have Charon make up a password for the legitimate ticket-owner to share with the service? Charon gives a copy of this session key to the service, and a copy to the user. When the service receives a ticket from a user, it can use the session key to test the user's identity.

Euripides:    等一等。Charon 将如何给双方会话密钥? Wait a second. How is Charon going to give both parties the session key?

Athena:    票证拥有者从 Charon 获得会话密钥作为回复的一部分。像这样: The ticket-owner gets the session key as part of the reply from Charon. Like this:
她在黑板上潦草地写着: She scrawls the following on a chalkboard:

 CHARON REPLY  -  [sessionkey|ticket]

服务的会话密钥副本包含在票证中,服务在解密票证时获取密钥。所以票是这样的: The service's copy of the session key comes inside the ticket, and the service gets the key when it decrypts the ticket. So the ticket looks like this:

 TICKET -  {sessionkey:username:address:servicename:lifespan:timestamp}

当你想获得一项服务时,你启动的客户端程序会构建我所说的 AUTHENTICATOR。身份验证器包含你的姓名和工作站的地址。客户端使用会话密钥(是在请求票证时收到的会话密钥的副本)加密此信息。
When you want to get to a service, the client program you start builds what I call an AUTHENTICATOR. The authenticator contains your name and your workstation's address. The client encrypts this information with the session key, the copy of the session key you received when you requested the ticket.

  AUTHENTICATOR - {username:address} encrypted with session key

构建身份验证器后,客户端将其和票证发送到服务。该服务还无法解密身份验证器,因为它没有会话密钥。该密钥在票证中,因此服务首先解密票证。
After building the authenticator, the client sends it and the ticket to the service. The service cannot decrypt the authenticator yet because it doesn't have the session key. That key is in the ticket, so the service first decrypts the ticket.

解密票证后,服务最终得到以下信息: After decrypting the ticket, the service ends up with the the following information:

The ticket's lifespan and timestamp;
The ticket-owner's name;
The ticket-owner's network address;
The session key.

该服务会检查票证是否已过期。如果在这方面一切正常,则服务接下来使用会话密钥来解密身份验证器。如果解密顺利进行,则服务会以用户名和网络地址结束。该服务会根据票证中的姓名和地址以及发送票证的人的姓名和地址以及身份验证器来测试此信息。如果一切都匹配,则服务已确定票证发送者确实是票证的真正所有者。
The service checks to see if the ticket has expired. If all is well in that regard, the service next uses the session key to decrypt the authenticator. If the decryption proceeds without a hitch, the service ends up with a username and a network address. The service tests this information against the name and address found in the ticket, AND the name and address of the person who sent the ticket and authenticator. If everything matches, the service has determined that the ticket-sender is indeed the ticket's real owner.

Athena 顿了顿,清了清嗓子,喝了点咖啡。 Athena pauses, clears her throat, drinks some coffee.

我认为会话密钥验证流程可以解决重放问题。 I think the session key-authenticator business takes care of the replay problem.

Euripides:    也许吧。但我想知道……要破解此版本的系统,我必须拥有该服务的适当身份验证器。 Maybe. But I wonder . . . To break this version of the system, I must have the proper authenticator for the service.

Athena:    不。你必须同时拥有身份验证器和服务票证。没有票证的验证器一文不值,因为服务不能在没有首先获得适当的会话密钥的情况下解密验证器,并且服务不能在没有首先解密票证的情况下获得适当的会话密钥。 No. You must have the authenticator AND the ticket for the service. The authenticator is worthless without the ticket because the service cannot decrypt the authenticator without first having the appropriate session key, and the service cannnot get the appropriate session key without first decrypting the ticket.
Euripides:    好的,我明白了,但是你不是说当客户端程序联系服务器时,它会一起发送票证和匹配的身份验证器吗? Okay, I understand that, but didn't you say that when a client program contacts the server, it sends the ticket and matching authenticator together?

Athena:    是的,我想我是这么说的。 Yes, I guess I said that.
Euripides:    如果这就是实际情况,是什么阻止我同时窃取票证和身份验证器?我确信我可以编写一个程序来完成这项工作。如果我有票和它的验证器,我相信只要票还没有过期,我就可以使用这两者。我只需要适当地更改我的工作站地址和用户名。你觉得呢? If that's what actually happens, what prevents me from stealing the ticket and authenticator at the same time? I'm sure I could write a program to do the job. If I've got the ticket and its authenticator, I believe I can use the two as long as the ticket has not expired. I just have to change my workstation address and username appropriately. True?

Athena:    没错。这太令人沮丧了。 (Biting her lip) True. How dispiriting.
Euripides:    等等,等等,等等!这没什么大不了的。票证只要没有过期就可以重复使用,但这并不意味着身份验证器必须是可重复使用的。假设我们将系统设计为验证器只能使用一次。这能给我们带来什么吗? Wait, wait, wait! This isn't such a big deal. Tickets are reusable as long as they haven't expired, but that doesn't mean that authenticators have to be reusable. Suppose we design the system so that authenticators can only be used once. Does that buy us anything?

Athena:    
嗯,它可能。让我们看看,客户端程序构建身份验证器,然后将其与票证一起发送到服务。当票证和身份验证器从我的工作站移动到服务器时,你可以复制它们。但是票证和身份验证器在你发送副本之前到达服务器。如果验证器只能使用一次,那么你的副本就没有用,并且当你尝试重放你的票证和验证器时你会失败。
Well, it might. Let's see, the client program builds the authenticator, then sends it with the ticket to the service. You copy both ticket and authenticator as they move from my workstation to the server. But the ticket and authenticator arrive at the server before you can send your copies. If the authenticator can only be used once, your copy of it is no good, and you lose when you attempt to replay your ticket and authenticator.

嗯,这是一种办法。因此,我们所要做的就是发明一种方法,使身份验证器成为一次性可用的东西。 Well, that's a relief. So all we have to do is invent a way to make the authenticator a one-time usable thing.

Euripides:    

没问题。让我们在它们上面加上一个生命周期和时间戳。假设每个身份验证器的生命周期为几分钟。当你想使用服务时,你的客户端程序会构建身份验证器,用当前时间标记它,然后将其和票证发送到服务器。
No problem. Let's just put a lifespan and timestamp on them. Suppose each authenticator has a lifespan of a couple of minutes. When you want to use a service, your client program builds the authenticator, stamps it with the current time, then sends it and the ticket to the server.

服务器接收到票证和身份验证器并开始进行校验。当服务器解密认证器时,它会检查认证器的生命周期和时间戳。如果身份验证器尚未过期,并且其他所有检查都正确,则服务器认为你已通过身份验证。
The server receives the ticket and authenticator and goes about its business. When the server decrypts the authenticator, it checks the authenticator's lifespan and timestamp. If the authenticator hasn't expired, and everything else checks properly, the server considers you authenticated.

假设我在它们通过网络时复制了身份验证器和票证。我必须更改我的工作站的网络地址和我的用户名,而且我必须在几分钟内完成这一切。这是一个相当高的要求。事实上,我认为这是不可能的。除非……
Suppose I copied the athenticator and ticket as they crossed the network. I have to change my workstation's network address and my username, and I have to do this all in a couple of minutes. That's a pretty tall order. In fact I don't think it's possible. Unless . . .

好吧,这是一个潜在的问题。假设当票证和身份验证器从你的工作站传输到服务器时,我没有复制票证和验证器,而是复制了来自 Charon 的原始票证包——当你要求 Charon 给你一张票证时你收到的数据包。
Well, here's a potential problem. Suppose that instead of copying the ticket and authenticator as they travel from your workstation to the server, I copy original ticket packet that comes from Charon, the packet you receive when you ask Charon to give you a ticket.

我记得,这个数据包中有两份会话密钥:一份给你,一份给服务。用于服务的一个隐藏在票证中,我无法找到它,但是另一个,你用来构建身份验证器的那个呢?
This packet, as I recall, has two copies of the session key in it: one for you and one for the service. The one for the service is hidden in the ticket and I can't get to it, but what about the other one, the one you use to build authenticators?

如果我能得到会话密钥的副本,我就可以构建自己的身份验证器,如果我能构建自己的身份验证器,我就可以破坏系统。
If I can get that copy of the session key, I can build my own authenticators, and if I can build my own authenticators, I can break the system.

Athena:    
这个问题我昨晚想过,但后来我追踪了获取门票的过程,发现用这种方式窃取身份验证器是不可能的。
That's something I thought about last night, but then I traced the process of acquiring tickets and found that it wasn't possible to steal authenticators that way.

你在工作站坐下并使用 kinit 程序获取你的票证授予票证。 Kinit询问你的用户名,输入后,kinit将名称转发给 Charon。
You sit down at a workstation and use the kinit program to get your ticket-granting ticket. Kinit asks for your username, and after you enter it, kinit forwards the name to Charon.

Charon 使用你的名字来查找你的密码,然后继续为你构建一个授予票证的票证。作为此过程的一部分,Charon 创建一个会话密钥,你将与票证授予服务共享该密钥。Charon 将会话密钥的副本放入授予票证的票证中,并将你的副本放入你即将收到的票证包中。但是在它向你发送这个数据包之前,Charon 会用你的密码对整个数据进行加密。
Charon uses your name to look up your password, then proceeds to build a ticket-granting ticket for you. As part of this process, Charon creates a session key that you will share with the ticket-granting service. Charon puts a copy of the session key in the ticket-granting ticket, and puts your copy in the the ticket packet that you are about to receive. But before it sends you this packet, Charon encrypts the whole thing with your password.

Charon 通过网络发送数据包。有人可以在数据包经过时复制它,但他们不能对它做任何事情,因为它已经用你的密码加密了。具体来说,没有人可以窃取授予票证的会话密钥。
Charon sends the packet across the network. Someone can copy the packet as it goes by, but they can't do anything with it because it has been encrypted with your password. Specifically, no one can steal the ticket-granting session key.

Kinit 收到票证包并提示你输入密码。如果你输入正确的密码, kinit可以解密数据包并为你提供会话密钥的副本。
Kinit receives the ticket packet and prompts you for a password, which you enter. If you enter the correct password, kinit can decrypt the packet and give you your copy of the session key.

现在你已经完成了 kinit 业务,那么你想要获取你的邮件,你启动邮件客户端程序。该程序查找邮件服务票,但没有找到(毕竟,你还没有尝试获取邮件)。客户端必须使用授予票证的票证向票证授予服务请求邮件服务票证。
Now that you've taken care of the kinit business, you want to get your mail. You start the mail client program. This program looks for a mail service ticket and doesn't find one (after all, you haven't tried to get your mail yet). The client must use the ticket-granting ticket to ask the ticket-granting service for a mail service ticket.

客户端为授予票证的交易构建一个身份验证器,并使用你的授予票证会话密钥的副本加密该身份验证器。然后客户端向 Charon 发送身份验证器、授予票证的票证、你的姓名、你的工作站地址和邮件服务的名称。
The client builds an authenticator for the ticket-granting transaction and encrypts the authenticator with your copy of the ticket-granting session key. The client then sends Charon the authenticator, the ticket-granting ticket, your name, your workstation's address, and the name of the mail service.

票证授予服务接收这些内容并运行身份验证检查。如果一切检查正确,票证授予服务最终会得到一份与你共享的会话密钥的副本。现在票证授予服务为你构建一个邮件服务票证,并在此过程中创建一个新的会话密钥供你与邮件服务共享。
The ticket-granting service receives this stuff and runs through the authentication checks. If everything checks properly, the ticket-granting service ends up with a copy of the session key that it shares with you. Now the ticket-granting service builds you a mail service ticket, and during this process, creates a new session key for you to share with the mail service.

票证授予服务现在准备一个票证包以发送回你的工作站。该数据包包含票证和你的邮件服务会话密钥副本。但在发送数据包之前,票证授予服务会使用其 TICKET-GRANTING 会话密钥的副本对数据包进行加密。完成后,数据包将在途中发送。
The ticket-granting service now prepares a ticket packet to send back to your workstation. The packet contains the ticket and your copy of the mail service session key. But before it sends the packet, the ticket-granting service encrypts the packet with its copy of the TICKET-GRANTING session key. That done, the packet is sent on its way.

所以这里是邮件服务票包,在网络上循环。假设一些网络食人魔在它经过时复制它。食人魔很不走运,因为数据包是用授予票证的会话密钥加密的;你和票证授予服务是唯一知道此密钥的实体。由于食人魔无法解密邮件票包,食人魔无法发现 MAIL SESSION KEY。如果没有这个会话密钥,食人魔就无法使用你随后可能通过网络发送的任何邮件服务票证。
So here comes the mail service ticket packet, loping across the network. Suppose some network ogre copies it as it goes by. The ogre is out of luck because the packet is encrypted with the ticket-granting session key; you and the ticket-granting service are the only entities that know this key. Since the ogre cannot decrypt the mail ticket packet, the ogre cannot discover the MAIL SESSION KEY. Without this session key, the ogre cannot use any of the mail service tickets you might subsequently send across the network.

所以我认为我们是安全的。你怎么看?
So I think we're safe. What do you think?

Euripides:    也许吧。Perhaps.

Athena:    也许!你能说的就这些吗! Perhaps! Is that all you can say!
Euripides:    (笑)别生气。你现在应该知道我的方法了。我想这对我来说很卑鄙,而你却熬了半夜。 (laughing) Don't get upset. You should know my ways by now. I guess it is mean of me, and you up half the night.

Athena:    气呼呼的! Pthhhhh!
Euripides:    好吧,已经解决3/4了。实际上,该系统开始听起来可以接受。这个会话密钥业务解决了我昨晚想到的一个问题:相互认证的问题。 All right, three-quarters of the night. Actually, the system is beginning to sound acceptible. This session key business solves a problem that I thought of last night: the problem of mutual authentication.

顿了顿。 Pause.
介意我多说一分钟吗? Mind if I talk for a minute?
Athena:    (A trifle coldly) Be my guest.
Euripides:    

你真好。(Euripides 清了清嗓子。)昨晚,当会话密钥和身份验证器的幻象在你的脑海中翩翩起舞时,我试图找出系统的新问题,我发现了一个我认为非常严重的问题。我将通过以下场景进行说明。
You are so kind. (Euripides clears his throat.) Last night, while visions of session keys and authenticators danced in your head, I was trying to find new problems with the system, and I found one that I thought was pretty serious. I'll illustrate it by way of the following scenario.

假设你厌倦了当前的工作,并确定离职才符合你的最大利益。你想在公司的 wizz-bang 激光打印机上打印你的简历,以便猎头和潜在雇主更容易注意到你。
Suppose you are sick of your current job and have determined that it is in your best interest to move on. You want to print your resume on the company's wizz-bang laser printer so that headhunters and potential employers can take note of your classiness.

因此,你输入打印命令,并指示它将简历发送到相应的打印服务器。该命令将获取到正确的服务票证(如果之前还没有的话),然后将你的名字的票发送到相应的打印服务器。至少那是你认为的方向。你实际上并不知道请求是发往正确的打印服务器的。
So you enter the printing command, and direct it to send the resume to the appropriate print server. The command gets the proper service ticket, if you don't already have it, then sends the ticket in your name to the appropriate print server. At least that's where you think it's headed. You don't in fact know that the request is headed for the right print server.

假设某个不道德的黑客——比如你的老板——搞定了系统,以便他将你的请求和它的票重定向到他办公室的打印服务器。他的打印服务程序不关心票或其内容。它会丢弃票据并向你的工作站发送一条消息,表明票据通过了集合,并且服务器已准备好并愿意打印你的工作。打印命令将作业发送到欺诈性打印服务器,而敌人最终会得到你的简历。
Suppose that some unscrupulous hacker--say it's your boss--has screwed system around so that he redirects your request and its ticket to the print server in his office. His print service program doesn't care about the ticket or its contents. It throws away the ticket and sends a message to your workstation indicating that the ticket passed muster, and that the server is ready and willing to print your job. The printing command sends the job to the fraudulant print server and the enemy ends up with your resume.

我将通过对比来说明问题。如果没有会话密钥和身份验证器,Charon 可以保护其服务器免受虚假用户的侵害,但它无法保护其用户免受虚假服务器的侵害。系统需要一种方法让客户端程序在向服务发送敏感信息之前对服务器进行身份验证。系统必须允许相互验证。
I'll state the problem by way of contrast. Without session keys and authenticators, Charon can protect its servers from false users, but it cannot protect its users from false servers. The system needs a way for client programs to authenticate the server before sending sensitive information to the service. The system must allow for mutual authentication.

但是只要你正确设计客户端程序,会话密钥就可以解决这个问题。回到打印服务器场景。我想要一个打印客户端程序,以确保它发送作业的服务是合法服务。
But the session key solves this problem as long as you design your client programs properly. Back to the print server scenario. I want a print client program that makes sure the service it's sending jobs to is the legitimate service.

这就是这样一个程序的作用。我输入打印命令并给它一个文件名,即我的简历的名称。假设我有一个打印服务票和会话密钥。客户端程序使用会话密钥来构建验证器,然后将验证器和票证发送到“假定的”打印服务器。客户尚未发送简历;它等待服务的响应。
Here's what such a program does. I enter the printing command and give it a filename, the name of my resume. Assume that I have a print service ticket and session key. The client program uses the session key to build an authenticator, then sends the authenticator and ticket to the "supposed" print server. The client DOES NOT send the resume yet; it waits for a response from the service.

真实服务接收票证和验证器,解密票证并提取会话密钥,然后使用会话密钥解密验证器。完成后,服务运行所有适当的身份验证测试。
The real service receives the ticket and authenticator, decrypts the ticket and extracts the session key, then uses the session key to decrypt the authenticator. This done, the service runs all the appropriate authentication tests.

假设测试证实了我的身份。现在服务器准备一个回复包,以便它可以向客户端程序证明它的身份。它使用它的会话密钥副本来加密回复数据包,然后将数据包发送给等待的客户端。
Assume the tests confirm my identity. Now the server prepares a reply packet so that it can prove its identity to the client program. It uses its copy of the session key to encrypt the reply packet, then sends the packet to the waiting client.

客户端收到数据包并尝试使用我的会话密钥副本对其进行解密。如果数据包正确解密并产生正确的服务器响应消息,我的客户端程序就知道加密数据包的服务器是真正的服务器。现在客户端将恢复作业发送到打印服务。
The client receives the packet and attempts to decrypt it with my copy of the session key. If the packet decrypts properly and yields the correct server response message, my client program knows that the server that encrypted the packet is the real server. Now the client sends the resume job to the print service.

假设我的老板搞定了系统,让他的打印服务器成为我想要的那个。我的客户端将身份验证器和票证发送到“打印服务”并等待响应。伪造的打印服务无法生成正确的响应,因为它无法解密票证并获取会话密钥。除非收到正确的响应,否则我的客户不会发送作业。最终客户端放弃等待并退出。我的打印工作没有完成,但至少我的简历没有落到敌人的办公桌上。
Suppose my boss screwed around the system so that his print server poses as the one I want. My client sends the authenticator and ticket to the "print service" and waits for a response. The fake print service cannot generate the correct response because it cannot decrypt the ticket and get the session key. My client will not send the job unless it receives the correct response. Eventually the client gives up waiting and exits. My print job does not get completed, but at least my resume did not end up on the desk of the enemy.

你知道,我认为我们有一个坚实的基础来实施 Charon 认证系统。
You know, I think we have a solid basis on which to implement the Charon Authentication System.

Athena:    也许吧,只是我不喜欢“Charon”这个名字。 Perhaps. Anyway, I don't like the name "Charon."
Euripides:    从什么时候开始不喜欢的呢? You don't? Since when?

Athena:    我从来就没喜欢过(这个名字),因为它没有任何含义。我昨天和我叔叔 Hades 谈起了这件事,他建议了另一个名字,他的三头看门狗的名字。 I've never liked it, because the name doesn't make sense. I was talking to my Uncle Hades about it the other day, and he suggested another name, the name of his three-headed watch dog.
Euripides:    哦,你的意思是“地狱犬-Cerberus”。 Oh, you mean "Cerberus."

Athena:    咬你的舌头 撕!确实是“地狱犬”,但不是这个名字…… Bite your tongue Rip! "Cerberus" indeed . . .
Euripides:    呃,不是这个名字吗? Er, isn't that the name?

Athena:    是的,可能和你碰巧是罗马人有关。我是希腊人,它是希腊看门狗,他的名字是“Kerberos”,“Kerberos”带有一个 K。 Yeah, if you happen to be a Roman! I'm a Greek goddess, he's a Greek watch dog, and his name is "Kerberos," "Kerberos" with a K.
Euripides:    好吧好吧,不要生气,我认可这个名字。实际上它的意义很好, Charon 再见,Kerberos 你好。 Okay, okay, don't throw thunderbolts. I'll buy the name. Actually, it has a nice ring to it. Adios Charon and hello to Kerberos.


# Afterword - 后记

该对话写于 1988 年,旨在帮助读者理解 Kerberos V4 协议为何如此的根本原因。多年来,它为这项工作提供了很好的服务。
The dialogue was written in 1988 to help its readers understand the fundamental reasons for why the Kerberos V4 protocol was the way it was. Over the years, it has served this job very well.

当我将此文档转换为 HTML 格式时,我很惊讶该文档中有如此多的内容仍然适用于 Kerberos V5 协议。尽管许多事情发生了变化,但协议的基本核心思想保持不变。实际上,Kerberos V5 与此对话中对“Kerberos”协议的描述只有两个不同之处。
When I converted this document to HTML, I was amazed how much of this document was still applicable for the Kerberos V5 protocol. Although many things were changed, the basic core ideas of the protocol have remained the same. Indeed, there are only two changes where Kerberos V5 differs from description of the "Kerberos" protocol in this dialoge.

第一个变化源于这样一种认识,即使用一个小的 5 分钟时间偏差不足以防止来自攻击者的重放攻击,若攻击者使用程序在网络中自动获取票证和身份验证器,然后立即让程序发动重放攻击。
The first change was born out of the recognition that using a small five minute time skew wasn't necessarily sufficient to prevent replay attacks from an attacker who used a program to automatically grab the ticket and the authenticator as they traversed the network, and then immediately resent them to launch a replay attack.

在 Kerberos V5 中,通过让接受票证的服务器拥有一个“重放缓存”来记录最近已向服务器提供的身份验证器,从而使身份验证器真正“一次性”。如果攻击者试图抢夺验证器并重新使用它,即使在五分钟的接受窗口期间,重放缓存也将能够确定验证器已被提交给服务器。
In Kerberos V5, authenticators are made to be truly "once-only" by having servers which accept tickets to have a "replay cache" which keeps note of authenticators have been presented to the server recently. If an attacker tries to snatch an authenticator and reuse it, even during the five-minute acceptance window, the replay cache will be able to determine that the authenticator has already been presented to the server.

该协议的第二个主要变化是,在初始票证交换期间,当票证从 Kerberos 服务器发送到kinit时,票证不再用用户密码中加密。票证已用票证授予服务器的密钥进行加密;此外,当它实际用于获取其他票证时,无论如何它都会以明文形式在网络中发送。因此,没有理由用用户密码中再次加密票证。(当然,Kerberos 服务器对用户的其余回复,例如包含用户的票证会话密钥副本,仍然用用户密码中加密。)
The second major change to the protocol is that the ticket is no longer encrypted in the user's password when it is sent from the Kerberos server to kinit during the initial ticket exchange. The ticket is already encrypted in the ticket granting server's secret key; furthermore when it is actually used to obtain other tickets, it gets sent in the network in the clear anyway. Hence, there is no reason why the ticket should be encrypted again in the user's password. (The rest of the Kerberos server's reply to the user, containing for example the user's copy of the ticket session key, is still encrypted in the user's password, of course.)

票证授予服务 (TGS) 协议也进行了类似的更改;TGS 返回的票证也不再由授予票证的票证的服务密钥加密,因为应用程序票证已由应用程序服务器的密钥加密。例如,Kerberos V4 中的数据包看起来像这样:
A similar change was also made to the ticket granting service (TGS) protocol; tickets returned by TGS are also no longer encrypted by the ticket-granting ticket's service key, since application tickets are already encrypted by the application server's secret key. So for example, the packet that in Kerberos V4 which would have looked like this:

   KDC_REPLY = {TICKET, client, server, K_session}K_user

其中“ {X}K_Y ”读作“使用密钥 K_Y 加密的 X”,并且
where "{X}K_Y" is read "X encrypted using key K_Y" and
   TICKET = {client, server, start_time, lifetime, K_session}K_server

在 Kerberos V5 中,KDC_REPLY 现在看起来像这样:
In Kerberos V5, the KDC_REPLY now would look like this:
  KDC_REPLY = TICKET, {client, server, K_session}K_user

当然,Kerberos V5 中也有许多新功能。用户现在可以安全地转发他们的票证,以便他们可以在另一个网络位置使用;此外,用户还可以将其授权权限的子集委托给服务器,以便服务器可以代表用户充当代理。其他新功能包括用更安全的加密算法(例如三重 DES)替换 DES 的能力。欢迎对 Kerberos V4 和 V5 之间的更多变化感兴趣的读者阅读由Cliff Neumann和 Theodore Ts'o撰写的 The Evolution of the Kerberos Authentication System。
Of course, there are many new features in Kerberos V5 as well. Users can now securely forward their tickets so that they can be used at another network location; in addition, users may also delagate a subset of their authorization rights to a server, so that the server can act as a proxy on behalf of a user. Other new features include the ability to replace DES with a more secure cryptographic algorithm, such as triple-DES. Readers who are interested in more of the changes between Kerberos V4 and V5 are invited to read The Evolution of the Kerberos Authentication System, which was authored by Cliff Neumann and Theodore Ts'o.

我希望你喜欢这个对 Kerberos 协议的简短介绍。祝你在未来的探索中一切顺利!
I hope you've enjoyed this quick little introduction to the Kerberos protocol. I wish you well in your futher explorations!

Theodore Ts'o, February 1997.
参考链接:

Designing an Authentication System: a Dialogue in Four Scenes
http://web.mit.edu/kerberos/dialogue.html

Kerberos: The Network Authentication Protocol
https://web.mit.edu/kerberos/

=END=


发表回复

您的电子邮箱地址不会被公开。 必填项已用 * 标注