• Najnowsze pytania
  • Bez odpowiedzi
  • Zadaj pytanie
  • Kategorie
  • Tagi
  • Zdobyte punkty
  • Ekipa ninja
  • IRC
  • FAQ
  • Regulamin
  • Książki warte uwagi

Pomoc z funkcją ataku na szyfr

0 głosów
96 wizyt
pytanie zadane 13 września 2020 w Python przez saseta00 Użytkownik (700 p.)

Cześć,

Mam problem z dokończeniem zadania w postaci programu, a mianowicie funkcji BFattackSubst tak aby generowała wszystkie możliwe klucze dla danego przedziału. Całość opiera się o Szyfr Nieregularnej transpozycji (https://mattomatti.com/pl/a35ad). Mógłby ktoś nakierunkować jak się za to zabrać i co wymaga poprawy? Ewentualnie jeśli ktoś byłby chętny napisać funkcję odpłatnie to również byłbym zainteresowany. Dziękuje za każdą pomoc i pozdrawiam. 

def createKey(key):
    dl = len(key)
    values = []
    for i in range(dl):
        values.append(2*int(key[i])+1)
    # print(values)
    return values

def encrypt(txt, vcode):
    txt_dl = len(txt)
    dl = 0  # ile liter mieści tabelka
    k = 0  # ile kolumn ma tabelka
    while dl < txt_dl:
        dl += vcode[k % len(vcode)]
        k += 1

    # print("txt_dl:", txt_dl)
    # print("dl:", dl)
    # print("k", k)

    table = []  # indeksy pierwszych znaków w każdej kolumnie
    table.append(0)
    for j in range(1, k):
        table.append(table[j - 1] + vcode[(j - 1) % len(vcode)])

    # print("table:", table)

    wynik = []
    maxkol = max(vcode)
    maxkol = int((maxkol - 1) / 2)

    # print("maxkol:", maxkol)

    zapis = 0  # ile znakow zostalo zapisane
    for j in range(maxkol, -maxkol-1, -1):
        # print("J:",j)
        for i in range(k):
            # print("I:",i)
            if((vcode[i % len(vcode)] - 1) / 2 >= abs(j)):
                # print("zapis:",zapis)
                # print("table[i]:",table[i])
                if table[i] >= txt_dl:
                    wynik.append("_")
                else:
                    wynik.append(txt[table[i]])
                zapis += 1
                table[i] += 1
    return "".join(wynik)

def decrypt(txt, vcode):
    txt_dl = len(txt)
    dl = 0  # ile liter mieści tabelka
    k = 0  # ile kolumn ma tabelka
    while (dl < txt_dl):
        dl += vcode[k % len(vcode)]
        k += 1

    # print("txt_dl:", txt_dl)
    # print("dl:", dl)
    # print("k", k)

    maxtab = max(vcode)
    table = []
    table.append(0)
    maxtab = int((maxtab - 1) / 2)

    for j in range(maxtab-1, -maxtab-1, -1):
        # print("J:", j)
        table.append(table[- j + maxtab - 1])
        for i in range(k):
            if((vcode[i % len(vcode)] - 1) / 2 >= abs(j + 1)):
                table[- j + maxtab] += 1
    print("TABLE:",table)
    wynik = []
    zapis = 0

    for i in range(k):
        for j in range(int(-(vcode[i % len(vcode)] - 1) / 2), int((vcode[i % len(vcode)] - 1) / 2 + 1)):
            print("I/J/litera",i,j,txt[table[j + maxtab]])
            wynik.append(txt[table[j + maxtab]])
            zapis += 1
            table[j + maxtab]+=1
    return "".join(wynik)

code = '021'
txt = 'TAJNA INFORMACJA'

vcode = createKey(code)
enctxt = encrypt(txt, vcode)
dectxt = decrypt(enctxt, vcode)

print("vcode:", vcode)
print("ENCRYPTED:", enctxt)
print("DECRYPTED:", dectxt)

#  zamiast listy ciag znakow

"""
klucz '021'
 A  R
 JI MA
TNNOA_
 AF C_
    J
ARJIMATNNOA_AFC_ J

dzielniki 18:
1('0'),2('00'),3('1' lub '000'),
6('0100' lub '11' lub '1000' lub '02' lub '20' itp),
9('102' lub '021' lub '0101' itp )

lub (zręczniej w postaci 'vcode'):
1( [1] ), 2( [1,1] ),  3 ( [3] lub [1,1,1] ),
6( [1,3,1,1] lub [3,3] lub [3,1,1,1] lub [1,5] lub [5,1] itp),
9( [3,1,5] lub [1,5,3] lub [1,3,1,3] itp )
"""

"""
Co jeszcze da się zrobić w miarę szybko:
implementować (w rozsądny sposób) atak BruteForcem
z ograniczeniem rozmiaru (ilością komórek) bloku dla szyfrowania (który zadajemy
ciągami cyfr rodzaju '021' lub [1,5,3]) liczbą 10.

Niżej podano przykładową funkcję, generującą wszystkie możliwe klucze
określonego rozmiaru. Z testowania (patrz niżej) wynika, że zaczynając
od rozmiaru bloku 11 BruteForce jest zbyt wolny.
Więc ograniczymy się krótkimi kluczami (dla dłuższych już jest niezbędnym
używanie bardziej zaawansowanych metod, którę już nie zdążycie realizować).

Funkcję 'FindAddons' podaję z tego powodu, że ona zawiera wyłącznie
obliczeniową logikę. A lepiej, jeśli skupicie się na częściach zadania,
bardziej powiązanych z kryptografią.

Co jeszcze pozostało zrobić:
- używając tą funkcję napisać podstawowy 'BruteForce' (sprawdzenie wszystkich
możliwych kluczy, zaczynając od najmniejszego rozmiaru i do 10);
- możliwe rozmiary muszą być dzielnikami długości kryptotekstu;
- w sposób identyczny do przykłądowych
programów ( w plikach w Teams pod numerami 3,4,5,6) dostosować użycie
modułu 'ngram' (i funkcji 'score' z niego) do automatyzowanego sprawdzenia
'czytelności' tekstów, które otrzymujemy po deszyfrowaniu _kryptotekstu_
za pomocą kolejnego klucza. Ta funkcją zwraca ujemne liczby,
czym większa liczba (albo czym mniejsza za modułem) - tym bardziej
prawdopodobne, że otrzymany tekst będzie czytelny. Pliki danych (rodzaju
'english_bigrams.txt' lub 'english_quadgrams.txt') stworzone dla
literackiego angielskiego języka, w którym litery są przekształcone do dużych,
a spację i wszystkie znaki interpunkcyjne są usunięte.

Tzn. tekst(y),
na którym(/których) trzeba testować program, muszą spełniać powyższe warunki.
Pomiędzy innym, to znaczy jeszcze to, że te znaki '_', którę generuję
funkcją deszyfrowania, trzeba usuwać.
"""

from itertools import combinations_with_replacement
from itertools import permutations
import time
import string
import random
import math
from ngram import Ngram_score
# combinations_with_replacement('ABCD', 2)

# n - sum,  returns list of possible lists of elements [1,3,5...] with sum = n
def FindAddons( n ):
    if n % 2 == 0 :
        AddonsNumbers = [ 2*i for i in range( 1, n // 2 +1 ) ]
    else:
        AddonsNumbers = [ 2*i+1 for i in range( (n+1)//2) ]

    lstN = [ 2*i+1 for i in range( (n+1) // 2 ) ]

    Addons1 = []
    sm = 0
    for i in AddonsNumbers :
        for j in combinations_with_replacement( lstN, i ):
            if sum(j) == n:
                Addons1.append( j )
    #print(Addons1)

    Addons2 = []
    for x in Addons1:
        for y in permutations(x):
            #if y not in Addons2 :
            Addons2.append( y )
    #print(Addons2)

    Addons3 = list( set( Addons2) )

    return( [ list( Addons3[i] ) for i in range(len(Addons3)) ] )

def TimeTest():
    for n in range(12):
        t1 = time.time()
        print('n = ', n, '  len(FindAddons(n)) = ', len(FindAddons(n)) )
        print('... time elapsed: ', time.time()-t1,' seconds')
    return()
"""
n =  0   len(FindAddons(n)) =  0
... time elapsed:  0.05337238311767578  seconds
n =  1   len(FindAddons(n)) =  1
... time elapsed:  0.031244754791259766  seconds
n =  2   len(FindAddons(n)) =  1
... time elapsed:  0.015619993209838867  seconds
n =  3   len(FindAddons(n)) =  2
... time elapsed:  0.015590667724609375  seconds
n =  4   len(FindAddons(n)) =  3
... time elapsed:  0.015619754791259766  seconds
n =  5   len(FindAddons(n)) =  5
... time elapsed:  0.015618324279785156  seconds
n =  6   len(FindAddons(n)) =  8
... time elapsed:  0.015624523162841797  seconds
n =  7   len(FindAddons(n)) =  13
... time elapsed:  0.022132396697998047  seconds
n =  8   len(FindAddons(n)) =  21
... time elapsed:  0.04686403274536133  seconds
n =  9   len(FindAddons(n)) =  34
... time elapsed:  0.2372438907623291  seconds
n =  10   len(FindAddons(n)) =  55
... time elapsed:  1.3357844352722168  seconds
n =  11   len(FindAddons(n)) =  89
... time elapsed:  42.12555551528931  seconds
"""

import string
import random
import time
import math
from ngram import Ngram_score

text = "TAJNA INFORMACJA__"
tj = text.upper().replace(" ", "").replace("_", "").replace("1", "").replace("(", "").replace(")", "").replace(".", "").replace(",","").replace("!", "").replace("?", "").replace("-", "")
alfabet = 'ABCDEFGHIJKLMNOPQRSTUVWXYZ'

ns = Ngram_score('english_bigrams.txt')

def BFattackSubst(C):

    lista = []

    t2 = time.time()
    for i in range(26):
        t2 = encrypt(C, i)
        lista += [[ns.score(t2), t2]]

    lista.sort()
    lista.reverse()
    print ('zatracono: ', time.time()-t1, 'sekund')
    return lista[:1]

ct = encrypt(tj, 3)

print(BFattackSubst(ct))

 

Zaloguj lub zarejestruj się, aby odpowiedzieć na to pytanie.

Podobne pytania

+1 głos
0 odpowiedzi 1,792 wizyt
pytanie zadane 23 listopada 2019 w Python przez Nieprofesjonalny Użytkownik (890 p.)
+1 głos
2 odpowiedzi 917 wizyt
pytanie zadane 1 marca 2017 w C i C++ przez Krystek102 Bywalec (2,440 p.)
0 głosów
2 odpowiedzi 499 wizyt
pytanie zadane 26 lutego 2016 w C i C++ przez rafalmagician Obywatel (1,290 p.)

87,940 zapytań

136,519 odpowiedzi

304,383 komentarzy

58,305 pasjonatów

Motyw:

Akcja Pajacyk

Pajacyk od wielu lat dożywia dzieci. Pomóż klikając w zielony brzuszek na stronie. Dziękujemy! ♡

Sklep oferujący ćwiczenia JavaScript, PHP, rozmowy rekrutacyjne dla programistów i inne materiały

Oto dwie polecane książki warte uwagi. Pełną listę znajdziesz tutaj.

...