斌头之计算机安全学

斌头之计算机安全学

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的步骤

  1. 字节代换 ByteSubstitution 查表操作 4x4字节矩阵 Sbox则是 16x16的字节矩阵

  2. 行移位Shift Rows 第0行不动 第一行左移1字节,第二行左移2字节,第三行左移3字节

  3. 列混淆Mix Columns 给定一个特殊的可逆矩阵,每一列分别和矩阵相乘 得到的列替换掉原来的列

  4. 轮密钥加 这个分组和扩展密钥中的4行 按位XOR

(密钥扩展函数将产生N+1轮密钥,它们是互不相同的4x4矩阵,作为轮密钥加的输入)

关于AES

AES可以构造 消息验证码 这时只使用了加密过程。(任何其他的分组密码也可以)


分组密码工作模式 讨论 多组明文需要发送时如何选择密钥

  1. 电码本 ECB 相同的密钥分别对明文分组独立加密

因为每次用一样的,所以一样的明文自然对应一样的输出。

  1. 密文分组链接 CBC 加密算法的输入是上一个密文组和自己这个明文组的异或

    面向分组的通用传输, 认证 意思就是 实际上加密的是上一个密文组和这个明文组的异或

解密时 分别解密 然后和上一块密文异或就行了

  1. 密文反馈 CFB 一次处理s位,上一块密文作为加密算法的输入,产生的伪随机数输出和明文异或作为下一单元的密文

    面向数据流的通用传输 、 认证

    搞一个移位寄存器(因为加密每次需要128位,我们每次只要s位)

    拿128位加密,加密完成后只拿前s位 然后和明文异或 异或的结果再加入移位寄存器。

  2. 输出反馈 OFB

    和CFB类似,加密算法的输入是上一次加密的输出,且使用整个分组

  3. 计数器 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的步骤

  1. 两个大素数 p q ,n = p * q
  2. phi(n) = (p-1) * (q-1)
  3. 选一个和 phi(n) 互素的 e 作为公钥,d 则是 e mod phi(n)的逆元
  4. 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$

这两种计算的结果是一样的 这也就算是完成了密钥交换(两边的密钥是一样的)

几个例子:

  1. 在知道q和a的情况下:用户A产生一个一次密钥XA,把自己算出的YA发给B,用户B则一样,并把自己算出的YB发给A,这样两边就都可以算出密钥K。并且在接下来的一段时间进行信息交互了。

  2. LAN上的一组用户共用q和a,他们每个人都产生一个永久的X,并把自己的Y公开。任何一个用户就都可以发送消息给对方了。不能抗重播攻击。

攻击Diffie-Hellman

  1. 直接穷举

    比如 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

    一个个试就完了

  2. 中间人攻击

    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来完成)

  1. 使用对称密码加密消息和Hash码。 或者对无需保密性,只需要认证性的,可以只加密Hash码
  2. 如果通信的双方已经共享了一个秘密值S,发送方可以将明文和S串联后计算Hash,接收方重新计算Hash。 这样可以不使用加密算法。当然 也可以再将整个消息和Hash值加密提供保密性。

Hash提供数字签名: 「知道公钥的人都可以通过数字签名验证消息完整性」

  1. 使用发送方PrivateKey 只对Hash码加密(又可签名又可认证) 。当然 也可以再用对称密码中的密钥加密。

Hash的安全要求

  1. 单向 「抗原像攻击」
  2. 弱抗碰撞性 给你一个x(是任意给的) 找到另一个x2 使得H(x) = H(x2) 是不可行的 「抗第二原像攻击」
  3. 强抗碰撞性 寻找任意的 (x, x2)对 使得他们的H(x)相等不可行。 「参考生日悖论」
  4. 伪随机
  5. 高效

安全Hash算法 SHA系列

SHA-512 输入小于 2^128位的消息,输出512位的消息摘要,输入的消息以1024bit 的分组进行处理。

  1. 附加填充位
  2. 附加长度
  3. 初始化Hash缓冲区
  4. 处理消息并且输出

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的描述如下:

  1. 在密钥K左边填充0至b位,令其为K+。
  2. K+和ipad进行位XOR,产生b位的分组Si。 「K的一半的信息位发生变化」
  3. 将M加在Si的后面(也是分组),然后对它们进行Hash,得到一个Hash码。 「⚠️ 密钥放在了最前面」
  4. K+和opad进行位XOR,产生b位的分组S0。 「K的另一半的信息位发生变化」
  5. 将步骤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中(或者任何对称加密),双方共享一个密钥,这也意味着接收方可以直接伪造出一条来自发送方的消息。而如果接收方可以伪造发送发发出的消息,那么发送方自然也可以就任何消息否认是自己发出的。|数字签名就是为了解决发送双方不互信时的情况

数字签名的特征: 「它一般也同时有认证性,必须得是 确认发送方身份的同时确认消息未被修改」(相当于覆盖了消息认证码的内容= =)

  1. 能验证签名者、签名日期+时间

  2. 能认证被签名的消息内容

  3. 能被第三方仲裁。

针对数字签名的攻击:

  1. 唯密钥攻击:C知道A的公钥
  2. 已知消息攻击:C掌握一些消息对应的合法签名。
  3. 一般选择/定向选择消息攻击:C对选定的消息在A处获取合法签名,并攻击A的签名方案。(前面那种是先选择消息获得签名,再获得公钥。后面的则是先获得公钥,再选择消息生成签名)

  4. 适应性选择消息攻击:允许C将A作为“oracle”轮询,A需要给出对于特定消息的签名,而它们可能和C之前已经获得[消息$\rightarrow$签名]对有关。

  5. 同时C也有一定概率完成以下的攻击:1. 完全破译(判断出私钥) 2. 通用伪造(掌握某种签名算法,任意消息都能造出一样的签名) 3. 选择伪造:对于特定消息能伪造合法签名 4. 存在性伪造:至少能伪造出一个消息的合法签名,但不能控制该消息的选择。

对数字签名的要求:

  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通过如下步骤产生数字签名:

  1. 随机选择整数K,1<= K <= q-1 并且gcd(K, q-1) = 1

  2. 计算$S1 = a^K\mod q~~然后计算K^{-1}\mod {q-1}(K模q-1的逆元))$

  3. 计算出$S2 = K^{-1}(m - X_AS1)\mod (q-1)$

  4. 签名就是 (S1, S2) 组成的

对于任何一个用户B来说,他可以这样验证签名:

  1. 计算$V1=a1^m \mod q,~V2 = (Y_A^{S1}·S1^{S2} \mod q)$ 如果说V1 = V2,则签名合法。

Schnorr 数字签名方案

同样也是基于离散对数

DSA 数字签名算法 同样是基于离散对数

使用安全Hash (SHA) 最新版本还包括基于RSA和椭圆曲线密码的数字签名算法

DSA使用的是 只提供数字签名功能的算法。虽然是一种公钥密码方案,但不能用来加密或者密钥交换

RSA和DSA在实现数字签名时的不同结构

在DSA中,k是随机数,签名函数(Sig)依赖于 发送方的私钥PRa 和通信伙伴们一起构建的参数,我们称其为全局公钥PUG。

签名由两部分组成,标记为s和r。

接收方对收到的消息进行Hash 产生的Hash码和签名 一起输入到验证函数(Ver) 。如果说函数的输出= r 部分,则签名有效。


斌头之计算机安全学
https://www.mementos.top/2021/12/12/斌头之计算机安全学/
作者
Natsumi
发布于
2021年12月12日
许可协议