密码
作者研读《图解密码技术-第三版》的学习总结
图表面对不同场景应运而生技术
信息安全所面对威胁 | 受威胁的特性 | 用来应对技术 |
---|---|---|
窃听(秘密泄露) | 机密性 | 对称密码、公钥密码即非对称密码 |
篡改(信息被修改) | 完整性 | 单项散列函数、消息认证码、数字签名 |
伪装(伪装成真正的发送者) | 认证 | 消息认证码、数字签名 |
否认(事后称自己没有做) | 不可否认性 | 数字签名 |
对称密码/共享密钥密码
算法涵盖:比特异或运算,XOR
用相同的密钥进行加密和解密
对称密码是通过将明文转换为复杂的形式来保证其机密性。
分组密码
分组密码是每次只能处理特定长度的一块明文数据的一类密码算法,这里的“一块”就是分组(block)
。此外一个分组的比特数称为分组长度(block length)
。
DES [2000年前被破译,可以废弃]
DES(Data Encryption Standard)是1977年美国联邦信息处理标准(FIPS)中采用的一种对称密码,也是分组密码,分组长度为64比特,密码算法一次只能加密64比特的明文,并生成64比特的密文。如果要加密的明文比较长,则需要使用DES加密算法反复迭代加密明文。DES的密钥长度是64比特,但由于每隔7比特会设置一个用于错误检查的比特,因此实质上其密钥长度为56比特。
后续DES破译后,出现了三重DES(triple-DES,DES-EDE3, 3DES)。三重DES是为了增加DES的强度,将DES重复3次所得到一种密码算法。
AES
AES(Advanced Encryption Standard, Rijdael)是分组密码,分组长度为128比特,密码算法一次可加密128比特的明文,并生成128比特的密文。如果要加密的明文比较长,则需要使用AES加密算法反复迭代加密明文。AES的规格中密钥长度有128、192和256比特三种。
分组密码的模式
模式
分组密码算法只能加密固定长度的分组,但是我们需要加密的明文长度可能会超过分组密码的分组长度,这是就需要对分组密码算法进行迭代,以便将一段明文全部加密完成。而迭代的方法就称为分组密码的模式
。
攻击模式:
- 直接操作密文从而直接影响到明文,导致解密后明文和加密前明文意思完全不一样。
- 通信过程某些比特缺失,导致密文无法解密。
- 填充提示攻击是一种利用分组密码中的填充部分来进行攻击的方法。
- 重放攻击是用使用历史上某次中几段分组密文替换本次密文中某些分组密文。这个方式让接收解密明文的人无法判断解密明文中错误是通信错误还是人为攻击。
常用分组密码的模式比较表:
CRYPTREC (Cryptography Research and Evaluation Committees) 密码学研究和评估委员会
模式 | 名称 | 优点 | 缺点 | 备注 |
---|---|---|---|---|
ECB模式 | Electronic CodeBook 电子密码本模式 | 不应使用 | ||
CBC模式 | Cipher Block Chainning 密文分组链接模式 | CRYPTREC 推荐;《实用密码学》推荐 | ||
CFB模式 | Cipher FeedBack 密文反馈模式 | CRYPTREC 推荐 | ||
OFB模式 | Output-FeedBack 输出反馈模式 | CRYPTREC 推荐 | ||
CTR模式 | CounTeR 计数器模式 | 主动攻击者反转密文分组中某些比特时,明文分组中相对应的比特也会被反转 | CRYPTREC 推荐;《实用密码学》推荐 |
公钥密码(非对称加密)
公钥密码(public-key Cryptography)中,密钥分为加密密钥和解密密钥两种。发送者用加密密钥对消息进行加密,接收者用解密密钥对密文机型解密。
公钥密码是基于数学上的困难的问题来保证机密性。
公钥密码中,加密密钥一般是公开的。由于加密密钥可以任意公开,因此该密钥被称为公钥(public key)
。解密密钥是绝对不能公开的,这个密钥只能有自己保管,因此称为私钥(private key)
。公钥和私钥是一一对应的,一对公钥和私钥统称为密钥对(key pair)
。由公钥进行加密的密文,必须使用由该公钥配对的私钥才能解密。
RSA
RSA 开发者首字母大写(Ron Rivest、Adi Shamir、Leonard Adleman)
RSA的机密性:
- 依赖目前发展,还没有发现求离散对数的高效算法
- 依赖目前发展,对大整数进行质因数分解的高效算法
RSA加密:密文 = 明文^E mod N
E和N的组合就是公钥
RSA解密:明文 = 密文^D mod N
D和N的组合就是私钥
攻击模式:
- 中间人攻击(man-in-the-middle Attack)
- 选择密文攻击(Chosen Cipher Attack )
对应解决方案是在RSA的明文中加入认证的信息,解密进行识别是否是认证人明文信息。即RSA-OAEP(Optimal Asymmetric Encryption Padding,最优非对称加密填充)
在RSA Chanllenge,有公开记录的被成功分解的最长的RSA数为RSA-768(232位)。但是长度为2048比特的整数目前是安全的即RSA-2048(617位)。因此默认RSA的密钥长度是2048比特。
公钥密码的运行速度远远低于对称密。
混合密码系统了解
用对称密码提高速度,用公钥密码保护会话密钥
应用:SSL/TLS
混合密码系统(hybrid cryptosystem)是将对称密码和公钥密码的优势相结合的方法。
组成机制:
会话密钥是指本次通信而生成的临时密钥,它一般是通过伪随机数生成器产生的。会话密钥是对称密码的密钥,同时也是公钥密码的明文。
- 用对称密码加密消息
- 通过伪随机数生成器生成对称密码作为会话密钥,加密时使用
- 用公钥密码加密会话密钥
- 从混合密码系统外部赋予公钥密码加密时使用的密钥
数字签名,是由单向散列函数和公钥密码组合而成的
证书,是由公钥和数字签名组合而成的
消息认证码,是由单向散列函数和密钥组合而成的,也可以通过对称密码来生成
单向散列函数
获取消息的“指纹”,单向散列函数也称为消息摘要函数(message digest function)、哈希函数。
输入单向散列函数的消息也称为原像。
单向散列函数输出的散列值也称为消息摘要(message digest)或者指纹(fingerprint)。完整性也称为一致性。
单向散列函数
(one-way hash function) 有一个输入和一个输出,其中输入消息称为消息(message),输出称为散列值(hash value)。单向散列函数可以根据消息内容计算出散列值,而散列值就可以被用来检查消息的完整性。
单向散列函数根据任意长度的消息计算出固定长度的散列值,能够快速计算出散列值。单向散列函数一般要具备弱抗碰撞性(要找到和该消息具有相同的散列值的另外一条消息是非常困难的)和强抗碰撞性(要找到散列值相同的两条不同消息是非常困难的)。
MD4和MD5
MD4 是1990年Rivest设计出的单向散列函数,可以产生出128比特的散列值。后续MD4已经被Dobbertin找到MD4散列碰撞方法,现在已经不安全了。
MD5 是1991年Rivest设计的单向散列函数,能够产生生128比特的散列值。后续MD5的强抗碰撞性被攻破,因此它也不安全了。
SHA-1和SHA-2
SHA-1和SHA-2是基于相同MD(message digest)结构的单向散列函数。
SHA-1是一种能够产生160比特的散列值的单向散列函数,但是针对于SHA-1的碰撞攻击算法在2005年已经实现了,所以SHA-1是不安全的。
SHA-2一共包含6种版本。但其实这6种版本SHA-2实质上都是由SHA-256和SHA-512这个两个版本衍生出来的,其他版本都是通过将上述两种版本所生成的结果截取得到的。SHA-2现在还没有攻破是安全的。
6种版本的SHA-2
名称 | 输出长度 | 内部状态 | 备注 |
---|---|---|---|
SHA-224 | 224 | 32*8 | 将SHA-256的结果截掉32比特 |
SHA-256 | 256 | 32*8 | |
SHA-512/224 | 224 | 64*8 | 将SHA-512的结果截掉288比特 |
SHA-512/256 | 256 | 64*8 | 将SHA-512的结果截掉256比特 |
SHA-385 | 384 | 64*8 | 将SHA-512的结果截掉128比特 |
SHA-512 | 512 | 64*8 |
SHA-3 (Keccak)
SHA-3(Secure Hash algorithm-3)是一种作为新标准发布的单向散列函数算法,用来替代在理论上已被找出攻击方法的SHA-1算法。全世界的企业和密码学家提交了很多SHA-3的标准方案,经过长达5年的选拔,最终于在2012年正式确定将Keccak算法作为SHA-3标准。
SHA-3(Keccak)可以生成任意长度的散列值,但为了配合SHA-2的散列值长度,SHA-3标准中共规定了SHA3-224,SHA3-256,SHA3-384,SHA3-512这4种版本。SHA-3是安全的。
消息认证码
目的解决消能够息被正确传送了,中间没有发生篡改且能否,确认消息是对方发送的
消息认证码的输入包括任意长度的消息和一个发送者与接收者之间共享的密钥
,它可以输出固定长度的数据,这个数据称为MAC值
。
消息认证码的实现方法:使用单向散列函数实现(eg: HMAC),使用分组密码实现(eg:AES-CMAC)等等
我们是可以对消息认证码进行重放攻击的,一般针对这种情况,我们可以是以下方法进行防御:
- 约定每次都对发送的消息赋予一个递增的编号(序号),并且在计算MAC的值时将序号也包含在消息中。这种方法虽然有效,但是对于每个通信都需要记录最后一个消息的序号。(微信支付中微信代扣requestId)
- 约定在发送消息时包含当前的时间啊,如果收到以前的消息,即便MAC值正确也将其当做错误消息来处理,这就能防御重放攻击。这种方法虽然有效,但是发送者和接收者的时钟必须一致,而且考虑到通信延迟,必须在时间的判断上留下缓冲,于是多多少少还是存在可以进行重放攻击的空间。
- 在通信之前,接收者先向发送者发送一个一次性的随机数,这个随机数一般称为nonce。发送者咋消息中包含这个nonce并计算MAC值。由于每次同时nonce的值发生变化,因此无法进行重放攻击。这种方法虽然有效,但是通信的数据会有所增加。(广泛运用在微信支付、支付宝支付上)
消息认证码对于防止否认和第三方证明上无法解决的。
HMAC
因为使用单向散列函数构造消息认证码,所以可以使用SHA-1,SHA-224,SHA-256,SHA-384,SHA-512构造消息认证码。这些方式构造消息认证码叫HMAC-SHA1,HMAC-SHA-224,HMAC-SHA-384,HMAC-SHA-512。
数字签名
目的是解决消息是谁写的问题
数字签名(digital signnature)是将消息认证码中对称密码换成公钥密码,这样发送者和接收者都使用者不同的密码。 发送者使用公钥密码的私钥对消息进行签名处理,接收者是用公钥密码的公钥验证消息的签名。
数字签名对签名密钥和验证密钥进行了区分,使用验证密钥是无法生成签名的。签名密钥只能由签名的人持有,而验证签名则是任何需要验证签名的人都可以持有。换句话说数字签名就是通过将公钥密码“反过来用”而实现的。
公钥密码与数字签名的密钥使用方式
私钥 | 公钥 | |
---|---|---|
公钥密码 | 接收者解密时使用 | 发送者加密时使用 |
数字签名 | 签名者生成签名时使用 | 验证者验证签名时使用 |
谁持有密钥? | 个人持有 | 只要需要,任何人都可以持有 |
对消息散列值签名的使用流程:
- 发送方使用单向散列函数将消息生成一个散列值
- 发送方使用数字签名的私钥对散列值进行签名
- 然后将消息和签名一起发送给接收方
- 接收方使用数字签名的公钥解密签名
- 接收方使用单向散列函数将接收消息生成一个散列值,和解密后签名进行对照
数字签名不会保证消息的机密性,数字签名的作用是防止否认的及第三方也可以认证。但是数字签名容易受到“中间人攻击”,同时我们也无法高效验证自己手中公钥是否是有效的。
对称密码的密钥是机密性的精华,单向散列函数的散列值是完整性的精华。
证书
为公钥加上数字签名
公钥证书(Public Key Certificat, PKC)其实和驾照很相似,里面记有姓名、组织、邮箱地址等个人信息,以及属于此人的公钥,并由认证机构(Certification Authority、Certifying Authority,CA)施加数字签名。只要看到公钥证书,我们就可以知道认证机构认定该公钥的确属于此人。公钥证书也简称为证书(certificate)。
公钥基础设施(Public Key Infrastructure),简称PKI.公钥基础设施是为了能够更有效地运用公钥而制定的一系列规范和规格的总称。
####随机数
不可预测性源泉
- 随机性 不存在统计学偏差,是完全杂乱的数列
- 不可预测性 不能从过去的数列推测出下一个出现的数
- 不可重现性 除非将数列本身部分保存下来,否则不能重现相同的数列
伪随机数生成器
通过硬件生成的随机数列,是根据传感器收集的热量、声音的变化等事实上无法预测和重现的自然现象信息来生成的。像这样的硬件设备就称为随机数生成器(Random Number Generator, RNG)。
而可以生成随机数的软件则称为伪随机数生成器(Pseudo Random Number Generator,PRNG)。因为仅靠软件无法生成真随机数。
为了生成伪随机数,伪随机数生成器需要被称为种子(seed)的信息。伪随机数的种子是用来对伪随机数生成器的内部状态进行初始化的。伪随机数的种子是一串随机的比特序列,根据种子就可以生成出专属于自己的伪随机数列。
单向单列函数的单向性是支撑伪随机数生成器不可预测性的基础。
密码的机密性是支持伪随机生成器不可预测的基础。
随机数应用:
- 生成密钥
用于对称密码和消息认证码 - 生成密钥对
用于公钥密码和数字签名 - 生成初始化向量(IV)
用分组密码的CBC、CFB和OFB模式 - 生成nonce
用于防御重放攻击以及分组密码的CTR模式等 - 生成盐
用于基于口令的密码(PBE)等
备注
Java中有个用于生成随机数数列的类,名叫java.util.Random,然而这个类也不能用于安全相关用途。如果要用于安全相关用途,可以使用另一个名叫java.security.SecureRandom的类。
应用
openssl 加密工具
摘抄至 OpenSSL
1 | base64 Base 64 |