Bueno el otro día a Blau le surgieron un par de problemas usando AES preimplementado, supuestamente por la codificación y me entró el gusanillo de implementar mi propio AES. Ya conocía DES y variantes tipo 3DES, pero de AES solo conocía algunas anécdotas de su desarrollo y algunas características superficiales.

El proceso ha sido seguido de aquí: [Enlace externo eliminado para invitados]. Podéis comparar los resultados del algoritmo con los resultados de las transparencias 12 y 13 de la animación.

Os dejo el código.

Código: Seleccionar todo

#!/usr/bin/env python
# -*- coding: utf-8 -*-

""" CONSTANTS """

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]
   
rcon = [[0x01,0x02,0x04,0x08,0x10,0x20,0x40,0x80,0x1b,0x36],
		[0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00],
		[0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00],
		[0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00]]
		
rgfield = [[0x02,0x03,0x01,0x01],
		   [0x01,0x02,0x03,0x01],
		   [0x01,0x01,0x02,0x03],
		   [0x03,0x01,0x01,0x02]]
		   
cnst = 0b00011011   # Constant XOR multiplication value 

class libutils:
	
	## Example of use libutils._changecolumn(antKey,[0x09,0xcf,0x4f,0x3c],0) ##
	@staticmethod
	def _changecolumn(block,column,n): 
		for i in xrange(4):
			block[i][n] = column[i]
		return block
		
	## PRECONDITION n<=col(block) ##
	@staticmethod
	def _getcolumn(block,n):
		return [block[i][n] for i in xrange(len(block))]
	
	@staticmethod
	def _getallcolumns(block):
		return [libutils._getcolumn(block,n) for n in xrange(len(block))]
		
	@staticmethod
	## Change first byte at last byte of the column ##
	def _rotword(column):
		tmp = column[0]
		for i in xrange(len(column)-1):
			column[i] = column[i+1]
		column[len(column)-1] = tmp
		return column
	
	@staticmethod
	## Make SubBytes process applied to column ##
	def _subbytes(column):
		return [sbox[i] for i in column]
	
	@staticmethod
	## Make SubBytes process applied to matrix ##
	def _subbytesmatrix(matrix):
		for i in xrange(len(matrix)):
			for j in xrange(len(matrix)):
				matrix[i][j] = sbox[matrix[i][j]]
		return matrix
		
	@staticmethod
	## Xor 3 columns -> key schedule col1 xor col2 xor Rcon[i] ##
	## PRECONDITION len(col1) == len(col2) == len(col3) ##
	def _xor3columns(col1,col2,col3):
		return [col1[i] ^ col2[i] ^ col3[i] for i in xrange(len(col1))]
		
	@staticmethod
	## Xor 2 columns ##
	## PRECONDITION: len(col1) == len(col2) ##
	def _xor2columns(col1,col2):
		return [col1[i] ^ col2[i] for i in xrange(len(col1))]
	
	@staticmethod
	## Build matrix by columns ##
	def _buildmatrixcol(*args):
		matrix = [[0x00]*len(args) for i in xrange(len(args))]
		for i in xrange(len(args)):
			libutils._changecolumn(matrix,args[i],i)
		return matrix
	
	@staticmethod
	## AddRoundKey process ##
	## PRECONDITION: Square matrices (4x4 in this case)
	def _addroundkey(matrix1,matrix2):
		matrix = [[0x00]*4 for i in xrange(len(matrix1))]
		for i in xrange(len(matrix1)):
			matrix = libutils._changecolumn(matrix,libutils._xor2columns(libutils._getcolumn(matrix1,i),libutils._getcolumn(matrix2,i)),i)
		return matrix
	
	@staticmethod
	## Rotate fil n of matrix i times ##
	## Trick: << i -> pos[0] = pos[i], pos[1] = pos[(1+i)%3], pos[2] = pos[(2+i)%3], pos[3] = pos[(3+i)%3]
	def _rotate(fil,n,i):
		auxfil = [p for p in fil]
		for j in xrange(len(fil)):
			fil[j] = 0x00 | auxfil[(j+i)%len(fil)]
		return fil
		
	@staticmethod
	## ShiftRows process   ##
	def _shiftrows(matrix):
		for i in xrange(len(matrix)):
			# Rotate fil i, i times #
			matrix[i] = libutils._rotate(matrix[i],i,i)
		return matrix


	@staticmethod
	## MixColumns process ##
	## PRECONDITION: 8-bits elements in matrix, else it will be truncated at 8-bits or filled with zeros ##
	def _mixcolumns(matrix):
		actCol  = []
		acum    = 0x00
		endCol  = [0x00]*4
		tmp     = 0x00
		for i in xrange(len(matrix)):
			actCol = libutils._getcolumn(matrix,i)
			for j in xrange(len(rgfield)):
				for x in xrange(len(rgfield[j])):
					actCol[x] = actCol[x] & 0x000000FF   # If it has more than 8-bits truncate it
					xored = actCol[x] & 0x00000080
					if rgfield[j][x] == 0x01:
						tmp = actCol[x]					
					elif rgfield[j][x] == 0x02:
						tmp = actCol[x] << 1
						if xored != 0x00000080:
							tmp = tmp ^ cnst											
					else:	
						tmp = actCol[x] << 1
						if xored != 0x00000080:
							tmp = tmp ^ cnst	
						tmp = tmp ^ actCol[x]				
					acum = acum ^ tmp
					acum &= 0x000000FF
					tmp = 0x00
				endCol[j] = acum
				acum 	  = 0x00
			matrix = libutils._changecolumn(matrix,endCol,i)
		return matrix
		
		
	@staticmethod
	## Extract round key n from schedule ##
	## 
	def _extractroundkey(schedule,n):
		roundKey = [[],[],[],[]]
		for i in xrange(len(schedule)):
			for j in range(n*4,(n*4)+4):
				roundKey[i].append(schedule[i][j])
		return roundKey
					
	
