《图解密码技术》总结整理

本文来自《图解密码技术》一书

基本概念

  • 信源、信宿、信道
  • 加密、解密、密钥
  • 对称密码、公钥密码、混合密码
  • 单向散列(hash)函数、信息认证
  • 数字签名 / 篡改和否认
  • 伪随机数

信息传递时面临的风险:

  • 窃听 -> 对称、公钥密码
  • 篡改 -> 散列函数、消息认证、数字签名
  • 伪装 -> 消息认证、数字签名
  • 否认 -> 数字签名

有悖常识的几点:

  • 不要使用保密的加密算法
  • 使用低强度密码不如不用
  • 任何密码都有可能被破解
  • 密码只是安全的一部分(社工)

入门

  • 凯撒密码 / 平移 / 暴力破解
  • 简单替换密码 / 替换 / 频率分析
  • Enigma / 加密密码的密码 / 针对每日密钥的破解

对称密码

  • 编码和异或
  • 一次性密码和它的问题
  • 使用对称密码时,我们通常默认密钥配送问题已解决

DES

全称Data Encryption Standard。于1977年在美国发明并使用。目前可以被暴力破解,因此不应再使用了。

  • DES以64bit为一个单位,使用和明文等长的密钥。
  • 密钥每8位包含1位纠错码
  • 基本结构使用Feistel网络
    • 加密/解密步骤以轮为单位,DES有16轮
    • 每轮运算不加密右半侧,同时右半侧比特和该轮密钥通过轮函数得到本轮加密左侧的密钥,和左侧做异或得到左侧密文
    • 每轮加密后,进行左右对调,保证右侧的保密
    • 解密时用相同结构,反向使用子密钥和轮函数即可
    • 轮函数可以任意复杂
  • 差分分析和线性分析衡量分组密码强度

三重DES

由IBM开发,步骤为DES加密 -> DES解密 -> DES加密。密钥长度是原来三倍,即168比特。

  • 三步使用同一密钥,即向下兼容DES
  • 根据1、3步是否使用同一密钥,分为DES-EDE2和DES-EDE3
  • 处理速度慢

AES

全称Advanced Encrytion Standard,用来取代DES。由NIST开于1997年开始募集,将作为国家标准。算法要求开源免费,并在社群里公开评审,最终于2000年确定为Rijndael。

  • 基本结构为SPN结构
  • 明文分组长度固定为128bit、密钥长度可以是128、192、256比特三种
  • 每轮分为SubBytes、ShiftRows、MixColumns、AddRoundKey四步
    • SubBytes,将4字节 * 4字节的矩阵与一个转换矩阵相乘,得到替换后的矩阵
    • ShiftRows,逐行做平移
    • MixColumns,逐列做矩阵运算
    • AddRoundKey,和轮密钥矩阵做对应位上的异或运算
  • 解密时,除了AddRoundKey一步,其余均需要做逆运算
  • 目前还没有针对Rijndael的有效攻击
  • 避免使用DES,选择AES

分组密码的迭代模式

分组密码只能加密固定长度的密码。因此,需要有模式来迭代加密任意长度的明文。与分组密码相对的是流密码,对数据进行连续处理。

ECB

全称为Electronic CodeBook。是最简单直接的分组方式。将明文分组加密后直接得到对应位置的密文。不足的位用特定数据填充

  • 问题很明显,不要使用
  • 相同的明文分组会得到相同的密文分组
  • 攻击者无需破译密码也可通过修改密文操纵明文,比如替换或删除分组

CBC

全称Cipher Block Chaining。和ECB的最大不同在于明文分组加密前会和上一个密文分组做一次异或运算。开头的明文分组会和一个随机序列做XOR。

  • 一个密文分组的损坏会影响关联的两个分组的解密
  • 比特的缺失将会影响整个密文的解密
  • 操纵初始化向量反转某一位比特可以反转第一个密文分组的某一位
  • 填充提示攻击,攻击padding部分
  • SSL/TLS使用CBC模式保证通信机密
  • CTS使用最后一个密文填充不足的明文部分

CFB

