Jump to content
Fórum Script Brasil
  • 0

Dúvida em código de criptografia


brdarkmoon

Question

Bom Dia pessoal, sou novo em Python. Comecei a estudar ele agora em um curso de segurança que estou fazendo.

Bom, eu travei em uma tarefa que me falaram ser simples, mas, infelizmente até agora eu não consegui chegar no objetivo e todos os recursos online que consegui achar também não ajudaram, bem, o que preciso fazer é o seguinte:
Implementar:
DES
3DES
AES
RSA
Esta parte eu fiz, tem muito recurso online e ajuda bastante, encriptar não é o problema, porque o monte de recursos que tem online, esta parte é bem fácil de entender e fazer, mas, onde eu travei é no seguinte:
A cada round da encriptação printar na tela as mudanças que acontecem em um plaintext até chegar no round final, e no final de tudo printar na tela também:
O tempo de encriptação
O tempo de decriptação
A Utilização de memória
O efeito avalanche

Alguém tem alguma idéia de como fazer?

Aqui abaixo tem o que consegui adaptar com o que encontrei online, O primeiro código pede a escolha do que você quer fazer, e baseado na resposta ele cncripta em DES(3D tb) ou chama arquivos externos para encriptar em AES ou RSA:

Código Principal:

#import commands <- This have to be replaced with subprocess for it to work in python 3
import subprocess
import os
from datetime import datetime, date, time
from pyDes import *


os.system("cls")
print("1. Encryption")
print("2. Decryption\n")
option = input("Enter your Choice:")

if option == '1':
	print("\n1. AES Encryption")
	print("2. DES Encryption")
	print("3. RSA Encryption\n")
	op = input("Enter your Choice :")
	if op == '1':
		print("AES Encrytion Started ...")
		before_time = datetime.now()
		#print "Time before AES Encryption Starts :", before_time
		os.system("python aes.py -e testfile.txt -o testfile_encrytped_AES.txt")
		after_time = datetime.now()
		#print "Time after AES Encryption completes :", after_time
		total_time = after_time - before_time
		print("Total Time conceeded by AES ", total_time)

	elif op == '2':
		print("1. Single DES Encryption")
		print("2. Triple DES Encryption\n")
		op2 = input("Enter your Choice:")
		if op2 == '1':
			print("DES Encryption Started...")
			before_time = datetime.now()
			#print "Time before AES Encryption Starts :", before_time
			with file('testfile.txt') as f:
				data = f.read()
			k = des("DESCRYPT", CBC, "\0\0\0\0\0\0\0\0", pad=None, padmode=PAD_PKCS5)
			d = k.encrypt(data)
			with open('testfile_encrypted_Single_DES.txt','w') as f:
				f.write(d)
			after_time = datetime.now()
			#print "Time after DES Encryption completes :", after_time
			total_time = after_time - before_time
			print("Total Time conceeded by DES ", total_time)
		elif op2 == '2':
			print("DES Encryption Started...")
			before_time = datetime.now()
			#print "Time before AES Encryption Starts :", before_time
			with file('testfile.txt') as f:
				data = f.read()
			k = triple_des("TRIPLE00DESCRYPT", CBC, "\0\0\0\0\0\0\0\0", pad=None, padmode=PAD_PKCS5)
			d = k.encrypt(data)
			with open('testfile_encrypted_Triple_DES.txt','w') as f:
				f.write(d)
			after_time = datetime.now()
			#print "Time after DES Encryption completes :", after_time
			total_time = after_time - before_time
			print("Total Time conceeded by DES ", total_time)
		else:
			print("Wrong Option")
			
	elif op == '3':
		print("\n1. Private Key Encryption")
		print("2. Public Key Encryption\n")
		op1=input("Enter your Choice:")
		if op1 == '1':
			print("RSA Private Key Encrytion Started ...")
			before_time = datetime.now()
			#print "Time before RSA Private Key Encryption Starts :", before_time
			os.system("python rsa.py -e testfile.txt -k rsa_privateKey.txt > testfile_encrytped_RSA_private.txt")
			after_time = datetime.now()
			#print "Time after RSA Private Key Encryption completes :", after_time
			total_time = after_time - before_time
			print("Total Time conceeded by RSA Private Key Encryption ", total_time)
		elif op1 == '2':
			print("RSA Public Key Encrytion Started ...")
			before_time = datetime.now()
			#print "Time before RSA Public Key Encryption Starts :", before_time
			os.system("python rsa.py -e testfile.txt -k rsa_publicKey.txt > testfile_encrytped_RSA_public.txt")
			after_time = datetime.now()
			#print "Time after RSA Public Key Encryption completes :", after_time
			total_time = after_time - before_time
			print("Total Time conceeded by RSA Public Key Encryption ", total_time)
		else:
			print("Wrong Choice, Exiting ...")
			
	else:
		print("Wrong Option")

