"""
Cryptographic system of ERODE
Author : Nausicaä & Jérémy Grelaud
"""
import sys
def pow_mod(x, y, modulo):
"""
Small function to calculate x^y [modulo]
"""
if y == 0:
return 1
elif y == 1:
return x % modulo
else:
root = pow_mod(x, y // 2, modulo)
if y % 2 == 0:
return (root * root) % modulo
else:
return (root * root * x) % modulo
def invert_a_number_in_a_ring(number, n, s=1, t=0, N=0):
"""
recursive function to invert a number in Z/nZ
"""
return (n < 2 and t % N or invert_a_number_in_a_ring(n, number % n, t, s-number//n*t, N or n), -1)[n < 1]
def convert_number_from_base10_to_baseX(number, base):
"""
Convert "number" from the base 10 to the base "base"
return a list with the unit in the base in a list
"""
numberInBase = []
quotient = 1
while(quotient != 0):
numberInBase.append(number % base)
quotient = number // base
number = quotient
# we invert the number of the the list to have the right order
return numberInBase[::-1]
def convert_number_from_base10_to_base16(number):
numberInBase = []
quotient = 1
while(quotient != 0):
numberInBase.append(number % 16)
if((number % 16) == 10):
numberInBase.append(0)
quotient = number // 16
number = quotient
# we invert the number of the the list to have the right order
return numberInBase[::-1]
def convert_number_from_baseX_to_base10(number, base):
"""
Convert "number" from the base "base to the base 10
return a number
"""
result = 0
power = len(number)-1
for x in number:
result += (x*(base**power))
power -= 1
return result
def one_complement(binary):
"""
do the one complement in binary
for [1,0,0,1,1], we get [0,1,1,0,0]
"""
new_binary = []
for i in binary:
if(i == 0):
new_binary.append(1)
else:
new_binary.append(0)
return new_binary
def project_Fatalis(message, tag_code):
Tab = [65,97,69,101,73,105,79,111,85,117,89,121]
x = [int(a) for a in str(tag_code)]
fatalis = (x[1]*x[3]+x[0]-x[2])%6
if(fatalis == 0):
fatalis = 4
newmessage = ""
for i in message:
if(ord(i) in Tab):
newmessage += chr(Tab[(Tab.index(ord(i))+(fatalis*2))%len(Tab)])
else:
newmessage += i
return newmessage
def project_Stark(message, tag_code):
Tab = [121,89,117,85,111,79,105,73,101,69,97,65]
x = [int(a) for a in str(tag_code)]
stark = (x[1]*x[3]+x[0]-x[2])%6
if(stark == 0):
stark = 4
newmessage = ""
for i in message:
if(ord(i) in Tab):
newmessage += chr(Tab[(Tab.index(ord(i))+(stark*2))%len(Tab)])
else:
newmessage += i
return newmessage
def Babylonia(message, tag_code):
Tab = [66,98,67,99,68,100,70,102,71,103,72,104,74,106,75,107,76,108,77,109,78,110,80,112,81,113,82,114,83,115,84,116,86,118,87,119,88,120,90,122]
x = [int(a) for a in str(tag_code)]
babylonia = (x[0]*x[3]+x[2]-x[1])%20
if(babylonia == 0):
babylonia = 13
newmessage = ""
for i in message:
if(ord(i) in Tab):
newmessage += chr(Tab[(Tab.index(ord(i))+(babylonia*2))%len(Tab)])
else:
newmessage += i
return newmessage
def Lutèce(message,tag_code):
Tab = [66,98,67,99,68,100,70,102,71,103,72,104,74,106,75,107,76,108,77,109,78,110,80,112,81,113,82,114,83,115,84,116,86,118,87,119,88,120,90,122]
x = [int(a) for a in str(tag_code)]
Lutece = (x[0]*x[3]+x[2]-x[1])%20
if(Lutece == 0):
Lutece = 13
newmessage = ""
for i in message:
if(ord(i) in Tab):
newmessage += chr(Tab[(Tab.index(ord(i))-(Lutece*2))%len(Tab)])
else:
newmessage += i
return newmessage
def possibility_of_encryption(message):
for i in message:
if(ord(i)>=256):
return False
def encryption_junior(message, tag_code):
"""
cipher a group of 10 digits with the tag code
[6,8,6,5,7,9,2,1,0,0] become 48144275502093940871982071991190135 (after base change and one complement)
return the number and a flag
"""
flag = 0
hexa_array = [] # we will get an array of array
message = Babylonia(message, tag_code)
message = project_Fatalis(message, tag_code)
for i in message:
hexa_array.append(convert_number_from_base10_to_base16(ord(i)))
#print(hexa_array)
# fusion of the array
newArray = []
for i in range(len(hexa_array)):
for j in range(len(hexa_array[i])):
newArray.append(hexa_array[i][j])
#print(newArray)
# completion to a certain size
while(len(newArray) < 10):
newArray.append(0)
# print(newArray)
group10 = convert_number_from_baseX_to_base10(newArray, tag_code)
# print(group10)
group10Binaire = convert_number_from_base10_to_baseX(group10, 2)
# print(group10Binaire)
group10BinaireComp = one_complement(group10Binaire)
# print(group10BinaireComp)
# if first element is 0 we need to mark it
i = 0
while(group10BinaireComp[i] == 0 and i < len(group10BinaireComp)):
flag += 1
i += 1
conversionEnChiffre = convert_number_from_baseX_to_base10(
group10BinaireComp, 2)
# print(conversionEnChiffre)
return conversionEnChiffre, flag
def encryption_senior(full_message, tag_code):
"""
"""
# we're gonna encrypt multiple blocks
allblocks = []
substring = ""
counter = 0
for i in range(len(full_message)):
if(counter == 5):
allblocks.append(substring)
substring = full_message[i]
counter = 1
else:
counter = counter+1
substring += full_message[i]
allblocks.append(substring)
#print(allblocks)
# we have blocks of 5 char or less
StoreCipheredNumbers = []
FlagNumbers = []
for i in allblocks:
result = encryption_junior(i, tag_code)
StoreCipheredNumbers.append(result[0])
FlagNumbers.append(result[1])
# print(StoreCipheredNumbers)
Storage = StoreCipheredNumbers, FlagNumbers
message = ""
for i in range(len(Storage[0])):
if(i==(len(Storage[0])-1)):
message += str(Storage[0][i])+"!"+str(Storage[1][i])
else:
message += str(Storage[0][i])+"!"+str(Storage[1][i])+"!"
return message
#decipher a group of 10 digits
def decipher_junior(ciphered, tag_code, flag):
"""
"""
# first goes from base 10 to binary
binary = convert_number_from_base10_to_baseX(ciphered, 2)
# print(binary)
# then one complement
if(flag != 0):
for i in range(flag):
binary.insert(0, 0)
binaryComp = one_complement(binary)
# print(binaryComp)
# goes back to base 10
base10 = convert_number_from_baseX_to_base10(binaryComp, 2)
# print(base10)
# convert back to base tag_code
FusedArray = convert_number_from_base10_to_baseX(base10, tag_code)
# print(FusedArray)
#we compare last digits if a group of 2 are both = 0 we delete this
newtable = []
#print(FusedArray)
for i in range(0, len(FusedArray), 2):
if (FusedArray[i] == 0) and (FusedArray[i+1] == 0):
a = 1
else:
newtable.append(FusedArray[i])
newtable.append(FusedArray[i+1])
#print(newtable)
# then we split in groups of 2 numbers to then convert back in hexa to ascii
str = ""
for i in range(0, len(newtable), 2):
str += chr(convert_number_from_baseX_to_base10(
[newtable[i], newtable[i+1]], 16))
str = Lutèce(str, tag_code)
str = project_Stark(str, tag_code)
# print(str)
return str
def decipher_senior(AllCipheredBlocks, tag_code):
"""
"""
Storage = AllCipheredBlocks.split("!")
blocks = []
Flags = []
for i in range(len(Storage)):
if(i%2==0):
blocks.append(int(Storage[i]))
else:
Flags.append(int(Storage[i]))
Ragnarock = ""
for i in range(len(blocks)):
Ragnarock += decipher_junior(blocks[i], tag_code, Flags[i])
return Ragnarock
if name == "main":
message = str(sys.argv[1])
#open text file in read mode
#text_file = open("key.txt", "r")
#read whole file to a string
#data = text_file.read()
#close file
#text_file.close()
#print(data)
#message = data
tag_code = int(sys.argv[2])
#tag_code = 9999
if(possibility_of_encryption(message)):
Storage = encryption_senior(message,tag_code)
print(Storage)
else:
print("Il y a un problème")