1.7 从理论到实践:选择独特冒险
在密码学领域金字塔上面的是提出并解决数学难题的密码分析师,在金字塔下面的是希望加密某些数据的软件工程师。
——Thai Duong (“So you want to roll your own crypto?”,2020)
在研究和使用密码学的这些年里,我从未见过以单一模式在实际应用程序中使用密码原语的例子。现实情况是,密码学的使用方式相当混乱。在某一理论原语被采用前,会有很多的密码学研究者对其进行研究和分析,最终将其变成更实用、更安全的密码学原语。我该怎么解释这些呢?
听说过Choose Your Own Adventure一书吗?这是一个相对老旧的故事集,我们必须选择逐步完成故事中的任务。原则很简单,先按顺序阅读,然后通过书中提供的一些选项让我们决定接下来选择阅读哪一部分。每个选项都与一个不同的节号相关联,我们可以直接跳到所选节号的内容。因此,我也按照这种方式安排本书内容。从下一段开始,我们可以按照本书所给顺序去读本书。
一切从这里开始。你是谁?你是密码学家Alice吗?还是在私企工作而且有问题亟待解决的David呢?或者你是在特殊部门工作,专门从事密码学研究的Eve?
● 如果你是Alice,请跳到步骤1。
● 如果你是David,请跳到步骤2。
● 如果你是Eve,请跳到步骤3。
步骤 1:研究人员必须进行研究。你是一位在大学工作的研究员,或者是一名任职于私人公司或非营利组织的研究者,或者你就职于NIST或NSA等美国政府研究机构。因此,你的研究资助可能来自不同的机构或组织,这可能会激励你研究不同的东西。
● 你会发明一个新的密码原语,请跳到步骤4。
● 你会提出一个新的构造,请跳到步骤5。
● 你打算参与一场密码竞赛,请跳到步骤6。
步骤 2:工业有需求。工作任务就是提出新的行业标准。例如,Wi-Fi联盟就是一个由专注于Wi-Fi协议的公司资助的非营利组织,该组织旨在制定一套有关Wi-Fi协议的标准。另一个与标准工作有关的例子是,多家银行联合制定支付卡行业数据安全标准(The Payment Card Industry Data Security Standard,PCI-DSS),在处理信用卡号时,该标准会强制要求使用规定的算法和协议。
● 你决定去资助一些需要的研究,请跳到步骤1。
● 你决定提出一些新的原语或协议,请跳到步骤5。
● 你打算发起一场密码算法竞赛,请跳到步骤6。
步骤 3:政府有需求。你为政府效力,需要设计一些新的密码算法。例如,NIST的任务就是发布联邦信息处理标准(The Federal Information Processing Standard,FIPS),该标准规定了处理政府事务的公司可以使用哪些密码算法。虽然这些标准中大多是成功的案例,人们对政府机构推行的标准也抱有高度的信任,但是关于这些标准的失败之处也值得一谈。
2013年,在爱德华·斯诺登(Edward Snowden)披露了一些美国政府的丑闻之后,人们发现美国国家安全局(NSA)故意将一个藏有后门的算法纳入其推行的标准中(见Bernstein等人的文章“Dual EC: A Standardized Back Door”),这个后门算法允许NSA(只有NSA)推测密钥。这些后门如同“魔法口令”一样,使美国政府(据说只有美国政府)可以破解加密的消息。之后,密码社区不再信任美国政府机构推出的标准和建议。在2019年,人们发现俄罗斯标准机构GOST也出现类似的情况。
密码学家一直怀疑GOST在2006年发布的一项NIST通过的标准中植入了漏洞,后来这项标准被由拥有163个成员方的国际标准化组织(International Organization for Standardization)采纳。而美国国家安全局的机密备忘录似乎也能证实:两位微软密码学家在2007年发现该标准中的致命弱点是由GOST机构设计的。值得注意的是,正是NSA编写了该标准,并积极在国际组织上推行该标准,并私下称其为“技巧上的挑战”。
——《纽约时报》(“N.S.A. Able to Foil Basic Safeguards of Privacy on Web”,2013)
● 你要资助一些研究,请跳到步骤1。
● 你要组织一场公开竞赛,请跳到步骤6。
● 你打算将正在使用的原语或协议标准化,请跳到步骤7。
步骤4:提出新概念。作为一名研究人员,总是设法做到一些不可能完成的事情;确实,尽管可用的加密原语已经有很多,但密码学家每年仍会提出一些新的原语。其中,有些概念是不可能实现的,而有些概念最终可以实现。也许,你已有实际的构造,并将其作为所提原语的一部分,或者选择等待,看看是否有人可以想出一些新的原语。
● 你提出的原语已经实现,请跳到步骤5。
● 你提出的原语最终不可以实现,请跳到开头部分。
步骤5:一个新的原语或协议被提出。密码学家通过提出一种新的算法来实例化一个概念。例如,AES是一个加密方案(AES最初由Vincent Rijmen和Joan Daemen提出,他们用其名字的缩写Rijndael来命名这个算法,又称Rijndael加密法)。下一步该怎么做呢?
● 某个人以你的构造为基础提出新的构造,请跳到步骤5。
● 你参加了一个公开的比赛,并且赢得这场赛事!请跳到步骤6。
● 你所做的工作受到大肆宣传,并且即将成为标准,请跳到步骤7。
● 你决定将你的构造申请成专利,请跳到步骤8。
● 你或其他人认为你构造的原语非常有趣,并决定将该构造实现出来,请跳到步骤9。
步骤 6:算法在竞赛中获胜。密码学家最喜欢的竞技就是一场公开的比赛!例如,AES就是一项由世界各地密码学研究者都可自由参加的竞赛。整个竞赛经过数十次的提交和几轮密码分析者的分析(这可能需要几年时间),候选算法名单中的算法逐渐减少,直至剩下一个算法,便将该算法作为标准。
● 你很幸运,经过多年的竞争,你的新构造最终赢得比赛!请跳到步骤7。
● 你不够走运,输掉了比赛,请回到开头。
步骤 7:标准化算法或协议。标准通常由政府或标准化机构发布。标准化的目的是最大限度地提高互操作性。例如,NIST会定期发布一些密码标准。著名的密码学标准化机构当属国际互联网工程任务组(Internet Engineering Task Force,IETF),本书中涉及的许多互联网标准(如TCP、UDP、TLS等)都出自该机构。IETF中的标准被称为征求意见(Request For Comment,RFC),并且几乎任何想要编写标准的人都可以编写。
为了强调不通过投票表决问题,我们还采用了“决议”的传统:例如,在面对面的会议中,工作组主席为了让大家获得“决策权”,有时会要求参会者就一个特定的问题(“赞成”或“反对”)进行交流,而不是举手表决。
——RFC 7282(“On Consensus and Humming in the IETF”,2014)
有时,某个公司会直接发布一个标准。例如,RSA Security LLC(由RSA算法的创建者出资)为了让本公司使用的算法和技术合法化,曾发布了15个称为公钥加密标准(Public Key Cryptography Standards,PKCS)的技术文件。如今,这种情况非常少见。现在,许多公司都是通过IETF将它们的协议或算法标准化为RFC文档,而不是去自定义一些新的标准化文档。
● 你提出的算法或协议得到实现,请跳到步骤9。
● 没有人关心你发布的标准,请回到开头。
步骤 8:专利到期。通常,密码算法被申请了专利就意味着没有人会使用该算法。然而,一旦专利到期,人们会对这个算法重新产生兴趣,这并不是什么罕见之事。最典型的例子可能是Schnorr签名,该算法是一个备受欢迎的签名算法,这种情形持续到1989年Schnorr为该签名算法申请专利。这导致NIST只能将一个较差的签名算法作为标准,称为数字签名算法(Digital Signature Algorithm,DSA),该算法在当时成为首选签名算法,但如今很少使用。Schnorr签名的专利于2008年到期,此后该算法再次流行起来。
● 时间过了很久,你提出的算法仍无人过问,请回到开头。
● 你的构造引发了一系列新的构造,这些新的构造都以你先前的构造为基础,请跳到步骤5。
● 现在很多人想使用你的构造,但只有你的构造成为标准后他们才肯使用,请跳到步骤7。
● 一些开发者正在使用你设计的算法,请跳到步骤10。
步骤9:实现一个新的构造或协议。实现者不仅要完全搞懂一篇论文或一项标准(尽管标准的撰写本来就应该是面向实现者的),而且必须使实现的算法易于使用,这是一项艰巨的任务。另外,使用者还可能会以一种错误的方式使用密码算法,因此做到正确使用密码算法也并非易事。
● 有人认为标准本身应该包含相应的实现,不提供具体实现的标准不够完备,请跳到步骤7。
● 你编写的密码程序库得到极力推广,请跳到步骤10。
步骤 10:作为开发人员在应用程序中使用密码协议或原语。你的密码程序库可以轻松满足开发人员的需要!
● 某个原语可以解决你的需求,但它没有被标准化。情况有点不好,请跳到步骤7。
● 我希望用我熟悉的编程语言实现这个原语,请跳到步骤9。
● 我以错误的方式使用这个密码库,或者使用的构造已被攻破,游戏结束。
让一个密码原语变得在现实世界可用的方法有很多。最好的方法应该是采用经过多年的安全分析、对算法实现者友好的标准,以及性能良好的密码程序库。最糟糕的方法是使用不安全的算法和不友好的实现。一个密码原语变得实用的最佳路线如图1.18所示。
图1.18 一个密码算法的理想生命周期始于密码学家实例化了某个概念。例如,AES是对称加密概念的一个实例(对称加密算法还有很多)。一个新的密码原语构造可以这样被标准化:每个人都同意以某种方式来实现它以最大限度地提高互操作性。然后,用不同的语言实现该标准,使标准化的密码算法得以广泛应用