elif option == '2':
	print("*** Please perform encryption before proceesing with decryption ***")
	print("\n1. AES Decryption")
	print("2. DES Decryption")
	print("3. RSA Decryption\n")
	op = input("Enter your Choice :")
	if op == '1':
		print("AES Decrytion Started ...")
		before_time = datetime.now()
		#print "Time before AES Encryption Starts :", before_time
		os.system("python aes.py -d testfile_encrytped_AES.txt -o testfile_decrypted_AES.txt ")
		after_time = datetime.now()
		#print "Time after AES Encryption completes :", after_time
		total_time = after_time - before_time
		print("Total Time conceeded by AES Decryption", total_time)

	elif op == '2':
		print("1. Single DES Decryption")
		print("2. Triple DES Decryption\n")
		op2 = input("Enter your Choice:")
		if op2 == '1':
			print("Single DES Decryption Started...")
			before_time = datetime.now()
			#print "Time before AES Encryption Starts :", before_time
			with file('testfile_encrypted_Single_DES.txt') as f:
				data = f.read()
			#password = getpass.getpass('Password :')		
			k = des("DESCRYPT", CBC, "\0\0\0\0\0\0\0\0", pad=None, padmode=PAD_PKCS5)
			d = k.decrypt(data)
			with open('testfile_decrypted_Single_DES.txt','w') as f:
				f.write(d)
			after_time = datetime.now()
			#print "Time after DES Encryption completes :", after_time
			total_time = after_time - before_time
			print("Total Time conceeded by DES ", total_time)
		elif op2 == '2':
			print("Triple DES Decryption Started...")
			before_time = datetime.now()
			#print "Time before AES Encryption Starts :", before_time
			with file('testfile_encrypted_Triple_DES.txt') as f:
				data = f.read()
			#password = getpass.getpass('Password :')		
			k = triple_des("TRIPLE00DESCRYPT", CBC, "\0\0\0\0\0\0\0\0", pad=None, padmode=PAD_PKCS5)
			d = k.decrypt(data)
			with open('testfile_decrypted_Triple_DES.txt','w') as f:
				f.write(d)
			after_time = datetime.now()
			#print "Time after DES Encryption completes :", after_time
			total_time = after_time - before_time
			print("Total Time conceeded by DES ", total_time)
		else:
			print("Wrong Option")
	
	elif op == '3':
		print("\n1. Private Key Decryption")
		print("2. Public Key Decryption\n")
		op1=input("Enter your Choice:")
		if op1 == '1':
			print("RSA Private Key Decrytion Started ...")
			before_time = datetime.now()
			#print "Time before RSA Private Key Encryption Starts :", before_time
			os.system("python rsa.py -d testfile_encrytped_RSA_private.txt -k rsa_privateKey.txt > testfile_decrytped_RSA_private.txt")
			after_time = datetime.now()
			#print "Time after RSA Private Key Encryption completes :", after_time
			total_time = after_time - before_time
			print("Total Time conceeded by RSA Private Key Decryption ", total_time)
		elif op1 == '2':
			print("RSA Public Key Decrytion Started ...")
			before_time = datetime.now()
			#print "Time before RSA Public Key Encryption Starts :", before_time
			os.system("python rsa.py -d testfile_encrytped_RSA_public.txt -k rsa_publicKey.txt > testfile_decrytped_RSA_public.txt")
			after_time = datetime.now()
			#print "Time after RSA Public Key Encryption completes :", after_time
			total_time = after_time - before_time
			print("Total Time conceeded by RSA Public Key Decryption ", total_time)
		else:
			print("Wrong Choice, Exiting ...")
			
	else:
		print("Wrong Option")


else :
	print("Author")

AES:

#!/usr/bin/python
# Copyright (c) 2013 Nagaraja . T
# Licensed under the GPL.
# Python AES Implementation

import sys, hashlib, string, getpass
from copy import copy
from random import randint

# The actual Rijndael specification includes variable block size, but
# AES uses a fixed block size of 16 bytes (128 bits)

# Additionally, AES allows for a variable key size, though this implementation
# of AES uses only 256-bit cipher keys (AES-256)

sbox = [
        0x63, 0x7c, 0x77, 0x7b, 0xf2, 0x6b, 0x6f, 0xc5, 0x30, 0x01, 0x67, 0x2b, 0xfe, 0xd7, 0xab, 0x76,
        0xca, 0x82, 0xc9, 0x7d, 0xfa, 0x59, 0x47, 0xf0, 0xad, 0xd4, 0xa2, 0xaf, 0x9c, 0xa4, 0x72, 0xc0,
        0xb7, 0xfd, 0x93, 0x26, 0x36, 0x3f, 0xf7, 0xcc, 0x34, 0xa5, 0xe5, 0xf1, 0x71, 0xd8, 0x31, 0x15,
        0x04, 0xc7, 0x23, 0xc3, 0x18, 0x96, 0x05, 0x9a, 0x07, 0x12, 0x80, 0xe2, 0xeb, 0x27, 0xb2, 0x75,
        0x09, 0x83, 0x2c, 0x1a, 0x1b, 0x6e, 0x5a, 0xa0, 0x52, 0x3b, 0xd6, 0xb3, 0x29, 0xe3, 0x2f, 0x84,
        0x53, 0xd1, 0x00, 0xed, 0x20, 0xfc, 0xb1, 0x5b, 0x6a, 0xcb, 0xbe, 0x39, 0x4a, 0x4c, 0x58, 0xcf,
        0xd0, 0xef, 0xaa, 0xfb, 0x43, 0x4d, 0x33, 0x85, 0x45, 0xf9, 0x02, 0x7f, 0x50, 0x3c, 0x9f, 0xa8,
        0x51, 0xa3, 0x40, 0x8f, 0x92, 0x9d, 0x38, 0xf5, 0xbc, 0xb6, 0xda, 0x21, 0x10, 0xff, 0xf3, 0xd2,
        0xcd, 0x0c, 0x13, 0xec, 0x5f, 0x97, 0x44, 0x17, 0xc4, 0xa7, 0x7e, 0x3d, 0x64, 0x5d, 0x19, 0x73,
        0x60, 0x81, 0x4f, 0xdc, 0x22, 0x2a, 0x90, 0x88, 0x46, 0xee, 0xb8, 0x14, 0xde, 0x5e, 0x0b, 0xdb,
        0xe0, 0x32, 0x3a, 0x0a, 0x49, 0x06, 0x24, 0x5c, 0xc2, 0xd3, 0xac, 0x62, 0x91, 0x95, 0xe4, 0x79,
        0xe7, 0xc8, 0x37, 0x6d, 0x8d, 0xd5, 0x4e, 0xa9, 0x6c, 0x56, 0xf4, 0xea, 0x65, 0x7a, 0xae, 0x08,
        0xba, 0x78, 0x25, 0x2e, 0x1c, 0xa6, 0xb4, 0xc6, 0xe8, 0xdd, 0x74, 0x1f, 0x4b, 0xbd, 0x8b, 0x8a,
        0x70, 0x3e, 0xb5, 0x66, 0x48, 0x03, 0xf6, 0x0e, 0x61, 0x35, 0x57, 0xb9, 0x86, 0xc1, 0x1d, 0x9e,
        0xe1, 0xf8, 0x98, 0x11, 0x69, 0xd9, 0x8e, 0x94, 0x9b, 0x1e, 0x87, 0xe9, 0xce, 0x55, 0x28, 0xdf,
        0x8c, 0xa1, 0x89, 0x0d, 0xbf, 0xe6, 0x42, 0x68, 0x41, 0x99, 0x2d, 0x0f, 0xb0, 0x54, 0xbb, 0x16
        ]

