gpt4 book ai didi

c - 如何将计数器模式下的AES_encrypt转换为EVP接口(interface)?

转载 作者:太空宇宙 更新时间:2023-11-04 04:23:12 24 4
gpt4 key购买 nike

我正在围绕需要 AES Ctr 128 的通用加密编写一些东西。所以我正在挖掘一些加密的东西。

目前我测试了一个有效的代码(在此处找到)(加密/解密文件):

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


struct ctr_state {
unsigned char ivec[AES_BLOCK_SIZE];
unsigned int num;
unsigned char ecount[AES_BLOCK_SIZE];
};

void print_hex(unsigned char *c) {
for(int i = 0; i < 16; i++) {
printf("%02X.", c[i]);
}
printf("\n");
}


void init_ctr(struct ctr_state *state, const unsigned char iv[16]) {
state->num = 0;
memset(state->ecount, 0, 16);
memset(state->ivec + 8, 0, 8);
memcpy(state->ivec, iv, 8);
}

void fencrypt(char* read, char* write, const unsigned char* enc_key) {

FILE *readFile;
FILE *writeFile;
AES_KEY key;

int bytes_read;
unsigned char indata[AES_BLOCK_SIZE];
unsigned char outdata[AES_BLOCK_SIZE];
unsigned char iv[AES_BLOCK_SIZE];

struct ctr_state state;


RAND_bytes(iv, AES_BLOCK_SIZE);

print_hex(iv);
readFile = fopen(read,"rb");
writeFile = fopen(write,"wb");


AES_set_encrypt_key(enc_key, 128, &key);

init_ctr(&state, iv);

fwrite(state.ivec, 1, AES_BLOCK_SIZE, writeFile);

print_hex(state.ivec);

while(1) {
bytes_read = fread(indata, 1, AES_BLOCK_SIZE, readFile);
AES_ctr128_encrypt(indata, outdata, bytes_read, &key, state.ivec, state.ecount, &state.num);

print_hex(state.ivec);
fwrite(outdata, 1, bytes_read, writeFile);
if (bytes_read < AES_BLOCK_SIZE) {
break;
}
}

fclose(writeFile);
fclose(readFile);
}

void fdecrypt(char* read, char* write, const unsigned char* enc_key) {

FILE *readFile;
FILE *writeFile;
AES_KEY key;

int bytes_read;
unsigned char indata[AES_BLOCK_SIZE];
unsigned char outdata[AES_BLOCK_SIZE];
unsigned char iv[AES_BLOCK_SIZE];

struct ctr_state state;

readFile=fopen(read,"rb");
writeFile=fopen(write,"wb");

fread(iv, 1, AES_BLOCK_SIZE, readFile);

AES_set_encrypt_key(enc_key, 128, &key);

init_ctr(&state, iv);

while(1) {
bytes_read = fread(indata, 1, AES_BLOCK_SIZE, readFile);
AES_ctr128_encrypt(indata, outdata, bytes_read, &key, state.ivec, state.ecount, &state.num);

print_hex(state.ivec);
fwrite(outdata, 1, bytes_read, writeFile);
if (bytes_read < AES_BLOCK_SIZE) {
break;
}
}
fclose(writeFile);
fclose(readFile);
}

int main(int argc, char *argv[]) {
char* secret = "supersecret";

fencrypt("encme.txt", "enced.enc", (const unsigned char*)secret);
fdecrypt("enced.enc", "unenced.txt", (const unsigned char*)secret);
}

这很好用。但似乎标准是现在使用 EVP 函数和 openssl。所以我尝试调整我的代码,但我的实现显然有问题。我不明白如何正确更新/增加 IV vector 。

这是我带有 EVP 的新代码(工作但不是增量/计数器):

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


struct ctr_state {
EVP_CIPHER_CTX* cipher;
int num;
};

void print_hex(unsigned char *c) {
for(int i = 0; i < 16; i++) {
printf("%02X.", c[i]);
}
printf("\n");
}

void init_ctr(struct ctr_state *state, unsigned char iv[16], unsigned char* key) {
state->num = 0;
state->cipher = EVP_CIPHER_CTX_new();
EVP_EncryptInit_ex(state->cipher, EVP_aes_128_ctr(), NULL, key, iv);
}