class cipheralgorithms:
	
	@staticmethod
	def _aes(*args):
		cipherText = [[0x32,0x88,0x31,0xe0],[0x43,0x5a,0x31,0x37],[0xf6,0x30,0x98,0x07],[0xa8,0x8d,0xa2,0x34]]
		cipherKey  = [[0x2b,0x28,0xab,0x09],[0x7e,0xae,0xf7,0xcf],[0x15,0xd2,0x15,0x4f],[0x16,0xa6,0x88,0x3c]]
		auxBlock   = [[0x00]*4]
		if args != ():
			cipherText = args[0]
			if len(args) == 2:
				cipherKey  = args[1]
		# Set schedule -> we can obtain later all round keys by this matrix #
		schedule  = cipheralgorithms.__keyschedule(cipherKey)
		
		###################### Show ###################### 
		def _showBlock(auxBlock):
			for i in auxBlock:
				for j in i:
					print hex(j)," ",
				print "\n"
		###################### End Show ######################
		 
		# Make init AddRoundKey with cipherKey #
		auxBlock = libutils._addroundkey(cipherText,libutils._extractroundkey(schedule,0))
		print "First AddRoundKey: \n"
		_showBlock(auxBlock)
		# Make 9 main rounds #
		for x in range(1,10):	
			## SubBytes      ##
			auxBlock = libutils._subbytesmatrix(auxBlock)
			print "Round " + str(x) + " SubBytes: \n"
			_showBlock(auxBlock)
			## ShiftRows     ##
			auxBlock = libutils._shiftrows(auxBlock)
			print "Round " + str(x) + " ShiftRows: \n"
			_showBlock(auxBlock)
			## MixColumns    ##
			auxBlock = libutils._mixcolumns(auxBlock)
			print "Round " + str(x) + " MixColumns: \n"
			_showBlock(auxBlock)
			## AddRoundKey   ##
			print "Round " + str(x) + " Key to cipher in this round: \n"
			_showBlock(libutils._extractroundkey(schedule,x))
			print "Round " + str(x) + " Keyed: \n"
			auxBlock = libutils._addroundkey(auxBlock,libutils._extractroundkey(schedule,x))
			_showBlock(auxBlock)
			
		## Make final round  ##	
		## SubBytes      ##
		auxBlock = libutils._subbytesmatrix(auxBlock)
		print "Final subbytes: \n"
		_showBlock(auxBlock)
		## ShiftRows     ##
		auxBlock = libutils._shiftrows(auxBlock)
		print "Final shiftrows: \n"
		_showBlock(auxBlock)
		## AddRoundKey   ##
		auxBlock = libutils._addroundkey(auxBlock,libutils._extractroundkey(schedule,10))
		print "Final keyed: \n"
		_showBlock(auxBlock)
			
	@staticmethod
	def __keyschedule(cipherKey):				
		antKey,schedule,actCol,i,actPos,actPosRcon = cipherKey,[],None,0,0,0
		## Fill schedule 4x40 ##
		schedule = [[0x00]*44 for i in xrange(4)]
		## Set initial status of schedule ##
		for col in libutils._getallcolumns(antKey):
			schedule = libutils._changecolumn(schedule,col,actPos)
			actPos += 1
		for i in xrange(40):
			## Take ant col ##
			actCol = libutils._getcolumn(schedule,actPos-1)
			## If is word in multiple of 4, rotword and subbytes ##
			if(actPos%4==0):
				actCol = libutils._rotword(actCol)
				actCol = libutils._subbytes(actCol)
				actCol = libutils._xor3columns(libutils._getcolumn(schedule,actPos-4),actCol,libutils._getcolumn(rcon,actPosRcon))
				actPosRcon += 1
			else:
				actCol = libutils._xor2columns(libutils._getcolumn(schedule,actPos-4),actCol)
			libutils._changecolumn(schedule,actCol,actPos)
			actPos += 1
		return schedule
		
	
