Kryptografia w javie - Pomoc

0

Witam, mam takie zadanie do zrobienia i nie mam bladego pojęcia jak się za nie zabrać. Chciałem napisać to w Javie, jako, że najlepiej ją ogarniam choć wiem , że jest wolna. Może ktoś z was jest w stanie naprowadzić mnie lub podesłać linki gdzie mogę znaleźć wskazówki do zrobienia zadania?

Podany kryptogram został wygenerowany za pomocą szyfru AES z kluczem
o długości n = 256-bitów, w trybie CBC. Napisz program, który przeszukuje całą przestrzeń
kluczy i deszyfruje podany kryptogram.
Klucz został wygenerowany w następujący sposób (NIGDY tak nie generuj kluczy!):
jest wynikiem obcięcia (do pierwszych 16 znaków) ciągu będącego hashem pewnej wartości
key ← SHA256(sekret).substr(0, 16).

Jako dane dla Twojego programu otrzymujesz:

• kryptogram,
• użyte IV,
• k2 będące sufiksem key (tj. key = k1k2 – key jest konkatenacją k1 i k2),
• określenie podprzestrzeni kluczy k1, które mają zostać sprawdzone.

0

jest wolna

Mało wiesz, bo to akurat jeden z najszybszych języków na rynku.

  1. W pythonie byłoby to łatwiej napisać, to będzie raptem kilka linijek kodu. W javie będzie to znacznie bardziej skomplikowane.
  2. Brakuje tutaj jakiejś informacji o plaintexcie żeby łatwo rozpoznać czy trafiliśmy z kluczem czy nie (np. jak na CTFach gdzie wiadomo że plaintext zaczyna się od jakiegos prefixu)
  3. Nie bardzo rozumiem czego ci brakuje. Zadanie jest opisane tak łopatologicznie że już bardziej się chyba nie da?
secret = random_string()
key = sha256(secret).substr(0, 16)
if key ends with k2:
  plaintext = aes.decode(ciphertext, iv, key)
  if plaintext is correct:
    print plaintext
    print key
0

Mam tylko podane:
sufiks klucza (56znaków)
iv(nie mam pojęcia co to jest, jakbyś mógł wytłumaczyć byłbym wdzięczny)
kryptogram
Dane wejściowe w postaci binarnej

Jakieś podpowiedzi jak to zrobić? Jak już nie w javie to w pythonie?

Dzięki z góry za pomoc:)

1
  1. Treść którą podałeś jest niespójna. Najpierw masz że klucz 256 bitów czyli 32 bajty, a potem że key jednak jest obcięty do 16 bajtów za pomocą substr. Więc ile ma ten klucz faktycznie?
  2. Napisałem ci wyżej w zasadzie cały kod potrzebny do tego zadania, bo generalnie jest trywialne.
  3. IV to wektor inicjalizacyjny. Tryb szyfrowania CBC charakteryzuje sie tym, ze każdy blok przed szyfrowaniem jest xorowany z zaszyfrowanym blokiem poprzednim. Pierwszy blok oczywiscie nie może, bo nie istnieje dla niego "poprzedni blok" więc zamiast niego używa się IV.
  4. Sufiks klucza nie może mieć 56 bajtów ;] bo sam klucz tyle nie ma...
0

Tak wygląda treść zadania:

[5 pkt.] znajdz klucz, a następnie zdeszyfruj kryptogram. Sufiks klucza to: 5382a21fb0d6c26bc65c24409bbbba23ff3a4b5168e57673df8e478e (długości: 56):

iv: 6fb94c522621eaf0ba5eb5a6a5f6bc2a

kryptogram: zhctBwuKMkgJomi7ZjAefMqgsA6NRYqo6L3N13uEhN0CJaYio2SDvLLptS+clRO8plU9rSMAXF3B3c4yyvOf+QkfqcO5yoxzE7k5O0Y4psJX7KR+h15FjKt2kVCyy1QrRFL9JrCWTQT/kooTDnbgOimiYpYnsnz+wXS7Rcyn9k13AYSkchsRjKThKAMWL+1qAYxpky0hpusDU/SHFOnkIh1cABItFdr6RbAlQYOZb1EPig7H341f7pnLReTfgWWw