全程Cipher FeedBack模式。和CBC模式的区别在密文分组先加密,再和下一个明文做异或运算。实际上明文分组和密文分组间只相差了一个异或运算。很类似一次性密码本的模式。

  • 解密时,需要对密文分组和初始向量做加密操作
  • 重放攻击,替换密文分组为原有分组,可使得解密出的明文为原有明文

OFB

全称Output-FeedBack模式。和CFB很像,区别在于OFB每次做XOR的密钥流仅来自于上一次的密钥,和密文分组无关。因为密钥流可以提前准备好,分组加密过程可以是并行的。

  • 第一次的密钥来自初始化向量
  • 速度快
  • 如果碰巧密钥加密后和加密前一样,那么之后的密钥就会是同一个值

CTR

全称CounTeR。CTR和OFB类似,区别在于它的密钥流来自于累加的计数器。密文分组来自于密钥流和明文分组的XOR运算。

  • 计数器由nonce和序号两部分各8字节组成,nonce是随机生成的,序号是从1累加的。
  • 和OFB一样,加密解密速度快,结构简单
  • CTR的密钥流在选定nonce后就确定了,因此可以以任意顺序并行加密、解密

公钥密码

解决了对称密码的密钥配送问题。

密钥配送问题

  • 事先共享,在现实生活中传送
  • 密钥配送中心,集中式管理用户密钥,用其加密临时的会话密钥
  • 使用Diffie-Hellman密钥交换
  • 使用公钥密码

公钥密码

使用加密密钥(公钥)加密,使用解密密钥(私钥)解密,避免密钥的泄露。

  • 发送者使用加密密钥
  • 接收者使用解密密钥
  • 加密密钥可以公开
  • 解密密钥一定要保密

目前所使用的公钥密码RSA来自于1978年的发明。流程上,

  • 接收者生成公私钥对,发送公钥给发送者
  • 发送者使用公钥加密明文
  • 接收者使用私钥解密密文

公钥密码有两个问题:

  • 认证公钥的合法性
  • 处理速度慢

RSA

利用了数论中求解离散对数困难且耗时的特点。

  • 加密,使用密文=明文 ^ E mod N。E和N组合成公钥。
  • 解密,使用明文=密文 ^ D mod N。D和N组合成密钥。

生成N、E、D和顺序如下:

  1. 寻找互质的两个大数p和q,N为二者的乘积
  2. p-1和q-1的最小公倍数记为L
  3. 寻找比L小的和L互质的数,即为E
  4. 寻找比L小的和E乘积取模L为1的数,即为D

因为解密时有对N取模操作,因此加密的明文不能大于N。

攻击方式

  • 破解密文 -> 求解离散对数很难
  • 暴力破解D -> 比特位太长,很难破解
  • 通过E求解D,只要知道p和q就能算出D -> 不知道p和q的组合 -> 对N质因数分解很难

中间人攻击里,攻击者可以替换掉原本的公钥,发送给接收者,使用自己的私钥解密,从而实现攻击。这时需要证书保证公钥的权威性。

选择密文攻击里,攻击者可以利用服务端返回的错误消息收集加密算法信息。RSA-OAEP会在明文开头加上明文散列值和填充位,解密时发现散列值和内容对不上时,会隐藏错误信息。

除了RSA外,还有ElGamal方式、Robin方式、ECC(椭圆曲线密码)等公钥密码。它们分别利用了mod N下求离散对数,mod N下求平方根,和椭圆曲线上做乘法运算逆运算在数学上很难求解的特点。

FAQ

Q: 和对称密码的强度对比
A: 达到同等强度,RSA大致需要密钥是AES长度的20倍

Q: RSA使用的质数会用完么
A: 512bit的质数数目大约是10 ^ 150。足够使用。

Q: RSA破解难度如何?
A: 和大整数质因数分解一样难度

Q: 要保证RSA强度,N的长度要达到多少位
A: 2048bit,4096bit更好

混合密码系统

  • 用对称密码加密明文
  • 用公钥密码加密上述对称密码的密钥(通常用随机数生成器得到,只用于此次会话)
  • 公钥密码的密钥由外部赋予(证书)

