gpt4 book ai didi

c - AES CTR 加解密

转载 作者:行者123 更新时间:2023-12-03 23:24:50 69 4
gpt4 key购买 nike

所以我有这个代码,它基本上加密两个纯文本消息,然后尝试解密它们,然后打印。问题是第一条消息恢复得很好,但第二条消息是垃圾。我从 this tutorial 下载了这段代码,然后将其修改为使用字符串而不是文件作为 我需要它来通过套接字发送加密文本。 所以其他端点不会知道明文的长度,有没有办法找到长度,或者我必须以某种方式将明文的长度与密码一起发送?

现在,我认为解密的中断条件存在问题。

另外,main() 代码在概念上是否正确:使用更新状态加密消息,然后重置状态并解密具有更新状态的消息?

有没有办法找出密文(不是缓冲区)的实际长度?

这只是一个我试图了解 AES CTR 将如何工作的虚拟程序。

#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>

// Code example uses partail code from: http://stackoverflow.com/questions/3141860/aes-ctr-256-encryption-mode-of-operation-on-openssl
// Mostly in the ctr_ state, and init_ctr functions.

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

int init_ctr(struct ctr_state *state, const unsigned char iv[16])
{
/* aes_ctr128_encrypt requires 'num' and 'ecount' set to zero on the
* first call. */
state->num = 0;
memset(state->ecount, 0, AES_BLOCK_SIZE);

/* Initialise counter in 'ivec' to 0 */
memset(state->ivec + 8, 0, 8);

/* Copy IV into 'ivec' */
memcpy(state->ivec, iv, 8);
}

void fencrypt(char* text, char* cipher, const unsigned char* enc_key, struct ctr_state* state)
{
AES_KEY key;
unsigned char indata[AES_BLOCK_SIZE];
unsigned char outdata[AES_BLOCK_SIZE];
int offset=0;
//Initializing the encryption KEY
if (AES_set_encrypt_key(enc_key, 128, &key) < 0)
{
fprintf(stderr, "Could not set encryption key.");
exit(1);
}

//Encrypting Blocks of 16 bytes and writing the output.txt with ciphertext
while(1)
{
printf("while going\n");
memcpy(indata, text+offset, AES_BLOCK_SIZE);
AES_ctr128_encrypt(indata, outdata, AES_BLOCK_SIZE, &key, state->ivec, state->ecount, &state->num);

memcpy(cipher+offset, outdata, AES_BLOCK_SIZE);
offset=offset+AES_BLOCK_SIZE;
if (offset > strlen(text))
{
break;
}
}
}

void fdecrypt(char* cipher, char* text, const unsigned char* enc_key, struct ctr_state* state)
{
AES_KEY key;
unsigned char indata[AES_BLOCK_SIZE];
unsigned char outdata[AES_BLOCK_SIZE];
int offset=0;
//Initializing the encryption KEY
if (AES_set_encrypt_key(enc_key, 128, &key) < 0)
{
fprintf(stderr, "Could not set decryption key.");
exit(1);
}

//Encrypting Blocks of 16 bytes and writing the output.txt with ciphertext
while(1)
{
memcpy(indata, cipher+offset, AES_BLOCK_SIZE);
//printf("%i\n", state.num);
AES_ctr128_encrypt(indata, outdata, AES_BLOCK_SIZE, &key, state->ivec, state->ecount, &state->num);

memcpy(text+offset, outdata, AES_BLOCK_SIZE);
offset=offset+AES_BLOCK_SIZE;
if (offset > strlen(cipher))
{
break;
}
}
}

int main(int argc, char *argv[])
{
unsigned char iv[AES_BLOCK_SIZE];
struct ctr_state state;
char* plain="quick brown fox jumped over the lazy dog what ";
char* plain2="a dog he is idiot who is the genius ";
char cipher[128];
char cipher2[128];
char recovered[128];
char recovered2[128];
const unsigned char* enc_key="123456789abcdef0";

if(!RAND_bytes(iv, AES_BLOCK_SIZE))
{
fprintf(stderr, "Could not create random bytes.");
exit(1);
}
init_ctr(&state, iv); //Counter call
printf("Plain text length:%lu\n",strlen(plain));
// BIO_dump_fp(stdout, plain, strlen(plain));
// printf("Plain text:%s\n",plain);
fencrypt(plain, cipher,enc_key,&state);
fencrypt(plain2, cipher2,enc_key,&state);
// cipher[strlen(plain)]='\0';
// BIO_dump_fp(stdout, cipher, strlen(plain));
init_ctr(&state, iv); //Counter call
fdecrypt(cipher,recovered,enc_key,&state);
fdecrypt(cipher2,recovered2,enc_key,&state);
// printf("Cipher text length:%lu\n",strlen(cipher));
printf("Recovered text:%s\n",recovered);
printf("Recovered text:%s\n",recovered2);
return 0;
}

最佳答案

CTR 模式不需要单独的加密和解密方法。加密 key 可以设置一次。 OpenSSL 的 AES_ctr128_encrypt 负责大部分工作,因此可以简化代码。

