123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462 |
- # %%
- 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']
- # %%
|