Biorę udział w kursie dotyczącym kryptografii i utknąłem na zleceniu. Instrukcje są w następujący sposób:Brutowe zmuszanie DES ze słabym kluczem
tekstu jawnego plain6.txt został zaszyfrowany za pomocą algorytmu DES do encrypt6.dat użyciu klucza 64-bitowego podane jako ciąg 8 znaków (64 bitów, z których każdy 8-cie bit jest ignorowany), wszystkie znaki to litery (małe litery lub wielkie litery) oraz cyfry (od 0 do 9).
Aby wykonać zadanie, wyślij mi klucz szyfrowania przed 12 lutego, 29,59.
Uwaga: Oczekuję uzyskania klucza 8-bajtowego (64-bitowego). Każdy bajt powinien być zbieżny z odpowiednim bajtem w moim kluczu, z wyjątkiem najmniejszego znaczącego bitu o wartości , który nie jest używany w DES, a zatem może być arbitralny.
Oto kod do mojej pierwszej próbie w Pythonie:
import time
from Crypto.Cipher import DES
class BreakDES(object):
def __init__(self, file, passwordLength = 8, testLength = 8):
self.file = file
self.passwordLength = passwordLength
self.testLength = testLength
self.EncryptedFile = open(file + '.des')
self.DecryptedFile = open(file + '.txt')
self.encryptedChunk = self.EncryptedFile.read(self.testLength)
self.decryptedChunk = self.DecryptedFile.read(self.testLength)
self.start = time.time()
self.counter = 0
self.chars = range(48, 58) + range(65, 91) + range(97, 123)
self.key = False
self.broken = False
self.testPasswords(passwordLength, 0, '')
if not self.broken:
print "Password not found."
duration = time.time() - self.start
print "Brute force took %.2f" % duration
print "Tested %.2f per second" % (self.counter/duration)
def decrypt(self):
des = DES.new(self.key.decode('hex'))
if des.decrypt(self.encryptedChunk) == self.decryptedChunk:
self.broken = True
print "Password found: 0x%s" % self.key
self.counter += 1
def testPasswords(self, width, position, baseString):
for char in self.chars:
if(not self.broken):
if position < width:
self.testPasswords(width, position + 1, baseString + "%c" % char)
self.key = (baseString + "%c" % char).encode('hex').zfill(16)
self.decrypt()
# run it for password length 4
BreakDES("test3", 4)
jestem coraz prędkość 60.000 stara/sekundę. Hasło 8 bajtów na 62 znaki daje 13 trylionów możliwości, co oznacza, że przy tej prędkości rozwiązywanie będzie wymagało 130 lat. Wiem, że to nie jest wydajna implementacja i że mogę uzyskać lepsze prędkości w szybszym języku, takim jak C lub jego smaki, ale nigdy w nich nie zaprogramowałem. Nawet jeśli otrzymam przyspieszenie o wartości 10, wciąż jesteśmy ogromnym skokiem z 10 000 000 000 na sekundę, aby uzyskać zakres godzin.
Czego mi brakuje? To ma być słaby klucz :). Cóż, słabszy niż pełny zestaw 256 znaków.
EDIT
Ze względu na pewne niejasności dotyczące cesji, tutaj jest pełny opis i niektóre pliki testowe do kalibracji: http://users.abo.fi/ipetre/crypto/assignment6.html
EDIT 2
Jest to realizacja surowej C to daje około 2.000.000 haseł/s na rdzeń na i7 2600K. Musisz określić pierwszy znak hasła i możesz ręcznie uruchomić wiele instancji na różnych rdzeniach/komputerach. Udało mi się rozwiązać problem za pomocą tego w ciągu kilku godzin na czterech komputerach.
#include <stdio.h> /* fprintf */
#include <stdlib.h> /* malloc, free, exit */
#include <unistd.h>
#include <string.h> /* strerror */
#include <signal.h>
#include <openssl/des.h>
static long long unsigned nrkeys = 0; // performance counter
char *
Encrypt(char *Key, char *Msg, int size)
{
static char* Res;
free(Res);
int n=0;
DES_cblock Key2;
DES_key_schedule schedule;
Res = (char *) malloc(size);
/* Prepare the key for use with DES_ecb_encrypt */
memcpy(Key2, Key,8);
DES_set_odd_parity(&Key2);
DES_set_key_checked(&Key2, &schedule);
/* Encryption occurs here */
DES_ecb_encrypt((unsigned char (*) [8]) Msg, (unsigned char (*) [8]) Res,
&schedule, DES_ENCRYPT);
return (Res);
}
char *
Decrypt(char *Key, char *Msg, int size)
{
static char* Res;
free(Res);
int n=0;
DES_cblock Key2;
DES_key_schedule schedule;
Res = (char *) malloc(size);
/* Prepare the key for use with DES_ecb_encrypt */
memcpy(Key2, Key,8);
DES_set_odd_parity(&Key2);
DES_set_key_checked(&Key2, &schedule);
/* Decryption occurs here */
DES_ecb_encrypt((unsigned char (*) [8]) Msg, (unsigned char (*) [8]) Res,
&schedule, DES_DECRYPT);
return (Res);
}
void ex_program(int sig);
int main(int argc, char *argv[])
{
(void) signal(SIGINT, ex_program);
if (argc != 4) /* argc should be 2 for correct execution */
{
printf("Usage: %s ciphertext plaintext keyspace \n", argv[0]);
exit(1);
}
FILE *f, *g;
int counter, i, prime = 0, len = 8;
char cbuff[8], mbuff[8];
char letters[] = "02468ACEGIKMOQSUWYacegikmoqsuwy";
int nbletters = sizeof(letters)-1;
int entry[len];
char *password, *decrypted, *plain;
if(atoi(argv[3]) > nbletters-2) {
printf("The range must be between 0-%d\n", nbletters-2);
exit(1);
}
prime = atoi(argv[1])
// read first 8 bytes of the encrypted file
f = fopen(argv[1], "rb");
if(!f) {
printf("Unable to open the file\n");
return 1;
}
for (counter = 0; counter < 8; counter ++) cbuff[counter] = fgetc(f);
fclose(f);
// read first 8 bytes of the plaintext file
g = fopen(argv[2], "r");
if(!f) {
printf("Unable to open the file\n");
return 1;
}
for (counter = 0; counter < 8; counter ++) mbuff[counter] = fgetc(g);
fclose(g);
plain = malloc(8);
memcpy(plain, mbuff, 8);
// fill the keys
for(i=0 ; i<len ; i++) entry[i] = 0;
entry[len-1] = prime;
// loop until the length is reached
do {
password = malloc(8);
decrypted = malloc(8);
// build the pasword
for(i=0 ; i<len ; i++) password[i] = letters[entry[i]];
nrkeys++;
// end of range and notices
if(nrkeys % 10000000 == 0) {
printf("Current key: %s\n", password);
printf("End of range ");
for(i=0; i<len; i++) putchar(letters[lastKey[i]]);
putchar('\n');
}
// decrypt
memcpy(decrypted,Decrypt(password,cbuff,8), 8);
// compare the decrypted with the mbuff
// if they are equal, exit the loop, we have the password
if (strcmp(mbuff, decrypted) == 0)
{
printf("We've got it! The key is: %s\n", password);
printf("%lld keys searched\n", nrkeys);
exit(0);
}
free(password);
free(decrypted);
// spin up key until it overflows
for(i=0 ; i<len && ++entry[i] == nbletters; i++) entry[i] = 0;
} while(i<len);
return 0;
}
void ex_program(int sig) {
printf("\n\nProgram terminated %lld keys searched.\n", nrkeys);
(void) signal(SIGINT, SIG_DFL);
exit(0);
}
Może przeczytać o strukturze DES. Istnieją exploity oparte na tym, w jaki sposób informacje propagowane są za pomocą karnetów. – Marcin
Bravo za nie czekanie aż do poprzedniej nocy. – roken
Jeśli masz pieniądze leżące w pobliżu i naprawdę chcesz to brutalnie wymóc, zastanów się, że możesz utworzyć 10^16 zadań amazon ec2, z których każda po prostu szyfruje dany tekst jawny za pomocą przydzielonego klucza. – Marcin