1. 程式人生 > >RC4原理以及python實現

RC4原理以及python實現

簡介

RC4(來自Rivest Cipher 4的縮寫)是一種流加密演算法,金鑰長度可變。它加解密使用相同的金鑰,一個位元組一個位元組地加密。因此也屬於對稱加密演算法。突出優點是在軟體裡面很容易實現。

加密流程

包含兩個處理過程:一是祕鑰排程演算法(KSA),用於之亂S盒的初始排列,另外一個是偽隨機數生成演算法(PRGA),用來輸出隨機序列並修改S的當前順序。

  1. 根據祕鑰生成S盒
  2. 利用PRGA生成祕鑰流
  3. 祕鑰與明文異或產生密文

單個點拿出來分析

根據祕鑰生成S盒

初始化S盒

直接構造一個S[256],遍歷0255,然後建立臨時T[256],用於儲存種子祕鑰,長度不夠迴圈填充直到T被填滿,根據T[i]將S[i]與S中的另外一個位元組對換,對S的操作僅僅是交換,唯一改變的是位置,但裡面的元素是沒變的還是0

255

    s_box = list(range(256)) #我這裡沒管祕鑰小於256的情況,小於256不斷重複填充即可
    j = 0
    for i in range(256):
        j = (j + s_box[i] + ord(key[i % len(key)])) % 256
        s_box[i], s_box[j] = s_box[j], s_box[i]
    #print(type(s_box)) #for_test
    return s_box

下圖很好的解釋了S盒被隨機化的過程

FyoTbQ.png

利用PRGA生成祕鑰流

從S盒選取一個元素輸出,並置換S盒便於下一輪取出,選取過程取決於索引i和j,這也體現了在加密過程中S盒會變化。下面的是流程:

    res = []
    i = j =0
    for s in plain:
        i = (i + 1) %256
        j = (j + box[i]) %256
        box[i], box[j] = box[j], box[i]
        t = (box[i] + box[j])% 256
        k = box[t]
        res.append(chr(ord(s)^k))  #直接與每一個位元組明文相異或

祕鑰與明文異或產生密文

至於這一點就不用多說了,由於異或運算的對合性,RC4加密解密使用同一套演算法。

python實現:

# -*- coding: utf-8 -*-
# Author:0verWatch

import base64

def get_message():
    print("輸入你的資訊:")
    s = input()
    return s

def get_key():
    print("輸入你的祕鑰:")
    key = input()
    if key == '':
        key = 'none_public_key'
    return key

def init_box(key):
    """
    S盒 
    """
    s_box = list(range(256)) #我這裡沒管祕鑰小於256的情況,小於256應該不斷重複填充即可
    j = 0
    for i in range(256):
        j = (j + s_box[i] + ord(key[i % len(key)])) % 256
        s_box[i], s_box[j] = s_box[j], s_box[i]
    #print(type(s_box)) #for_test
    return s_box

def ex_encrypt(plain,box,mode):
    """
    利用PRGA生成祕鑰流並與密文位元組異或,加解密同一個演算法
    """

    if mode == '2':
        while True:
            c_mode = input("輸入你的解密模式:Base64 or ordinary\n")
            if c_mode == 'Base64':
                plain = base64.b64decode(plain)
                plain = bytes.decode(plain)
                break
            elif c_mode == 'ordinary':
                plain = plain
                break
            else:
                print("Something Wrong,請重新新輸入")
                continue

    res = []
    i = j =0
    for s in plain:
        i = (i + 1) %256
        j = (j + box[i]) %256
        box[i], box[j] = box[j], box[i]
        t = (box[i] + box[j])% 256
        k = box[t]
        res.append(chr(ord(s)^k))

    cipher = "".join(res)
    #print(cipher)
    if  mode == '1':
        # 化成可視字元需要編碼
        print("加密後的輸出(沒經過任何編碼):")
        print(cipher)
        # base64的目的也是為了變成可見字元
        print("base64後的編碼:")
        print(str(base64.b64encode(cipher.encode('utf-8')),'utf-8'))
    if mode == '2':
        print("解密後的密文:")
        print(cipher)


def get_mode():
    print("請選擇加密或者解密")
    print("1. Encrypt")
    print("2. Decode")
    mode = input()
    if mode == '1':
        message = get_message()
        key = get_key()
        box = init_box(key)
        ex_encrypt(message,box,mode)
    elif mode == '2':
        message = get_message()
        key = get_key()
        box = init_box(key)
        ex_encrypt(message, box, mode)
    else:
        print("輸入有誤!")





if __name__ == '__main__':
    while True:
        get_mode()


安全性

  1. 由於RC4演算法加密是採用的xor,所以,一旦子金鑰序列出現了重複,密文就有可能被破解。所以必須對加密金鑰進行測試,判斷其是否為弱金鑰。
  2. 當然,現在RC4已經不安全了,可以參考這篇文章,破解RC4現在是具有很高效率的。