Tech Ideas

C++,Linux,Algorithm,Crypto,Lisp,etc

【翻译】密码学一小时必知

本文翻译了Colin Percival 于2010年在bsdcan的演讲ppt

原文标题:Everything you need to know about cryptography in 1 hour

演讲时间:May 13, 2010

原文在 https://www.bsdcan.org/2010/schedule/attachments/135_crypto1hr.pdf

演讲视频在 https://www.youtube.com/watch?v=jzY3m5Kv7Y8 ( 请自行翻墙 )

Colin Percival 是密码学方面的专家,FreeBSD项目的安全长官,Tarsnap在线备份服务的创始人,scrypt密钥衍生算法的作者,致力于改进软件中密码学的应用,向程序员传播密码学的正确使用。


为什么要 cryptography in 1 hour:

因为有例如下面这些错误的使用案例:

  1. Google keyczar(时间通道攻击)

  2. SSL( session renegotiation)

  3. Amazon AWS 签名方法 (可能碰撞的签名算法)

  4. Flicker API 签名(hash length-extension) 错误地使用了错误的工具

  5. Intel Hyper Threading (architectual side channel) 不常用的环境

  6. WEP,WPA,GSM…(多种漏洞)

密码学被攻破通常是由于:

  1. 愚蠢

  2. 使用了错误的工具,或者以错误的方式使用它们

  3. 不常用的环境


经验智慧:不要亲自写密码学代码!

  1. 使用SSL做传输
  2. 使用GPG保护静止数据

“如果你在输入A-E-S到你的代码里,你已经开始犯错” — Tomas Ptacek

现实:如果你无论如何都要写密码学代码,你最好知道你在干什么

现实:大多数应用程序只需要众所周知的标准模式的一个子集,而这是很容易保证正确的

55分钟后,你应该:

知道在99%的情况下应该怎么做

知道一些常见的错误在哪里

知道当你在做一些非标准的事情的时候,你真的需要咨询一个密码学专家


密码学做保护,并对抗一些攻击,但不能对抗所有攻击:

贿赂,盗窃,敲诈

监狱刑罚

攻击人通常比攻击数据更贵

攻击人通常比攻击数据更危险

数据被拷打时不会开记者招待会来控诉

密码学的目的是强迫美国政府拷打你

希望他们认为你的信息不是这么重要


密码学有3个主要目的:加密 Encryption认证 Authentication 识别 Identification

  1. 加密阻止恶意者读取你的数据
  2. 认证阻止恶意者在不被发现的情况下改动你的数据
  3. 识别阻止恶意者假装你

有时认证和识别在一个步骤中进行:“这条消息自从我写下它之后没有被篡改”和“我是Colin” 可以替换成“这条消息自从Colin写下它之后没有被改过”

在大多数case里,你需要把2个,或者更多的密码学组件合起来使用


概念定义

  1. plaintext是我们关心的数据
  2. ciphertext是恶意者可以得到的数据
  3. key用于在这两者之间做转换,有时候我们需要多个key

对称密码学就是 ,使用相同的key,来把plaintext转换成ciphertext,和把ciphertext转换成 plaintext

非对称密码学就是,这两个方向的转换使用不同的key

理想的密码学组件并不存在,但是如果一个密码学组件被识别出不理想,一般就认为它是被攻破的


hashing

一个理想的hash函数H(x)是一个函数映射,把任意长度的输入映射成n-bit的输出, 保证:

抵抗碰撞

单向

抵抗碰撞意味着需要 2n/2的时间来找到2个输入,使得它们的hash相同

单向意味着给定hash后,需要2n的时间来找到一个输入,使得它的hash是给定hash

没有保证任何其他性质

特别是: 知道H(x)可能允许一个攻击者计算某些y的H(y)


实践:

使用 SHA-256

考虑切换到SHA-3,在未来5-10年内(2010年算起)

使用一个hash,如果你可以安全地分布 H(x),并且想验证不安全地收到的x’实际上等于x

不要使用:MD2 MD4 MD5 SHA-1 RIPEMD

不要把 FreeBSD-8.0-RELEASE-amd64-disc1.iso和CHECKSUM.SHA256放到同一个FTP 服务器上,还以为自己干了件有用的事情

不要尝试把一个hash函数当成对称签名用


对称认证

对称认证是通过提供一个消息认证码(MAC,message authentication code)来进行的。

一个理想的 MAC fk(x)使用一个key,来把任意长度的输入映射到n-bit的输出,确保需要 2n 的时间,一个攻击者才能在得到任意(x, fx(x))对的情况下,生成任意(y,fk(y))对。 有时MAC被称作随机函数

与hashing不同,知道fk(x)不能使你对另一个key计算出 fk(y),

Flicker的API使用了hashing来认证API请求,他们实际需要的是 MAC


对称认证

实践

使用 HMAC-SHA256

确保同样的输入,HMAC-SHA256不会生成不同的消息

Amazon和Flicker都做错了

不要使用 CBC-MAC

理论上安全,但是把你的块加密算法暴露给了攻击者

不要使用 Poly1305

太新,除非你是Daniel Bernstein(Poly 1305的发明者),否则你基本不可能做出一个

安全和正确的实现

不要 当验证一个签名的时候,通过timing side channel的形式泄露信息


Side channel 攻击

一个side channel 是攻击者除了ciphertext以外可以获取信息的任何方式

密码系统是以它们的数学设计被定义的,但是side channel 是由于密码系统的人工实现导致的。

最常见的side channel是timing — 你花费多长时间来 加密/解密/签名/验证 一个消息

其他side channel包括:电磁辐射,电力消耗,和微架构特征(例如L1缓存替换,在支持 HyperThreading的Intel CPU上)