void fencrypt(char* read, char* write, unsigned char* enc_key) {

FILE *readFile;
FILE *writeFile;

int bytes_read;
unsigned char indata[AES_BLOCK_SIZE];
unsigned char outdata[AES_BLOCK_SIZE];
unsigned char iv[AES_BLOCK_SIZE];

struct ctr_state state;

RAND_bytes(iv, AES_BLOCK_SIZE);

readFile = fopen(read,"rb");
writeFile = fopen(write,"wb");

fwrite(iv, 1, AES_BLOCK_SIZE, writeFile);
init_ctr(&state, iv, enc_key);
print_hex(iv);

while(1) {
bytes_read = fread(indata, 1, AES_BLOCK_SIZE, readFile);

EVP_EncryptUpdate(state.cipher, outdata, &state.num, indata, bytes_read);

EVP_EncryptUpdate(state.cipher, outdata, &state.num, indata, bytes_read);

fwrite(outdata, 1, bytes_read, writeFile);
if (bytes_read < AES_BLOCK_SIZE) {
break;
}
}

fclose(writeFile);
fclose(readFile);
}

void fdecrypt(char* read, char* write, unsigned char* enc_key) {

FILE *readFile;
FILE *writeFile;

int bytes_read;
unsigned char indata[AES_BLOCK_SIZE];
unsigned char outdata[AES_BLOCK_SIZE];
unsigned char iv[AES_BLOCK_SIZE];

struct ctr_state state;

readFile = fopen(read,"rb");
writeFile = fopen(write,"wb");

fread(iv, 1, AES_BLOCK_SIZE, readFile);
init_ctr(&state, iv, enc_key);

print_hex(iv);

while(1) {
bytes_read = fread(indata, 1, AES_BLOCK_SIZE, readFile);

EVP_EncryptUpdate(state.cipher, outdata, &state.num, indata, bytes_read);
printf("Pass %d ",state.num);

fwrite(outdata, 1, bytes_read, writeFile);
if (bytes_read < AES_BLOCK_SIZE) {
break;
}
}

fclose(writeFile);
fclose(readFile);
}

int main(int argc, char *argv[]) {
char* secret = "supersecret";

fencrypt("encme.txt", "enced.enc", (unsigned char*)secret);
fdecrypt("enced.enc", "unenced.txt", (unsigned char*)secret);
}

感谢任何帮助。谢谢。

最佳答案

好的,我想我明白了。

我将在这里复制我的两个程序示例:

AES_CTR_128(无 EVP):

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

struct ctr_state {
unsigned int num;
unsigned char ivec[AES_BLOCK_SIZE];
unsigned char ecount[AES_BLOCK_SIZE];
};

void init_ctr(struct ctr_state *state, const unsigned char iv[16]) {
state->num = 0;
memset(state->ecount, 0, 16);
memset(state->ivec + 8, 0, 8);
memcpy(state->ivec, iv, 8);
}

void fencrypt(char* read, char* write, const unsigned char* enc_key) {

FILE *readFile;
FILE *writeFile;
AES_KEY key;

int bytes_read;
unsigned char indata[AES_BLOCK_SIZE];
unsigned char outdata[AES_BLOCK_SIZE];
struct ctr_state state;
unsigned char *iv = (unsigned char *)"0123456789012345";

readFile = fopen(read,"rb");
writeFile = fopen(write,"wb");

fwrite(iv, 1, AES_BLOCK_SIZE, writeFile);

AES_set_encrypt_key(enc_key, 128, &key);
init_ctr(&state, iv);

while(1) {
bytes_read = fread(indata, 1, AES_BLOCK_SIZE, readFile);

AES_ctr128_encrypt(indata, outdata, bytes_read, &key, state.ivec, state.ecount, &state.num);

fwrite(outdata, 1, bytes_read, writeFile);
if (bytes_read < AES_BLOCK_SIZE) {
break;
}
}

fclose(writeFile);
fclose(readFile);
}

void fdecrypt(char* read, char* write, const unsigned char* enc_key) {

FILE *readFile;
FILE *writeFile;
AES_KEY key;

int bytes_read;
unsigned char indata[AES_BLOCK_SIZE];
unsigned char outdata[AES_BLOCK_SIZE];
unsigned char iv[AES_BLOCK_SIZE];
struct ctr_state state;

readFile=fopen(read,"rb");
writeFile=fopen(write,"wb");

fread(iv, 1, AES_BLOCK_SIZE, readFile);

AES_set_encrypt_key(enc_key, 128, &key);
init_ctr(&state, iv);

while(1) {
bytes_read = fread(indata, 1, AES_BLOCK_SIZE, readFile);
AES_ctr128_encrypt(indata, outdata, bytes_read, &key, state.ivec, state.ecount, &state.num);

fwrite(outdata, 1, bytes_read, writeFile);
if (bytes_read < AES_BLOCK_SIZE) {
break;
}
}

fclose(writeFile);
fclose(readFile);
}

