今天学习了RC4算法,加密逻辑比较简单,主要是分成三部分
- 密钥调度算法(KSA)
- 生成密钥流K表(PRGA)
- 最后将密钥调度算法得到的s表和密钥流产生的k表进行异或,得到密钥
下面上代码,解密的逻辑把加密反过来就好
'''
RC4算法加解密
'''
#1.密钥调度算法ksa,通过种子密钥打乱s表
def KSA(seed):
#创建s表
s = list(range(256))
print(f's为{s}')
#创建t表
t = list(range(256))
for i in range(256):
t[i] = seed[i%len(seed)]
print(f't为{t}')
#用t表置换s表
j = 0
for i in range(256):
j = (j + s[i] + ord(t[i])) % 256
tmp = s[i]
s[i] = s[j]
s[j] = tmp
return s
#新的s表替换完毕
#2.通过明文的长度,生成密钥流PRGA
def PRGA(plaintext,length):
i = 0
j = 0
k = list(range(length))
for x in k:
i = (i + 1) % 256
j = (j + s[i]) % 256
#置换s[i]和s[j]
s[i],s[j] = s[j],s[i]
t = (s[i] + s[j]) % 256
k[x] = s[t]
print(f'{x,k[x]}')
return k
if __name__ == '__main__':
enter = int(input('加密输入0\n解密输入1\n'))
# enter = 1
if enter == 0:
seed = input('请输入种子密钥: ')
# seed = 'love'
s = KSA(seed)
plaintext = input('请输入明文: ').lower()
# plaintext = 'wozuishuai'
length = len(plaintext)
#得到的是十进制的数据
k = PRGA(plaintext,length)
print(f'k为{k}')
#明文的十六进制和k的十六进制异或可得密文
p_list = []
for i in plaintext:
p_list.append(ord(i))
print(f'p_list为{p_list}')
ciphertext = []
for p,kk in zip(p_list,k):
c = hex(int(p)^int(kk)).replace('0x','')
if len(c) < 2:
c = '0' + c
ciphertext.append(c)
else:
ciphertext.append(c)
print(f'种子密钥为: {seed}' + '密文为: ' + ''.join(ciphertext))
if enter == 1:
seed = input('请输入种子密钥: ')
# seed = 'secret'
s = KSA(seed)
# ciphertext = '9c5fbc7bfbd1afdf56b8'
ciphertext = input('请输入密文: ').lower()
length = int(len(ciphertext)/2)
k = PRGA(ciphertext,length)
print(f'k为{k}')
c = []
for i,j in zip(ciphertext,range(int(len(ciphertext)/2))):
c.append(ciphertext[0 + 2 * j:2 + 2 * j])
print(f'c为{c}')
result = []
for i,j in zip(k,c):
r = chr(int(i ^ int(j,16)))
result.append(r)
print(f'种子密钥为: {seed}' + '明文为: ' + ''.join(result))
有一个问题需要注意的是,比如给wozuishuai(10位)加密的密钥应该是970cdb33d77a03b18a28(20位)而不是97cdb33d77a3b18a28(18位),如果k的字符不是成对存在的,比如c需要补成0c,否则会影响解密结果(在代码加密中已经自动补0了,解密的话直接用产生的密钥即可)