0

I have a program that successfully encrypts a piece of plain text information and outputs the encrypted data as hexadecimal. i can decrypt this data on http://www.fyneworks.com/encryption/rc4-encryption/index.asp by putting in the hex data i received from my program and the key i used (in plain text)

the next step i am trying to accomplish is to have two inputs where i can input an encrypted message in hex and the encryption key (also in hex).

i'm having trouble getting the decryption part of my program to work...

If i enter the key as password and the ciphertext as 8c905b7c294a94c30422d81d552e which successfully decrypts on the website above... it doesn't work.

anyone have any ideas how i can get decryption working in RC4 with hexadecimal inputs?

# Global variables
state = [None] * 256
p = q = None

def setKey(key):
   ##RC4 Key Scheduling Algorithm (KSA)
    global p, q, state
    state = [n for n in range(256)]
    p = q = j = 0
    for i in range(256):
        if len(key) > 0:
            j = (j + state[i] + key[i % len(key)]) % 256
        else:
            j = (j + state[i]) % 256
        state[i], state[j] = state[j], state[i]

def byteGenerator():
    ##RC4 Pseudo-Random Generation Algorithm (PRGA)
    global p, q, state
    p = (p + 1) % 256
    q = (q + state[p]) % 256
    state[p], state[q] = state[q], state[p]
    return state[(state[p] + state[q]) % 256]

def encrypt(key,inputString):
    ##Encrypt input string returning a byte list
    setKey(string_to_list(key))
    return [ord(p) ^ byteGenerator() for p in inputString]

def decrypt(inputByteList):
    ##Decrypt input byte list returning a string

    return "".join([chr(c ^ byteGenerator()) for c in inputByteList])



def intToList(inputNumber):
    ##Convert a number into a byte list
    inputString = "{:02x}".format(inputNumber)
    return [int(inputString[i:i + 2], 16) for i in range(0, len(inputString), 2)]

def string_to_list(inputString):
    ##Convert a string into a byte list
    return [ord(c) for c in inputString]

key = raw_input("Enter Key: ")
ciphertext = raw_input("enter ciphertext: ")
print decrypt(intToList(ciphertext))

1 Answer 1

1

Here is general idea of how encryption / decryption can be done using reference implementation of RC4 for python:

def KSA(key):
    keylength = len(key)

    S = range(256)

    j = 0
    for i in range(256):
        j = (j + S[i] + key[i % keylength]) % 256
        S[i], S[j] = S[j], S[i]  # swap

    return S


def PRGA(S):
    i = 0
    j = 0
    while True:
        i = (i + 1) % 256
        j = (j + S[i]) % 256
        S[i], S[j] = S[j], S[i]  # swap

        K = S[(S[i] + S[j]) % 256]
        yield K


def RC4(key):
    S = KSA(key)
    return PRGA(S)


if __name__ == '__main__':

    # ciphertext should be 9D5AB375EC
    key = 'secret'
    plaintext = 'plain'

    def convert_key(s):
        return [ord(c) for c in s]
    key = convert_key(key)

    keystream = RC4(key)

    ciphertext = ''.join([("%02X" % (ord(c) ^ keystream.next())) for c in plaintext])
    print ciphertext

    keystream = RC4(key)

    def convert_ct(s):
        import binascii
        return [ord(ch) for ch in binascii.unhexlify(s)]

    ciphertext = convert_ct(ciphertext)

    plaintext = ''.join([chr(c ^ keystream.next()) for c in ciphertext])
    print plaintext

With your code base it can be done like so:

import binascii
# Global variables
state = [None] * 256
p = q = None

def setKey(key):
    ##RC4 Key Scheduling Algorithm (KSA)
    global p, q, state
    state = [n for n in range(256)]
    p = q = j = 0
    for i in range(256):
        if len(key) > 0:
            j = (j + state[i] + key[i % len(key)]) % 256
        else:
            j = (j + state[i]) % 256
        state[i], state[j] = state[j], state[i]

def byteGenerator():
    ##RC4 Pseudo-Random Generation Algorithm (PRGA)
    global p, q, state
    p = (p + 1) % 256
    q = (q + state[p]) % 256
    state[p], state[q] = state[q], state[p]
    return state[(state[p] + state[q]) % 256]

def encrypt(key, plaintext):
    ##Encrypt input string returning a byte list
    pt = string_to_list(plaintext)
    ct = rc4(key, pt)
    return list_to_string(ct, hex=True)

def decrypt(key, ciphertext):
    ##Decrypt input byte list returning a string
    ct = string_to_list(ciphertext, hex=True)
    pt = rc4(key, ct)
    return list_to_string(pt, hex=False)

def string_to_list(input_srt, hex=False):
    ##Convert a string into an int list
    if hex:
        res = [ord(ch) for ch in binascii.unhexlify(input_srt)]
    else:
        res = [ord(ch) for ch in input_srt]
    return res

def list_to_string(lst, hex=True):
    ##Convert an int list into a string
    if hex:
        res = ''.join(["%0.2X" % el for el in lst])
    else:
        res = ''.join([chr(el) for el in lst])
    return res

def rc4(key, ints):
    """Xor list of ints with output generated by RC4. Output list of ints"""
    setKey(string_to_list(key))
    return [x ^ byteGenerator() for x in ints]

# key = raw_input("Enter Key: ")
# ciphertext = raw_input("enter ciphertext: ")
key = 'secret'
plaintext = 'plain'

ciphertext = encrypt(key, plaintext)
print ciphertext
print decrypt(key, ciphertext)

Decryption and encryption are basically the same procedures

Sign up to request clarification or add additional context in comments.

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.