if __name__ == "__main__":
	# If there isn't arguments, values are set by default #
	# 1º -> CipherText (128bits Block)
	# 2º -> CipherKey  (128bits Block)
	cipheralgorithms._aes()
Al final de la ejecución obtendréis el valor del cifrado final (Final keyed), también se van imprimiendo los valores de las rondas intermedias por temas de depuración.

Imagen


Un saludo :D
Bastante buena la adaptación colega.. pero creo(sin ofender) que deberías citar fuente del código basado [Enlace externo eliminado para invitados]
Saludos.
NvK escribió:Bastante buena la adaptación colega.. pero creo(sin ofender) que deberías citar fuente del código basado [Enlace externo eliminado para invitados]
Saludos.
Jaja fui yo el que subió el código a pastebin NvK, soy el autor xD.
De hecho ese es el pastebin anterior a este: [Enlace externo eliminado para invitados] :)
Última edición por overxfl0w13 el 22 Jun 2014, 17:03, editado 3 veces en total.
NvK escribió:Perdon no sabía es que vi un código muy parecido a demas de ese, un saludo.
No creo que se pareciesen mucho, es escrito desde 0 sin mirar fuentes que no fuesen la animación xD.

Un saludo tio :)
overxfl0w13 escribió:
NvK escribió:Bastante buena la adaptación colega.. pero creo(sin ofender) que deberías citar fuente del código basado [Enlace externo eliminado para invitados]
Saludos.
Jaja fui yo el que subió el código a pastebin NvK, soy el autor xD.
De hecho ese es el pastebin anterior a este: [Enlace externo eliminado para invitados] :)
yo mismo estuve compartiendo scritorio a traves de skype con overxfl0w13 y estuvo mandandome pastebins y ese codigo de pastebin es suyo sullisimo , buen codigo tio y un magnifico trabajo, salu2
Abolición para el torneo del toro de la vega. Death to the murderers of bulls.
strup escribió:
overxfl0w13 escribió:
NvK escribió:Bastante buena la adaptación colega.. pero creo(sin ofender) que deberías citar fuente del código basado [Enlace externo eliminado para invitados]
Saludos.
Jaja fui yo el que subió el código a pastebin NvK, soy el autor xD.
De hecho ese es el pastebin anterior a este: [Enlace externo eliminado para invitados] :)
yo mismo estuve compartiendo scritorio a traves de skype con overxfl0w13 y estuvo mandandome pastebins y ese codigo de pastebin es suyo sullisimo , buen codigo tio y un magnifico trabajo, salu2
Si pero no lo decía por eso... es que cuando hay alguien nuevo en el foro tengo cierta desconfianza.
Ya sabes por lo que paso hace poco con los rippers(y gente que sube cosas infectadas), pero me he dado cuenta de su trabajo, por eso pedí disculpas ¬¬.
NvK escribió:
strup escribió:
overxfl0w13 escribió:
NvK escribió:Bastante buena la adaptación colega.. pero creo(sin ofender) que deberías citar fuente del código basado [Enlace externo eliminado para invitados]
Saludos.
Jaja fui yo el que subió el código a pastebin NvK, soy el autor xD.
De hecho ese es el pastebin anterior a este: [Enlace externo eliminado para invitados] :)
yo mismo estuve compartiendo scritorio a traves de skype con overxfl0w13 y estuvo mandandome pastebins y ese codigo de pastebin es suyo sullisimo , buen codigo tio y un magnifico trabajo, salu2
Si pero no lo decía por eso... es que cuando hay alguien nuevo en el foro tengo cierta desconfianza.
Ya sabes por lo que paso hace poco con los rippers(y gente que sube cosas infectadas), pero me he dado cuenta de su trabajo, por eso pedí disculpas ¬¬.
si te comprendi pero quise reafirmar la autoria por si las moscas xDD, te comprendo y fue buena tu intencion (un buen gesto de hecho), siempre es bueno estar atento a todos esos que postean codes robados o infectados, un saludo maquina
Abolición para el torneo del toro de la vega. Death to the murderers of bulls.
Disculpa mi ignorancia(soy nuevo en python y quiero entender) podrias darme un ejemplo de como utilizar el archivo .py que has hecho para encryptat y desencriptar y asi ver el funcionamiento del mismo.
¡Grande over! Ahora te toca pasarlo a Java
enfermo1804 escribió:Disculpa mi ignorancia(soy nuevo en python y quiero entender) podrias darme un ejemplo de como utilizar el archivo .py que has hecho para encryptat y desencriptar y asi ver el funcionamiento del mismo.
Lee las últimas líneas del code.
Excelente trabajo! En cuanto tenga tiempo le echo un ojo que luce bastante interesante, felicitaciones por el trabajo!
1337 & culture!
Responder

Volver a “Python”