RC4算法
RC4算法是一种对称加密算法,即加密与解密的过程相同。假设其运算过程表示为rc4(key, data),其中key为密钥,data为待处理的数据,则:
密文=rc4(key,data)
data=rc4(key,密文)
也就是说,对一段数据(原文)做奇数次RC4运算,得到密文,做偶数次RC4运算,结果还是原文。
RC4算法是基于密钥流的加密算法。
假设要加密的数据(明文)长度为N个字节,通过某种算法产生N字节的数据(密钥),将这两串数据按位异或(XOR),得到密文。把密文与这串密钥再XOR,就能得到明文。这一串由某种算法产生的N字节(8N位),称为密钥流,对应算法就叫做密钥流生成算法。区分不同基于密钥流的加密算法的标准就是其密钥流的生成方式。
算法特点:
简单,运行速度快,密钥长度可变(长度范围为 1-256 字节)。
RC4算法组成:
1、S盒生成
根据用户输入的秘钥 key,使用 密钥调度算法(key-scheduling algorithm,KSA)生成 S 盒。
2、生成密钥流,加密数据
使用伪随机生成算法(Pseudo-random generation algorithm,PRGA)生成秘钥流,然后使用生成的密钥流加密明文数据,得到密文。
对应得到的密文,可以根据需要再做处理,例如base64编码。
这里需要注意的是,对于包含中文的明文,需要做适当的编码(encode)和解码(decode)处理,编码方法一般为“utf-8”,同时还涉及字符转ascii编码(10进制)等操作。
算法实现
可以通过导入Crypto.Cipher中的ARC4来实现,也可以自定义实现,本文通过自定义方法实现。
代码运行环境:
windows 10
python 3.7
# coding=utf-8
# python 3.7
import sys
def bytesToHex(bytes):
sb = ''
for i in range(len(bytes)):
hexs = hex(bytes[i] & 0xFF)[2:]
if len(hexs) < 2:
sb += '0'
sb += hexs
return sb
def hexToByte(inHex):
hexlen = len(inHex)
result = []
if (hexlen % 2 == 1):
hexlen += 1
inHex="0"+inHex
for i in range(0, hexlen, 2):
result.append(int(inHex[i:i+2],16))
return result
def initKey(aKey):
state = list(range(256))
bkey =[ord(i) for i in list(aKey)]
index1 = 0
index2 = 0
if (len(bkey) == 0):
return []
for i in range(256):
index2 = ((bkey[index1] & 0xff) + (state[i] & 0xff) + index2) & 0xff
state[i], state[index2] = state[index2], state[i]
index1 = (index1 + 1) % len(bkey)
return state
def RC4Base(input, mKkey):
x = 0
y = 0
key = initKey(mKkey)
result = list(range(len(input)))
for i in range(len(input)):
x = (x + 1) & 0xff
y = ((key[x] & 0xff) + y) & 0xff
key[x], key[y] = key[y], key[x]
xorIndex = ((key[x] & 0xff) + (key[y] & 0xff)) & 0xff
result[i] = (input[i] ^ key[xorIndex])
return result
def encryRC4Byte(data, key, chartSet='utf-8'):
if not chartSet:
bData = [ord(i) for i in data]
return RC4Base(bData, key)
else:
bData = list(data.encode(chartSet))
return RC4Base(bData, key)
def decryRC4(data, key, chartSet='utf-8'):
r = RC4Base(hexToByte(data), key)
return bytes(r).decode(chartSet)
def encryRC4String(data, key, chartSet='utf-8'):
return bytesToHex(encryRC4Byte(data, key, chartSet))
def main(data, key, signs):
if signs == 'encode':
datas = encryRC4String(data, key)
else:
datas = decryRC4(data, key)
print(datas)
if __name__ =='__main__':
try:
key = sys.argv[2] #"key"
data = sys.argv[1] #"encoded_string"
choices=sys.argv[3].strip() # decode or encode
if choices not in ['decode', 'encode']:
print('usage: %s string2decode key_string decode' % sys.argv[0])
print(' or: %s string2encode key_string encode' % sys.argv[0])
exit()
except:
print('usage: %s string2decode key_string decode' % sys.argv[0])
print(' or: %s string2encode key_string encode' % sys.argv[0])
exit()
main(data,key,choices)
使用方法很简单,需要的参数共3个,第一个data参数为明文或密文,第二个参数key为密钥,第三个choices为加密(encode)或者解密(deocde)操作,假设代码保存为rc4.py文件,在命令行中执行:
python rc4.py dsadasMI明文 thisiskey encode
得到密文:efc3c7d2cb1ffc0b1fd84d6f000b 。
进行解密:
python rc4.py efc3c7d2cb1ffc0b1fd84d6f000b thisiskey decode
得到明文: dsadasMI明文 。