sboxInv = [
        0x52, 0x09, 0x6a, 0xd5, 0x30, 0x36, 0xa5, 0x38, 0xbf, 0x40, 0xa3, 0x9e, 0x81, 0xf3, 0xd7, 0xfb,
        0x7c, 0xe3, 0x39, 0x82, 0x9b, 0x2f, 0xff, 0x87, 0x34, 0x8e, 0x43, 0x44, 0xc4, 0xde, 0xe9, 0xcb,
        0x54, 0x7b, 0x94, 0x32, 0xa6, 0xc2, 0x23, 0x3d, 0xee, 0x4c, 0x95, 0x0b, 0x42, 0xfa, 0xc3, 0x4e,
        0x08, 0x2e, 0xa1, 0x66, 0x28, 0xd9, 0x24, 0xb2, 0x76, 0x5b, 0xa2, 0x49, 0x6d, 0x8b, 0xd1, 0x25,
        0x72, 0xf8, 0xf6, 0x64, 0x86, 0x68, 0x98, 0x16, 0xd4, 0xa4, 0x5c, 0xcc, 0x5d, 0x65, 0xb6, 0x92,
        0x6c, 0x70, 0x48, 0x50, 0xfd, 0xed, 0xb9, 0xda, 0x5e, 0x15, 0x46, 0x57, 0xa7, 0x8d, 0x9d, 0x84,
        0x90, 0xd8, 0xab, 0x00, 0x8c, 0xbc, 0xd3, 0x0a, 0xf7, 0xe4, 0x58, 0x05, 0xb8, 0xb3, 0x45, 0x06,
        0xd0, 0x2c, 0x1e, 0x8f, 0xca, 0x3f, 0x0f, 0x02, 0xc1, 0xaf, 0xbd, 0x03, 0x01, 0x13, 0x8a, 0x6b,
        0x3a, 0x91, 0x11, 0x41, 0x4f, 0x67, 0xdc, 0xea, 0x97, 0xf2, 0xcf, 0xce, 0xf0, 0xb4, 0xe6, 0x73,
        0x96, 0xac, 0x74, 0x22, 0xe7, 0xad, 0x35, 0x85, 0xe2, 0xf9, 0x37, 0xe8, 0x1c, 0x75, 0xdf, 0x6e,
        0x47, 0xf1, 0x1a, 0x71, 0x1d, 0x29, 0xc5, 0x89, 0x6f, 0xb7, 0x62, 0x0e, 0xaa, 0x18, 0xbe, 0x1b,
        0xfc, 0x56, 0x3e, 0x4b, 0xc6, 0xd2, 0x79, 0x20, 0x9a, 0xdb, 0xc0, 0xfe, 0x78, 0xcd, 0x5a, 0xf4,
        0x1f, 0xdd, 0xa8, 0x33, 0x88, 0x07, 0xc7, 0x31, 0xb1, 0x12, 0x10, 0x59, 0x27, 0x80, 0xec, 0x5f,
        0x60, 0x51, 0x7f, 0xa9, 0x19, 0xb5, 0x4a, 0x0d, 0x2d, 0xe5, 0x7a, 0x9f, 0x93, 0xc9, 0x9c, 0xef,
        0xa0, 0xe0, 0x3b, 0x4d, 0xae, 0x2a, 0xf5, 0xb0, 0xc8, 0xeb, 0xbb, 0x3c, 0x83, 0x53, 0x99, 0x61,
        0x17, 0x2b, 0x04, 0x7e, 0xba, 0x77, 0xd6, 0x26, 0xe1, 0x69, 0x14, 0x63, 0x55, 0x21, 0x0c, 0x7d
        ]

