2013-08-09 9 views
18

Voglio solo testare AES da openSSL con queste 3 modalità: con 128,192 e 256 lunghezze chiave ma il mio il testo decodificato è diverso dal mio input e non so perché. Inoltre, quando passo un'enorme lunghezza di input (diciamo 1024 byte) il mio programma mostra core dumped ... Il mio input è sempre lo stesso, ma non importa, almeno per ora. Heres il codice:AES (aes-cbc-128, aes-cbc-192, aes-cbc-256) crittografia/decrittografia con openssl C

#include <stdio.h> 
#include <stdlib.h> 
#include <string.h> 
#include <openssl/aes.h> 

int main(int argc, char **argv) 
{ 
    int i; 
    int keylength; 
    printf("Give a key length [only 128 or 192 or 256!]:\n"); 
    scanf("%d", &keylength); 

    /* generate a key with a given length */ 
    unsigned char aes_key[keylength]; 
    memset(aes_key, 0, sizeof(aes_key)); 
    if (!RAND_bytes(aes_key, keylength)) 
    { 
     exit(-1); 
    } 
    aes_key[keylength-1] = '\0'; 

    int inputslength; 
    printf("Give an input's length:\n"); 
    scanf("%d", &inputslength); 

    /* generate input with a given length */ 
    unsigned char aes_input[inputslength+1]; 
    memset(aes_input, '0', sizeof(aes_input)); 
    aes_input[inputslength] = '\0'; 

    /*printf("original:\t"); 
    for(i=0; i<inputslength; i++) 
    { 
     printf("%c ", aes_input[i]); 
    } 
    printf("\n");*/ 

    /* init vector */ 
    unsigned char iv[AES_BLOCK_SIZE]; 
    if (!RAND_bytes(iv, AES_BLOCK_SIZE)) 
    { 
     exit(-1); 
    } 

    //printf("AES_BLOCK_SIZE = %d\n", AES_BLOCK_SIZE); // aes block size is 16 bytes = 128 bits 
    AES_KEY enc_key, dec_key; 
    unsigned char enc_out[AES_BLOCK_SIZE]; 
    unsigned char dec_out[AES_BLOCK_SIZE]; 

    // so i can do with this aes-cbc-128 aes-cbc-192 aes-cbc-256 
    AES_set_encrypt_key(aes_key, keylength, &enc_key); 
    AES_cbc_encrypt(aes_input, enc_out, inputslength, &enc_key, iv, AES_ENCRYPT); 

    AES_set_decrypt_key(aes_key, keylength, &dec_key); 
    AES_decrypt(enc_out, dec_out, &dec_key); 

    printf("original:\t"); 
    for(i=0;*(aes_input+i)!=0x00;i++) 
     printf("%X ",*(aes_input+i)); 
    printf("\nencrypted:\t"); 

    for(i=0;*(enc_out+i)!=0x00;i++) 
     printf("%X ",*(enc_out+i)); 

    printf("\ndecrypted:\t"); 
    for(i=0;*(dec_out+i)!=0x00;i++) 
     printf("%X ",*(dec_out+i)); 
    printf("\n"); 

    /*printf("\n\noriginal:\t"); 
    for(i=0; i<inputslength; i++) 
    { 
     printf("%x ", dec_out[i]); 
    } 
    printf("\n");*/ 


    return 0; 
} 

EDIT:

Quando ho cambiato uscite dimensioni per inputslength invece di AES_BLOCK_SIZE ho ottenuto risultati:

Give a key length [only 128 or 192 or 256!]: 
128 
Give an input's length: 
5 
original:  30 30 30 30 30 
encrypted:  94 56 50 7E 19 B2 1C CE 20 23 4A E7 10 AF DB E3 30 30 30 30 30 
decrypted:  E1 5F F4 3D E8 8D 91 19 CD 3E 22 1E AF 1C 8F 5A 94 56 50 7E 19 B2 1C CE 20 23 4A E7 10 AF DB E3 30 30 30 30 30 

Quindi è possibile che theres un problema con outpus taglie e le dimensioni della iv? Quali dimensioni dovrebbero avere (per AES-CBC-128, AES-CBC-192, AES-CBC-256)?

+2

Sidenote: la chiave AES non deve essere terminata con null. è un blocco casuale di byte; È tutto. Non c'è nulla di nullo a riguardo, quindi 'aes_key [keylength-1] = '\ 0'' è inutile (tranne che imposta sempre l'ultimo byte della tua chiave (che è incidentalmente 8 volte più grande di quanto deve essere) a zero.) – WhozCraig

+0

