2016-04-10 10 views
-1

Der Entschlüsselungs- und Verschlüsselungscode (im Folgenden enthalten) ist möglicherweise falsch. Sie kompilieren fehlerfrei, jedoch ist die entschlüsselte Datei nicht die gleiche wie die Klartextdatei. Es ist verstümmelt.(Sprache C) Verstümmelte Entschlüsselung im AES-CTR-basierten Verschlüsselungsentschlüsselungstool

Ich versuche herauszufinden, warum es verstümmelt ist. Ich bezweifle, dass mein Code in Ordnung ist.

Ich habe eine Reihe von Dingen, die möglicherweise das Problem lösen könnten, aber keiner funktionierte. Ich habe eine bestimmte Art der Verwendung von AES-CTR, d. H. Ich schließe nicht direkt OpenSSL ein. Ich bin abhängig von /dev/urandom/dev/random für Zufälligkeit (von IV, et cetera).

Die Menge Dinge beinhaltet die Art, wie ich mit meinem encrypt befasse und entschlüsseln Funktion (wie: *(ptr) statt ptr[] und mehrere anderen gleichwertigen Ersatz verwenden, die in der Regel nicht notwendig sind), welche Argumente ich vorbei und Kontrolle für bestimmte Validierungen bevor Sie schließlich die verschlüsselten oder entschlüsselten Texte speichern.

Ich werde die initialisierte IV nicht erhöhen (oder ändern). IV ist 16 Bytes.

Früher, ich tat dies das letzte Byte von IV zu erhöhen:

size_t blocksize = CCA_STRENGTH; /* CCA_STRENGTH is "#define CCA_STRENGTH 16" */ 
char *iv = (char *) malloc(16 * sizeof(char)); 
ri(); /* PRNG initialized.*/ 
prng_getbytes(iv, blocksize); 
* 
* 
* 
* 
size_t iv_counter = 0; 
while loop starts here... 
* 
* 
*(iv +(block_size - 1)) += iv_counter; 
* 
* 
while loop ends here... 

Diese while-Schleife, wo die Verschlüsselung und Entschlüsselung geschieht vorhanden ist unten (dieser Teil vorübergehend, da es eine Sicherheit entfernt wird Anforderung und nicht ein Kodierungsstandard oder die Anforderung der Entschlüsselungs- oder Entschlüsselungsfunktion).

Hier ist meine Entschlüsseln Code:

#include "pv.h" 

void decrypt_file (const char *ptxt_fname, void *raw_sk, size_t raw_len, int fin) 
{ 
    int fd; 
    if((fd = open(ptxt_fname, O_RDWR | O_CREAT | O_EXCL, 0600)) < 0) 
     { 
      /*fd will become -1 on failure.*/ 
      perror("plaintext file permission error\n"); 
      exit(EXIT_FAILURE); 
      } 

    size_t block_size = CCA_STRENGTH; 

    const char *aes_key; 
    aes_key = (const char *) raw_sk; 
    aes_ctx aes; 

    aes_setkey(&aes, aes_key, block_size); 
    char *iv; 
    iv = (char *) malloc(block_size * sizeof(char)); 
    size_t bytes_read; 
    bytes_read = read(fin, iv, block_size); 

    char *buf = (char *) malloc(block_size * sizeof(char)); /*ctxt-file read buffer*/ 
    char *ptxt = (char *) malloc(block_size * sizeof(char)); /*p-text buffer*/ 
    memset(ptxt, 0, block_size); 

    bytes_read = read(fin, buf, block_size); 

     while(bytes_read >= 1) 
    { 

     aes_encrypt(&aes, ptxt, iv); /* earlier it was "aes_decrypt(&aes, ptxt, iv);" which was not the correct reverse transformation function */ 
     for(loop_variable = 0; loop_variable < bytes_read; loop_variable++) 
     { 
      *(ptxt + loop_variable) = *(ptxt + loop_variable)^*(buf + loop_variable); 
     } 

     if((result = write_chunk(fd, ptxt, bytes_read)) == -1) 
     { 
      perror("Problem when writing to ptxt file... \n"); 
      close(fd); 
      unlink(ptxt_fname); /*for file deletion*/ 
      aes_clrkey(&aes); 
      free(ptxt); 
      free(iv); 
      free(buf); 
      exit(EXIT_FAILURE); 
     } 
     if((bytes_read = read(fin, buf, block_size)) < 1) 
     { 
      close(fd); 
      aes_clrkey(&aes); 
      free(ptxt); 
      free(iv); 
      free(buf); 
      break; 
     } 
    } 

} 

