Fiestel_cipher in python

Sun, Jun 14, 2020 2-minute read

This is simple approach for fiestel cipher

import random
import hmac
import hashlib

def xor(byteseq1, byteseq2):
    l1 = [b for b in byteseq1]
    l2 = [b for b in byteseq2]
    l1xorl2 = [bytes([elem1^elem2]) for elem1,elem2 in zip(l1,l2)]
    result = b''.join(l1xorl2)
    return result

def feistel_block(LE_inp, RE_inp, k):
    LE_out = RE_inp
    RE_xor = F(RE_inp,k)
    RE_out = xor(LE_inp,RE_xor)
    return LE_out, RE_out

def F(byteseq, k):
    h = hmac.new(bytes(k), byteseq, hashlib.sha1)
    return h.digest()[:8]

def gen_keylist(keylenbytes, numkeys, seed):
    keylist = []
    random.seed(seed)
    keylist = [random.randint(0,255) for i in range(numkeys)]
    return keylist

def feistel_enc(inputblock, num_rounds, seed):
    keylist = gen_keylist(8, num_rounds, seed)
    left_inputblock = inputblock[0:4]
    right_inputblock = inputblock[4:8]
    for i in range(0,16):
        left_inputblock, right_inputblock = feistel_block(left_inputblock, right_inputblock, keylist[i])


    cipherblock = right_inputblock + left_inputblock
    return cipherblock

def feistel_enc_test(input_fname, seed, num_rounds, output_fname):
    finp = open(input_fname, 'rb')
    inpbyteseq = finp.read()
    finp.close()
    inpbyteseq=inpbyteseq+(b'\x20'*(8-(len(inpbyteseq)%8))) if len(inpbyteseq)%8 !=0 else inpbyteseq

    blocklist=[inpbyteseq[i:i+8] for i in range(0,len(inpbyteseq),8)]
    cipherblock = [feistel_enc(inputblock,num_rounds,seed) for inputblock in blocklist]

    cipherbyteseq = b''.join(cipherblock)
    fout = open(output_fname, 'wb')
    fout.write(cipherbyteseq)
    fout.close()

def feistel_dec(inputblock, num_rounds, seed):
    keylist = gen_keylist(8, num_rounds, seed)
    left_inputblock = inputblock[0:4]
    right_inputblock = inputblock[4:8]
    for i in range(0,16):
        left_inputblock, right_inputblock = feistel_block(left_inputblock, right_inputblock, keylist[15-i])

    plainblock = right_inputblock + left_inputblock

    return plainblock

def feistel_dec_test(input_fname, seed, num_rounds, output_fname):
    finp = open(input_fname, 'rb')
    inpbyteseq = finp.read()
    finp.close()
    inpbyteseq=inpbyteseq+(b'\x20'*(8-(len(inpbyteseq)%8))) if len(inpbyteseq)%8 !=0 else inpbyteseq

    blocklist=[inpbyteseq[i:i+8] for i in range(0,len(inpbyteseq),8)]
    plainblock = [feistel_dec(inputblock,num_rounds,seed) for inputblock in blocklist]
    plainbyteseq = b''.join(plainblock)
    fout = open(output_fname, 'wb')
    fout.write(plainbyteseq)
    fout.close()

def main():
    feistel_enc_test("test.txt", 8, 16, "test_enc.txt")
    feistel_dec_test("test_enc.txt",8,16, "test_dec.txt")

if __name__ == "__main__":
    main()