def trouver_dernier_octet(login, IV, r, Y_n_before, Y_n):
	"""
	Fonction permettant de trouver le dernier octet de X_n, en fonction des blocs Y_n-1 et Y_n.
	Renverra l'octet trouvé, ainsi que son état intermédiaire (dans un tuple)
	login : login de l'utilisateur
	IV : vecteur d'initialisation, donné par le serveur lors de la demande avec SEED
	r : l'objet Block aléatoire permettant l'attaque
	Y_n_before : bloc Y_n-1
	Y_n : bloc Y_n
	"""

	#Création de l'oracle
	oracle = Oracle(BASE_URL, ORACLE_URL, login, SEED)

	i = 0

	while True:
		h = "0x{:02x}".format(i)
		r[15] = int(h, 16)
		if debug:
			print("i : {0} ; r : {1}".format(h, r.hex() + Y_n.hex()))
		reponse = oracle.demande_informations(r.hex() + Y_n.hex(), IV.hex())
		if reponse['status'] != 'invalid padding':
			print("VALIDE : " + reponse['status'] + " - " + str(i))
			break
		i = i+1

	#L'octet intermédiaire est i ^ 01
	byte_IS = i ^ 1

	#Le dernier octet de X_n est donc byte_IS ^ Y_n[len(Y_n)-1]
	last_byte = byte_IS ^ Y_n_before[15]

	last_byte = hex(last_byte)

	#Récupération des deux derniers hexa -> un octet
	last_byte = last_byte[2:]
	
	#Vérification - si la longueur vaut 1, dans ce cas on concatène 0 avec le dernier octet
	if len(last_byte) == 1:
		last_byte = "0"+last_byte

	#Destruction de l'oracle
	del oracle

	return (byte_IS, last_byte)
def trouver_bloc(login, bytes_IS_block, IV, r, Y_n_before, Y_n, last_byte, nb_block):
	"""
	Fonction permettant de trouver le dernier bloc X_n du message à déchiffrer.
	Renverra le bloc contenant tous les octets trouvés.
	login : login de l'utilisateur
	bytes_IS_block : objet Block qui contenant absolument tous les états intermédiaires calculés (pour évaluation padding)
	IV : vecteur d'initialisation, donné par le serveur lors de la demande avec SEED
	r : l'objet Block aléatoire permettant l'attaque
	Y_n_before : bloc Y_n-1
	Y_n : bloc Y_n
	last_byte : dernier octet trouvé du bloc sur lequel on effectue l'attaque
	"""
	
	#Création de l'oracle
	oracle = Oracle(BASE_URL, ORACLE_URL, login, SEED)

	#Bloc d'octets - initialisé à last_byte
	bloc = last_byte

	#i sert à chercher l'octet en question
	i = 0

	#j sert à changer de position dans le block (on décrémente)
	j = 14

	#Boucle permettant de calculer le bloc entier concerné 
	while True:
		#Calcul de h en hexadécimal
		h = "0x{:02x}".format(i)
		#Transformation de r[j] via h entier (hexa)
		r[j] = int(h, 16)
		if debug:
			print("i : {0} ; r : {1}".format(h, r.hex() + Y_n.hex()))
		reponse = oracle.demande_informations(r.hex() + Y_n.hex(), IV.hex())
		#Si la réponse renvoyée par le serveur n'est pas invalide, le padding est bon!
		if reponse['status'] == 'invalid padding':
			i = i+1
		else:
			if debug:
				print("VALIDE : {0} - i={1}".format(reponse['status'],str(i)))
			#L'octet de l'état intermédiaire est calculé
			bytes_IS_block[j] = i ^ (16 - j)
			#On le xor avec le bloc précédent à l'état j+1
			byte = bytes_IS_block[j] ^ Y_n_before[j]
			byte = hex(byte)
			byte = byte[2:]
			if len(byte) == 1:
				byte = "0"+byte
			print("L'octet {0} de X_n est {1}".format(j, byte))
			#envoie_octet_intermediaire(login, (nb_block * 16 + (16 - j)), byte)
			bloc = "{0}{1}".format(byte, bloc)
			#L'état intermédiaire est modifié de façon à calculer le nouvel octet à la position donnée
			for k in range (j, 16):
				r[k] = bytes_IS_block[k] ^ (16 - (j - 1))
			#On décrémente j -> passage vers une position moindre
			j = j-1
			#Réinitialisation de i, permettant de commencer l'attaque à 0
			i=0
			#Si la position de l'octet est inférieure à 0, on stoppe!
			if j<0:
				break

	#Destruction de l'oracle
	del oracle

	return bloc