RC4加密——python实现&java实现

1.RC4算法简介

​ RC4算法由Ron rivest于1987年设计出的一种对称加密算法,其加密密钥和解密密钥是相同的,加密和解密过程也相同。

​ 属于对称加密算法中的流密码加密算法,流密码不对明文数据进行分组,而是用密钥生成与明文一样长短的密码流对明文进行加密。密钥长度可变,面向字节操作。是以一个足够大的表s为基础,对表进行非线性变换,产生密钥流。

  • 加密:原文和Keystream进行异或得到密文
  • 解密:密文和Keystream进行异或得到原文

2.加密过程

img

(1)密钥调度算法KSA(Key Scheduling Algorithm)

​ 1、对S表进行线性填充(一般为256字节,用来作为密钥流生成的种子1)

img

​ 2、用种子密钥(就是我们的秘钥)循环填充另一个256字节的K表,(用来作为密钥流生成的种子2)

如果输入长度大于等于256个字节,则进行截取

如果输入长度小于256个字节,则进行轮转,直到填满

例如输入密钥的是1,2,3,4,5   ,  那么填入的是1,2,3,4,5,1,2,3,4,5,1,2,3,4,5........

​ 3、用K表S表进行初始置换(用来打乱初始种子1)

按照下列规则进行

//从第零个字节开始,执行256次,保证每个字节都得到处理
j = 0;

for  i=0 to 255 do
	j = (j+S[i]+K[i])mod 256;
	Swap(S[i],S[j]);

(2)伪随机数生成算法(PRGA)

  • 为每个待加密字节生成一个伪随机数,用来异或
  • 表S一旦完成初始化,种子密钥就不再被使用
i,j = 0;
for  r=0 to len do // len为明文长度,len字节
    i=(i+1)mod 256
	j=(j+S[i])mod 256
	Swap(S[i],S[j]);
	t=(S[i]+S[j])mod256;
	K[r]=S[t];

经过上述步骤后,得到和明文长度相同的密钥流

python实现

import base64


def rc4_setup(key):
    """RC4初始化"""
    if isinstance(key, str):
        key = key.encode()

    S = list(range(256))
    j = 0
    for i in range(256):
        j = (j + S[i] + key[i % len(key)]) % 256
        S[i], S[j] = S[j], S[i]

    return S


def rc4_crypt(data, key):
    """RC4加解密"""
    if isinstance(data, str):
        data = data.encode()

    S = rc4_setup(key)
    i, j = 0, 0
    res = []
    for byte in data:
        i = (i + 1) % 256
        j = (j + S[i]) % 256
        S[i], S[j] = S[j], S[i]
        res.append(byte ^ S[(S[i] + S[j]) % 256])

    return bytes(res)


def rc4_encrypt(data, key):
    """RC4加密"""
    return rc4_crypt(data, key)


def rc4_decrypt(data, key):
    """RC4解密"""
    return rc4_crypt(data, key)


def rc4_hex(key_hex, data_hex):
    """RC4加解密(16进制)"""
    key = bytes.fromhex(key_hex)
    data = bytes.fromhex(data_hex)
    res = rc4_crypt(data, key)
    return res.hex()


def rc4_encrypt_base64(data, key):
    """RC4加密并转换为base64格式"""
    encrypted_data = rc4_encrypt(data, key)
    return base64.b64encode(encrypted_data).decode()


def rc4_decrypt_base64(data, key):
    """base64格式解码后RC4解密"""
    encrypted_data = base64.b64decode(data)
    return rc4_decrypt(encrypted_data, key).decode()


if __name__ == '__main__':
    plaintext = b'Thisismessage'
    key = b'password123'

    # RC4加密
    ciphertext = rc4_encrypt(plaintext, key)
    print("RC4加密", ciphertext)

    # RC4解密
    decrypted_text = rc4_decrypt(ciphertext, key)
    print("RC4解密", decrypted_text)

    # 16进制数据的RC4加解密
    ciphertext_hex = rc4_hex(key.hex(), plaintext.hex())
    print("16进制数据的RC4加密:", ciphertext_hex)

    decrypted_text_hex = rc4_hex(key.hex(), ciphertext_hex)
    print("16进制数据的RC4解密:", decrypted_text_hex)

    # base64数据的RC4加解密
    ciphertext_base64 = rc4_encrypt_base64(plaintext, key)
    print("base64数据的RC4加密:", ciphertext_base64)

    decrypted_text_base64 = rc4_decrypt_base64(ciphertext_base64, key)
    print("base64数据的RC4解密:", decrypted_text_base64)

java实现

import java.util.Base64;

public class RC4 {
    private int[] S = new int[256];
    private int[] T = new int[256];

