2016-03-21 54 views
1

私はシンプルなファイル暗号化/復号化を行った。モードとファイルが引数として動作するようになります。暗号化するとき、ランダムな文字列を生成し、それを使ってファイルを暗号化します。ファイルを解読すると、ユーザーにパスワードの入力を促し、解読時にそのパスワードを使用します。aes-256-cbc暗号化/復号化キーが機能しない

私の問題は、入力に同じキーを慎重に書き込んでも、復号化するときに平文の代わりに不器用になります。

私は

unsigned char constkey[] = "asd123"; 

のような一定のパスワードを使用して暗号化と復号化の両方のためにそれを使用する場合、すべてが完璧に働いていたので、私はパスワードの問題を追跡。

私のキーは何を変えていますか?

暗号化/復号化コードのためのJames K Polkに対する大変感謝!

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

#ifndef TRUE 
#define TRUE 1 
#endif 

#ifndef FALSE 
#define FALSE 0 
#endif 


/* Encrypt or decrypt, depending on flag 'should_encrypt' */ 
void en_de_crypt(int should_encrypt, FILE *ifp, FILE *ofp, unsigned char *ckey, unsigned char *ivec) { 

    const unsigned BUFSIZE=4096; 
    unsigned char *read_buf = malloc(BUFSIZE); 
    unsigned char *cipher_buf; 
    unsigned blocksize; 
    int out_len; 
    EVP_CIPHER_CTX ctx; 

    EVP_CipherInit(&ctx, EVP_aes_256_cbc(), ckey, ivec, should_encrypt); 
    blocksize = EVP_CIPHER_CTX_block_size(&ctx); 
    cipher_buf = malloc(BUFSIZE + blocksize); 

    while (1) { 

     // Read in data in blocks until EOF. Update the ciphering with each read. 

     int numRead = fread(read_buf, sizeof(unsigned char), BUFSIZE, ifp); 
     EVP_CipherUpdate(&ctx, cipher_buf, &out_len, read_buf, numRead); 
     fwrite(cipher_buf, sizeof(unsigned char), out_len, ofp); 
     if (numRead < BUFSIZE) { // EOF 
      break; 
     } 
    } 

    // Now cipher the final block and write it out. 

    EVP_CipherFinal(&ctx, cipher_buf, &out_len); 
    fwrite(cipher_buf, sizeof(unsigned char), out_len, ofp); 

    // Free memory 

    free(cipher_buf); 
    free(read_buf); 
} 

int rand_string(char *str, size_t size) 
{ 
    size_t n; 
    const char charset[] = "ABCDEFGHIJKLMNOPQRSTUWVXYZO1234567890"; 

    for (n = 0; n < size; n++) { 
     int key = rand() % (int) (sizeof charset - 1); 
     str[n] = charset[key]; 
    } 

    str[size] = '\0'; 
    return 0; 
} 

void copyfile(FILE* from, FILE* to) 
{ 
    fseek(from, 0, SEEK_END); 
    long filesize = ftell(from); 
    fseek(from, 0, SEEK_SET); 
    char b[2]; 
    long a; 

    for(a=0; a<filesize; a++) 
    { 
     fread(b, 1, 1, from); 
     fwrite(b, 1, 1, to); 
    } 
} 

int main(int argc, char *argv[]) { 

    if (argc != 3) { printf("usage: %s mode file\n", argv[0]); return 0; } 

    unsigned char ivec[] = "dontusethisinput"; 
    FILE *fIN, *fOUT; 

    if (!strcmp(argv[1],"e")) 
    { 
     srand(time(NULL)); /* seed random */ 

     char passkey[6]; 
     rand_string(passkey,5); /* generate random password */ 

     if((fIN = fopen(argv[2], "rb")) == NULL){ printf("ERROR: %s\n", strerror(errno)); return 0; } 
     fOUT = fopen("tempfile", "wb+"); 

     en_de_crypt(TRUE, fIN, fOUT, (unsigned char*)passkey, ivec); /* encrypt the file */ 

     fclose(fIN); 
     fclose(fOUT); 

     if((fIN = fopen(argv[2], "wb+")) == NULL){ printf("ERROR: %s\n", strerror(errno)); return 0; } 
     fOUT = fopen("tempfile", "rb"); 

     copyfile(fOUT, fIN); /* replace the file with encrypted one */ 

     fclose(fIN); 
     fclose(fOUT); 

     printf("file encrypted with key [%s]\n", passkey); 
    } 
    else if(!strcmp(argv[1],"d")) 
    { 
     char key[6]; 
     printf("Password: "); 
     fgets(key, 6, stdin); /* prompt for the key */ 
     key[5] = '\0'; 

     if((fIN = fopen(argv[2], "rb")) == NULL){ printf("ERROR: %s\n", strerror(errno)); return 0; } 
     fOUT = fopen("tempfile", "wb+"); 

     en_de_crypt(FALSE, fIN, fOUT, (unsigned char*)key, ivec); /* decrypt the file */ 

     fclose(fIN); 
     fclose(fOUT); 

     if((fIN = fopen(argv[2], "wb+")) == NULL){ printf("ERROR: %s\n", strerror(errno)); return 0; } 
     fOUT = fopen("tempfile", "rb"); 

     copyfile(fOUT, fIN); /* replace the file with decrypted one */ 

     fclose(fIN); 
     fclose(fOUT); 

     printf("file decrypted with key [%s]\n",key); 
    } 
    else { printf("invalid mode\n"); return 0; } 

    remove("tempfile"); 
    return 0; 
} 
+0

'EVP_CipherInit()'の戻り値は何ですか? 'fread()'が '0'や' -1'を返すとどうなりますか? 'fwrite()'は何を返しますか? –

+0

*** 'unsigned char constkey [] =" asd123 ";' *** - あなたは短いキーで幸運になっているようです。 – jww

答えて

2

私は

unsigned char constkey[] = "asd123";

のような一定のパスワードを使用して暗号化 と復号化の両方のためにそれを使用する場合、すべてが完璧に を働いていたので、私はパスワードの問題を追跡。

AESパスワード(バイナリ)を使用しないでください。 AES-256の場合、256ビットロングキーが必要です。 OpenSSLはあなたのconstkeyをの256ビットのというキーとして扱いますので、あなたが提供したものを超えて読み込み、キーの最後にいくつかのランダムなデータで終わります(アクセス違反を避けることができれば幸いです)。

同じプログラム内でこれを行うと、暗号化と復号化の両方で同じランダムデータが鍵に正しく格納されます。はすべてと思われます。

正しいキーの長さで試してください。