rcon = [
        0x8d, 0x01, 0x02, 0x04, 0x08, 0x10, 0x20, 0x40, 0x80, 0x1b, 0x36, 0x6c, 0xd8, 0xab, 0x4d, 0x9a,
        0x2f, 0x5e, 0xbc, 0x63, 0xc6, 0x97, 0x35, 0x6a, 0xd4, 0xb3, 0x7d, 0xfa, 0xef, 0xc5, 0x91, 0x39,
        0x72, 0xe4, 0xd3, 0xbd, 0x61, 0xc2, 0x9f, 0x25, 0x4a, 0x94, 0x33, 0x66, 0xcc, 0x83, 0x1d, 0x3a,
        0x74, 0xe8, 0xcb, 0x8d, 0x01, 0x02, 0x04, 0x08, 0x10, 0x20, 0x40, 0x80, 0x1b, 0x36, 0x6c, 0xd8,
        0xab, 0x4d, 0x9a, 0x2f, 0x5e, 0xbc, 0x63, 0xc6, 0x97, 0x35, 0x6a, 0xd4, 0xb3, 0x7d, 0xfa, 0xef,
        0xc5, 0x91, 0x39, 0x72, 0xe4, 0xd3, 0xbd, 0x61, 0xc2, 0x9f, 0x25, 0x4a, 0x94, 0x33, 0x66, 0xcc,
        0x83, 0x1d, 0x3a, 0x74, 0xe8, 0xcb, 0x8d, 0x01, 0x02, 0x04, 0x08, 0x10, 0x20, 0x40, 0x80, 0x1b,
        0x36, 0x6c, 0xd8, 0xab, 0x4d, 0x9a, 0x2f, 0x5e, 0xbc, 0x63, 0xc6, 0x97, 0x35, 0x6a, 0xd4, 0xb3,
        0x7d, 0xfa, 0xef, 0xc5, 0x91, 0x39, 0x72, 0xe4, 0xd3, 0xbd, 0x61, 0xc2, 0x9f, 0x25, 0x4a, 0x94,
        0x33, 0x66, 0xcc, 0x83, 0x1d, 0x3a, 0x74, 0xe8, 0xcb, 0x8d, 0x01, 0x02, 0x04, 0x08, 0x10, 0x20,
        0x40, 0x80, 0x1b, 0x36, 0x6c, 0xd8, 0xab, 0x4d, 0x9a, 0x2f, 0x5e, 0xbc, 0x63, 0xc6, 0x97, 0x35,
        0x6a, 0xd4, 0xb3, 0x7d, 0xfa, 0xef, 0xc5, 0x91, 0x39, 0x72, 0xe4, 0xd3, 0xbd, 0x61, 0xc2, 0x9f,
        0x25, 0x4a, 0x94, 0x33, 0x66, 0xcc, 0x83, 0x1d, 0x3a, 0x74, 0xe8, 0xcb, 0x8d, 0x01, 0x02, 0x04,
        0x08, 0x10, 0x20, 0x40, 0x80, 0x1b, 0x36, 0x6c, 0xd8, 0xab, 0x4d, 0x9a, 0x2f, 0x5e, 0xbc, 0x63,
        0xc6, 0x97, 0x35, 0x6a, 0xd4, 0xb3, 0x7d, 0xfa, 0xef, 0xc5, 0x91, 0x39, 0x72, 0xe4, 0xd3, 0xbd,
        0x61, 0xc2, 0x9f, 0x25, 0x4a, 0x94, 0x33, 0x66, 0xcc, 0x83, 0x1d, 0x3a, 0x74, 0xe8, 0xcb
        ]

# returns a copy of the word shifted n bytes (chars)
# positive values for n shift bytes left, negative values shift right
def rotate(word, n):
    return word[n:]+word[0:n]

# iterate over each "virtual" row in the state table and shift the bytes
# to the LEFT by the appropriate offset
def shiftRows(state):
    for i in range(4):
        state[i*4:i*4+4] = rotate(state[i*4:i*4+4],i)

# iterate over each "virtual" row in the state table and shift the bytes
# to the RIGHT by the appropriate offset
def shiftRowsInv(state):
    for i in range(4):
        state[i*4:i*4+4] = rotate(state[i*4:i*4+4],-i)

# takes 4-byte word and iteration number
def keyScheduleCore(word, i):
    # rotate word 1 byte to the left
    word = rotate(word, 1)
    newWord = []
    # apply sbox substitution on all bytes of word
    for byte in word:
        newWord.append(sbox[byte])
    # XOR the output of the rcon[i] transformation with the first part of the word
    newWord[0] = newWord[0]^rcon[i]
    return newWord

# expand 256 bit cipher key into 240 byte key from which
# each round key is derived
def expandKey(cipherKey):
    cipherKeySize = len(cipherKey)
    assert cipherKeySize == 32
    # container for expanded key
    expandedKey = []
    currentSize = 0
    rconIter = 1
    # temporary list to store 4 bytes at a time
    t = [0,0,0,0]

    # copy the first 32 bytes of the cipher key to the expanded key
    for i in range(cipherKeySize):
        expandedKey.append(cipherKey[i])
    currentSize += cipherKeySize

    # generate the remaining bytes until we get a total key size
    # of 240 bytes
    while currentSize < 240:
        # assign previous 4 bytes to the temporary storage t
        for i in range(4):
            t[i] = expandedKey[(currentSize - 4) + i]

        # every 32 bytes apply the core schedule to t
        if currentSize % cipherKeySize == 0:
            t = keyScheduleCore(t, rconIter)
            rconIter += 1

        # since we're using a 256-bit key -> add an extra sbox transform
        if currentSize % cipherKeySize == 16:
            for i in range(4):
                t[i] = sbox[t[i]]

        # XOR t with the 4-byte block [16,24,32] bytes before the end of the
        # current expanded key.  These 4 bytes become the next bytes in the
        # expanded key
        for i in range(4):
            expandedKey.append(((expandedKey[currentSize - cipherKeySize]) ^ (t[i])))
            currentSize += 1
            
    return expandedKey

# do sbox transform on each of the values in the state table
def subBytes(state):
    for i in range(len(state)):
        #print "state[i]:", state[i]
        #print "sbox[state[i]]:", sbox[state[i]]
        state[i] = sbox[state[i]]

# inverse sbox transform on each byte in state table
def subBytesInv(state):
    for i in range(len(state)):
        state[i] = sboxInv[state[i]]