密码软件PGP、HTTPS中使用的SSL/TLS就使用了混合密码系统。当然它们还包含数字签名、认证、私钥管理等更多处理。

类似混合密码系统,后面要介绍的数字签名、证书、消息认证、伪随机数生成也都是基础密码技术的组合

单向散列函数

  • 将任意长度的消息转换到固定长度散列
  • 具有抗碰撞性,即找到具有相同散列函数的消息很困难
  • 单向性,即无法从三列中还原原信息

MD4、MD5

全称Message Digest。由Rivest设计于1990和1991年。能够产生128bit的散列值。它们的强抗碰撞性已被攻破,不建议使用

RIPEMD-160

1996年设计,是欧盟RIPE项目的修订版,能产生160bit长度的散列值。比特币中使用的散列函数就是RIPEMD-160。

SHA

SHA于1993年由NIST设计,在1995年发布了SHA-1修订版,能够产生160bit的散列值。它的强抗碰撞性已被攻破,也不建议使用

SHA-2于2002年发布,它是包括SHA-256,SHA-384和SHA-512的集合,分别产生256、384和512bit的散列值。目前未被攻破。SHA-2的几种散列长度来自SHA-256和SHA-512的组合。

SHA-3作为SHA-1的升级替代算法,和AES一样,由NIST公开选拔,并在2012年确定为一个叫Keccak的算法。之后会和SHA-2并存一段时间。

Keccak

Keccak可以输入任意长度的数据,产生任意长度的散列值。实现上,Keccak采用海绵结构,有吸收挤出两阶段。

  • 吸收阶段,按分组长度r逐段读入消息内容,和内部状态做异或运算,之后和长度为c的内部状态一起交给函数f做“搅拌”。完成一轮处理,输出作为内部状态继读入输入的消息分组。
  • 挤出阶段,内部消息r和c逐段和函数f做运算,一段段输出散列值。

Keccak的双工结构下,输入和输出可以同时进行。Keccak内部状态由5 * 5 * z的一个三维比特数组组成,共有b个bit。Keccak的本质就是实现一个充分搅拌上述数组的函数f。SHA-3中使用的是Keccak-f[1600]函数。其中b就是内部状态的bit数。函数的每一轮包含θ、ρ、π、χ、ι5步。循环轮数为12 + 2 * log2(b / 25)。

  • θ,将不同两个column的各5个bit通过异或运算加起来,再和当前位做异或替换
  • ρ,各比特沿z轴方向进行平移
  • π,对一个slice上的5 * 5个比特做旋转、轮换操作
  • χ,对一个row上的各位做某个逻辑运算
  • ι,用某个轮常数对所有比特做异或运算,避免对称性

Keccak采用的海绵结构和此前各散列算法使用的MD结构(循环执行压缩函数)方法截然不同,这也是它最后成为标准的一个原因。目前还未出现针对Keccak的有效攻击手段。

攻击方式

利用文件的冗余性,构造一大堆和想要内容一样的数据,找到和原内容散列值一样的结果。

  • 原像攻击,给定散列值,找到具有该散列值的任意消息
  • 第二原像攻击,给定消息1,找到和消息1有相同散列值的消息2
  • 生日攻击,攻击散列算法的“强抗碰撞性”(寻找两个具有相同散列值的消息),利用了从有N个元素的集合中依次取并放回M个元素,两次取到同一元素的概率约为根号N的特点。大大减少暴力破解需要的次数。

消息认证

可以同时防止消息的伪装和篡改。消息认证码简称MAC(Message Authentication Code)。可以简单理解成需要密钥参与的单向散列过程。在使用时:

  • 发送者伴随消息发送计算出的MAC
  • 接受者对消息通过共享密钥计算出MAC值,进行对比,一致则表示认证成功
  • 这个密钥不能被中间人获取!

使用消息认证码(MAC)机制的场景有:

  • SWIFT
  • IPSec
  • SSL/TLS

在认证加密时,Encrypt-then-MAC表示对密文计算MAC值,从而能判断密文是由知道明文和密钥的人生成的。除了Encrypt-then-MAC外,还有Encrypt-and-MAC和MAC-then-Encrypt两种方式。

HMAC