void 
usage (const char *pname) 
{ 
    printf ("Simple File Decryption Utility\n"); 
    printf ("Usage: %s SK-FILE CTEXT-FILE PTEXT-FILE\n", pname); 
    printf ("  Exits if either SK-FILE or CTEXT-FILE don't exist, or\n"); 
    printf ("  if a symmetric key sk cannot be found in SK-FILE.\n"); 
    printf ("  Otherwise, tries to use sk to decrypt the content of\n"); 
    printf ("  CTEXT-FILE: upon success, places the resulting plaintext\n"); 
    printf ("  in PTEXT-FILE; if a decryption problem is encountered\n"); 
    printf ("  after the processing started, PTEXT-FILE is truncated\n"); 
    printf ("  to zero-length and its previous content is lost.\n"); 

    exit (1); 
} 

int main (int argc, char **argv) 
{ 
    int fdsk, fdctxt; 
    char *sk = NULL; 
    size_t sk_len = 0; 

    if (argc != 4) { 
    usage (argv[0]); 
    } 
    else if (((fdsk = open (argv[1], O_RDONLY)) == -1) 
     || ((fdctxt = open (argv[2], O_RDONLY)) == -1)) { 
    if (errno == ENOENT) { 
     usage (argv[0]); 
    } 
    else { 
     perror (argv[0]); 

     exit (-1); 
    } 
    } 
    else { 
    setprogname (argv[0]); 

    if (!(sk = import_sk_from_file (&sk, &sk_len, fdsk))) { 
     printf ("%s: no symmetric key found in %s\n", argv[0], argv[1]); 

     close (fdsk); 
     exit (2); 
    } 
    close (fdsk); 

    decrypt_file (argv[3], sk, sk_len, fdctxt);  
    bzero(sk, sk_len); 
    free(sk); 


    close (fdctxt); 
    } 

    return 0; 
} 

Hier ist meine encrypt Code:

#include "pv.h" 

void encrypt_file (const char *ctxt_fname, void *raw_sk, size_t raw_len, int fin) 
{ 

    size_t block_size = CCA_STRENGTH; 
    int fd; /* ctxt fd */ 
    if((fd = open(ctxt_fname,O_WRONLY|O_TRUNC|O_CREAT,0600)) < 0) 
    { 
     perror("Ciphertext file permission error\n"); 
     exit(EXIT_FAILURE); 
    } 

    char *iv; 
    iv = (char *) malloc(block_size * sizeof(char)); 

    ri(); /*IV initialized*/ 
    prng_getbytes(iv, block_size); 

    struct aes_ctx aes; 
    const char *aes_key = aes_key = (const char *) raw_sk; 

    aes_setkey(&aes, aes_key, block_size); /*sets the encryption key.*/ 

    char *buf = buf = (char *) malloc(block_size * sizeof(char)); /*file read buffer*/ 
    char *ctxt = ctxt = (char *) malloc(block_size * sizeof(char)); /*ciphertext buffer*/ 
    int result; 
    size_t looper = 0; 
    size_t bytes_read; 
    result = write_chunk(fd, iv, block_size); 

    if(result == -1) 
    { 
     exit(-1); 
    } 

    bytes_read = read(fin, buf, block_size); /*returns how many bytes read*/ 
    while(bytes_read >= 1) 
    { 
     aes_encrypt(&aes, ctxt, iv); 
     for(looper = 0; looper < bytes_read; looper++) 
     { 

      *(ctxt + looper) = *(ctxt + looper)^*(buf + looper); 
     } 

     result = write_chunk(fd, ctxt, bytes_read); 
     if(result == -1) 
     { 
      perror("Problem when writing to ctxt file... \n"); 
      close(fd); 
      unlink(ctxt_fname); /*for file deletion*/ 
      aes_clrkey(&aes); 
      free(ctxt); 
      free(iv); 
      free(buf); 
      exit(EXIT_FAILURE); 
     }  
     printf("crossed written to file\n"); 

     if((bytes_read = read(fin, buf, block_size)) < 1) 
     { 
      close(fd); 
      aes_clrkey(&aes); 
      free(ctxt); 
      free(iv); 
      free(buf); 
      break; 
     } 

    } 
} 

void usage (const char *pname) 
{ 
    printf ("Personal Vault: Encryption \n"); 
    printf ("Usage: %s SK-FILE PTEXT-FILE CTEXT-FILE\n", pname); 
    printf ("  Exits if either SK-FILE or PTEXT-FILE don't exist.\n"); 
    printf ("  Otherwise, encrpyts the content of PTEXT-FILE under\n"); 
    printf ("  sk, and place the resulting ciphertext in CTEXT-FILE.\n"); 
    printf ("  If CTEXT-FILE existed, any previous content is lost.\n"); 

    exit (1); 
} 