# XOR each byte of the roundKey with the state table
def addRoundKey(state, roundKey):
    for i in range(len(state)):
        #print i
        #print "old state value:", state[i]
        #print "new state value:", state[i] ^ roundKey[i]
        state[i] = state[i] ^ roundKey[i]

# Galois Multiplication
def galoisMult(a, b):
    p = 0
    hiBitSet = 0
    for i in range(8):
        if b & 1 == 1:
            p ^= a
        hiBitSet = a & 0x80
        a <<= 1
        if hiBitSet == 0x80:
            a ^= 0x1b
        b >>= 1
    return p % 256

# mixColumn takes a column and does stuff
def mixColumn(column):
    temp = copy(column)
    column[0] = galoisMult(temp[0],2) ^ galoisMult(temp[3],1) ^ \
                galoisMult(temp[2],1) ^ galoisMult(temp[1],3)
    column[1] = galoisMult(temp[1],2) ^ galoisMult(temp[0],1) ^ \
                galoisMult(temp[3],1) ^ galoisMult(temp[2],3)
    column[2] = galoisMult(temp[2],2) ^ galoisMult(temp[1],1) ^ \
                galoisMult(temp[0],1) ^ galoisMult(temp[3],3)
    column[3] = galoisMult(temp[3],2) ^ galoisMult(temp[2],1) ^ \
                galoisMult(temp[1],1) ^ galoisMult(temp[0],3)

# mixColumnInv does stuff too
def mixColumnInv(column):
    temp = copy(column)
    column[0] = galoisMult(temp[0],14) ^ galoisMult(temp[3],9) ^ \
                galoisMult(temp[2],13) ^ galoisMult(temp[1],11)
    column[1] = galoisMult(temp[1],14) ^ galoisMult(temp[0],9) ^ \
                galoisMult(temp[3],13) ^ galoisMult(temp[2],11)
    column[2] = galoisMult(temp[2],14) ^ galoisMult(temp[1],9) ^ \
                galoisMult(temp[0],13) ^ galoisMult(temp[3],11)
    column[3] = galoisMult(temp[3],14) ^ galoisMult(temp[2],9) ^ \
                galoisMult(temp[1],13) ^ galoisMult(temp[0],11)

# mixColumns is a wrapper for mixColumn - generates a "virtual" column from
# the state table and applies the weird galois math
def mixColumns(state):
    for i in range(4):
        column = []
        # create the column by taking the same item out of each "virtual" row
        for j in range(4):
            column.append(state[j*4+i])

        # apply mixColumn on our virtual column
        mixColumn(column)

        # transfer the new values back into the state table
        for j in range(4):
            state[j*4+i] = column[j]

# mixColumnsInv is a wrapper for mixColumnInv - generates a "virtual" column from
# the state table and applies the weird galois math
def mixColumnsInv(state):
    for i in range(4):
        column = []
        # create the column by taking the same item out of each "virtual" row
        for j in range(4):
            column.append(state[j*4+i])

        # apply mixColumn on our virtual column
        mixColumnInv(column)

        # transfer the new values back into the state table
        for j in range(4):
            state[j*4+i] = column[j]

# aesRound applies each of the four transformations in order
def aesRound(state, roundKey):
    #print "aesRound - before subBytes:", state
    subBytes(state)
    #print "aesRound - before shiftRows:", state
    shiftRows(state)
    #print "aesRound - before mixColumns:", state
    mixColumns(state)
    #print "aesRound - before addRoundKey:", state
    addRoundKey(state, roundKey)
    #print "aesRound - after addRoundKey:", state

# aesRoundInv applies each of the four inverse transformations
def aesRoundInv(state, roundKey):
    #print "aesRoundInv - before addRoundKey:", state
    addRoundKey(state, roundKey)
    #print "aesRoundInv - before mixColumnsInv:", state
    mixColumnsInv(state)
    #print "aesRoundInv - before shiftRowsInv:", state
    shiftRowsInv(state)
    #print "aesRoundInv - before subBytesInv:", state
    subBytesInv(state)
    #print "aesRoundInv - after subBytesInv:", state


# returns a 16-byte round key based on an expanded key and round number
def createRoundKey(expandedKey, n):
    return expandedKey[(n*16):(n*16+16)]

# create a key from a user-supplied password using SHA-256
def passwordToKey(password):
    sha256 = hashlib.sha256()
    sha256.update(password)
    key = []
    for c in list(sha256.digest()):
        key.append(ord(c))
    return key

# wrapper function for 14 rounds of AES since we're using a 256-bit key
def aesMain(state, expandedKey, numRounds=14):
    roundKey = createRoundKey(expandedKey, 0)
    addRoundKey(state, roundKey)
    for i in range(1, numRounds):
        roundKey = createRoundKey(expandedKey, i)
        aesRound(state, roundKey)
    # final round - leave out the mixColumns transformation
    roundKey = createRoundKey(expandedKey, numRounds)
    subBytes(state)
    shiftRows(state)
    addRoundKey(state, roundKey)

# 14 rounds of AES inverse since we're using a 256-bit key
def aesMainInv(state, expandedKey, numRounds=14):
    # create roundKey for "last" round since we're going in reverse
    roundKey = createRoundKey(expandedKey, numRounds)
    # addRoundKey is the same funtion for inverse since it uses XOR
    addRoundKey(state, roundKey)
    shiftRowsInv(state)
    subBytesInv(state)
    for i in range(numRounds-1,0,-1):
        roundKey = createRoundKey(expandedKey, i)
        aesRoundInv(state, roundKey)
    # last round - leave out the mixColumns transformation
    roundKey = createRoundKey(expandedKey, 0)
    addRoundKey(state, roundKey)
    