HMAC即Hash MAC,是使用单向散列函数构造认证码的方法。分为下面几步:

  1. 在密钥后填充0到长度达到单向散列函数的分组长度
  2. 填充后的密钥和ipad序列做XOR运算,ipad序列是00110110为单位循环的比特序列
  3. 组合在消息头部,并计算出散列值
  4. 填充后的密钥和opad做XOR运算,opad是01011100位单位循环的比特序列
  5. 结果拼在散列值后面
  6. 根据5的结果计算最终的散列值

应对攻击方式

  • 消息认证需要解决重放攻击的问题,即再次发送相同的消息和MAC值。可以在消息中额外带上序号、时间戳,或先发送一个nonce一次性随机数保证相同的消息也会有完全不同的MAC值。
  • 密钥推测攻击,应保证不能根据MAC值推测出双方使用的密钥,必须使用安全、高强度的伪随机数生成器。

另外,消息认证无法解决下面的问题:

  • 向第三方证明,密钥的共享只在通信的双方,无法证明给第三方
  • 同样的,不能防止通信的一方否认消息

数字签名

和公钥密码相反的使用方式:

  • 发布者使用私钥加密消息,私钥保密
  • 使用发布者的公钥可以解密消息,公钥公开

签名有两种方式:对消息签名对消息的散列值签名。它们主要区别在签名的对象不同。基本过程是:

  1. 生成公、私钥对,发送公钥给接收者
  2. 使用私钥加密消息/消息的hash值,得到签名
  3. 发送消息和签名给接收者
  4. 接收者使用公钥解密,对比消息/消息hash值,验证发送者身份

在签名中,密钥只是起着“保证消息发送者的可靠来源目的的”,被复制并不影响它发挥作用。同时,由于不知道私钥,修改消息后无法伪造消息的签名。

实际应用数字签名的地方有很多:

  • 安全信息公告
  • 软件下载
  • 公钥证书,确保公钥的合法来源
  • SSL/TLS,交换公钥的过程

数字签名基于公钥密码,因此数字签名的实现方式因采用的公钥密码而异,如RSA、ElGamal、ECDSA(椭圆曲线密码)。对数字签名的攻击可以基于单向散列函数或是公钥密码。

  • 不要对不清楚来源的数据做数字签名
  • 对消息的散列值函数做数字签名

数字签名无法解决验证签名正确性的公钥被伪造的问题,因为公钥正确性也依赖于数字签名技术。这里需要证书以及公钥基础设施PKI这种社会学的基础设施辅助。

证书

证书即公钥证书,用来验证公钥密码和数字签名的公钥,由认证机构(CA)发布,认证机构可以是政府机关、一般企业或个人。证书的发布过程包括:

  1. 申请人生成一对密钥,并把公钥发送给CA
  2. CA验证申请人身份
  3. 通过验证后,CA使用自己的私钥对公钥施加数字签名并生成证书
  4. 使用申请人证书的使用者通过CA的公钥验证申请人的公钥是否合法
  5. 验证通过后,使用公钥完成公钥密码或数字签名

PKI是为了能够更有效运用公钥制定的一系列规范的总称。PKI组成要素有3个:使用PKI的用户、认证机构、仓库。

  • 用户,分为注册公钥的用户和使用注册公钥的用户
  • CA,包括生成密钥、验证本人身份、验证公钥合法性、作废证书
  • 仓库,是保存证书的数据库

其中认证机构做了以下事情:

  • 生成密钥对,可以由用户或是CA生成,若是CA生成,需要根据规范发送私钥给用户
  • 注册证书,用户根据规范申请证书,认证机构根据业务准则生成符合X.509规范的证书
  • 作废证书,因为私钥丢失等原因需要作废证书时,需要认证机构制作CRL(Certificate Revocation List,证书作废清单),PKI用户总需要从CA获取最新的CRL,以确认自己拿到的公钥证书是否有效。

认证机构的证书认证

认证机构的公钥证书可以由其他的认证机构施加数字签名。这个关系可以嵌套很多层,比如部门认证机构、分公司认证机构、总公司认证机构。一直往上直到根CA,可以对自己的公钥做自签名。