Side channel 攻击 实践

咨询一个密码学专家,如果你计划使恶意者可以物理接触到任何密码设备

咨询一个密码学专家,如果你计划允许恶意者在你允许密码学的物理硬件上运行代码(虚拟化系统)

咨询一个密码学专家,如果你计划发布一个以新方式泄露信息的CPU

intel可能做错了 不要写其运行时间泄露信息的代码


Timing attacks

避免 依赖于key,或者依赖于plaintext的表查找

不要有依赖于key,或者依赖于plaintext的分支(if, for, while , foo?bar:baz 等代码指令)

不要想这种代码:

for(int i=0;i<MACLEN;i++){
    if(MAC-computed[i] != MAC-received[i])
        return MAC_IS_BAD ;
return  MAC_IS_GOOD;

应该这样写

for(int i=0;i<MACLEN;i++){
    x  |= (MAC-computed[i] - MAC-received[i]);

return  x?MAC_IS_BAD:MAC_IS_GOOD;

Google Keyczar就做错了


块加密

对称加密通常构建在块加密算法的基础之上

一个理想的块加密算法使用一个key来双向地把n-bit的输入x转换成n-bit的输出Ek(x),这样当 知道(x,Ek(x))时,对任意的(x’,k’)!=(x,k),你没法以大于2^-n的概率猜出(x’,Ek’(x’))

有时被称为“随机排列”

通常我们关心的是Ek(x)不透露出 当x!=x’时Ek(x’)的信息。

如果一个攻击者可以通过观察一个块加密算法怎么处理不同key,来获取有用信息,该块加密算法 被认为可被 key相关攻击 (key-related attack)攻破。


实践:

使用 AES-256

AES-256有related key攻击漏洞,但是当你把其它事情做对时,这并不是问题

AES-128理论上足够强壮,但是块加密算法很难没有side channel地正确实现 ,

并且key里面的额外bit 在key的一些bit泄露之后是有用的。

不要使用 blowfish

想都不要想使用DES

避免 triple-des(3des)

不要使用块加密算法”raw”,替代地,在一个已经建立的操作模式中使用它(?)。


块加密算法操作模式

一个块加密算法操作模式告诉你怎么使用一个块加密算法来保护数据流

在很多case中,plaintext需要被填充到块大小的整数倍,块密码算法操作模式会 告诉你怎么做到这一点

流行的模式有: ECB ,CBC , CFB , OFB,CTR,IAPM,CCM,EAX,GCM …

大多数模式只提供了加密,但也有一些提供了认证

实践: 使用:CTR模式

不要使用同时提供加密和认证的模式

想都不要想使用ECB

使用一个MAC(例如HMAC-SHA256)来认证你的加密数据

如果你认为你不需要这么做,咨询一个密码学专家,他会告诉你你为什么是错的。

验证你的加密数据的真实性,在你揭秘数据之前。


非对称加密

一个非对称加密模式使用一个签名key来把plaintext转换成ciphertext,使用一个认证码来把 ciphertext转化成plaintext或者“错误的签名”

签名key不能从认证key算出,但是认证key可以从签名key算出

ciphertext通常由 plaintext加一个签名构成

如果一个攻击者接触到了验证key,并且可以说服你签名任意的plaintext,那就可以认为这个 非对称加密系统被攻破了。


非对称认证

使用 RSASSA-PSS(RSA签名,使用Probabilistic Signature Scheme padding)

使用 2048-bit的RSA key,使用65537作为公钥的公共幂,和SHA256

不要使用 PKCS v1.5 padding

想都不要想 使用不带消息padding的RSA(即RAW)

可能避免: DSA

可能避免:椭圆曲线签名模式

想都不要想使用相同的RSA key既做认证,又做加密


非对称加密

非对称加密类似于非对称签名,除了方向相反,使用公钥把plaintext转成ciphertext,但是要 使用私钥把ciphertext转成plaintext

一个

大多数非对称加密模式都限制能加密的消息大小到一个很低的数字以下。


非对称加密

使用 RSAES-OAEP(RSA加密,使用Optimal Asymmeric Encryption Padding)

使用2048-bit的RSA key,以65537为幂底数,SHA256和MGF1-SHA256

不要使用 PCKS v1.5 padding

不要使用不带消息padding的RSA

生成一个随机key,用这个key使用对称加密加密你的消息,然后使用非对称加密算法加密你的key

小心避免RSAES-OAEP的timing攻击通道


密码

密码通常被直接用于识别,但是也可以被用于加密或者认证。

实践:

尽可能避免密码

使用一个key继承函数,来尽快把密码转成key。

使用PBKDF2,如果你跟随流行趋势

使用scrypt,如果你希望28倍地比严肃的攻击者更安全

想都不要想把用户的密码存储在服务器上。绝对不能,就算它们被加密了也不能。


SSL

SSL是一个可怕的系统

SSL的复杂性导致它很难别安全地实现

SSL给了攻击者很多攻击选项

SSL要求你决定你想信任什么CA

你相信中国政府吗?

不幸的是,SSL是唯一可行的选项

实践:

随客户端分发非对称签名key,并且使用这个key开始你的整个密码系统

使用SSL加密你的网站,Email,和其他公开的标准面向Internet的服务器。

认真地想想你信任哪些CA。


奇奇怪怪地部分:

咨询一个密码学专家,如果

你的密码学硬件设备,攻击者可以物理接触到。(例如smartcards)

你想使用最少的电力消耗(例如在手机上)

你需要处理尽可能大的数据流量(例如 10Gbps的 IPSec 隧道)

你需要传输尽可能少的bit(例如和一个核潜艇的通信)

你想忽视我在这个talk中提出的任何建议


QA

Comments