循环中的连接无符号char *

发布于 2025-02-04 02:20:35 字数 2142 浏览 1 评论 0原文

我正在使用库OpenSSL通过AE进行加密。由于AES是一个块密码,因此我需要将数据分成16个字节。因此,如果我想恢复消息,我需要在程序结束时团结块。

这是我的代码:

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

char key[] = "secretkey123";

int main() {
    unsigned char text_slice[128];
    unsigned char enc_slice[128];
    unsigned char dec_slice[128];
    
    unsigned char in[160];
    
    unsigned char enc_out[160] = "";
    unsigned char dec_out[160] = "";
    
    int i;
    int k = 10;
    for (i = 0; i < 16 * k; i++) {
        in[i] = 'A' + (rand() % 26);
    }
    in[160] = '\0';
    printf("IN:%s\n", in);
    
    AES_KEY enc_key, dec_key;
    
    AES_set_encrypt_key(key, 128, &enc_key);
    
    AES_set_decrypt_key(key, 128, &dec_key);
    
    for (i = 0; i < k; i++) {
        text_slice[0] = '\0';
        enc_slice[0] = "\0";
        dec_slice[0] = "\0";
        memcpy(&text_slice[0], &in[15 * i], 15);
        text_slice[16] = "\0";
        printf("TEXT SLICE: %s \n", text_slice);
        AES_encrypt(text_slice, enc_slice, &enc_key);
        memcpy(&enc_out[16 * i], &enc_slice[0], 16);
    }
    printf("ENC:%s\n", enc_out);
    for (i = 0; i < k; i++) {
        text_slice[0] = '\0';
        enc_slice[0] = "\0";
        dec_slice[0] = "\0";
        memcpy(enc_slice, &enc_out[16 * i], 16);
        enc_slice[16] = "\0";
    
        AES_decrypt(enc_slice, dec_slice, &dec_key);
        printf("Dec slice:%s \n", dec_slice);
        memcpy(&dec_out[16 * i], &dec_slice[0], 16);
    }
    printf("DEC OUT:%s\n", dec_out);
    
    return 0;
}

程序的输出如下:

IN:NWLRBBMQBHCDARZOWKKYHIDDQSCDXRJMOWFRXSJYBLDBEFSARCBYNECDYGGXXPKLORELLNMPAPQFWKHOPKMCOQHNWNKUEWHSQMGBBUQCLJJIVSWMDKQTBXIXMVTRRBLJPTNSNFWZQFJMAFADRRWSOFSBCNUVQHFF
TEXT SLICE: NWLRBBMQBHCDARZ 
TEXT SLICE: OWKKYHIDDQSCDXR 
TEXT SLICE: JMOWFRXSJYBLDBE 
TEXT SLICE: FSARCBYNECDYGGX 
TEXT SLICE: XPKLORELLNMPAPQ 
TEXT SLICE: FWKHOPKMCOQHNWN 
TEXT SLICE: KUEWHSQMGBBUQCL 
TEXT SLICE: JJIVSWMDKQTBXIX 
TEXT SLICE: MVTRRBLJPTNSNFW 
TEXT SLICE: ZQFJMAFADRRWSOF 
ENC:j�Q���

              

I'm using the library OpenSSL for encrypting through AES. Since AES is a block cipher, I need to split the data in chunks of 16 bytes. Thus, if I want to recover the message, I need to unite the chunks at the end of the program.

This is my code:

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

char key[] = "secretkey123";

int main() {
    unsigned char text_slice[128];
    unsigned char enc_slice[128];
    unsigned char dec_slice[128];
    
    unsigned char in[160];
    
    unsigned char enc_out[160] = "";
    unsigned char dec_out[160] = "";
    
    int i;
    int k = 10;
    for (i = 0; i < 16 * k; i++) {
        in[i] = 'A' + (rand() % 26);
    }
    in[160] = '\0';
    printf("IN:%s\n", in);
    
    AES_KEY enc_key, dec_key;
    
    AES_set_encrypt_key(key, 128, &enc_key);
    
    AES_set_decrypt_key(key, 128, &dec_key);
    
    for (i = 0; i < k; i++) {
        text_slice[0] = '\0';
        enc_slice[0] = "\0";
        dec_slice[0] = "\0";
        memcpy(&text_slice[0], &in[15 * i], 15);
        text_slice[16] = "\0";
        printf("TEXT SLICE: %s \n", text_slice);
        AES_encrypt(text_slice, enc_slice, &enc_key);
        memcpy(&enc_out[16 * i], &enc_slice[0], 16);
    }
    printf("ENC:%s\n", enc_out);
    for (i = 0; i < k; i++) {
        text_slice[0] = '\0';
        enc_slice[0] = "\0";
        dec_slice[0] = "\0";
        memcpy(enc_slice, &enc_out[16 * i], 16);
        enc_slice[16] = "\0";
    
        AES_decrypt(enc_slice, dec_slice, &dec_key);
        printf("Dec slice:%s \n", dec_slice);
        memcpy(&dec_out[16 * i], &dec_slice[0], 16);
    }
    printf("DEC OUT:%s\n", dec_out);
    
    return 0;
}