    private void ksa(byte[] key) {
        for (int i = 0; i < 256; i++) {
            S[i] = i;
            T[i] = key[i % key.length];
        }

        int j = 0;
        for (int i = 0; i < 256; i++) {
            j = (j + S[i] + T[i]) % 256;
            swap(i, j);
        }
    }

    private void swap(int i, int j) {
        int temp = S[i];
        S[i] = S[j];
        S[j] = temp;
    }

    public byte[] encrypt(byte[] plaintext, byte[] key) {
        ksa(key);
        int i = 0, j = 0;
        byte[] ciphertext = new byte[plaintext.length];

        for (int k = 0; k < plaintext.length; k++) {
            i = (i + 1) % 256;
            j = (j + S[i]) % 256;
            swap(i, j);
            int t = (S[i] + S[j]) % 256;
            ciphertext[k] = (byte) (plaintext[k] ^ S[t]);
        }

        return ciphertext;
    }

    public byte[] decrypt(byte[] ciphertext, byte[] key) {
        return encrypt(ciphertext, key);
    }

    public String encryptToBase64(String plaintext, String key) {
        byte[] bytes = encrypt(plaintext.getBytes(), key.getBytes());
        return Base64.getEncoder().encodeToString(bytes);
    }

    public String decryptFromBase64(String ciphertext, String key) {
        byte[] bytes = Base64.getDecoder().decode(ciphertext);
        byte[] decrypted = decrypt(bytes, key.getBytes());
        return new String(decrypted);
    }

    public String encryptToHex(String plaintext, String key) {
        byte[] bytes = encrypt(plaintext.getBytes(), key.getBytes());
        StringBuilder sb = new StringBuilder();

        for (byte b : bytes) {
            sb.append(String.format("%02x", b));
        }

        return sb.toString();
    }

    public String decryptFromHex(String ciphertext, String key) {
        byte[] bytes = new byte[ciphertext.length() / 2];

        for (int i = 0; i < ciphertext.length(); i += 2) {
            bytes[i / 2] = (byte) Integer.parseInt(ciphertext.substring(i, i + 2), 16);
        }

        byte[] decrypted = decrypt(bytes, key.getBytes());
        return new String(decrypted);
    }

    public static void main(String[] args) {
        RC4 rc4 = new RC4();
        String plaintext = "Thisismessage";
        String key = "password123";

        //16进制数据的RC4加解密
        String ciphertext_hex = rc4.encryptToHex(plaintext, key);
        System.out.println("16进制数据的RC4加密:" + ciphertext_hex);

        //16进制数据的RC4解密

        String decrypted_text_hex = rc4.decryptFromHex(ciphertext_hex, key);
        System.out.println("16进制数据的RC4解密:" + decrypted_text_hex);

        //base64数据的RC4加密
        String ciphertext_base64 = rc4.encryptToBase64(plaintext, key);
        System.out.println("base64数据的RC4加密:" + ciphertext_base64);

        //base64数据的RC4解密
        String decrypted_text_base64 = rc4.decryptFromBase64(ciphertext_base64, key);
        System.out.println("base64数据的RC4解密:" + decrypted_text_base64);


    }
}

在线生成RC4网站为什么每次值都不一样

CryptoJS库生成的RC4加密值每次不同是因为它使用了一个称为“随机盐”的概念。这个随机盐是根据随机值和固定值4294967296生成的,在每个加密操作中都是不同的。盐的目的是确保每个加密结果都是不同的,即使输入相同。

random: function(c) {
        for (var a = [], m = 0; m < c; m += 4)
            a.push(4294967296 * s.random() | 0);
        return new d.init(a,c)
}

在使用随机盐时,它是作为加密过程的一部分引入的。使用随机盐的过程是RC4加密的第一步——密钥调度算法。

密钥调度算法是一个基于密钥的伪随机数生成器,用于生成 RC4 加密中使用的密钥流。在这个算法中,随机盐值被添加到给定的密钥中,以创建更随机的、更安全的密钥流,进而提高加密安全性。

具体而言,密钥调度算法会将随机盐值添加到密钥中,然后将调度算法的状态初始化为一个固定的矢量(通常是一个全0的数组)。然后,该算法会执行一些循环迭代,使用密钥和矢量来创建一个伪随机的密钥流。

在 RC4 加密的实际加密过程中,该密钥流和明文进行异或运算来生成加密结果。因此,随机盐值是生成 RC4 加密结果的关键组成部分。

结论

在安卓逆向中,RC4的特征并没有Base64那么明显,但是也可以根据S表的长度、密钥流的产生过程及异或运算的特征来确定是否是RC4,当然,因为RC4属于流加密,所以也可以把明文的长度和加密后的长度是否相等作为入手点。

参考

(41条消息) 密码学 | 对称加密算法RC4_rc4加密算法_FalsePlus的博客-CSDN博客

  • 4
    点赞
  • 20
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

飞得更高肥尾沙鼠

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值