int main(int argc, char *argv[]) {
unsigned char *secret = (unsigned char *)"0123456789012345";

fencrypt("encme.txt", "enced.enc", secret);
fdecrypt("enced.enc", "unenced.txt", secret);
}

在另一个例子中,一切都是经典的。IV(或随机数)是常量以使调试更容易(不要那样做)。

在我的 EVP 代码下面:

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


struct ctr_state {
EVP_CIPHER_CTX* cipher;
unsigned int num;
unsigned char ivec[AES_BLOCK_SIZE];
unsigned char ecount[AES_BLOCK_SIZE];
};

static void AES_ctr128_inc(unsigned char *counter) {
unsigned char* cur_pos;

for (cur_pos = counter + 15; cur_pos >= counter; cur_pos--) {
(*cur_pos)++;
if (*cur_pos != 0) {
break;
}
}
}

void AES_ctr128_EVPencrypt(EVP_CIPHER_CTX* cipher, const unsigned char *in, unsigned char *out,
const unsigned long length,
unsigned char counter[AES_BLOCK_SIZE],
unsigned char ecount_buf[AES_BLOCK_SIZE],
unsigned int *num) {

int nb;
unsigned int n;
unsigned long l=length;

n = *num;

while (l--) {
if (n == 0) {
EVP_EncryptUpdate(cipher, ecount_buf, &nb, counter, AES_BLOCK_SIZE);
AES_ctr128_inc(counter);
}
*(out++) = *(in++) ^ ecount_buf[n];
n = (n+1) % AES_BLOCK_SIZE;
}

*num=n;
}

void init_ctr(struct ctr_state *state, unsigned char iv[16], unsigned char* key) {
state->num = 0;
memset(state->ecount, 0, 16);
memset(state->ivec + 8, 0, 8);
memcpy(state->ivec, iv, 8);
state->cipher = EVP_CIPHER_CTX_new();
EVP_EncryptInit_ex(state->cipher, EVP_aes_128_ecb(), NULL, key, NULL);
}

void fencrypt(char* read, char* write, unsigned char* enc_key) {

FILE *readFile;
FILE *writeFile;

int bytes_read;
unsigned char indata[AES_BLOCK_SIZE];
unsigned char outdata[AES_BLOCK_SIZE];
struct ctr_state state;
unsigned char *iv = (unsigned char *)"0123456789012345";

readFile = fopen(read,"rb");
writeFile = fopen(write,"wb");

fwrite(iv, 1, AES_BLOCK_SIZE, writeFile);

init_ctr(&state, iv, enc_key);

while(1) {
bytes_read = fread(indata, 1, AES_BLOCK_SIZE, readFile);

AES_ctr128_EVPencrypt(state.cipher, indata, outdata, bytes_read, state.ivec, state.ecount, &state.num);

fwrite(outdata, 1, bytes_read, writeFile);
if (bytes_read < AES_BLOCK_SIZE) {
break;
}
}

fclose(writeFile);
fclose(readFile);
}

void fdecrypt(char* read, char* write, unsigned char* enc_key) {

FILE *readFile;
FILE *writeFile;

int bytes_read;
unsigned char indata[AES_BLOCK_SIZE];
unsigned char outdata[AES_BLOCK_SIZE];
unsigned char iv[AES_BLOCK_SIZE];
struct ctr_state state;

readFile = fopen(read,"rb");
writeFile = fopen(write,"wb");

fread(iv, 1, AES_BLOCK_SIZE, readFile);

init_ctr(&state, iv, enc_key);

while(1) {
bytes_read = fread(indata, 1, AES_BLOCK_SIZE, readFile);

AES_ctr128_EVPencrypt(state.cipher, indata, outdata, bytes_read, state.ivec, state.ecount, &state.num);

fwrite(outdata, 1, bytes_read, writeFile);
if (bytes_read < AES_BLOCK_SIZE) {
break;
}
}

fclose(writeFile);
fclose(readFile);
}

int main(int argc, char *argv[]) {
unsigned char *secret = (unsigned char *)"0123456789012345";

fencrypt("encme.txt", "enced.enc", (unsigned char*)secret);
fdecrypt("enced.enc", "unenced.txt", secret);
}

所以我基本上复制了 AES_ctr_encrypt 函数来使用 EVP,并对其进行适配。

它对我有用,因为我可以使用这两种实现来加密/解密同一个程序。

欢迎评论。问题仍然是 EVP 中的 aes_ctr_128 是做什么的?以及如何使用它?我想我已经重新发明了轮子。

关于c - 如何将计数器模式下的AES_encrypt转换为EVP接口(interface)?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/44246967/

24 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com