The output of the program is the following:

IN:NWLRBBMQBHCDARZOWKKYHIDDQSCDXRJMOWFRXSJYBLDBEFSARCBYNECDYGGXXPKLORELLNMPAPQFWKHOPKMCOQHNWNKUEWHSQMGBBUQCLJJIVSWMDKQTBXIXMVTRRBLJPTNSNFWZQFJMAFADRRWSOFSBCNUVQHFF
TEXT SLICE: NWLRBBMQBHCDARZ 
TEXT SLICE: OWKKYHIDDQSCDXR 
TEXT SLICE: JMOWFRXSJYBLDBE 
TEXT SLICE: FSARCBYNECDYGGX 
TEXT SLICE: XPKLORELLNMPAPQ 
TEXT SLICE: FWKHOPKMCOQHNWN 
TEXT SLICE: KUEWHSQMGBBUQCL 
TEXT SLICE: JJIVSWMDKQTBXIX 
TEXT SLICE: MVTRRBLJPTNSNFW 
TEXT SLICE: ZQFJMAFADRRWSOF 
ENC:j�Q���
????�7֡���*n���R  ��m7�zI#4��=v�#�(��V7��ח9.R�q����:C�%��_��!q��(��l��j�3�1�h��
Dec slice:NWLRBBMQBHCDARZ 
Dec slice:OWKKYHIDDQSCDXR 
Dec slice:JMOWFRXSJYBLDBE 
Dec slice:FSARCBYNECDYGGX 
Dec slice:XPKLORELLNMPAPQ 
Dec slice:FWKHOPKMCOQHNWN 
Dec slice:KUEWHSQMGBBUQCL 
Dec slice:JJIVSWMDKQTBXIX 
Dec slice:MVTRRBLJPTNSNFW 
Dec slice:ZQFJMAFADRRWSOF 
DEC OUT:NWLRBBMQBHCDARZ