从而,在验证证书合法性上,也会出现从上至下的验证过程。

证书的攻击

对证书的攻击即对数字签名的攻击。

  • 对施加数字签名前的公钥攻击
  • 注册相似人名进行攻击
  • 窃取CA的私钥
  • 伪装成CA发放证书进行攻击,认证机构本身的可信度也很重要
  • 利用发送CRL的时间间隔,窃取了使用者的私钥,当使用者联系CA发布CRL时,有一定的时间间隔
  • 同样利用CRL,使用合法私钥发送消息后,发送CRL作废自己的公钥,否认自己之前发送的消息

不可能在完全不可信的状态下创建出信任关系,除非以已经存在的信任关系为基础。

密钥

  • 密钥长度(DES:56bit,三重DES:112bit或168bit,AES:128、192、256bit

  • 对称密码和公钥密码用于确保机密性,消息认证码和数字签名使用的密码用于认证,防止篡改内容和伪装身份

  • 只使用一次的密钥称为会话密钥,重复使用的密钥称为主密钥

  • 密码学用途的随机数生成器必须为密码学用途专门设计

  • 定期改变会话密钥可以减少密钥泄露的损失

  • 保存密钥时,使用KEK(Key Encrypting Key)方式保存密钥可以减少管理密钥的数目。

Diffie-Hellman密钥交换

Diffie-Hellman密钥交换里,通信的双方通过交换一些可以公开的消息,就能够生成共享的密钥。

  1. 确定一个非常大的质数P,寻找P的生成元(原根)G
  2. 通信双方各自找1个1 ~ P-2的随机数A、B,生成G ^ A mod P与G ^ B mod P,发送给对方
  3. 对方用收到的数字根据自己选的随机数做乘方运算,得到相等的值作为密钥

它同样利用了离散对数问题难以快速求解的特点。这种交换方法可以做中间人攻击,可以用数字签名、证书等方式应对。

基于口令的密码(PBE)

基于口令的密码避免了:记忆CEK -> 记忆KEK -> 记忆KEK的KEK的死循环。使用好记忆的口令配合盐生成CEK。使用过程如下:

  1. 使用随机数生成器生成盐(随机数),加上用户口令,使用单向散列函数得到KEK
  2. 使用KEK加密会话使用的CEK
  3. 保存好盐以及使用KEK加密的会话秘钥
  • 盐的目的是避免字典攻击
  • 口令虽然便于生成,但是强度不高,因此需要格外地小心保管
  • 可以对KEK迭代使用单向散列函数得到最后的KEK(拉伸),这将加大攻击者的攻击负担

生成安全的口令

  • 使用只有自己知道的信息
    • 不包括别人见过的信息
    • 不包括可以很容易推测的信息
  • 不应该重复使用口令,容易受牵连影响
  • 物理保存是可以的,但要注意安全
  • 可以使用口令生成和管理工具(比如1Password)

随机数生成

随机数生成在密码学中很常用:

  • 生成密钥
  • 生成分组密码的初始化向量
  • 生成CTR模式的nonce
  • 生成盐

随机数至少需要具有下面的属性:

  • 随机等概性
  • 无状态,即无法从上一个推测下一个,生成序列无法重现

由于计算机构成的抽象世界是离散的,内部状态有限,不能满足无状态的特点,因此只能称作伪随机数生成器。基于计算机硬件的随机数生成器可以认为是“真”随机数,它通常提前储存在一个随机数池中,在需要的时候直接从池中取用。伪随机数生成器根据随机的种子(seed)通过算法将内部状态转化为最终的随机数。

  • 线性同余法,以当前随机数为内部状态(初始值为种子),(A x Rn + C) mod M,计算下一个值。其中A、C、M都需要事先选好,线性同余法生成的随机数数列具有可预测性,即不需要知道种子也可以推测下随机数值
  • 单向散列函数,利用单向散列函数保护内部状态,以种子为初始值,逐次递加得到新的内部状态,再通过单向散列函数输出为随机数
  • 密码法,类似单向散列函数,使用密钥加密内部状态输出也可以作为随机数,此时保护内部状态的加密算法和密钥
  • ANSI X9.17中,使用AES和三重DES作为密码算法
    1. 初始化内部状态
    2. 使用当前时间生成掩码
    3. 掩码和内部状态做XOR
    4. 加密3的输出,作为随机数输出
    5. 对加密后的输出与掩码做XOR
    6. 加密5的结果作为新的内部状态

PGP介绍

PGP全程Pretty Good Privacy,编写于1990年,具备现代密码软件所需的几乎所有功能。OpenPGP是一对密文和数字签名进行定义的标准规格。

加密和解密

加密时,使用混合密码系统的流程:

  1. 用伪随机数生成会话密钥
  2. 接收者的公钥加密会话密钥
  3. 压缩消息,并使用对称密码加密,密钥为上面生成的会话密钥
  4. 将加密后的密钥和密文拼接在一起
  5. 将4的结果转换为文本数据,即为报文数据

解密时,PGP的私钥通过用户口令加密保存。在收到密文时:

  1. 输入接收者的口令
  2. 求口令的散列值,生成用户解密私钥的秘钥
  3. 解密得到私钥
  4. 将报文数据转换为二进制,并拆解成加密的会话密钥和压缩的密文
  5. 用自己的私钥解密得到会话密钥
  6. 用会话密钥解密密文
  7. 解压缩明文得到原始消息

生成数字签名

同样,生成数字签名时:

  1. 输入接收者的口令
  2. 求口令的散列值,生成用户解密私钥的秘钥
  3. 解密得到私钥
  4. 使用单向散列函数计算消息散列值
  5. 对散列值签名,即使用私钥加密
  6. 拼合签名和消息,进行压缩
  7. (可选)转换二进制为文本数据,即最后的报文数据

类似地,验证时:

  1. 转换为二进制文件,解压缩数据
  2. 分解出签名和消息两部分
  3. 使用公钥解密签名,得到散列值
  4. 使用单向散列函数计算消息散列值,对比3中的散列值
  5. 相等即验证成功

生成数字签名并加密

实际情况下,我们往往需要使用加密算法加密数字签名中的原消息。实现步骤是上两节的组合。即先进行数字签名,再对签名结果加密。

验证过程是相反的,先解密密文得到签名结果,再验证数字签名。

信任网

PGP确认公钥合法性的方法不依赖于认证机构颁发证书,而是采用所有者信任级别构成信任网(也叫信任圈、朋友圈)的方式,让用户自己决定该信任谁。建立信任有三种方式:

  • 通过自己的签名来确认。用户在通过其他方式(比如线下)确认公钥可信任后,对该公钥加上自己的数字签名。由于PGP中,使用者本人的公钥是绝对信任,被施加签名的公钥因此可信任。注意:这并不代表被施加签名的公钥所有者被完全信任
  • 通过自己完全信任的数字签名进行确认。即完全信任某个公钥进行的数字签名,用户可对当前信任的每个公钥所有者设置信任级别,级别为完全信任时,所有者公钥施加签名的公钥也会被信任。
  • 通过有限信任的多个数字签名进行确认。在设置信任级别为有限信任时,有限信任的公钥施加数字签名后,新的公钥才会被信任。

通过上面三种方式,PGP使用者可以构建起自己的信任网,从而根据自己的决定信任某个公钥。

SSL/TLS

TLS是SSL的后续版本,但在大多数情况下,可以统一写成SSL/TLS。SSL/TLS可以承载应用层协议,保证应用层传输的安全性,HTTP就是其中一种。其余SSL/TLS可以承载的应用层协议还包括SMTP、POP3等等。

SSL于1994年在网景公司开发,在1995年发布了SSL3.0版本,后被发现会导致POODLE攻击。TLS是IETF在1999年作为SSL3.1发布。2006年发布TLS1.1,之后又发布了TLS1.2。

HTTPS中SSL/TLS要保证以下三点:

  • 保证消息传输中不被窃听 -> 对称密码加密消息,公钥密码加密对称密码的密钥
  • 保证消息传输中不被篡改 -> 消息认证
  • 保证消息传输双方的合法性 -> 数字签名生成证书

通信过程

下面的流程以TLS1.2为例。TLS协议分为两层:

  • TLS握手协议,位于上层,处理除加密的部分。可以进一步分为:
    • 握手协议,负责在客户端和服务器间协商密码算法和共享密钥
    • 密码规格变更协议,向通信对象传达变更密码方式
    • 警告协议,在发生错误时将错误传达给对方
    • 应用数据协议,将TLS上承载的应用数据传达给通信对象
  • TLS记录协议,位于底层,处理加密的部分。使用了对称密码和消息认证码,但具体的算法和密钥需要通信双方具体协商

TLS记录协议

记录协议负责数据的压缩、加密、数据认证,工作方式如下:

  1. 分割消息为较小的片段,再分段压缩,压缩方式需要协商决定
  2. 对压缩过的消息进行消息认证,加上MAC值。为了避免重放攻击,在计算MAC值时,加上了片段的编号。其中的单向散列函数的算法、使用的密钥都需要协商确定
  3. 把MAC值和压缩过的消息片段组合在一起,使用对称密码加密。迭代模式使用CBC模式,CBC模式的初始化向量通过主密码生成。对称密码的算法、密钥则需要协商决定
  4. 上述经过加密的数据,再加上数据类型、版本号、压缩后的长度,构成最终的报文数据。数据类型就是之前提到的TLS握手协议的4类子协议

握手协议

握手协议负责生成对称密码中的共享密钥以及交换证书。因为握手的整个过程都是明文进行的,因此需要使用公钥密码或是Diffie-Hellman密钥交换。整个握手协议有下面几步:

  1. ClientHello,客户端发送一些信息给服务器,便于协商算法和密钥
  • 可用版本号,即支持的SSL/TLS版本号
  • 客户端生成的随机数,在后面的步骤会用到
  • 会话ID,在需要重新使用以前的会话时用到
  • 客户端可用的密码套件清单
  • 客户端可用的压缩方式清单
  • 当前时间
  1. ServerHello,服务器根据客户端传来的信息,选择合适的算法和密码套件,返回的消息中带有下面几条
  • 使用的版本号
  • 服务端生成的随机数,后面步骤会用到
  • 会话ID,作用同上
  • 使用的密码套件
  • 使用的压缩方式
  • 当前时间
  1. Certificate非匿名通信时,服务器发送自己的证书,以及对服务器证书签名的CA的证书
  2. ServerKeyExchange,当Certificate消息不足时,服务器通过此消息传递额外信息
  3. CertificateRequest,需要进行客户端认证时,服务端发送此消息,并带上服务器能理解的证书类型、CA名称清单。
  4. ServerHelloDone,服务器发送此消息结束服务器的返回
  5. Certificate,作为CertificateRequest的回应,客户端发送自己的证书,交给服务器验证
  6. ClientKeyExchange,密码套件包含RSA时,会发送经过服务器公钥加密的预备主密码;密码套件包含Diffie-Hellman密钥交换时,会发送Diffie-Hellman密钥交换中的公开值。预备主密码(pre-master secret)是客户端生成的随机数,之后会用做生成主密码的种子。根据预备主密码,通信双方计算出相同的主密码。主密码会用做以下用途:
  • 对称密码的密钥
  • 消息认证码的密钥
  • CBC模式中的初始化向量
  1. CertificateVerify,在服务器发送CertificateRequest时,通过此消息发送客户端使用自己私钥签名的主密码和握手协议传输消息的散列值。证明自己是客户端证书的持有人。
  2. ChangeCipherSpec,客户端发送,表示切换密码开始,实际上是密码规格变更协议的一类报文
  3. Finished,握手结束,此时已使用切换后的密码套件来加密发送。
  4. ChangeCipherSpecFinished。来自服务器,作用同上。

通过上面的步骤,双方达成了下面的目标:

  • 客户端获得了服务器的公钥,完成了服务器认证
  • 服务器获得了客户端公钥,完成了客户端认证(如果需要的话)
  • 生成了对称密码的密钥
  • 生成了消息认证码中的共享密钥

密码规格变更协议

用于在一开始从明文通信切换到使用密码套件沟通。

警告协议

用在握手协议异常、消息认证码错误、无法解压数据等异常情况。

应用数据协议

通信对象间传递应用数据。

主密码

主密码根据预备主密码(pre-master secret)或Diffie-Hellman密钥交换的公开值生成。生成的主密码用于生成对称密码的密钥、消息认证码的密钥、CBC模式的初始化向量

对SSL/TLS的攻击

  • SSL/TLS框架性的特点让它不依赖于某个特定的密码技术,因此对特定密码技术的攻击对SSL/TLS本身影响不大
  • 心脏出血漏洞,发现于2014年,利用TLS心跳拓展对请求的数据大小没有检查,可以获取内存中与请求无关的信息。是OpenSSL实现的漏洞。
  • POODLE攻击,利用CBC中的填充提示攻击,发现于2014年SSL3.0中。
  • FREAK攻击,可以在密码套件协商时,利用中间人攻击,强制使用强度很低的RSA Export Suites。从而在加密后,暴力破解明文。
  • 对伪随机数生成器的攻击
  • 利用之前提过的CRL

总结

密码技术因为人类的不完美而必定不会完美。

  • 对称密码,使用相同密钥加密、解密,保证消息机密性。目前主要使用AES。
  • 公钥密码,使用不同密钥加密、解密,作用同上。使用最广泛的是RSA,还有相关的Diffie-Hellman密钥交换
  • 单向散列函数,将消息转为固定长度散列值的技术,保证消息完整性,目前使用SHA2和SHA3(Keccak)
  • 消息认证码,结合单向散列函数和对称密码,保证消息完整性认证消息,但无法防御否认。目前主要使用HMAC
  • 数字签名,结合单向散列函数和公钥秘钥,保证完整性不可否认性认证消息。是公钥证书采用的技术
  • 伪随机数生成器,配合上述技术使用,需要保证不可预测性不可重现性

密码技术从某种角度看是一种压缩技术:

  • 密钥是机密性的压缩
  • 散列值是消息完整性的压缩
  • 认证值时认证的压缩
  • 随机数种子是不可预测性的压缩

比特币

比特币来自于Satoshi Nakamoto(中本聪,化名)的一篇论文,并于2009年开始实际运用。比特币是一种基于P2P网络的支付结算系统。用户通过它进行进行价值转移。

  • 地址,将公钥使用散列函数求散列值得到,地址都以1开头,剩下内容 不包含O,0,1和I。
  • 钱包,即比特币客户端,可以生成密钥对,公钥用于收款,密钥用于付款
  • 区块链,保存了比特币所有交易记录的账簿,若干交易组成一个区块,在区块头有所有交易的散列值,以及上一个区块的散列值,有交易添加时会触发区块头的散列值变化,并链式传递下去
  • 交易,收、付款方各自生成密钥对,付款方创建交易“地址A向地址B转账x BTC”,并用自己的私钥签署数字签名,之后广播至P2P网络中,完成交易。比特币使用的数字签名基于椭圆曲线DSA,方程为x^2 = y^3 + 7
  • 挖矿,向区块链中添加新区块的行为被称为挖矿,第一个挖矿成功的矿工会获得挖矿奖励和区块所有交易的手续费。为了证明自己确实完成了规定工作,矿工需要进行工作量证明(PoW),即生成的区块头中,前一区块头的散列值必须以若干位的0开头,这个工作需要投入大量的计算资源。区块大约每10分钟添加一个,为了避免通货膨胀,所需的0的个数会不断调整。
    • 根据协议规定,挖矿奖励每4年减少一半
    • 当区块链上同时出现分支时,P2P网络会选择计算量大的分支进行工作
  • 比特币的匿名性只限于交易地址

附录:椭圆曲线

  • 椭圆曲线(EC)源自于求椭圆弧长的椭圆积分的反函数。
  • 定义椭圆曲线上的加法运算
  • 椭圆曲线上的离散对数(ECDLP) - 已知点G和点xG,求整数x
  • 有限域上的离散对数,对点进行模运算
  • 椭圆曲线Diffie-Hellman密钥交换
  • 椭圆曲线ElGamal密码
  • 椭圆曲线DSA(ECDSA)