Я плохо знаком с OpenSSL, Может кто-либо давать мне подсказку в том, как инициализировать режим AES CTR из файла C. Я знаю, что это - подпись метода, но у меня есть проблемы с параметрами, нет многих документации ни один ясный пример, как сделать простое шифрование. Я ценил бы, если кто-то мог бы иллюстрировать вызов к этому методу.Заранее спасибо!
void AES_ctr128_encrypt(const unsigned char *in, unsigned char *out,
const unsigned long length, const AES_KEY *key,
unsigned char ivec[AES_BLOCK_SIZE],
unsigned char ecount_buf[AES_BLOCK_SIZE],
unsigned int *num);
Привет Caf, я действительно ценю Ваш быстрый ответ, это было действительно полезно, и defenetly лучший пример, который я нашел в сети. Я пытаюсь открыть файл с неопределенной длиной, зашифровать ее и записать другой файл со сгенерированным шифрованным текстом, затем открыть зашифрованный файл и восстановить простой текст. Я должен использовать файл значительного количества причины МБ, я хотел бы сравнить производительности ЦП. Однако у меня все еще есть проблема при дешифровании. Так или иначе при дешифровании значительных txt файлов (1504 КБ) это привычка дешифрует его завершенный, и я получаю половину из него в простом тексте и другой половине все еще зашифрованного. Я думаю, что это могло бы быть связано с размером iv или способа, которым я называю счетчик. Вот то, что я имею до сих пор:
#include <openssl/aes.h>
#include <stdio.h>
#include <string.h>
struct ctr_state {
unsigned char ivec[16];
unsigned int num;
unsigned char ecount[16];
};
FILE *fp;
FILE *rp;
FILE *op;
size_t count;
char * buffer;
AES_KEY key;
int bytes_read, bytes_written;
unsigned char indata[AES_BLOCK_SIZE];
unsigned char outdata[AES_BLOCK_SIZE];
unsigned char ckey[] = "thiskeyisverybad"; // It is 128bits though..
unsigned char iv[8] = {0};//This should be generated by RAND_Bytes I will take into consideration your previous post
struct ctr_state state;
int init_ctr(struct ctr_state *state, const unsigned char iv[8]){
state->num = 0;
memset(state->ecount, 0, 16);
memset(state->ivec + 8, 0, 8);
memcpy(state->ivec, iv, 8);
}
void encrypt(){
//Opening files where text plain text is read and ciphertext stored
fp=fopen("input.txt","a+b");
op=fopen("output.txt","w");
if (fp==NULL) {fputs ("File error",stderr); exit (1);}
if (op==NULL) {fputs ("File error",stderr); exit (1);}
//Initializing the encryption KEY
AES_set_encrypt_key(ckey, 128, &key);
//Encrypting Blocks of 16 bytes and writing the output.txt with ciphertext
while (1) {
init_ctr(&state, iv); //Counter call
bytes_read = fread(indata, 1, AES_BLOCK_SIZE, fp);
AES_ctr128_encrypt(indata, outdata, bytes_read, &key, state.ivec, state.ecount, &state.num);
bytes_written = fwrite(outdata, 1, bytes_read, op);
if (bytes_read < AES_BLOCK_SIZE)
break;
}
fclose (fp);
fclose (op);
free (buffer);
}
void decrypt(){
//Opening files where text cipher text is read and the plaintext recovered
rp=fopen("recovered.txt","w");
op=fopen("output.txt","a+b");
if (rp==NULL) {fputs ("File error",stderr); exit (1);}
if (op==NULL) {fputs ("File error",stderr); exit (1);}
//Initializing the encryption KEY
AES_set_encrypt_key(ckey, 128, &key);
//Encrypting Blocks of 16 bytes and writing the output.txt with ciphertext
while (1) {
init_ctr(&state, iv);//Counter call
bytes_read = fread(indata, 1, AES_BLOCK_SIZE, op);
AES_ctr128_encrypt(indata, outdata, bytes_read, &key, state.ivec, state.ecount, &state.num);
bytes_written = fwrite(outdata, 1, bytes_read, rp);
if (bytes_read < AES_BLOCK_SIZE)
break;
}
fclose (rp);
fclose (op);
free (buffer);
}
int main(int argc, char *argv[]){
encrypt();
//decrypt();
system("PAUSE");
return 0;
}
Каждый шифрует и дешифрует функцию, названы в различных выполнениях, таким образом, все всегда инициализируется с теми же значениями. Еще раз спасибо за подсказки можно предоставить мне заранее и Отношениям!!!
Обычно вы намереваетесь повторно вызывать AES_ctr128_encrypt ()
, чтобы отправить несколько сообщений с одним и тем же ключом, IV и увеличивающимся счетчиком. Это означает, что вам необходимо отслеживать значения 'ivec', 'num' и 'ecount' между вызовами - поэтому создайте struct
для их хранения и функцию инициализации:
struct ctr_state {
unsigned char ivec[16]; /* ivec[0..7] is the IV, ivec[8..15] is the big-endian counter */
unsigned int num;
unsigned char ecount[16];
};
int init_ctr(struct ctr_state *state, const unsigned char iv[8])
{
/* aes_ctr128_encrypt requires 'num' and 'ecount' set to zero on the
* first call. */
state->num = 0;
memset(state->ecount, 0, 16);
/* Initialise counter in 'ivec' to 0 */
memset(state->ivec + 8, 0, 8);
/* Copy IV into 'ivec' */
memcpy(state->ivec, iv, 8);
}
Теперь, когда вы Чтобы начать связь с адресатом, вам необходимо сгенерировать IV для использования и инициализировать счетчик:
unsigned char iv[8];
struct ctr_state state;
if (!RAND_bytes(iv, 8))
/* Handle the error */;
init_ctr(&state, iv);
Затем вам нужно будет отправить 8-байтовый IV в пункт назначения. Вам также необходимо инициализировать AES_KEY
из байтов исходного ключа:
AES_KEY aes_key;
if (!AES_set_encrypt_key(key, 128, &aes_key))
/* Handle the error */;
Теперь вы можете начать шифрование данных и их отправку по назначению с повторными вызовами AES_ctr128_encrypt ()
примерно так:
if (!AES_ctr128_encrypt(msg_in, msg_out, msg_len, &aes_key, state->ivec, state->ecount, &state->num))
/* Handle the error */;
( msg_in
- указатель на буфер, содержащий сообщение с открытым текстом, msg_out
- указатель на буфер, в который должно быть отправлено зашифрованное сообщение, и msg_len
- длина сообщения).
Расшифровка точно такая же, за исключением того, что вы не генерируете IV с помощью RAND_bytes ()
- вместо этого вы берете значение, данное вам другой стороной.
Важно:
Не вызывайте init_ctr ()
более одного раза в процессе шифрования. Счетчик и IV должны быть инициализированы только один раз до начала шифрования.
Ни при каких обстоятельствах не поддавайтесь соблазну получить IV где-нибудь, кроме RAND_bytes ()
на стороне шифрования. Не устанавливайте фиксированное значение; не используйте хеш-функцию; не используйте имя получателя; не читайте это с диска. Сгенерируйте его с помощью RAND_bytes ()
и отправьте по назначению. Каждый раз, когда вы начинаете с нулевого счетчика, вы должны начинать с совершенно нового IV, который вы никогда раньше не использовали.
Если возможно, что вы отправите 2 ** 64 байта без изменения IV и / или ключа, вам нужно будет проверить переполнение счетчика.
Не пропускайте проверку ошибок. Если функция не работает, и вы ее игнорируете, вполне возможно (даже вероятно), что ваша система будет работать нормально, но на самом деле будет работать совершенно небезопасно.
Похоже, основная проблема с вашей тестовой программой заключается в том, что значения режима вызовов fopen
неверны. Я думаю, вам нужно изменить ваши вызовы fopen в шифровании на это:
fp=fopen("input.txt","rb");
op=fopen("output.txt","wb");
А те, что в дешифровании, на:
rp=fopen("recovered.txt","wb");
op=fopen("output.txt","rb");
Еще одна вещь, на которую стоит обратить внимание, это то, что ckey
, вероятно, должен быть объявлен как 32-байтовый (256 бит) буфер. Это правда, что 128-битное шифрование использует только 16 байт данных из ключа. Но функция OpenSSL AES_set_encrypt_key
(по крайней мере, в используемой мной версии) считывает 32 байта из этого буфера. Он использует только соответствующее количество байтов, но чтение происходит. Это означает, что если буфер имеет размер всего 16 байт и заканчивается в конце страницы, примыкающей к нечитаемой странице в памяти, это приведет к нарушению прав доступа.
О, и я только что заметил, что там есть посторонний вызов free
. Вызов free(buffer);
недействителен, поскольку буфер никогда не выделялся. Я понимаю, что ваш код — всего лишь простой тест, но... ну, мы программисты и не можем помочь себе сами.