# %% import csv ''' ## Premessa 1 La mia prima versione di convertitore è stata fatta ad occhio. Ora, tornando sulla questione, ho individuato funzioni _built-in_ (e quindi, in teoria, altamente ottimizzate) che fanno il grosso del lavoro: in particolare: - int - hex - chr - ord ''' ''' ## Premessa 2 *Unicode* assegna ad 'ogni' (o meglio: ad un numero parecchio grande di) carattere un codice numerico. Seguendo lo standard, il codice Unicode di un carattere si scrive 'U+' seguito da un numero _esadecimale_ da 4 a 6 cifre (con le prime cifre che possono essere zeri). Ad esempio, le lettere latine maiuscole A-Z sono rappresentate dai codici U+0041 -- U+005A e le minuscole dai codici U+0061 -- U+007A . I codici dei primi 128 caratteri (da U+0000 a U+007F) corrispondono ai codici ASCII degli stessi caratteri. Questi codici hanno anche una versione _decimale_, che si ottiene semplicemente convertendo il numero dopo 'U+' da base 16 a base 10. Per fare la conversione in GATTO, ci occorrono entrambe le versioni. ''' # %% # 1. Le funzioni 'int' e 'hex' permettono di convertire al volo numeri decimali in esadecimali e viceversa. # Da esadecimale a int: print('Da base 16 a base 10:', int("AF", 16) ) # Da int a esadecimale: print ('Da base 10 a base 16 -- notare il prefisso:', hex(175) ) ''' Note: 1. In 'int', il secondo parametro specifica la base: la funzione può essere usata anche per convertire numeri da altre basi. 2. Sempre in 'int', l'input va dato come stringa, per evitare che il Python lo interpreti come variabile data la possibile presenza di lettere. La string *non* è case-sensitive. 3. In 'hex', si può notare che l'output ha un prefisso '0x'. Questo serve per specificare ''' # Altri esempi: print('La stringa in int ignora il prefisso:', int('0xaf', 16) ) print('e non è case-sensitive:', int('Af', 16) ) # %% # Le funzioni 'ord' e 'chr' convertono un carattere nel suo codice Unicode *DECIMALE* e viceversa. print( 'Il codice decimale non è (chiaramente) uguale a quello esadecimale, altrimenti il prossimo carattere sarebbe una A:' ) print( chr(41) ) print( 'Ma combinando chr ed int:' ) print( chr(int("41", 16)) ) # %% # Credo convenga caricare 'vettSpec' una volta per tutte invece che inserire il caricamento della tabella nella funzione: with open("vettSpec.csv", 'r') as file1: reader = csv.DictReader(file1) vettSpec = [row for row in reader] # %% # Una volta che uno ha vettSpec, la conversione *di un singolo carattere* si fa in 3 passaggi: def db_decode(string0): res = "" for char0 in string0: #1 char0Dec = ord(char0) # Dal carattere al codice Unicode DECIMALE corrispondente #2 char0ConvDec = next((el['unicode'] for el in vettSpec if el['intcode'] == str(char0Dec)), None) # Il codice DECIMALE (passato come stringa) viene ricercato in vettSpec, ritornando l'Unicode ESADECIMALE del carattere decriptato o None se non c'è riscontro -- il che non DOVREBBE succedere. #3 res += chr(int(char0ConvDec, 16)) # Si converte il codice esadecimale a decimale e si usa la built-in chr per recuperare il carattere return res def db_encode(string0): res = "" for char0 in string0: #1 char0Hex = hex(ord(char0)) # Dal carattere al codice Unicode ESADECIMALE corrispondente #2 char0ConvDec = next((el['intcode'] for el in vettSpec if el['unicode'] == char0Hex[2:].upper()), None) # Il codice ESADECIMALE, senza il prefisso '0x' (rimosso tramite [2:]) e convertito in maiuscole per rispettare il formato di vettSpec, viene ricercato in vettSpec, ritornando l'Unicode DECIMALE del carattere criptato o None se non c'è riscontro -- il che non DOVREBBE succedere. #3 res += chr(int(char0ConvDec)) # Si usa la built-in chr per recuperare il carattere return res # %% # Test: testEncrNorm = 'КѢӗГԂғМϩϩ' testEncrSpec = 'ГѢӗГԂғМϩϩ' testDecrNorm = db_decode(testEncrNorm) testDecrSpec = db_decode(testEncrSpec) print( testDecrNorm ) print( testDecrSpec ) print( db_encode(testDecrNorm) ) print( db_encode(testDecrSpec) ) # %% # Altri test: testdec = 'ӗЫГҨғϩҘМϩӲѢҨҘ' testenc = "recomandaţion" testdec2 = 'ӻ' testenc2 = "çà" print( db_decode(testdec) ) print( db_encode(testenc) ) print( db_decode(testdec2) ) print( db_encode(testenc2) ) # %% # La prova sui testi! # %% def GenerateKeyParam(sigla, parametersObj): vals = [] vals.append(parametersObj[sigla]['notea']) vals.append(parametersObj[sigla]['noteb']) vals.append(parametersObj[sigla]['notec']) partial = vals[0] + vals[1] keyLength = 50 + (vals[2] % 300) if (keyLength // 2) * 2 != keyLength: keyLength = keyLength + 1 seed = partial % (vals[2] + 123) return seed, keyLength # %% priva = {'p07': {'notea': 557968080, 'noteb': 8457403318, 'notec': 561881}} print( GenerateKeyParam('p07', priva) ) with open("key_p07.csv", 'r') as file1: aaa = csv.reader(file1) key_p07 = [int(val[0]) for val in aaa] with open('../../../db/ndg2.gat4/itxt/p07', 'rb') as file1: file1.seek(4) p07 = file1.read().decode(encoding="utf-32-le") # %% def code(char0, shift): return chr(ord(char0) + shift) def decodeText(text, key, startInFile): initialOffset = startInFile % len(key) res = "" for k, char0 in enumerate(text): offset = k + initialOffset if offset >= len(key): offset = offset % len(key) res += code(char0, -key[offset]) return res # %% p07micro = p07[:100] ii = 0 for char in p07micro: ii = ii+1 if ii>20: break print(ii, ord(char), char) # %% decodeText(p07micro, key_p07, 6) # %% def CifraS(stringa, StartInFile, key, verso): # Cifra o decifra una stringa # StartInFile = posizione, all'interno del testo cifrato, del primo carattere della stringa da cifrare (base 1) # stringa = stringa da cifrare o decifrare # verso = 1 => cifra; 2 => decifra # FirstInStringa = indice del primo byte considerato all'interno del vettore da decifrare # LastInStringa = indice dell'ultimo byte considerato all'interno del vettore da decifrare # PosizInKey = indice del primo carattere da utilizzare all'interno della chiave fissa NumCharsToConv = 0 LastInStringa = 0 LengKey2 = len(key) // 2 while LastInStringa < len(stringa): StartInFile = StartInFile + NumCharsToConv NumKeyAppl = 1 + (StartInFile - 1) // LengKey2 FirstInStringa = LastInStringa + 1 PosizInKey = StartInFile % LengKey2 if PosizInKey == 0: PosizInKey = LengKey2 MaxCharsToConv = len(key) - PosizInKey + 1 if MaxCharsToConv > LengKey2 - PosizInKey + 1: MaxCharsToConv = LengKey2 - PosizInKey + 1 NumCharsToConv = len(stringa) - FirstInStringa + 1 if NumCharsToConv > MaxCharsToConv: NumCharsToConv = MaxCharsToConv LastInStringa = FirstInStringa + NumCharsToConv - 1 for k in range(FirstInStringa - 1, LastInStringa): if verso == 1: stringa = stringa[:k] + chr(ord(stringa[k]) + key[PosizInKey-1]) + stringa[k+1:] else: stringa = stringa[:k] + chr(ord(stringa[k]) - key[PosizInKey-1]) + stringa[k+1:] print("Stringa: "+stringa) PosizInKey += 1 return stringa # %% CifraS(p07micro, 1, key_p07, 1) # %% ## ANCORA! ### # %% def code(char0, shift): return chr(ord(char0) + shift) def decodeText(text, key, startInFile): initialOffset = startInFile % len(key) res = "" for k, char0 in enumerate(text): offset = k + initialOffset if offset >= len(key): offset = offset % len(key) res += code(char0, -key[offset]) return res def CifraS(stringa, StartInFile, key, verso): # Cifra o decifra una stringa # StartInFile = posizione, all'interno del testo cifrato, del primo carattere della stringa da cifrare (base 1) # stringa = stringa da cifrare o decifrare # verso = 1 => cifra; 2 => decifra # FirstInStringa = indice del primo byte considerato all'interno del vettore da decifrare # LastInStringa = indice dell'ultimo byte considerato all'interno del vettore da decifrare # PosizInKey = indice del primo carattere da utilizzare all'interno della chiave fissa NumCharsToConv = 0 LastInStringa = 0 LengKey2 = len(key) // 2 while LastInStringa < len(stringa): StartInFile = StartInFile + NumCharsToConv #NumKeyAppl = 1 + (StartInFile - 1) // LengKey2 FirstInStringa = LastInStringa + 1 PosizInKey = StartInFile % LengKey2 if PosizInKey == 0: PosizInKey = LengKey2 MaxCharsToConv = len(key) - PosizInKey + 1 if MaxCharsToConv > LengKey2 - PosizInKey + 1: MaxCharsToConv = LengKey2 - PosizInKey + 1 NumCharsToConv = len(stringa) - FirstInStringa + 1 if NumCharsToConv > MaxCharsToConv: NumCharsToConv = MaxCharsToConv LastInStringa = FirstInStringa + NumCharsToConv - 1 for k in range(FirstInStringa - 1, LastInStringa): if verso == 1: stringa = stringa[:k] + chr(ord(stringa[k]) + key[PosizInKey-1]) + stringa[k+1:] else: stringa = stringa[:k] + chr(ord(stringa[k]) - key[PosizInKey-1]) + stringa[k+1:] #print("Stringa: "+stringa) PosizInKey += 1 return stringa # %% # Tira fuori la chiave A FORZA! with open('../../../db/ndg2.gat4/itxt/p07', 'rb') as file1: file1.seek(4) p07_enc = file1.read().decode(encoding="utf-32-le") with open('../../../db/first_db/itxt/p07', 'rb') as file1: file1.seek(4) p07_dec = file1.read().decode(encoding="utf-32-le") # %% # Stesso testo? Check lunghezza! len(p07_enc)==len(p07_dec) # %% ii = 0 for char in p07_dec[:1000]: ii = ii+1 if ii>20: break print(ii, ord(char), char) caz_dec = [ord(char) for char in p07_dec[:1000]] caz_enc = [ord(char) for char in p07_enc[:1000]] # %% appela = [] for i in range(len(caz_dec)): appela.append(caz_enc[i] - caz_dec[i]) # %% with open('matto.csv', 'w') as file1: wtr = csv.writer(file1) for row in appela: wtr.writerow([row]) # %% affa = appela[:332] nculo = appela[332:664] # %% affa == nculo # %% min(appela) # %% with open('furioso.csv', 'w') as file1: wtr = csv.writer(file1) for row in appela[:332]: wtr.writerow([row]) # %% # Ok, 'furioso.csv' è -- sperabilmente -- la chiave # Riapro furioso with open('furioso.csv', 'r') as file1: rdr = csv.reader(file1) affa2 = [int(row[0]) for row in rdr] # %% decodeText(p07_enc[:100], affa2, 0) # %% chiaro = decodeText(p07_enc, affa2, 0) print(chiaro) # %% CifraS(p07_enc[:100], 1, affa2, 2) == decodeText(p07_enc[:100], affa2, 0) # ... e funziona! # %% ''' Programmino in VB che DOVREBBE tirar fuori la chiave (è copiato praticamente verbatim da GeneraKey di Gatto4), ma non lo fa -- differenza di implementazione di Rnd? Altro? Module VBModule Sub Main() Dim k, a, dato, iniziale, valore(3) As Integer Dim LengKey, KeyBody() as Integer valore(1) = 557968080 valore(2) = 845740318 valore(3) = 561881 dato = valore(1) + valore(2) LengKey = 50 + (valore(3) Mod (300)) If (LengKey \ 2) * 2 <> LengKey Then LengKey = LengKey + 1 ReDim KeyBody(LengKey) iniziale = dato Mod (valore(3) + 123) a = Rnd(-1) Randomize(iniziale) Console.WriteLine("Iniziale: " + Str(iniziale)) Console.WriteLine("Lunghezza chiave: " + Str(LengKey)) For k = 1 To LengKey KeyBody(k) = 1000 * Rnd() Console.WriteLine(Str(k) + ": " + Str(KeyBody(k))) Next k End Sub End Module ''' # %% # Un esperimento aVB = 1140671485 cVB = 12820163 mVB = 2**24 aMS = 214013 cMS = 2531011 mMS = 2**31 class randomLCG: def __init__(self, a=134775813, c=1, m=2**32, seed=0): self.seed = seed self._initial_seed = seed self.a = a self.c = c self.m = m def random(self): pre = (self.a*self.seed + self.c) % self.m self.seed = pre return pre/self.m def setSeed(self, seed): self.seef = seed def reset(self): self.seed = self._initial_seed # %% seed0 = 384410 rnd1 = randomLCG(seed=seed0) rnd2 = randomLCG(aVB, cVB, mVB, seed0+327680) rnd3 = randomLCG(aMS, cMS, mMS, seed=seed0) # %% rnd1.reset() for ind in range(4): print( round(1000*rnd1.random()) ) # %% rnd2.reset() for ind in range(4): print( round(1000*rnd2.random()) ) # %% rnd3.reset() for ind in range(4): print( round(1000*rnd3.random()) ) # %% # THE LAST TEST import csv def getKeyByCode(keyFile): with open(keyFile, 'r') as file1: reader = csv.reader(file1) key = [int(row[0]) for index, row in enumerate(reader) if index>1] # Apparently, only the first half of the key is actually used! halfKeyLen = len(key)//2 key=key[:halfKeyLen] return key def decodeTextByKey(text, key, startInFile): initialOffset = startInFile % len(key) res = "" for k, char0 in enumerate(text): offset = k + initialOffset if offset >= len(key): offset = offset % len(key) try: res += shiftchar(char0, -key[offset]) except: res+=' -- Error in key!' break return res # def codeTextByKey(text, key, startInFile): initialOffset = startInFile % len(key) res = "" for k, char0 in enumerate(text): offset = k + initialOffset if offset >= len(key): offset = offset % len(key) try: res += shiftchar(char0, +key[offset]) except: res+=' -- Error in key!' break return res # def shiftchar(char0, shift): return chr(ord(char0) + shift) # %% from os import listdir keyPath = 'keys/' itxtPath = '../../../db/ndg2.gat4/itxt/' files = listdir(keyPath) keyFiles = [file for file in files if (file.startswith('key_') and file.endswith('.csv'))] keys = {} files = {} for keyFile in keyFiles: code = keyFile.replace('key_', '').replace('.csv', '') try: keys[code] = getKeyByCode(keyPath+keyFile) with open('../../../db/ndg2.gat4/itxt/'+code, 'rb') as file1: file1.seek(4) files[code] = file1.read().decode(encoding="utf-32-le") except: pass # codes = keys.keys() # %% import random decoded = {} for ind, code in enumerate(codes): rand1 = random.randint(1, 15) rand2 = random.randint(1, 15)+500 decoded[code] = decodeTextByKey(files[code][rand1:rand2], keys[code], rand1) print(ind, code) print(decoded[code]) print() # %% codes # %% decoded['fq'] # %%