# aesEncrypt - encrypt a single block of plaintext
def aesEncrypt(plaintext, key):
    block = copy(plaintext)
    expandedKey = expandKey(key)
    aesMain(block, expandedKey)
    return block

# aesDecrypt - decrypte a single block of ciphertext
def aesDecrypt(ciphertext, key):
    block = copy(ciphertext)
    expandedKey = expandKey(key)
    aesMainInv(block, expandedKey)
    return block

# return 16-byte block from an open file
# pad to 16 bytes with null chars if needed
def getBlock(fp):
    raw = fp.read(16)
    # reached end of file
    if len(raw) == 0:
        return ""
    # container for list of bytes
    block = []
    for c in list(raw):
        block.append(ord(c))
    # if the block is less than 16 bytes, pad the block
    # with the string representing the number of missing bytes
    if len(block) < 16:
        padChar = 16-len(block)
        while len(block) < 16:
            block.append(padChar)
    return block

# encrypt - wrapper function to allow encryption of arbitray length
# plaintext using Output Feedback (OFB) mode
def encrypt(myInput, password, outputfile=None):
    block = [0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0] # plaintext
    ciphertext = [0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0] # ciphertext
    # Initialization Vector
    IV = []
    for i in range(16):
        IV.append(randint(0, 255))

    # convert password to AES 256-bit key
    aesKey = passwordToKey(password)

    # create handle for file to be encrypted
    try:
        fp = open(myInput, "rb")
    except:
        print "pyAES: unable to open input file -", myInput
        sys.exit()

    # create handle for encrypted output file
    if outputfile is not None:
        try:
            outfile = open(outputfile,"w")
        except:
            print "pyAES: unable to open output file -", outputfile
            sys.exit()
    else:
        filename = myInput+".aes"
        try:
            outfile = open(filename,"w")
        except:
            print "pyAES: unable to open output file -", filename
            sys.exit()

    # write IV to outfile
    for byte in IV:
        outfile.write(chr(byte))

    # get the file size (bytes) 
    # if the file size is a multiple of the block size, we'll need 
    # to add a block of padding at the end of the message
    fp.seek(0,2)
    filesize = fp.tell()
    # put the file pointer back at the beginning of the file
    fp.seek(0)

    # begin reading in blocks of input to encrypt
    firstRound = True
    block = getBlock(fp)
    while block != "":
        if firstRound:
            blockKey = aesEncrypt(IV, aesKey)
            firstRound = False
        else:
            blockKey = aesEncrypt(blockKey, aesKey)

        for i in range(16):
            ciphertext[i] = block[i] ^ blockKey[i]

        # write ciphertext to outfile
        for c in ciphertext:
            outfile.write(chr(c))

        # grab next block from input file
        block = getBlock(fp)
    # if the message ends on a block boundary, we need to add an
    # extra block of padding
    if filesize % 16 == 0:
        outfile.write(16*chr(16))
    # close file pointers
    fp.close()
    outfile.close()

# decrypt - wrapper function to allow decryption of arbitray length
# ciphertext using Output Feedback (OFB) mode
def decrypt(myInput, password, outputfile=None):
    block = [0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0] # ciphertext
    plaintext = [0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0] # plaintext container

    # convert password to AES 256-bit key
    aesKey = passwordToKey(password)

    # create handle for file to be encrypted
    try:
        fp = open(myInput, "rb")
    except:
        print "pyAES: unable to open input file -", myInput
        sys.exit()

    # create handle for file to be decrypted
    try:
        fp = open(myInput, "rb")
    except:
        print "pyAES: unable to open input file -", myInput
        sys.exit()

    # create handle for decrypted output file
    if outputfile is not None:
        try:
            outfile = open(outputfile,"w")
        except:
            print "pyAES: unable to open output file -", filename
            sys.exit()
    else:
        if myInput[-4:] == ".aes":
            filename = myInput[:-4]
            print "Using", filename, "for output file name."
        else:
            filename = raw_input("output file name: ")
        try:
            outfile = open(filename,"w")
        except:
            print "pyAES: unable to open output file -", filename
            sys.exit()

    # recover Initialization Vector, the first block in file
    IV = getBlock(fp)

    # get the file size (bytes) in order to handle the
    # padding at the end of the file
    fp.seek(0,2)
    filesize = fp.tell()
    # put the file pointer back at the first block of ciphertext
    fp.seek(16)

    # begin reading in blocks of input to decrypt
    firstRound = True
    block = getBlock(fp)
    while block != "":
        if firstRound:
            blockKey = aesEncrypt(IV, aesKey)
            firstRound = False
        else:
            blockKey = aesEncrypt(blockKey, aesKey)

        for i in range(16):
            plaintext[i] = block[i] ^ blockKey[i]

        # if we're in the last block of text -> throw out the
        # number of bytes represented by the last byte in the block
        if fp.tell() == filesize:
            plaintext = plaintext[0:-(plaintext[-1])]

        # write ciphertext to outfile
        for c in plaintext:
            outfile.write(chr(c))

        # grab next block from input file
        block = getBlock(fp)
    # close file pointers
    fp.close()
    outfile.close()

def printUsage():
    print "./pyAES.py [-e <input file> | -d <input file>] [(optional) -o <output file>]"
    print "You will be prompted for a password after you specify the encryption/decryption args.\n"
    sys.exit()

