斌头之计算机安全学
斌头之计算机安全学
1. 概论
「要在一条不安全的信道中传递信息,这是计算机安全存在的原因。」
CIA三元组:
integrity 完整性 系统完整+数据完整
availability 可用性
confidentiality 机密性
真实性;可追溯性 不被算在这之中
6种安全服务
认证:
- 1.在连接的初始化阶段,认证服务要保证两个实体是可信的 2. 保证连接不受第三方的干扰(在交互中,不能有第三方能伪装成合法的实体传输或接受信息)
- 包括对等实体认证(有连接) 和 数据源认证(通信实体在通信前没有预先交互(无连接))
访问控制:限制和控制通过通信连接对主机与应用进行访问的能力。每个试图获得访问控制的实体在获取权限之前必须被识别/认证
数据保密性(防止被动攻击)
数据完整性(防止主动攻击) 确保收到的消息 和 发送出的消息是一致的。(同时也保护数据被破坏)
不可否认性:防止发送或者接收方 否认传输/收到过某条信息。 「也就是 接收方能证明发送方确实发送了消息,而发送方能证明接收方肯定收到了这条消息」
可用性服务:系统资源可以被授权实体访问或使用时 称系统是可用的。
安全攻击
security attack 分为被动攻击和主动攻击 (OSI ITU-T X.800)
- 被动攻击:试图了解或利用系统信息 但不影响系统资源
- 截获、监听都是被动攻击 除了利用信息还可以 流量分析「判断通信性质、判断主机身份和位置」
- 使用VPN(虚拟专用网) 加密网络来预防
- 主动攻击:试图改变系统资源或者影响系统运作 篡改数据流 或制造虚假流 可以被检测
- 假冒、重放、篡改、拒绝服务
- 不容易被有效防止
security mechanisms 安全机制 「加密、数字签名、访问控制、认证交换」
2. 密码系统与古典密码
5个部分: M 明文空间 | C 密文空间 | K密钥空间 | E(encryption)| D(decryption)
加密: E(M, K1) = C
解密: D(C, K2) = M 而D(E(M, K1), K2) = M 对称加密时 K1 = K2 公钥加密 K1 != K2
(古典密码系统是不存在认证概念的)
公钥加密:M = D(E(M, pubkey), privatekey)
认证:M = E(D(M, privatekey), pubkey)
密码分析(攻击难度由高至低):
- 唯密文攻击
- 已知明文攻击 (掌握一段密文以及其对应的明文)
- 选择明文攻击 (掌握加密机,可以对任意明文加密得到密文)
- 选择密文攻击(掌握解密机,可以对任意密文解密得到明文)
- 选择文本攻击
密码的安全性
无条件安全
计算上安全
- 破译代价超过密文价值
- 破译时间超过生命周期
古典密码的基本模块
- Substitution 代换(用其他符号代替)
- Permutation 置换(得到类型不同的映射)
3. 分组密码、AES、分组密码的工作模式
分组密码的设计思想: 「扩散与混淆」
- diffusion 扩散 「将明文冗余的分散到密文中,要实现这种思想 可以采用 置换 permutation」 (增加方程次数)
- confusion 混淆 「防止统计分析攻击的方法。 通常使用 代换 substitution」(增加)
应当注意的是, 我认为分组密码和对称/非对称密码是不同的分类,分组密码对应的是流密码。
AES
- 分组长度必须 128 bit 密钥长度可为 128 196 256 bit 三种
- 密码需要加密N轮 轮数由密钥长度决定 16字节 $\rightarrow$ 10轮 24字节 $\rightarrow$ 12轮 32字节 $\rightarrow$ 14轮
- 加密时 前N-1轮是相同的4个步骤。而最后一轮只包含3个步骤(没有列混淆),第一轮之前有一次轮密钥加
- 解密时 先进行一次轮密钥加 然后 逆向行移位、逆向字节代替、轮密钥加、逆向列混淆,最后一轮不进行列混淆
- (以128为例)在最开始需要输入一个16字节密钥。输入的密钥被扩展成由 44个32位字(4bit) 组成的数组 w[i]。 10轮之中,每一轮搞4个w[i]数组作为这一轮的轮密钥。 扩展密钥 $\rightarrow$ 44个w[i]数组
AES的步骤
字节代换 ByteSubstitution 查表操作 4x4字节矩阵 Sbox则是 16x16的字节矩阵
行移位Shift Rows 第0行不动 第一行左移1字节,第二行左移2字节,第三行左移3字节
列混淆Mix Columns 给定一个特殊的可逆矩阵,每一列分别和矩阵相乘 得到的列替换掉原来的列
轮密钥加 这个分组和扩展密钥中的4行 按位XOR
(密钥扩展函数将产生N+1轮密钥,它们是互不相同的4x4矩阵,作为轮密钥加的输入)
关于AES
AES可以构造 消息验证码 这时只使用了加密过程。(任何其他的分组密码也可以)
分组密码工作模式 讨论 多组明文需要发送时如何选择密钥
因为每次用一样的,所以一样的明文自然对应一样的输出。
解密时 分别解密 然后和上一块密文异或就行了
密文反馈 CFB 一次处理s位,上一块密文作为加密算法的输入,产生的伪随机数输出和明文异或作为下一单元的密文
面向数据流的通用传输 、 认证
搞一个移位寄存器(因为加密每次需要128位,我们每次只要s位)
拿128位加密,加密完成后只拿前s位 然后和明文异或 异或的结果再加入移位寄存器。
输出反馈 OFB
和CFB类似,加密算法的输入是上一次加密的输出,且使用整个分组
计数器 CTR
每个明文分组都与一个经过加密的计数器相异或。对每个后续分组计数器递增。
明文还是和加密后的异或直接得到密文。但不链接各个明文!
《实用密码学》[Schneier,2003]一书中指出,不应使用ECB模式,而推荐使用CBC模式和CTR模式。
4. 公钥密码学RSA ECC(Ellptic Curve) DSS
提问: 与公私钥加密相比 对称加密又是建立在什么概念上的?
对一个对称加密来说 $E_k(M) = C; D_k(C) = M$
- 加密与解密算法可以不同
- 对密钥K的使用方法可以不同
对称密码
算法
包括
- 分组加密 DES, AES, TEA, SM4
- 流密码 RC4, ZUC(中国4G国标)
- 哈希函数 SHA , SM3
- 消息认证码 CBC-MAC. AES-GCM. HMAC/NMAC
公钥密码学解决的问题 「加解密 密钥交换 和 数字签名」
加/解密:发送方用接收方的公钥来加密 接收方用其私钥来解密
密钥交换:通信的双方交换会话密钥 「将使用一方或者双方的私钥」
数字签名:发送方用私钥对消息签名。(可以加密整个信息,也可以加密消息的一个小数据块,这个数据块是整条消息的函数(Hash)) 注意数字签名因为用私钥加密, 会丧失保密性
但也可以先PR加密,再PU加密。 接收方就先用自己的私钥解密,再用发送方的公钥获取数字签名
其中RSA和ECC可以实现3种功能 Diffie-Hellman只能进行密钥交换 DSS只能进行数字签名
对公钥密码体制的要求
产生一对密钥(公+私)是容易的。 发送方加密和接收方解密是容易的。 已知公钥PUb 不能确定私钥。 已知公钥PUb和密文C 不能恢复出明文M。 加解密函数可以互换顺序。
总结起来就是:加解密容易。公钥 $\rightarrow$ 私钥不可行。公钥+密文 $\rightarrow$ 明文不可行。 并且加密函数和解密函数最好可以交换(支持公钥加密 私钥解密)这条不是必须的
RSA Rivest-Shamir-Adleman
明文和密文是 0-n-1之间的整数
n一般为 1024位二进制(309位10进制)
RSA的步骤
- 两个大素数 p q ,n = p * q
- phi(n) = (p-1) * (q-1)
- 选一个和 phi(n) 互素的 e 作为公钥,d 则是 e mod phi(n)的逆元
- e和n可以公开, d和p q 必须保密
公钥{E, K}. 私钥{D, N};
RSA的加解密
明文^e^ = 密文 (mod n)
密文^d^ = 明文 (mod n)
大数因式分解的困难造就了RSA的安全性
我们为什么使用混合加密:
公钥密码的加解密比较慢,我们可以用公钥加密来加密密钥,对称加密来加密消息,接收方先用私钥解密出密钥然后再进行对称解密 (这里其实也一定程度上揭示了TLS和SSL的原理)
Diffie-Hellman 密钥交换
离散对数的计算困难造就了Diffie-Hellman的可行性
产生一个密钥,所以一般用在对称加密里
Diffie-Hellman预备知识:
定义素数p的原根:一个整数,其幂可以产生1-p-1之间的所有整数
产生整数的原则是模运算 一共模p-1次
$a \space mod \space p\space | \space \space a^2 \space mod \space p \space| \space a^3\space mod\space p\space …a^{p-1} \space mod\space p$
⚠️它们的顺序可以不是1-p-1,但是一定不能重复
计算离散对数
: 对于素数p和其原根a, 任意的 $b \equiv a^i \mod{m}$
计算出指数i 就是离散对数。
在Diffie-Hellman中 素数q和原根a 是公开的这时A和B想要交换密钥,他们俩要分别选择一个小于素数q的数
令它们分别为 XA 、XB(这两个是保持私有的) 利用原根a 算出YA和YB(这两个对另一方可见)
$用户A计算出:Y_A = a^{X_A}\mod q$
$用户B计算出:Y_B = a^{X_B}\mod q$
$用户A计算密钥K=Y_B^{X_A}\mod q$
$用户B计算密钥K = Y_A^{X_B}\mod q$
这两种计算的结果是一样的 这也就算是完成了密钥交换(两边的密钥是一样的)
几个例子:
在知道q和a的情况下:用户A产生一个一次密钥XA,把自己算出的YA发给B,用户B则一样,并把自己算出的YB发给A,这样两边就都可以算出密钥K。并且在接下来的一段时间进行信息交互了。
LAN上的一组用户共用q和a,他们每个人都产生一个永久的X,并把自己的Y公开。任何一个用户就都可以发送消息给对方了。不能抗重播攻击。
攻击Diffie-Hellman
直接穷举
比如 q = 353;a = 3。XA = 97, XB = 233
这时 YA = 3^97 mod 353 = 40, YB = 3^233 mod 353 = 248
K = 248^97 mod 353 = 40^233 mod 353 = 160
攻击者知道:q = 353, a = 3, YA = 40, YB = 248
那么 解方程 3^a mod 353 = 40, 或者 3^b mod 353 = 248 就能找到XA或者XB,那么就相当于确定了密钥K
一个个试就完了
中间人攻击
A和B想交换密钥, q 和 a 已知。 现在C同时拦截了YA和YB,他生成XC1和XC2两个私钥,然后求出YC1和YC2,现在他将YC1和YC2分别给A和B,这样他和A就共享密钥K1,和B共享密钥K2,到这一步,攻击就已经奏效了。
接下来,C可以只窃听,也可以修改,并且A和B是无法解密对方的消息的,因为密钥K不对。
Diffie- Hellman无法抵抗中间人攻击,因为没有认证机制。
数字签名
公钥证书
可以克服这个问题
ECC 可以使用比RSA短的多的密钥得到相同的安全性 具体见Ellptic Curve.pdf
Hash&MAC
- Hash不是用来加密或解密的而是用来产生数字指纹或者进行消息认证
- Hash的应用:消息认证「消息没有被修改等」|数字签名|单向口令文件|入侵检测|随机函数(PRF)/伪随机数发生器(PRNG)
- 哈希函数的构造: 1. 分块 2. 填充 3. 迭代压缩
Hash提供消息认证时的几种情况:(由MAC来完成)
- 使用对称密码加密消息和Hash码。 或者对无需保密性,只需要认证性的,可以只加密Hash码
- 如果通信的双方已经共享了一个秘密值S,发送方可以将明文和S串联后计算Hash,接收方重新计算Hash。 这样可以不使用加密算法。当然 也可以再将整个消息和Hash值加密提供保密性。
Hash提供数字签名: 「知道公钥的人都可以通过数字签名验证消息完整性」
- 使用发送方PrivateKey 只对Hash码加密(又可签名又可认证) 。当然 也可以再用对称密码中的密钥加密。
Hash的安全要求
- 单向 「抗原像攻击」
- 弱抗碰撞性 给你一个x(是任意给的) 找到另一个x2 使得H(x) = H(x2) 是不可行的 「抗第二原像攻击」
- 强抗碰撞性 寻找任意的 (x, x2)对 使得他们的H(x)相等不可行。 「参考生日悖论」
- 伪随机
- 高效
安全Hash算法 SHA系列
SHA-512 输入小于 2^128位的消息,输出512位的消息摘要,输入的消息以1024bit 的分组进行处理。
- 附加填充位
- 附加长度
- 初始化Hash缓冲区
- 处理消息并且输出
SHA-3 「Keccak」⚠️和SHA-512区分
海绵结构是Keccak使用的基本迭代结构。输入的消息 仍然是被分成固定长度的分组,每个分组逐次作为每轮迭代的输入,同时上一轮迭代的输出也会反馈至下一轮的迭代中,最终产生一组输出块。
可以被看作轻量级密码(因为海绵函数允许输入和输出的长度都可变),有着新的压缩函数(XOR AND NOT,没有查表和算术运算)
海绵函数由 ƒ(内部函数,每轮迭代中执行一次 包括置换和代替) r(输入分组的位长度,称其为位速率) pad 填充算法(为了保持格式一致,哪怕刚好整除,也会直接填充一个块)
Keccak的 Sponge Structure 分为Absorbing和Squeezing(挤压)
- 吸水:initialize state $\rightarrow$ XOR some of the message to the state $\rightarrow$ Apply compression function「调用压缩函数压缩」 (然后在XOR和压缩函数中不断往复)
- 状态变量s的长度为 b ,b = r + c(r为每个分组的长度,c是容量)。 默认情况下,c = 1024bit, r = 576bit, 所以b = 1600bit
- 状态变量的初始长度为0。吸水时:通过填充0,将分组的长度从r 扩展到b位 (加入c位的0) $\rightarrow$ 扩展后的消息分组,和s进行XOR得到b位,并且作为ƒ的输入。(ƒ的输出则作为下一轮迭代时s的取值)
- 不是每个SHA-3都需要挤压。如果需要的输出长度 L 比 b(一个分组的长度)还要小,那么就不需要挤压了。直接返回前L位。
- 挤压:Apply compression function $\rightarrow$ Extract some output「提取部分输出」 (在这两个部分不断往复)
- 先在s中拿出前r位作为Z0,之后将s加入ƒ中进行运算,结果再取前r位。直到输出长度 = L。
- 现在来讨论压缩函数ƒ 每次输入s的都是1600bit,我们把这1600bit分成5x5x64的矩阵,5x5作为面,64的称为纵。形成一个纵深64格的长方体。函数对矩阵执行24圈操作,每圈5个步骤,除了最后一步之外完全一样的
- $R=\theta
\rho\pi\chi\iota$- theta:代替。每个字中都每一位的新值取决于当前值、其前一列的每个字的同一位、后一列的每个字的邻接位
- rho :置换。每个字的内部使用循环移位进行置换 向后移位。W[0, 0]不变。
- pi:置换。字之间进行5x5矩阵的置换。W[0, 0]不变
- chi:代替。每个字中的每一位的新值取决于当前值、相同行下一个字的对应位的值、相同行的下下一个字的对应位的值。
- iota:代替。W[0, 0]和圈常数进行XOR运算。
- 其中: theta步实现的扩散非常明显
报文认证码(消息认证码) :
验证收到的消息确实来自真实的发送方,且没有被修改,并且顺序和时间正确。MAC是多对一函数
在网络通信中的攻击 这里的认证码不阻止被动攻击
消息认证防止:1. 伪装 2. 内容修改、顺序修改、时间修改(延时、重播)
在设计消息认证函数时 一般需要分层。底层负责产生认证符,而上层则指导验证消息真实性。 我们把消息认证符分为三类: Hash函数|消息加密函数(整个消息加密后的密文作为认证符)|消息认证码(消息和密钥的函数。产生定长的值作为认证符)
消息认证码(消息和密钥的函数 产生定长的值作为认证符 MAC = C(K, M) 「C$\rightarrow$MAC函数」
发送方把消息认证码和消息一起发送出去,接收方根据收到的消息以及密钥K再计算一次MAC(不是解密,是再加密然后比对)。
值得注意的是 双方共享密钥K,这使得MAC无法进行数字签名,MAC也不能防止顺序修改。而且,虽然与加密函数类似,但是MAC是不需要可逆的。(接收方和发送方实际上都是进行了加密操作) MAC也可以做PRNG
对称加密其实是可以实现认证的(因为只有收发的双方持有密钥K),但是它无法处理广播、明文认证和快速认证。并且消息在被解密之后就失去了认证性,而MAC则将认证和加密分离,并且可以维持认证性
一般情况下 先认证 后加密更好一些,为什么更好一些? 我也不知道。我觉得先加密后认证更好
MAC需要具有抗计算性:给定多对[message->MAC],对于新的message, 计算出其MAC是不可行的
基于Hash的HMAC,但是SHA这样的Hash不需要密钥K,我们需要把密钥加入到现有的Hash方案里。HMAC在IP安全和其他Internet协议中(SSL)中使用
HMAC的描述如下:
- 在密钥K左边填充0至b位,令其为K+。
- K+和ipad进行位XOR,产生b位的分组Si。 「K的一半的信息位发生变化」
- 将M加在Si的后面(也是分组),然后对它们进行Hash,得到一个Hash码。 「⚠️ 密钥放在了最前面」
- K+和opad进行位XOR,产生b位的分组S0。 「K的另一半的信息位发生变化」
- 将步骤3中的Hash码加在S0的后面,然后再Hash一次就得到结果了。
基于分组密码的DAA和CMAC(AES、3DES适用)
DAA 数据认证算法:建立在DES之上,采用CBC。已经被证明不安全
CMAC使用3个密钥,一个长度为k的K,用在密文分组链接的每一步,两个
首先,消息长度是分组长度b(每个分组称为Mi)的整数倍时,对AES,b = 128,有一个b位的常数K1。按照如下方式计算:
如果不是整数倍,则在最后一个分组的右边填充一个1和若干0使得它也是b长度。
C1 = E(K, M1);
C2 = E(K, [M2 xor C1]);
C3 = E(K, [M3 xor C2]);
Cn = E(K, [Mn xor Cn-1 xor K1])
$T = MSB_{Tlen}(C_n)~~~~~~~T为消息认证码(tag),MSB_s(X)->X最左边的s位$
两个密钥K1,K2的长度都是b位,并且由密钥K(k位)导出
$L = E(K,~0^b); K1 = L·x;K2 = L·x^2= L·x·x$
$乘法”·”在GF(2^b)内进行,所以说x对应b-2个0跟上10,x^2则是b-3个0跟上100$
认证加密 CCM &GCM
认证加密AE指的是通信中实现保密性+认证性的加密系统。
- 先Hash再加密:无线加密协议WEP中用来保护WIFI网络
- 先认证再加密 :先计算MAC,T = MAC(K1, M), 然后再把消息和MAC一起加密。(比如SSL)
- 先加密再认证: IP安全使用的就是这种。
- 独立进行加密和认证
6. 数字签名
提问:我们应该先加密后签名还是先签名后加密?
A和B发送消息的过程中,假设B不使用其他安全措施的情况下,应该先签名后加密。(的确,先验签再解密更加方便,但这也给中间人攻击带来了可能。)
具体的攻击方式非常简单:Oscar拦截A发给B的消息,然后对消息签名,并且把Alice的换掉就行了。 就这么简单。 所以先签名后加密更好
数字签名可以防止 发送方否认。 但是接收方否认不行,需要用到协议。
在MAC中(或者任何对称加密),双方共享一个密钥,这也意味着接收方可以直接伪造出一条来自发送方的消息。而如果接收方可以伪造发送发发出的消息,那么发送方自然也可以就任何消息否认是自己发出的。|数字签名就是为了解决发送双方不互信时的情况
数字签名的特征: 「它一般也同时有认证性,必须得是 确认发送方身份的同时确认消息未被修改」(相当于覆盖了消息认证码的内容= =)
针对数字签名的攻击:
唯密钥攻击:C知道A的公钥
已知消息攻击:C掌握一些消息对应的合法签名。
一般选择/定向选择消息攻击:C对选定的消息在A处获取合法签名,并攻击A的签名方案。(前面那种是先选择消息获得签名,再获得公钥。后面的则是先获得公钥,再选择消息生成签名)
适应性选择消息攻击:允许C将A作为“oracle”轮询,A需要给出对于特定消息的签名,而它们可能和C之前已经获得[消息$\rightarrow$签名]对有关。
同时C也有一定概率完成以下的攻击:1. 完全破译(判断出私钥) 2. 通用伪造(掌握某种签名算法,任意消息都能造出一样的签名) 3. 选择伪造:对于特定消息能伪造合法签名 4. 存在性伪造:至少能伪造出一个消息的合法签名,但不能控制该消息的选择。
对数字签名的要求:
- 必须是和消息相关的二进制串
- 必须使用发送方独有的信息。 防止伪造和否认
- 产生签名、识别和验证签名都比较容易。 并且可以保存数字签名的副本。
- 伪造数字签名 「从数字签名伪造消息,从消息伪造数字签名 都不可行」
ElGamal数字签名方案
同样用到原根。 p 和 a
ElGamal的加密方案和Diffie很像。同样生产随机整数XA, 其范围是1~q-1 (不取q-1)
XA作为A的PriKey,计算Y A = a ^ XA mod q , A的PubKey {q,a,YA},
为了对消息签名, A首先计算 m = H(M) 同时要求m是小于等于q-1的整数。 然后A通过如下步骤产生数字签名:
随机选择整数K,1<= K <= q-1 并且gcd(K, q-1) = 1
计算$S1 = a^K\mod q~~然后计算K^{-1}\mod {q-1}(K模q-1的逆元))$
计算出$S2 = K^{-1}(m - X_AS1)\mod (q-1)$
签名就是 (S1, S2) 组成的
对于任何一个用户B来说,他可以这样验证签名:
Schnorr 数字签名方案
同样也是基于离散对数
DSA 数字签名算法 同样是基于离散对数
使用安全Hash (SHA) 最新版本还包括基于RSA和椭圆曲线密码的数字签名算法