0

provaは、 hello i am a pcを含むプレーンテキスト ファイルです。

暗号化:

FILE *fp = fopen("prova", "r+");
FILE *fpout = fopen("out", "w+");
while(!feof(fp)){
    memset(plain_text, 0, sizeof(plain_text));
    retval = fread(plain_text, 1, 16, fp);
    txtLenght = sizeof(plain_text);
    encBuffer = malloc(txtLenght);
    algo = gcry_cipher_map_name(name);
    gcry_cipher_open(&hd, algo, GCRY_CIPHER_MODE_CBC, 0);
    gcry_cipher_setkey(hd, key, keyLength);
    gcry_cipher_setiv(hd, iniVector, blkLength);
    gcry_cipher_encrypt(hd, encBuffer, txtLenght, plain_text, txtLenght);
    fwrite(encBuffer, 1, 16, fpout);
}

復号化:

FILE *fp = fopen("out", "r+");
FILE *fpout = fopen("origdec", "w+");
while(!feof(fp)){
    memset(plain_text, 0, sizeof(plain_text));
    retval = fread(plain_text, 1, 16, fp);
    txtLenght = sizeof(plain_text);
    encBuffer = malloc(txtLenght);
    algo = gcry_cipher_map_name(name);
    gcry_cipher_open(&hd, algo, GCRY_CIPHER_MODE_CBC, 0);
    gcry_cipher_setkey(hd, key, keyLength);
    gcry_cipher_setiv(hd, iniVector, blkLength);
    gcry_cipher_decrypt(hd, encBuffer, txtLenght, plain_text, txtLenght);
    fwrite(encBuffer, 1, 16, fpout);
}

どこ:

char key[32] = {0x80};
char iniVector[16] = {0};
char plain_text[16];
char *encBuffer = NULL;

問題: 暗号化されたファイルを解読すると、ファイルorigdecにはプレーン テキストとランダムな無用で読み取り不能な文字が含まれています。

4

2 に答える 2

3

文字列を読むと、

fread(plain_text, 1, 16, fp);

おそらく、"Hello I am a PC" (15 バイト) とリターンが返されます。

次に、16 バイトを暗号化し、それらの 16 バイトを復号化しますが、まだ文字列 terminator がないため、printf は余分なもの (またはコアダンプ) を書き込みます。

文字列の最後にバイナリ ゼロを追加する必要があります。試す:

fread(plain_text, 1, 16, fp);
plain_text[15] = 0x0;

これで何かが変わるかどうかを確認します。

アップデート

コードにいくつかのエラーがあります。たとえば、常に暗号を再初期化し、常に再割り当てencBufferすると、メモリリークが発生します。いくつかのバグを修正しました。暗号化されたファイルが 16 バイトにパディングされるという機能が残っています。パディングを取り除くテクニックがあります。たとえば、PKCS#7 を見たいと思うかもしれません。

いくつかの定数を任意に初期化し、インプレース暗号化/復号化を採用しました (bufSize は 16 に制限されていませんが、パディング戦略を確認する必要があります)。

#include <stdio.h>
#include <gcrypt.h>

int main()
{
    char iniVector[16];
    char *encBuffer = NULL;
    FILE *fp, *fpout;
    char *key       = "topolino e minni";
    gcry_cipher_hd_t hd;
    int     bufSize = 16, bytes, algo = GCRY_CIPHER_AES128, keyLength = 16, blkLength = 16;

    memset(iniVector, 0, 16);

    encBuffer = malloc(bufSize);

    fp = fopen("prova", "r");
    fpout = fopen("out", "w");

    gcry_cipher_open(&hd, algo, GCRY_CIPHER_MODE_CBC, 0);
    gcry_cipher_setkey(hd, key, keyLength);
    gcry_cipher_setiv(hd, iniVector, blkLength);

    while(!feof(fp))
    {
        bytes = fread(encBuffer, 1, bufSize, fp);
        if (!bytes) break;
        while(bytes < bufSize)
            encBuffer[bytes++] = 0x0;
        gcry_cipher_encrypt(hd, encBuffer, bufSize, NULL, 0);
        bytes = fwrite(encBuffer, 1, bufSize, fpout);
    }
    gcry_cipher_close(hd);
    fclose(fp);
    fclose(fpout);

    // Decrypt. Same algo as before

    gcry_cipher_open(&hd, algo, GCRY_CIPHER_MODE_CBC, 0);
    gcry_cipher_setkey(hd, key, keyLength);
    gcry_cipher_setiv(hd, iniVector, blkLength);

    fp = fopen("out", "r");
    fpout = fopen("origdec", "w");
    while(!feof(fp))
    {
        bytes = fread(encBuffer, 1, bufSize, fp);
        if (!bytes) break;
        gcry_cipher_decrypt(hd, encBuffer, bufSize, NULL, 0);
        bytes = fwrite(encBuffer, 1, bufSize, fpout);
    }
    gcry_cipher_close(hd);

    free(encBuffer); encBuffer = NULL;
    return 0;
}
于 2013-01-05T17:47:13.873 に答える
0

データベースなどのバイナリ ファイルでは、大きすぎる復号化ファイルを取得することは問題です。ただし、実際の長さをプレフィックスとしてファイルを書き込む場合は、暗号化プログラムと復号化プログラムがこのプロトコルに同意していると仮定して、「大きすぎる」ファイルを適切に切り捨てることができます。

また、復号化プログラムが推測する必要がなく、2 つのプログラムが両方のプログラムで IV をハードコードする必要がないように、プレフィックスに初期化ベクトルを含めます。そのため、暗号化プログラムは gcry_create_nonce() を使用して IV を生成し、復号化プログラムはそれをファイルから読み取ってから、ファイルの残りの部分を復号化します。

秘密鍵をどのように管理しますか?

パスワードベースの暗号化は、gcrypt gcry_kdf_derive() 関数 (SHA512 と 128 バイトのソルトを使用する PBKDF2) でうまく機能します。繰り返しになりますが、salt は暗号化プログラムによって生成され、ファイルの先頭に配置されます。デクリプタは、gcrypt gcry_kdf_derive() 呼び出しで同じパスワードとともにソルトを使用する前に、ファイルの先頭からソルトを取得します。

したがって、暗号化プログラムは平文を読み取り、次のファイルを生成します。

 salt || IV || source-size || ciphertext-blocks

これで、デクリプタは元のファイルを再構築できます。

HMAC でコンテンツを保護しますか?

楽しむ。

于 2016-09-01T23:17:21.883 に答える