int main (int argc, char **argv) 
{ 
    int fdsk, fdptxt; 
    char *raw_sk; 
    size_t raw_len; 



    if (argc != 4) 
    { 
     usage (argv[0]); 
    } 
    else if (((fdsk = open (argv[1], O_RDONLY)) == -1) || ((fdptxt = open (argv[2], O_RDONLY)) == -1)) 
    { 
     if (errno == ENOENT) 
     { 
      usage (argv[0]); 
     } 
     else 
     { 
      perror (argv[0]); 

      exit (-1); 
     } 
    } 
    else 
    { 
     setprogname (argv[0]); 

     if (!(import_sk_from_file (&raw_sk, &raw_len, fdsk))) 
     { 
      printf ("%s: no symmetric key found in %s\n", argv[0], argv[1]); 

      close (fdsk); 
      exit (2); 
     } 
     close (fdsk); 


     bzero(raw_sk, raw_len); 
     free(raw_sk); 


     close (fdptxt); 
    } 

    return 0; 
} 

Der encrypt Code 16 Bytes IV der Chiffretext-Datei wird das Voranstellen erste (wie es sein sollte, ich denke, wir lesen diese 16 Bytes aus der ctxt-Datei im Entschlüsselungsprozess) und dann passiert die eigentliche Verschlüsselung (wenn man sie als Blackbox betrachtet) w hier senden wir die IV und den Schlüssel; 16 Byte werden zurückgegeben. Diese 16 Bytes, die zurückgegeben werden, müssen mit dem Klartext-Dateipuffer XOR-verknüpft werden (bis zu 16 Bytes für jede Runde, wenn eine Datei mehr als 16 Bytes hat).

Post, dass die XORed-Bytes (die bis zu 16 Bytes sein werden) in die Datei geschrieben werden. Diese Sache passiert bis zur letzten Runde, die schließlich die Schleife unterbricht, wenn sie versucht, die Datei zu lesen, die keinen Inhalt mehr zu lesen hat. Lesefunktion versucht bei jedem Aufruf die nächsten verfügbaren Bytes zu lesen (bis zur angegebenen Anzahl an Bytes).

Dies ist keine perfektionierte Implementierung, da ich den Sicherheitsaspekt (Randomisierung der IV für jeden Zyklus) gelockert habe, jedoch muss es so zuerst funktionieren.

Mathematisch was ich versuche, die exakte Kopie dieses Konzepts zu tun sein sollte:

ciphertext_block = message_block^[AES(IV, Key)]

message_block = ciphertext_block^[AES(IV, Key)]

Hier Chiffretext/message_block bezieht sich auf einen Block von Zeichen das sind 16 Bytes für 1. bis n-1 Runden, können aber in der letzten Runde 16 Bytes sein oder nicht.

In jedem Fall XORing wird zwischen 16 Bytes Zeichen (Ausgabe von AES-CTR) und einem anderen Block (Block für die Verschlüsselung, Chiffretext-Block für die Entschlüsselung, auf jeden Fall kann es bis zu 16 Bytes und damit sind sie getan die XOR-Bedingungen, dh sie sind die Entscheider der Länge der XOR-Ausgabe).

Da sie die Entscheider sind, sobald die XORing-Operation ihre Länge abdeckt, stoppt die XORing-Schleife und wir gehen vorwärts in Richtung Schreiben in eine Datei (ctxt-Datei für Verschlüsselung, ptxt-Datei für Entschlüsselung).

Es sollte keine Polsterungsanforderungen geben.

Ich bin mir nicht sicher, ob ich realloc Funktionen an irgendeinem Ort verwenden sollte.

Ich werde gerne zusätzliche Dokumentationen zur Verfügung stellen, wenn ein Leser Probleme hat zu verstehen, was ich versuche zu tun.

Das Programm hat mehrere Bibliotheksabhängigkeiten, der Code wird jedoch fehlerfrei kompiliert.

Das ist meine Sammlung Befehl:

gcc -g -O2 -ansi -Wall -Wsign-compare -Wchar-subscripts -Werror -I. -I/usr/include/ -I/home/devel/libdcrypt/include/ -c pv_keygen.c pv_misc.c 
gcc -g -O2 -ansi -Wall -Wsign-compare -Wchar-subscripts -Werror -o pv_keygen pv_keygen.o pv_misc.o -L. -L/usr/lib/ -L/home/devel/libdcrypt/lib/ -ldcrypt -lgmp 

Dies ist nur für die Erstellung meiner verschlüsseln Datei. Fast gleiche (und ebenso strenge) Befehle sind für meine keygen- und entschlüsselte Datei. Keygen Code scheint gut zu funktionieren (ich habe das hier noch nicht aufgenommen); Ich kann einen Schlüssel erzeugen und ihn in eine Datei serialisieren. Diese Schlüsseldatei enthält tatsächlich zwei Schlüssel und ich lese nur die erste Hälfte für AES-CTR. Die nächste Hälfte wird MAC-Zwecken dienen (mit AES-CBC).