While dec_slice works as expected, dec_out just get a copy of the memory of the first chunk. What is more surprising for me, is that enc_out performs correctly when following the same logic as dec_out. What am I missing?

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(2

泛滥成性 2025-02-11 02:20:35

钥匙必须至少具有16个字节,因为您将许多位等于128英寸的位:

AES_set_encrypt_key(key, 128, &enc_key);
AES_set_decrypt_key(key, 128, &dec_key);

您在这里的行为不确定:

    in[160] = '\0';

这些行没有道理:

    enc_slice[0] = "\0";
    dec_slice[0] = "\0";
    text_slice[16] = "\0";
    enc_slice[16] = "\0";

为什么您要编码15个字符而不是16个字符的块?

    memcpy(&text_slice[0], &in[15 * i], 15);

这是一个修改版本:

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

char key[] = "secretkey1234567";

int main() {
    unsigned char text_slice[128];
    unsigned char enc_slice[128];
    unsigned char dec_slice[128];
    unsigned char in[160];
    unsigned char enc_out[160];
    unsigned char dec_out[160];
    
    int i, k = 10;
    for (i = 0; i < 16 * k; i++) {
        in[i] = 'A' + (rand() % 26);
    }
    printf("IN: \"%.160s\"\n", (char *)in);
    
    AES_KEY enc_key, dec_key;
    AES_set_encrypt_key(key, 128, &enc_key);
    AES_set_decrypt_key(key, 128, &dec_key);
    
    for (i = 0; i < k; i++) {
        memcpy(text_slice, &in[16 * i], 16);
        printf("TEXT SLICE: %.16s\n", (char *)text_slice);
        AES_encrypt(text_slice, enc_slice, &enc_key);
        memcpy(&enc_out[16 * i], enc_slice, 16);
    }
    printf("ENC:");
    for (i = 0; i < 16 * k; i++) {
       printf(" %02X\n", enc_out[i]);
    }
    printf("\n");
    for (i = 0; i < k; i++) {
        memcpy(enc_slice, &enc_out[16 * i], 16);
        AES_decrypt(enc_slice, dec_slice, &dec_key);
        printf("Dec slice: %.16s \n", (char *)dec_slice);
        memcpy(&dec_out[16 * i], dec_slice, 16);
    }
    printf("DEC OUT: \"%.160s\"\n", (char *)dec_out);
    return 0;
}

The key must have at least 16 bytes since you pass a number of bits equal to 128 in:

AES_set_encrypt_key(key, 128, &enc_key);
AES_set_decrypt_key(key, 128, &dec_key);

You have undefined behavior here:

    in[160] = '\0';

These lines don't make sense:

    enc_slice[0] = "\0";
    dec_slice[0] = "\0";
    text_slice[16] = "\0";
    enc_slice[16] = "\0";

Why do you encode chunks of 15 characters instead of 16?

    memcpy(&text_slice[0], &in[15 * i], 15);

Here is a modified version:

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

char key[] = "secretkey1234567";

int main() {
    unsigned char text_slice[128];
    unsigned char enc_slice[128];
    unsigned char dec_slice[128];
    unsigned char in[160];
    unsigned char enc_out[160];
    unsigned char dec_out[160];
    
    int i, k = 10;
    for (i = 0; i < 16 * k; i++) {
        in[i] = 'A' + (rand() % 26);
    }
    printf("IN: \"%.160s\"\n", (char *)in);
    
    AES_KEY enc_key, dec_key;
    AES_set_encrypt_key(key, 128, &enc_key);
    AES_set_decrypt_key(key, 128, &dec_key);
    
    for (i = 0; i < k; i++) {
        memcpy(text_slice, &in[16 * i], 16);
        printf("TEXT SLICE: %.16s\n", (char *)text_slice);
        AES_encrypt(text_slice, enc_slice, &enc_key);
        memcpy(&enc_out[16 * i], enc_slice, 16);
    }
    printf("ENC:");
    for (i = 0; i < 16 * k; i++) {
       printf(" %02X\n", enc_out[i]);
    }
    printf("\n");
    for (i = 0; i < k; i++) {
        memcpy(enc_slice, &enc_out[16 * i], 16);
        AES_decrypt(enc_slice, dec_slice, &dec_key);
        printf("Dec slice: %.16s \n", (char *)dec_slice);
        memcpy(&dec_out[16 * i], dec_slice, 16);
    }
    printf("DEC OUT: \"%.160s\"\n", (char *)dec_out);
    return 0;
}
酷到爆炸 2025-02-11 02:20:35

该代码中有很多问题。

AES_SET_ENCRYPT_KEYaes_set_decrypt_key不是密钥推导函数,第二个参数应该代表第一个参数(userkeykey)的位中的长度。

如果您提供一个任意的字符串常数,例如“ secretKey123”,长度不是128,则可能会导致内存损坏或创建非常不安全的上下文以进行加密。

通常,对于基于用户密码的加密,我们使用键推导功能从任何密码生成一个密钥(例如pbkdf2scrypt)。

该行也很不好:

in[160] = '\0';

由于缓冲区的大小为160,因此最后一个索引应为160-1。如果您在索引160上写作,则实际上是溢出的。

另外,在编写C代码时,您必须真正注意到单引号和双引号之间的区别。

这很不好:

enc_slice[0] = "\0";
dec_slice[0] = "\0";

如果您使用双引号,则实际上并未在enc_slicedec_slice的第一个索引上写下值0。您正在编写一个空的仅读取常数字符串的地址。

另外:

unsigned char enc_out[160] = "";
unsigned char dec_out[160] = "";

如果您想拥有空的缓冲区,则应该做:

unsigned char enc_out[160] = {0};
unsigned char dec_out[160] = {0};

希望这是改进代码并使其正常工作的好开始。

There are many problems in that code.

The AES_set_encrypt_key and AES_set_decrypt_key are not key derivation functions, the second parameter is supposed to represent the length in bits of the first parameter (userKey).

If you provide an arbitrary string constant like "secretkey123" with a length that is not 128 in bits, it may cause memory corruption or create a very insecure context for your encryption.

In general, for user password based encryption, we generate a key from any password using a key derivation function (for example PBKDF2, or scrypt).

This line is also bad:

in[160] = '\0';

Since the buffer has a size of 160, the last index should be 160 - 1. If you write at index 160, you are actually overflowing.

Also, you must really notice the difference between single quote and double quotes when writing C code.

This is bad:

enc_slice[0] = "\0";
dec_slice[0] = "\0";

If you use double quotes, you are not actually writing the value 0 at the first index of enc_slice and dec_slice. You are writing the address of an empty read-only constant string.

Also this:

unsigned char enc_out[160] = "";
unsigned char dec_out[160] = "";

If you want to have empty buffers, you should just do:

unsigned char enc_out[160] = {0};
unsigned char dec_out[160] = {0};

Hopefully this is a good start to improve your code and make it work.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文