# gather command line arguments and validate input
def main():
    # containers for command line arguments
    inputfile = None
    outputfile = None

    for a in range(len(sys.argv)):
        if sys.argv[a] == "-e":
            try:
                inputfile = sys.argv[a+1]
            except:
                inputfile = raw_input("File to encrypt: ")
        elif sys.argv[a] == "-d":
            try:
                inputfile = sys.argv[a+1]
            except:
                inputfile = raw_input("File to decrypt: ")
        if sys.argv[a] == "-o":
            try:
                outputfile = sys.argv[a+1]
            except:
                pass
    # print help message
    if ("-h" in sys.argv) or ("--help" in sys.argv):
        printUsage()
    if inputfile is None:
        print "Error: please specify options for encryption or decryption."
        printUsage()
    # encrypt file per user instructions
    if "-e" in sys.argv:
        #password = getpass.getpass("Password: ")
        password = 'godwin'
        print "Encrypting file:", inputfile
        if outputfile is not None:
            encrypt(inputfile, password, outputfile)
        else:
            encrypt(inputfile, password)
        print "Encryption complete."
    # decrypt file per user instructions
    elif "-d" in sys.argv:
        #password = getpass.getpass("Password: ")
        password = 'godwin'
        print "Decrypting file:", inputfile
        if outputfile is not None:
            decrypt(inputfile, password, outputfile)
        else:
            decrypt(inputfile, password)
        print "Decryption complete."

if __name__ == "__main__":
    main()

RSA:

#!/usr/bin/python

from random import randint, choice
from math import log
from string import atoi, replace, join
from time import time
import sys

""" Globals to catch command line options """
infile = None
outfile = None
keyfile = None
keylen = None

# print help message
def printHelp():
    print "Usage: ./pyrsa.py [OPTION] [FILE]"
    print "   or: ./pyrsa.py [OPTION] [VALUE]"
    print "Perform pyrsa function specified by OPTION on FILE or VALUE."
    print "  -e, --encrypt\t\tencrypt FILE"
    print "  -d, --decrypt\t\tdecrypt FILE"
    print "  -k, --key\t\tencrypt or decrypt using FILE as key"
    print "  -g, --generate\tgenerate public/private key pair of length" + \
          " VALUE bits"
    print "  -h, --help\t\tprint help message"

# parse command line options
def getOptions():
    global infile, outfile, keyfile, keylen
    if (len(sys.argv) < 2):
        print "pyrsa: too few arguments"
        printHelp()
        sys.exit()
    try:
        for i in range(len(sys.argv)):
            if (sys.argv[i][0] == "-"):
                option = sys.argv[i][1:]
                if (option == "e") or (option == "-encrypt"):
                    infile = sys.argv[i+1]
                elif (option == "d") or (option == "-decrypt"):
                    outfile = sys.argv[i+1]
                elif (option == "k") or (option == "-key"):
                    keyfile = sys.argv[i+1]
                elif (option == "g") or (option == "-generate"):
                    keylen = sys.argv[i+1]
                elif (option == "h") or (option == "-help"):
                    printHelp()
                    sys.exit()
    except:
        print "pyrsa: error reading arguments"
        printHelp()
        sys.exit()

# Return the highest bit that is set in decimal number n
def highbit(n):
    return 2**(int(log(n, 2)))

# Here is a modular exponentiation function that I wrote.  It turns
# out that the built-in function pow(x, y, z) is substantially faster.
# We will use pow(x, y, z) for our purposes, but I will leave  this code
# in to demonstrate how the exponentiation might be done.
def modExp(x, y, n):
    d = 1
    mask = highbit(y)
    # step through the bits of y, the exponent
    while (mask > 0):
        d = (d*d)%n
        # if the mask bit is 1, multiply the result by x mod n
        if (y & mask):
            d = (d*x)%n
        # shift the mask bit
        mask = mask >> 1L
    return d    

# The witness function used in the Miller-Rabin primality test.
# Returns true if a is a witness to the compositeness i.e. non-primality
# of n.  If true is returned, it is guaranteed that n is composite.  However,
# if false is returned, there is a chance that n is only pseudoprime.  We
# account for this in the actual primality test
def witness(a, n):
    # return Composite right away if n is even
    if not n & 1:
        return True
    # solve for n-1 = (2^t)u, where (t >= 1) and u is odd
    num = n - 1
    t = int(log(num,2))
    while (t >= 1):
        if (num % (2**t) == 0):
            break
        t -= 1
    u = num / (2**t)

    test = {}
    test[0] = pow(a, u, n)
    # square
    for i in range(1, t+1):
        test[i] = pow(test[i-1], 2, n)
        if (test[i]==1) and (test[i-1]!=1) and (test[i-1]!=n-1):
            return True
    if (test[t]!=1):
        return True
    return False

# The Miller-Rabin test for primality:
# The function tests witnesses for compositeness in the range of [1, n-1].
# Test is done s times to reduce chance of false positives for primality.
# The probability of a false positive is at most 2^(-s)
def isPrime(n, s):
    if n in [2, 3, 5, 7, 11, 13, 17, 19, 23, 29, 31, 37, 41, \
             43, 47, 53, 59, 61, 67, 71, 73, 79, 83, 89, 97]:
        return True
    for i in range(s):
        a = randint(1, n-1)
        if witness(a, n):
            return False
    return True

# return an N bit prime number.  Since we are using a value of 20 for
# s in the Miller-Rabin test, the probability of a false prime is about
# .000095%
def bigPrime(N):
    p = randint(2**(N-1),2**N)
    while 1:
        # check primality with Miller-Rabin test with certainty of
        # 99.9999046% that p is prime
        if isPrime(p, 20): return p
        p += 1