@WhozCraig: grazie, bello saperlo. Che ne dici del problema principale, hai qualche idea? – ivy

+1

Abbondanza. Le dimensioni del buffer per la crittografia e la decifrazione non sono mai * abbastanza * abbastanza grandi. e hai bisogno di una funzione di stampa esadecimale generale piuttosto che cercare di trattare queste cose come dati di carattere. * È binario *. Formando una risposta ufficiale ora, ma inizia a guardare lì. – WhozCraig

risposta

25

Dai un'occhiata a questa versione modificata del tuo codice. Notare quanto segue:

  1. aggiunte hex_print (minore)
  2. Aggiunto corretto dimensionamento del buffer delle chiavi (medio).
  3. Aggiunto il corretto dimensionamento del buffer di crittografia di output (che deve essere un multiplo a dimensione di blocco e se il buffer di origine originale è un multiplo esatto di blocco, è comunque necessario un blocco completo di riempimento (vedere PKCS 5 padding per ulteriori informazioni) .
  4. stesso IV utilizzato sia per cifrare e decifrare.
  5. Infine, per quanto strano possa sembrare AES_cbc_encrypt() viene utilizzato per sia la crittografia e la decrittografia (vedi l'ultimo parametro nella chiamata).

Codice sorgente

#include <stdio.h> 
#include <stdlib.h> 
#include <string.h> 
#include <openssl/aes.h> 
#include <openssl/rand.h> 

// a simple hex-print routine. could be modified to print 16 bytes-per-line 
static void hex_print(const void* pv, size_t len) 
{ 
    const unsigned char * p = (const unsigned char*)pv; 
    if (NULL == pv) 
     printf("NULL"); 
    else 
    { 
     size_t i = 0; 
     for (; i<len;++i) 
      printf("%02X ", *p++); 
    } 
    printf("\n"); 
} 

// main entrypoint 
int main(int argc, char **argv) 
{ 
    int keylength; 
    printf("Give a key length [only 128 or 192 or 256!]:\n"); 
    scanf("%d", &keylength); 

    /* generate a key with a given length */ 
    unsigned char aes_key[keylength/8]; 
    memset(aes_key, 0, keylength/8); 
    if (!RAND_bytes(aes_key, keylength/8)) 
     exit(-1); 

    size_t inputslength = 0; 
    printf("Give an input's length:\n"); 
    scanf("%lu", &inputslength); 

    /* generate input with a given length */ 
    unsigned char aes_input[inputslength]; 
    memset(aes_input, 'X', inputslength); 

    /* init vector */ 
    unsigned char iv_enc[AES_BLOCK_SIZE], iv_dec[AES_BLOCK_SIZE]; 
    RAND_bytes(iv_enc, AES_BLOCK_SIZE); 
    memcpy(iv_dec, iv_enc, AES_BLOCK_SIZE); 

    // buffers for encryption and decryption 
    const size_t encslength = ((inputslength + AES_BLOCK_SIZE)/AES_BLOCK_SIZE) * AES_BLOCK_SIZE; 
    unsigned char enc_out[encslength]; 
    unsigned char dec_out[inputslength]; 
    memset(enc_out, 0, sizeof(enc_out)); 
    memset(dec_out, 0, sizeof(dec_out)); 

    // so i can do with this aes-cbc-128 aes-cbc-192 aes-cbc-256 
    AES_KEY enc_key, dec_key; 
    AES_set_encrypt_key(aes_key, keylength, &enc_key); 
    AES_cbc_encrypt(aes_input, enc_out, inputslength, &enc_key, iv_enc, AES_ENCRYPT); 

    AES_set_decrypt_key(aes_key, keylength, &dec_key); 
    AES_cbc_encrypt(enc_out, dec_out, encslength, &dec_key, iv_dec, AES_DECRYPT); 

    printf("original:\t"); 
    hex_print(aes_input, sizeof(aes_input)); 

    printf("encrypt:\t"); 
    hex_print(enc_out, sizeof(enc_out)); 

    printf("decrypt:\t"); 
    hex_print(dec_out, sizeof(dec_out)); 

    return 0; 
} 

Test uscita

Give a key length [only 128 or 192 or 256!]: 
128 
Give an input's length: 
10 
original: 58 58 58 58 58 58 58 58 58 58 
encrypt: A9 66 C5 24 A4 02 AB 96 08 65 F7 22 A5 FB BE 26 
decrypt: 58 58 58 58 58 58 58 58 58 58 

seconda uscita di prova

Give a key length [only 128 or 192 or 256!]: 
128 
Give an input's length: 
10 
original: 58 58 58 58 58 58 58 58 58 58 
encrypt: C2 47 6D B1 A1 68 29 53 55 74 C5 CC 3F 27 0A 3F 
decrypt: 58 58 58 58 58 58 58 58 58 58 

Mi auguro sinceramente che questo aiuta.

+0

scusa per averti disturbato, hai ragione, ora va tutto bene :) – ivy

3

@WhozCraig: grazie mille per l'aiuto! Mi ha spiegato molto! Ma c'è solo un altro problema. Ho cambiato gli array statici in quelli dinamici. Quando l'ho fatto, si sono verificati alcuni errori. Ma si verificano solo quando fornisco una grande quantità di input, dai un'occhiata all'output di valgrind: http://pastie.org/private/bzofrrtgrlzr0doyb3g. L'errore si verifica solo quando passo un input enorme, quando passo una piccola dimensione (come nel tuo esempio, 10) è ok. Tutto il resto funziona perfettamente.

#include <stdio.h> 
#include <stdlib.h> 
#include <string.h> 
#include <openssl/aes.h> 
#include <openssl/rand.h> 

// a simple hex-print routine. could be modified to print 16 bytes-per-line 
static void hex_print(const void* pv, size_t len) 
{ 
    const unsigned char * p = (const unsigned char*)pv; 
    if (NULL == pv) 
     printf("NULL"); 
    else 
    { 
     size_t i = 0; 
     for (; i<len;++i) 
      printf("%02X ", *p++); 
    } 
    printf("\n"); 
} 

// main entrypoint 
int main(int argc, char **argv) 
{ 
    size_t inputslength = 0; 
    printf("Give an input's length:\n"); 
    scanf("%lu", &inputslength); 

    int keylength; 
    printf("Give a key length [only 128 or 192 or 256!]:\n"); 
    scanf("%d", &keylength); 


    // generate a key with a given length 
    unsigned char *aes_key = (unsigned char*)malloc(sizeof(unsigned char) * (keylength/8)); 
    memset(aes_key, 0, keylength/8); 
    RAND_bytes(aes_key, keylength/8); 

    // generate input with a given length 
    unsigned char *aes_input = (unsigned char*)malloc(sizeof(unsigned char) * (inputslength)); 
    memset(aes_input, 'X', sizeof(aes_input)); 

    // init vectors 
    unsigned char *iv_enc = (unsigned char*)malloc(sizeof(unsigned char) * (AES_BLOCK_SIZE)); 
    unsigned char *iv_dec = (unsigned char*)malloc(sizeof(unsigned char) * (AES_BLOCK_SIZE)); 
    // iv_dec == iv_enc 
    RAND_bytes(iv_enc, AES_BLOCK_SIZE); 
    memcpy(iv_dec, iv_enc, AES_BLOCK_SIZE); 

    // buffers for encryption and decryption 
    const size_t length = (((inputslength + AES_BLOCK_SIZE)/AES_BLOCK_SIZE) * AES_BLOCK_SIZE); 
    unsigned char *enc_out = (unsigned char*)malloc(sizeof(unsigned char) * (length)); 
    unsigned char *dec_out = (unsigned char*)malloc(sizeof(unsigned char) * (inputslength)); 

    // so i can do with this aes-cbc-128 aes-cbc-192 aes-cbc-256 
    AES_KEY encKey, decKey; 
    AES_set_encrypt_key(aes_key, keylength, &encKey); 
    AES_cbc_encrypt(aes_input, enc_out, inputslength, &encKey, iv_enc, AES_ENCRYPT); 

    AES_set_decrypt_key(aes_key, keylength, &decKey); 
    AES_cbc_encrypt(enc_out, dec_out, length, &decKey, iv_dec, AES_DECRYPT); 

    printf("original:\t"); 
    hex_print(aes_input, sizeof(aes_input)); 

    printf("encrypt:\t"); 
    hex_print(enc_out, sizeof(enc_out)); 

    printf("decrypt:\t"); 
    hex_print(dec_out, sizeof(dec_out)); 

    free(aes_key); 
    aes_key = NULL; 
    free(aes_input); 
    aes_input = NULL; 
    free(iv_enc); 
    iv_enc = NULL; 
    free(iv_dec); 
    iv_dec = NULL; 
    free(enc_out); 
    enc_out = NULL; 
    free(dec_out); 
    dec_out = NULL; 

    return 0; 
} 

EDIT:

Ok, c'era qualcosa di sbagliato con il codice prev ho postato, ecco uno nuovo, perfettamente funzionante, anche per un enorme ingressi. Grazie ancora per avermi aiutato!:)

#include <stdio.h> 
#include <stdlib.h> 
#include <string.h> 
#include <openssl/aes.h> 
#include <openssl/rand.h> 

// a simple hex-print routine. could be modified to print 16 bytes-per-line 
static void hex_print(const void* pv, size_t len) 
{ 
    const unsigned char * p = (const unsigned char*)pv; 
    if (NULL == pv) 
     printf("NULL"); 
    else 
    { 
     size_t i = 0; 
     for (; i<len;++i) 
      printf("%02X ", *p++); 
    } 
    printf("\n"); 
} 

// main entrypoint 
int main(int argc, char **argv) 
{ 
    int keylength; 
    printf("Give a key length [only 128 or 192 or 256!]:\n"); 
    scanf("%d", &keylength); 

    /* generate a key with a given length */ 
    unsigned char *aes_key = (unsigned char*)malloc(sizeof(unsigned char) * (keylength/8)); 
    memset(aes_key, 0, keylength/8); 
    if (!RAND_bytes(aes_key, keylength/8)) 
     exit(-1); 

    size_t inputslength = 0; 
    printf("Give an input's length:\n"); 
    scanf("%lu", &inputslength); 

    /* generate input with a given length */ 
    unsigned char *aes_input = (unsigned char*)malloc(sizeof(unsigned char) *inputslength); 
    memset(aes_input, 'X', inputslength); 

    /* init vector */ 
    unsigned char *iv_enc = (unsigned char*)malloc(sizeof(unsigned char) *AES_BLOCK_SIZE), *iv_dec = (unsigned char*)malloc(sizeof(unsigned char) *AES_BLOCK_SIZE); 
    RAND_bytes(iv_enc, AES_BLOCK_SIZE); 
    memcpy(iv_dec, iv_enc, AES_BLOCK_SIZE); 

    // buffers for encryption and decryption 
    const size_t encslength = ((inputslength + AES_BLOCK_SIZE)/AES_BLOCK_SIZE) * AES_BLOCK_SIZE; 
    unsigned char *enc_out = (unsigned char*)malloc(sizeof(unsigned char) *encslength); 
    unsigned char *dec_out = (unsigned char*)malloc(sizeof(unsigned char) *inputslength); 
    memset(enc_out, 0, sizeof(enc_out)); 
    memset(dec_out, 0, sizeof(dec_out)); 

    // so i can do with this aes-cbc-128 aes-cbc-192 aes-cbc-256 
    AES_KEY enc_key, dec_key; 
    AES_set_encrypt_key(aes_key, keylength, &enc_key); 
    AES_cbc_encrypt(aes_input, enc_out, inputslength, &enc_key, iv_enc, AES_ENCRYPT); 

    AES_set_decrypt_key(aes_key, keylength, &dec_key); 
    AES_cbc_encrypt(enc_out, dec_out, encslength, &dec_key, iv_dec, AES_DECRYPT); 

    printf("original:\t"); 
    hex_print(aes_input, inputslength); 

    printf("encrypt:\t"); 
    hex_print(enc_out, encslength); 

    printf("decrypt:\t"); 
    hex_print(dec_out, inputslength); 

    // free memory here 

    return 0; 
} 
+6

Guarda di nuovo. 'sizeof()' assume un significato completamente nuovo se usato con un puntatore piuttosto che con una matrice fissa o variadica. Diventa la dimensione di un * puntatore *, *** non *** la dimensione dei dati assegnati per esso. Tutte le tue dimensioni dovrebbero essere variabili; ** non ** 'sizeof (qualcosa)'. Correggilo e scommetto che i tuoi ultimi problemi non ci saranno più. (sidenote: non cast 'malloc()' durante la programmazione in C. normale Può causare problemi molto sottili, specialmente per la portabilità. C++ lo richiede, ma poi di nuovo, non dovresti usare 'malloc()' in C++ in primo luogo.) = P – WhozCraig

+1

grazie ancora così tanto! Ecco un esempio funzionante: http://pastie.org/private/dtvmftozmru02webkzzq. Ho lanciato il 'malloc' beacuese che il mio gcc mi ha detto -' malloc' restituisce vuoto come ricordo, giusto? Quando scrivo in C++, uso 'new' e' delete', so che non dovrei usare 'malloc' in C++;) – ivy

+2

Il cast di' malloc() 'nella programmazione C presenta potenziali insidie. Ovviamente è richiesto in C++, ma come hai detto tu usi 'new' e' delete'. Cerca "casting malloc [c]" su questo sito. È un problema abbastanza dibattuto. A parte questo, sono molto contento che tu sia attivo e funzionante. – WhozCraig