11001110 00010111 00101101 00000111 00001011 10001010 00110010 01001000 00001001 10100010 01101000 10111011 01100110 00110000 00011110 01111100 11001010 10100000 10110000 00001110 10001101 01000101 10001010 10101000 11101000 10111101 11001101 11010111 01111011 10000100 10000100 11011101 00000010 00100101 10100110 00100010 10100011 01100100 10000011 10111100 10110010 11101001 10110101 00101111 10011100 10010101 00010011 10111100 10100110 01010101 00111101 10101101 00100011 00000000 01011100 01011101 11000001 11011101 11001110 00110010 11001010 11110011 10011111 11111001 00001001 00011111 10101001 11000011 10111001 11001010 10001100 01110011 00010011 10111001 00111001 00111011 01000110 00111000 10100110 11000010 01010111 11101100 10100100 01111110 10000111 01011110 01000101 10001100 10101011 01110110 10010001 01010000 10110010 11001011 01010100 00101011 01000100 01010010 11111101 00100110 10110000 10010110 01001101 00000100 11111111 10010010 10001010 00010011 00001110 01110110 11100000 00111010 00101001 10100010 01100010 10010110 00100111 10110010 01111100 11111110 11000001 01110100 10111011 01000101 11001100 10100111 11110110 01001101 01110111 00000001 10000100 10100100 01110010 00011011 00010001 10001100 10100100 11100001 00101000 00000011 00010110 00101111 11101101 01101010 00000001 10001100 01101001 10010011 00101101 00100001 10100110 11101011 00000011 01010011 11110100 10000111 00010100 11101001 11100100 00100010 00011101 01011100 00000000 00010010 00101101 00010101 11011010 11111010 01000101 10110000 00100101 01000001 10000011 10011001 01101111 01010001 00001111 10001010 00001110 11000111 11011111 10001101 01011111 11101110 10011001 11001011 01000101 11100100 11011111 10000001 01100101 10110000

0

No ok, ale w takim razie WTF z tym obcięciem klucza? Jak dla mnie treść jest dość jasna teraz -> masz podany suffix 28 bajtowy dla SHA256, czyli efektywnie brakuje ci tylko 4 bajtów tego SHA żeby odzyskać cały klucz. Ja bym w takim razie brutował po prostu te 4 brakujące bajty i liczył na to, że plaintext ma padding PKCS7 i na tej podstawie można rozpoznać poprawne deszyfrowanie.

Ale mimo wszystko ja bym jednak dopytał czy o to chodzi, bo treść jest niespójna.

Zakładajac że klucz ma jednak 32 bajty a to co masz podane to jego suffix to kod wyglądałby mniej więcej tak:

import base64
import itertools
import string
from Crypto.Cipher import AES


def main():
    IV = '6fb94c522621eaf0ba5eb5a6a5f6bc2a'.decode("hex")
    ct = base64.b64decode(
        "zhctBwuKMkgJomi7ZjAefMqgsA6NRYqo6L3N13uEhN0CJaYio2SDvLLptS+clRO8plU9rSMAXF3B3c4yyvOf+QkfqcO5yoxzE7k5O0Y4psJX7KR+h15FjKt2kVCyy1QrRFL9JrCWTQT/kooTDnbgOimiYpYnsnz+wXS7Rcyn9k13AYSkchsRjKThKAMWL+1qAYxpky0hpusDU/SHFOnkIh1cABItFdr6RbAlQYOZb1EPig7H341f7pnLReTfgWWw")
    suffix = '5382a21fb0d6c26bc65c24409bbbba23ff3a4b5168e57673df8e478e'
    for prefix in itertools.product(string.hexdigits, repeat=8):
        key = ("".join(prefix) + suffix).decode("hex")
        decryptor = AES.new(key, AES.MODE_CBC, IV)
        pt = decryptor.decrypt(ct)
        if all(c in string.printable for c in pt[:16]):
            print(key.encode("hex"), pt)


main()

Przy założeniu że pierwsze 16 bajtów odszyfrowanej wiadomości to są normalne drukowalne znaki.

0

Oki program śmiga lecz nie wiem do końca czy zwróci mi dobry wynik. Mam coś takiego:

 if (Pattern.matches("[\\p{ASCII}\\p{IsLatin}]*", plain)) {
                                            System.out.println(testKey + "\t" + plain);
                                            writer.println(testKey + "\t" + plain);
                                            writer.flush();
                                        }

Chce sprawdzić czy zwrócony wynik jest w zakresie ASCII lub Latina. Ale przeszukałem plik który mi zwrócił i na razie, są tam same jakieś krzaczki, zamiast zdań. Czy ma ktoś pomysł jak zawęzić poszukiwania aby tych wyników nie bylo około 1000??

0

O to powinieneś zapytać autora zadania, bo to nie problem brutować te kilka bajtów, ale potem wybrać poprawne rozwiązanie. Poza tym dopytaj jak to jest z tym kluczem, bo może ten kod brutuje nie to co trzeba ;]

1 użytkowników online, w tym zalogowanych: 0, gości: 1