CTF流密码之RC4基础
在CTF中 Re和Crypto方向中会经常遇到RC4加密,本篇将对CTF密码学中RC4的考点进行解析分享,笔者水平有限,文中若有疏漏或不当之处,欢迎各位读者批评指正,交流探讨。
RC4简介
RC4算法,是一种对称加密算法,属于流密码的一种形式,流密码逐字节操作数据流。对称密码算法的工作方式有四种:电子密码本(ECB)方式、密码分组链接(CBC)方式、密文反馈(CFB)方式、输出反馈(OFB)方式。
RC4算法采用的是输出反馈工作方式,所以可以用一个短的密钥产生一个相对较长的密钥序列。
RC4流密码是使用最广泛的流密码之一,通过算法一次一字节地加密消息,算法简单,运行速度快。
算法中变量
密钥流:RC4算法的关键就是根据明文和密钥生成对应的密钥流,密钥流的长度和明文的长度相对应, Cipher[i] = Message[i]^密钥流[i]。
状态向量S(S盒): 长度为256 每个单元都是一个字节。
临时变量T:长度为256 如果密钥长度为256个字节,俺们将把密钥的值赋给T,否则轮转的将密钥的每个字节赋给T。
密钥K:长度 1-256字节,与明文长度 密钥流长度无必然关系。
算法原理与加密过程
假设定义RC4运算过程为 rc4(key,data),那么密文C = rc4(key, M),明文M = rc4(key, C)。
C算法实现
1 | void rc4_init(unsigned char *s, unsigned char *key, unsigned long Len) //初始化函数 根据key定义s盒 |
加密过程
RC4由伪随机数生成器和异或运算组成,主要包含两块内容 初始化算法(KSA) 、伪随机子密码生成算法(PRGA)。
1.初始化算法(KSA)
KSA(The key-scheduling algorithm)算法初始化长度为256的S盒,将0-255 互不重复的元素装入S盒,在根据密钥打乱S盒。
1 | j = 0 |
2.伪随机子密码生成算法(PRGA)、加密阶段
1 | for i in range(len(message)) |
伪随机的子密码的生成只受初始化后的S盒的影响,要加密的明文并不会影响密钥。只要得到初始化后的s盒,那么秘钥也是固定的。
明文流与密钥流异或得到密文流,密文流与密钥流异或得到明文流。
题目解析
[SEETF 2023]BabyRC4
题目描述
1 | from Crypto.Cipher import ARC4 |
题目分析
使用同一个key 对 反转后的flag和明文进行rc4加密
c0 = rc4(key,flag) c1 = rc4(key,m0) 计算出数据流keystream
c0 = flag_rev ^ keystream ,c1 = a36 ^ keystream
c0 ^ c1 = flag_rev ^ a36
进而求得 反转后的flag
WP
1 | c0 = bytes.fromhex('b99665ef4329b168cc1d672dd51081b719e640286e1b0fb124403cb59ddb3cc74bda4fd85dfc') |
[hgame-week2] notRC4
题目描述
Oo0o0 It's a reverse game!! 0Oo0o
1 | #!/usr/bin/env python3 |
题目分析
题目中的脚本函数名做了混淆,仍可以看出是 rc4加密。rc4按字节加密,所以明文长度和密文长度是相同的 。
已知明文最后一位为 } ,异或密文最后一位和明文最后一位 可以得到 密钥的最后一位s[t]。
然后在根据给出的s盒 确定t的值 t = (s[i] + s[j]) % 256
s盒确定 i=50、 t已知 就可以推出j j = (j + s[i]) % 256
可以在推出上一个j。得到上一个j ,i也确定 ,
t = (s[i] + s[j]) % 256 这样就可以推出上一个t的值 从而确定s[t] 。
以此类推 最终得到完整的密钥 就可以推出明文。
1 | for i in range(len(message)) |
WP
1 | enc = b'\x14\xe3s,\xcbq\xa8\xd1\x86\x12\xba\x9f\x88\xa9J}\xf5\xd8BF\x93x\x94\x8a\xdc\xdb\xa0\xb9O0SeJ^\xc7\xce\xcf\xe3\x1c\x10s\xe2\xb6\xceA\xfd\xd6\x87\x95W' |
References
https://lazzzaro.github.io/2020/11/07/crypto-%E6%B5%81%E5%AF%86%E7%A0%81/index.html