# Compute the multiplicative inverse of a and b.  This function is
# essentially Euclid's Extended Algorithm.
def inverse(a, b):
    e = a ; phiN = b
    v1 = [1, 0]
    v2 = [0, 1]
    while (a != 0) and (b != 0):
        if (a > b):
            m = a / b
            a %= b
            for i in range(2):
                v1[i] = v1[i] - m*v2[i]
        else:
            m = b / a
            b %= a
            for i in range(2):
                v2[i] = v2[i] - m*v1[i]
    if (a == 1):
        if (v1[0] < 0): return (v1[0]%phiN)
        else: return v1[0]
    else:
        if (v2[0] < 0): return (v2[0]%phiN)
        else: return v2[0]

# Function to generate a public/private key pair.  For N, we take
# the product of two primes of user-specified length.  For e, we use 17,
# a moderate value in the balance between high security and ease of
# computation.  For d, we use Extended Euclidean to find the inverse of
# e mod N
def generateKey(keylen):
    # take a string to append to the begining of the key file names
    firstName = raw_input("\nEnter file identifier (i.e. first name): ")
    publicKey = firstName + "_publicKey.txt"
    privateKey = firstName + "_privateKey.txt"

    # exponentiation value
    e = 17

    # generate public key: (e, N) with N as the product of two large primes
    fp = open(publicKey, "w")
    p = bigPrime(keylen/2)
    q = bigPrime(keylen/2)
    fp.write("----- Begin pyRSA Public Key Block -----\n")
    fp.write(str(e))
    fp.write("\n")
    fp.write(str(p*q))
    fp.write("\n")
    fp.write("----- End pyRSA Public Key Block -----")
    fp.close()

    # generate private key: (e, N) with d as the multiplicative inverse of
    # e mod N
    fp = open(privateKey, "w")
    phiN = (p - 1)*(q - 1)
    d = inverse(e, phiN)
    fp.write("----- Begin pyRSA Private Key Block -----\n")
    fp.write(str(d))
    fp.write("\n")
    fp.write(str(p*q))
    fp.write("\n")
    fp.write("----- End pyRSA Private Key Block -----")
    fp.close()

# Function to convert a character string to a long integer.  We use 8 bits
# per character so the long integer takes no more space than the byte string
# representing the ASCII text
def string2long(s):
    m = 0
    x = len(s) - 1
    # loop backwards through string, for each character add its ASCII value
    # multiplied by its position in the string to the return value
    for char in s:
        m += (256**x)*ord(char)
        x -= 1
    return m

# Function to convert a long integer to a string.
def long2string(m):
    try:
        m = atol(m)
    except:
        pass
    # temporary container for message characters
    letters = []
    # string which will hold the return value
    cleartext = ""
    # treat the long integer as base-256 and loop through, converting each
    # base-256 "digit" to a character
    i = int(log(m, 256))
    while (i >= 0):
        c = m / (256**i)
        letters.append(chr(c))
        m -= c*(256**i)
        i -=1
    # convert the list of characters to a single string
    for l in letters:
        cleartext += l
    return cleartext

# Function to encrypt a character string into a numeric ciphertext.
# KNOWN BUG: when message is too long, i.e. longer than the value of N, this
# function cannot encrypt the message.
# POSSIBLE FIX: in this case, break the message into fixed-sized blocks and
# encrypt each block separately
def encrypt(m):
    # container for the encryption key filename
    global keyfile

    if (keyfile == None):
        print "pyrsa: no encryption key specified.  Use [-k FILE] option.\n"
        sys.exit()

    # convert the character string to a long integer
    message = string2long(m)

    # attempt to take the encryption key data from the key file
    try:
        fp = open(keyfile, "r")
        fp.readline()
        e = int(fp.readline())
        N = int(fp.readline())
        fp.close()
    except:
        print "Cannot read from private key file: ", keyfile
        return None

    # bail out if message is too long
    if (message > N):
        print "Message string is too long.\n"
        return None

    # encrypt the message with modular exponentiation using the values
    # from the encryption key
    message = pow(message, e, N)
    return message

# decrypt a numeric ciphertext and convert it to a plaintext message
def decrypt(m):
    # container for decryption key filename
    global keyfile
    
    if (keyfile == None):
        print "pyrsa: no decryption key specified.  Use [-k FILE] option.\n"
        sys.exit()

    # attempt to take the decryption key data from the key file    
    try:
        fp = open(keyfile, "r")
        fp.readline()
        d = int(fp.readline())
        N = int(fp.readline())
        fp.close()
    except:
        print "Cannot read from key file: ", keyfile
        return None

    # decrypt message using modular exponentiation
    message = pow(int(m), d, N)

    return long2string(message)

# Main Function: get command line options and perform RSA functions based
# on options
def main():
    global infile, outfile, keyfile, keylen

    # get command line options
    getOptions()
    if infile:
        m = open(infile, "r")
        message = m.readlines()
        m.close()
        message = join(message)
        print encrypt(message)
    elif outfile:
        c = open(outfile, "r")
        ciphertext = c.readlines()
        c.close()
        ciphertext = join(ciphertext)
        print "Decrypted text:\n", decrypt(ciphertext)
    elif keylen:
        generateKey(int(keylen))
        
if __name__ == "__main__":
    main()

 

Edited by brdarkmoon
Link to post
Share on other sites

0 answers to this question

Recommended Posts

There have been no answers to this question yet

Join the conversation

You can post now and register later. If you have an account, sign in now to post with your account.

Guest
Answer this question...

×   Pasted as rich text.   Paste as plain text instead

  Only 75 emoji are allowed.

×   Your link has been automatically embedded.   Display as a link instead

×   Your previous content has been restored.   Clear editor

×   You cannot paste images directly. Upload or insert images from URL.



  • Forum Statistics

    • Total Topics
      148692
    • Total Posts
      644525
×
×
  • Create New...