Dateigröße Details

Klartext-Datei: x Bytes

Chiffretext-Datei: (x + 16) Bytes

entschlüsselten Text-Datei: x Bytes

Statistik Recht, Inhalte ist nicht. Die entschlüsselte Textdatei und die Klartextdatei müssen identisch sein.

Ich versuche: diff plaintext_file decrypted_file auf RedHat zum Dateivergleich.

Schlüssel-Datei ist eigentlich 32 Bytes, von denen die ersten 16 Bytes für die Verschlüsselung verwendet werden und die späteren 16 Bytes für die MAC-Post-Verschlüsselung verwendet werden.

Schlüsseldatei (die serialisiert bis 64 Basen) (hex):

0000000 4662 6e4b 6631 7268 4876 676c 772f 664e 
0000010 4d5a 6f32 384e 5141 7139 6635 3442 7245 
0000020 646c 4a77 5553 4c30 4f63 3d6f 000a  
000002d 

Eingangsklartextdatei (hex):

0000000 6161 6161 6161 6161 6161 6161 610a 6161 
0000010 000a         
0000011 

Verschlüsselte Datei (hex):

0000000 540e 0e30 d74d 5000 78c1 13e3 0476 d4a2 
0000010 61c9 76ac e717 cd6d 013e e872 8e16 4827 
0000020 00a2         
0000021 

Entschlüsselte Datei (hex):

0000000 8bea 616a 1f1b d6b0 fd13 da46 5824 ec00 
0000010 0081         
0000011 

Externe Verweise (I abgeschnitten haben unten Dinge, wo der Fehler existieren kann):

1.) http://www.scs.stanford.edu/nyu/05sp/lab/lab1.html

2) http://www.scs.stanford.edu/nyu/05sp/lab/install-libs.html

+0

Side: "Hat eine Menge zufälliger Dinge gemacht" - Dartboards und Augenbinden funktionieren selten selbst bei scheinbar einfachen Aufgaben und ziemlich viel - nie auf Dinge wie Kryptographie. so dass das Ergebnis etwas selbstprophezeiendes war. – WhozCraig

+0

@WhozCraig Zufälligkeit wird nicht helfen. Lass mich nochmal fragen. Das waren eher nachdenkliche Versuche, es zum Laufen zu bringen. Es scheint, dass etwas furchtbar schief geht (nur verschlüsseln und/oder entschlüsseln). Darauf freue ich mich. – Avineshwar

+2

Dies ist ziemlich komplex zu * überprüfen * oder * debug *. Stellen Sie vor dem Verfassen sicher, dass Sie zuerst Ihr Antragsrecht verfassen. Entfernen Sie also die Dateiverwaltung aus dem Krypto-Code und schreiben Sie Unit-Tests darum herum. Es ist gut zu sehen, dass Sie Komplexität um z. IV-Erstellung, aber Sie müssen dies ein paar Schritte weiter gehen. –

Antwort

-1

Hier ist das Update:

Das Problem den Weg gab ich es tun wollte und so, wie ich es tue. Da es kein implementierungsbezogenes Problem gibt, war das Problem in meinem Entschlüsselungscode vorhanden.

In meinem Entschlüsselungs-Code, gab es keinen Punkt die AES_DECRYPT Funktion auch dann, wenn die Sache, die ich für wirklich suche ein exakter Rücktransformation (korrekter Fachbegriff über Entschlüsselung WRT AES) im Gegenteil gleichen Schlüssel wird verwendet, um die gleiche Datei zu entschlüsseln.

Als fix, AES_DECRYPT sollte AES_ENCRYPT sein einfach und es wird funktionieren.

Jetzt kann ich zu zusätzlichen Ergänzungen (Sicherheit Stärkung und Datenintegrität Überlegungen) gehen.

0

Warum nicht einfach AES verwenden in CTR-Modus, kein müssen für alle 16 Bytes einen AES-Aufruf machen und dann XOR die Ausgabe mit den Daten.

Der CTR-Modus akzeptiert Nur-Text, Schlüssel und IV und erzeugt verschlüsselte AES CTR-Daten. Der IOW-CTR-Modus führt alle XOR- und Zählerinkrementierungen durch.

Seien Sie vorsichtig mit CTR-Modus, das gleiche Schlüssel/IV-Paar darf nur einmal verwendet werden.

Die meisten Bibliotheken, die AES und andere Blockchiffren unterstützen, haben die Blockverschlüsselung auf niedriger Ebene und verwenden diese, um die fortgeschritteneren Modi wie CBC, CFB, CTR, OFB und Optionen wie PKCS # 7, PKCS zu implementieren # 5 Polsterung.