我们也真的需要 vector 测试。在这里,我们只是用随机文本“quick brown fox...”进行测试,我们得到相同的文本,但不能保证“密码”是正确的,无论加密是否是 AES 质量。如果有时间,我稍后会添加一个快速 vector 测试。

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

void crypt_message(const u8* src, u8* dst, unsigned int src_len, const AES_KEY* key, const u8* iv)
{
struct ctr_state state;
init_ctr(&state, iv);
AES_ctr128_encrypt(src, dst, src_len, key, state.ivec, state.ecount, &state.num);
}

int main()
{
int len;
char source[128];
char cipher[128];
char recovered[128];
unsigned char iv[AES_BLOCK_SIZE];

const unsigned char* enc_key = (const unsigned char*)"123456789abcdef0";

if(!RAND_bytes(iv, AES_BLOCK_SIZE))
{
fprintf(stderr, "Could not create random bytes.");
exit(1);
}

AES_KEY key;
AES_set_encrypt_key(enc_key, 128, &key);

strcpy(source, "quick brown fox jumped over the lazy dog what.");
len = strlen(source);
memset(recovered, 0, sizeof(recovered));
crypt_message((const u8*)source, (u8*)cipher, len, &key, iv);
crypt_message((const u8*)cipher, (u8*)recovered, len, &key, iv);
printf("Recovered text:%s\n", recovered);

strcpy(source, "a dog he is idiot who is the genius.");
len = strlen(source);
memset(recovered, 0, sizeof(recovered));
crypt_message((const u8*)source, (u8*)cipher, len, &key, iv);
crypt_message((const u8*)cipher, (u8*)recovered, len, &key, iv);
printf("Recovered text:%s\n", recovered);

return 0;
}

加密/解密文件,或发送/接收:
void crypt_file(const u8* src_file, const u8* dst_file, const AES_KEY* key, const u8* iv)
{
struct ctr_state state;
init_ctr(&state, iv);

const int buffer_size = 512; //not less than 16
unsigned char buffer_in[buffer_size];
unsigned char buffer_out[buffer_size];
int bytes_read;

//open files and/or socket
//file/message loop
{
//read source, obtain buffer_in and bytes_read
AES_ctr128_encrypt(buffer_in, buffer_out, bytes_read, key, state.ivec, state.ecount, &state.num);
//write buffer_out/bytes_read to destination
}
//close handles
}

在您的代码中, fdecrypt() 包含 strlen(cipher) 。然而 cipher 是纯二进制数据, strlen 不能使用它。您必须手动提供长度。我将 len 参数添加到 fdecrypt 。在 main 中,为了简单起见,我使用 strlen(plaintext),尽管它应该是 cipher 数据的真实长度。更改由##change 表示
void fdecrypt(unsigned int len, char* cipher, char* text, const unsigned char* enc_key, struct ctr_state* state)
{
AES_KEY key;
unsigned char indata[AES_BLOCK_SIZE];
unsigned char outdata[AES_BLOCK_SIZE];
int offset=0;
//Initializing the encryption KEY
if (AES_set_encrypt_key(enc_key, 128, &key) < 0)
{
fprintf(stderr, "Could not set decryption key.");
exit(1);
}

//Encrypting Blocks of 16 bytes and writing the output.txt with ciphertext
while(1)
{
memcpy(indata, cipher+offset, AES_BLOCK_SIZE);
//printf("%i\n", state.num);
AES_ctr128_encrypt(indata, outdata, AES_BLOCK_SIZE, &key, state->ivec, state->ecount, &state->num);

memcpy(text+offset, outdata, AES_BLOCK_SIZE);
offset=offset+AES_BLOCK_SIZE;
//if (offset > strlen(cipher))##changed
if (offset > len)
{
break;
}
}
}

int main(int argc, char *argv[])
{
unsigned char iv[AES_BLOCK_SIZE];
struct ctr_state state;
char* plain="quick brown fox jumped over the lazy dog what ";
char* plain2="a dog he is idiot who is the genius ";
char cipher[128];
char cipher2[128];
char recovered[128];
char recovered2[128];
const unsigned char* enc_key=(const unsigned char*)"123456789abcdef0";

if(!RAND_bytes(iv, AES_BLOCK_SIZE))
{
fprintf(stderr, "Could not create random bytes.");
exit(1);
}

init_ctr(&state, iv); //Counter call
printf("Plain text length:%lu\n",strlen(plain));
// BIO_dump_fp(stdout, plain, strlen(plain));
// printf("Plain text:%s\n",plain);
fencrypt(plain, cipher,enc_key,&state);
fencrypt(plain2, cipher2,enc_key,&state);
// cipher[strlen(plain)]='\0';
// BIO_dump_fp(stdout, cipher, strlen(plain));
init_ctr(&state, iv); //Counter call
fdecrypt(strlen(plain), cipher,recovered,enc_key,&state);//##changed
fdecrypt(strlen(plain2), cipher2,recovered2,enc_key,&state);//##changed
// printf("Cipher text length:%lu\n",strlen(cipher));
printf("Recovered text:%s\n",recovered);
printf("Recovered text:%s\n",recovered2);
return 0;
}

关于c - AES CTR 加解密,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/29441005/

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