Warning: file_get_contents(/data/phpspider/zhask/data//catemap/4/c/70.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
使用openssl C进行AES(AES-cbc-128、AES-cbc-192、AES-cbc-256)加密/解密_C_Openssl_Aes - Fatal编程技术网

使用openssl C进行AES(AES-cbc-128、AES-cbc-192、AES-cbc-256)加密/解密

使用openssl C进行AES(AES-cbc-128、AES-cbc-192、AES-cbc-256)加密/解密,c,openssl,aes,C,Openssl,Aes,我只想用这3种模式测试openSSL中的AES:128192和256密钥长度,但我解密的文本与我的输入不同,我不知道为什么。此外,当我传递一个巨大的输入长度(比如1024字节)时,我的程序显示核心转储。。。我的意见总是一样的,但这并不重要,至少现在是这样。代码如下: #include <stdio.h> #include <stdlib.h> #include <string.h> #include <openssl/aes.h> int mai

我只想用这3种模式测试openSSL中的AES:128192和256密钥长度,但我解密的文本与我的输入不同,我不知道为什么。此外,当我传递一个巨大的输入长度(比如1024字节)时,我的程序显示
核心转储
。。。我的意见总是一样的,但这并不重要,至少现在是这样。代码如下:

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

int main(int argc, char **argv)
{
    int i;
    int keylength;
    printf("Give a key length [only 128 or 192 or 256!]:\n");
    scanf("%d", &keylength);

    /* generate a key with a given length */
    unsigned char aes_key[keylength];
    memset(aes_key, 0, sizeof(aes_key));
    if (!RAND_bytes(aes_key, keylength))
    {
        exit(-1);
    }
    aes_key[keylength-1] = '\0';

    int inputslength;
    printf("Give an input's length:\n");
    scanf("%d", &inputslength);

    /* generate input with a given length */
    unsigned char aes_input[inputslength+1];
    memset(aes_input, '0', sizeof(aes_input));
    aes_input[inputslength] = '\0';

    /*printf("original:\t");
    for(i=0; i<inputslength; i++)
    {
        printf("%c ", aes_input[i]);
    }
    printf("\n");*/

    /* init vector */
    unsigned char iv[AES_BLOCK_SIZE];
    if (!RAND_bytes(iv, AES_BLOCK_SIZE))
    {
        exit(-1);
    }

    //printf("AES_BLOCK_SIZE = %d\n", AES_BLOCK_SIZE); // aes block size is 16 bytes = 128 bits
    AES_KEY enc_key, dec_key;
    unsigned char enc_out[AES_BLOCK_SIZE];
    unsigned char dec_out[AES_BLOCK_SIZE];

    // so i can do with this aes-cbc-128 aes-cbc-192 aes-cbc-256
    AES_set_encrypt_key(aes_key, keylength, &enc_key);
    AES_cbc_encrypt(aes_input, enc_out, inputslength, &enc_key, iv, AES_ENCRYPT);

    AES_set_decrypt_key(aes_key, keylength, &dec_key);
    AES_decrypt(enc_out, dec_out, &dec_key);

    printf("original:\t");
    for(i=0;*(aes_input+i)!=0x00;i++)
        printf("%X ",*(aes_input+i));
    printf("\nencrypted:\t");

    for(i=0;*(enc_out+i)!=0x00;i++)
        printf("%X ",*(enc_out+i));

    printf("\ndecrypted:\t");
    for(i=0;*(dec_out+i)!=0x00;i++)
        printf("%X ",*(dec_out+i));
    printf("\n");

    /*printf("\n\noriginal:\t");
    for(i=0; i<inputslength; i++)
    {
        printf("%x ", dec_out[i]);
    }
    printf("\n");*/


    return 0;
}

那么,输出口的大小和iv的大小是否可能存在问题?它们应该有多大的尺寸(适用于AES-CBC-128、AES-CBC-192、AES-CBC-256)?

看看您的代码的这个修改版本。注意以下几点:

  • 添加十六进制打印(小调)
  • 添加了密钥缓冲区的适当大小(中等)
  • 添加了输出加密缓冲区的适当大小(必须是块大小的倍数,如果原始源缓冲区是块大小的精确倍数,则仍然需要一个完整的填充块(有关更多信息,请参阅PKCS 5填充)
  • 相同的IV用于加密和解密
  • 最后,加密和解密都使用了看似奇怪的
    AES\u cbc\u encrypt()
    (请参阅调用中的最后一个参数)
  • 源代码

    #include <stdio.h>
    #include <stdlib.h>
    #include <string.h>
    #include <openssl/aes.h>
    #include <openssl/rand.h>
    
    // a simple hex-print routine. could be modified to print 16 bytes-per-line
    static void hex_print(const void* pv, size_t len)
    {
        const unsigned char * p = (const unsigned char*)pv;
        if (NULL == pv)
            printf("NULL");
        else
        {
            size_t i = 0;
            for (; i<len;++i)
                printf("%02X ", *p++);
        }
        printf("\n");
    }
    
    // main entrypoint
    int main(int argc, char **argv)
    {
        int keylength;
        printf("Give a key length [only 128 or 192 or 256!]:\n");
        scanf("%d", &keylength);
    
        /* generate a key with a given length */
        unsigned char aes_key[keylength/8];
        memset(aes_key, 0, keylength/8);
        if (!RAND_bytes(aes_key, keylength/8))
            exit(-1);
    
        size_t inputslength = 0;
        printf("Give an input's length:\n");
        scanf("%lu", &inputslength);
    
        /* generate input with a given length */
        unsigned char aes_input[inputslength];
        memset(aes_input, 'X', inputslength);
    
        /* init vector */
        unsigned char iv_enc[AES_BLOCK_SIZE], iv_dec[AES_BLOCK_SIZE];
        RAND_bytes(iv_enc, AES_BLOCK_SIZE);
        memcpy(iv_dec, iv_enc, AES_BLOCK_SIZE);
    
        // buffers for encryption and decryption
        const size_t encslength = ((inputslength + AES_BLOCK_SIZE) / AES_BLOCK_SIZE) * AES_BLOCK_SIZE;
        unsigned char enc_out[encslength];
        unsigned char dec_out[inputslength];
        memset(enc_out, 0, sizeof(enc_out));
        memset(dec_out, 0, sizeof(dec_out));
    
        // so i can do with this aes-cbc-128 aes-cbc-192 aes-cbc-256
        AES_KEY enc_key, dec_key;
        AES_set_encrypt_key(aes_key, keylength, &enc_key);
        AES_cbc_encrypt(aes_input, enc_out, inputslength, &enc_key, iv_enc, AES_ENCRYPT);
    
        AES_set_decrypt_key(aes_key, keylength, &dec_key);
        AES_cbc_encrypt(enc_out, dec_out, encslength, &dec_key, iv_dec, AES_DECRYPT);
    
        printf("original:\t");
        hex_print(aes_input, sizeof(aes_input));
    
        printf("encrypt:\t");
        hex_print(enc_out, sizeof(enc_out));
    
        printf("decrypt:\t");
        hex_print(dec_out, sizeof(dec_out));
    
        return 0;
    }
    
    第二次测试输出

    Give a key length [only 128 or 192 or 256!]:
    128
    Give an input's length:
    10
    original:   58 58 58 58 58 58 58 58 58 58 
    encrypt:    A9 66 C5 24 A4 02 AB 96 08 65 F7 22 A5 FB BE 26 
    decrypt:    58 58 58 58 58 58 58 58 58 58 
    
    Give a key length [only 128 or 192 or 256!]:
    128
    Give an input's length:
    10
    original:   58 58 58 58 58 58 58 58 58 58 
    encrypt:    C2 47 6D B1 A1 68 29 53 55 74 C5 CC 3F 27 0A 3F 
    decrypt:    58 58 58 58 58 58 58 58 58 58 
    

    我真诚地希望这能有所帮助。

    @WhozCraig:非常感谢您的帮助!它向我解释了很多!但还有一个问题。我将静态数组更改为动态数组。当我这样做时,出现了一些错误。但只有当我提供了大量输入时才会出现错误,请查看valgrind输出:。错误仅在我传递大量输入时发生,当我通过一个小尺寸的(如你的例子中的10)就可以了。其他一切都很好地工作

    #include <stdio.h>
    #include <stdlib.h>
    #include <string.h>
    #include <openssl/aes.h>
    #include <openssl/rand.h>
    
    // a simple hex-print routine. could be modified to print 16 bytes-per-line
    static void hex_print(const void* pv, size_t len)
    {
        const unsigned char * p = (const unsigned char*)pv;
        if (NULL == pv)
            printf("NULL");
        else
        {
            size_t i = 0;
            for (; i<len;++i)
                printf("%02X ", *p++);
        }
        printf("\n");
    }
    
    // main entrypoint
    int main(int argc, char **argv)
    {
        size_t inputslength = 0;
        printf("Give an input's length:\n");
        scanf("%lu", &inputslength);
    
        int keylength;
        printf("Give a key length [only 128 or 192 or 256!]:\n");
        scanf("%d", &keylength);
    
    
        //  generate a key with a given length
        unsigned char *aes_key = (unsigned char*)malloc(sizeof(unsigned char) * (keylength/8));
        memset(aes_key, 0, keylength/8);
        RAND_bytes(aes_key, keylength/8);
    
        //  generate input with a given length
        unsigned char *aes_input = (unsigned char*)malloc(sizeof(unsigned char) * (inputslength));
        memset(aes_input, 'X', sizeof(aes_input));
    
        // init vectors
        unsigned char *iv_enc = (unsigned char*)malloc(sizeof(unsigned char) * (AES_BLOCK_SIZE));
        unsigned char *iv_dec = (unsigned char*)malloc(sizeof(unsigned char) * (AES_BLOCK_SIZE));
        // iv_dec == iv_enc
        RAND_bytes(iv_enc, AES_BLOCK_SIZE);
        memcpy(iv_dec, iv_enc, AES_BLOCK_SIZE);
    
        // buffers for encryption and decryption
        const size_t length = (((inputslength + AES_BLOCK_SIZE) / AES_BLOCK_SIZE) * AES_BLOCK_SIZE);
        unsigned char *enc_out = (unsigned char*)malloc(sizeof(unsigned char) * (length));
        unsigned char *dec_out = (unsigned char*)malloc(sizeof(unsigned char) * (inputslength));
    
        // so i can do with this aes-cbc-128 aes-cbc-192 aes-cbc-256
        AES_KEY encKey, decKey;
        AES_set_encrypt_key(aes_key, keylength, &encKey);
        AES_cbc_encrypt(aes_input, enc_out, inputslength, &encKey, iv_enc, AES_ENCRYPT);
    
        AES_set_decrypt_key(aes_key, keylength, &decKey);
        AES_cbc_encrypt(enc_out, dec_out, length, &decKey, iv_dec, AES_DECRYPT);
    
        printf("original:\t");
        hex_print(aes_input, sizeof(aes_input));
    
        printf("encrypt:\t");
        hex_print(enc_out, sizeof(enc_out));
    
        printf("decrypt:\t");
        hex_print(dec_out, sizeof(dec_out));
    
        free(aes_key);
        aes_key = NULL;
        free(aes_input);
        aes_input = NULL;
        free(iv_enc);
        iv_enc = NULL;
        free(iv_dec);
        iv_dec = NULL;
        free(enc_out);
        enc_out = NULL;
        free(dec_out);
        dec_out = NULL;
    
        return 0;
    }
    
    #包括
    #包括
    #包括
    #包括
    #包括
    //一个简单的十六进制打印例程。可以修改为每行打印16字节
    静态无效十六进制打印(常量无效*pv,尺寸长度)
    {
    常量无符号字符*p=(常量无符号字符*)pv;
    如果(NULL==pv)
    printf(“空”);
    其他的
    {
    尺寸i=0;
    
    对于(;IsIdefine:您的AES密钥不需要以null结尾。这是一个随机的字节块;仅此而已。它没有任何null项,因此
    AES_key[keylength-1]='\0'
    是无意义的(除非它总是将密钥的最后一个字节(顺便说一句,它比需要的字节大8倍)设置为零)@WhozCraig:谢谢,很高兴知道这一点。主要问题是什么,你有什么想法吗?很多。加密和解密的缓冲区大小远远不够大。你需要一个通用的十六进制打印函数,而不是试图把这些东西当作字符数据。它是二进制的。现在就形成一个正式的答案,但从那里开始寻找。你应该uld不能使用
    AES\u encrypt
    和friends。您应该使用
    EVP\u*
    函数。请参阅OpenSSL wiki上的。事实上,您可能应该使用经过身份验证的加密,因为它提供机密性和真实性。请参阅OpenSSL wiki上的。很抱歉打扰您,您是对的,现在一切都很好:)我认为这段代码是错误的。我的测试用例:keylen=128,inputlen=100。你应该再测试一次。@g10guang如果你能描述你认为它应该做什么,它实际上在做什么,以及它们之间的区别,我会感兴趣的是你为什么认为它是错误的。它不是。它正是我想要做的:生成一个随机键,一个随机键四、 加密由
    'X'
    字符填充的恒定数据块,解密相同的数据,并演示原始数据、加密数据和解密数据(其中原始数据和解密数据最好相同,并且它们是相同的),使用十六进制转储进行输出。它可能没有执行您认为的操作,这可能就是断开连接的地方。请再次查看。
    sizeof()
    当与指针而不是固定或可变数组一起使用时,具有全新的含义。它成为指针的大小,而不是分配给它的数据的大小。您所有的大小都应该是变量;而不是
    sizeof(某物)
    。解决了这个问题,我打赌您最后的问题将消失。(旁注:不要抛出
    malloc()在常规C编程时,它会引起非常微妙的问题,尤其是对于可移植性。C++需要它,但是,首先,不应该在C++中使用<代码> MalCube()/<代码>。“我的GCC告诉我,-<代码> MalOC/<代码>返回空,我在用C++编写的时候,我使用<代码>新< /COD>和<代码>删除< /代码>,我知道我不应该在C++中使用<代码> MalOC/<代码>;在C编程中有可能存在的缺陷。显然,C++是必需的,但是正如你所说的,你使用<代码>新< /COD>和<代码>删除< /C> >查找“MulcC[C]”。在这个网站上。这是一个相当有争议的问题。除此之外,非常高兴您已经启动并运行。感谢您的实施!!@Puffin这是不正确的。必须有足够的空间容纳一整块填充。PKCS#5填充就是这样工作的。任何“有效”的东西都可以对于您来说,如果不考虑这种情况,那么这样做只是因为加密的明文不是AES块大小(16字节)的精确倍数,因此当这种情况最终出现时,它是一个滴答作响的定时炸弹。具体来说,描述遇到精确块大小倍数时会发生什么的段落。
    
    #include <stdio.h>
    #include <stdlib.h>
    #include <string.h>
    #include <openssl/aes.h>
    #include <openssl/rand.h>
    
    // a simple hex-print routine. could be modified to print 16 bytes-per-line
    static void hex_print(const void* pv, size_t len)
    {
        const unsigned char * p = (const unsigned char*)pv;
        if (NULL == pv)
            printf("NULL");
        else
        {
            size_t i = 0;
            for (; i<len;++i)
                printf("%02X ", *p++);
        }
        printf("\n");
    }
    
    // main entrypoint
    int main(int argc, char **argv)
    {
        size_t inputslength = 0;
        printf("Give an input's length:\n");
        scanf("%lu", &inputslength);
    
        int keylength;
        printf("Give a key length [only 128 or 192 or 256!]:\n");
        scanf("%d", &keylength);
    
    
        //  generate a key with a given length
        unsigned char *aes_key = (unsigned char*)malloc(sizeof(unsigned char) * (keylength/8));
        memset(aes_key, 0, keylength/8);
        RAND_bytes(aes_key, keylength/8);
    
        //  generate input with a given length
        unsigned char *aes_input = (unsigned char*)malloc(sizeof(unsigned char) * (inputslength));
        memset(aes_input, 'X', sizeof(aes_input));
    
        // init vectors
        unsigned char *iv_enc = (unsigned char*)malloc(sizeof(unsigned char) * (AES_BLOCK_SIZE));
        unsigned char *iv_dec = (unsigned char*)malloc(sizeof(unsigned char) * (AES_BLOCK_SIZE));
        // iv_dec == iv_enc
        RAND_bytes(iv_enc, AES_BLOCK_SIZE);
        memcpy(iv_dec, iv_enc, AES_BLOCK_SIZE);
    
        // buffers for encryption and decryption
        const size_t length = (((inputslength + AES_BLOCK_SIZE) / AES_BLOCK_SIZE) * AES_BLOCK_SIZE);
        unsigned char *enc_out = (unsigned char*)malloc(sizeof(unsigned char) * (length));
        unsigned char *dec_out = (unsigned char*)malloc(sizeof(unsigned char) * (inputslength));
    
        // so i can do with this aes-cbc-128 aes-cbc-192 aes-cbc-256
        AES_KEY encKey, decKey;
        AES_set_encrypt_key(aes_key, keylength, &encKey);
        AES_cbc_encrypt(aes_input, enc_out, inputslength, &encKey, iv_enc, AES_ENCRYPT);
    
        AES_set_decrypt_key(aes_key, keylength, &decKey);
        AES_cbc_encrypt(enc_out, dec_out, length, &decKey, iv_dec, AES_DECRYPT);
    
        printf("original:\t");
        hex_print(aes_input, sizeof(aes_input));
    
        printf("encrypt:\t");
        hex_print(enc_out, sizeof(enc_out));
    
        printf("decrypt:\t");
        hex_print(dec_out, sizeof(dec_out));
    
        free(aes_key);
        aes_key = NULL;
        free(aes_input);
        aes_input = NULL;
        free(iv_enc);
        iv_enc = NULL;
        free(iv_dec);
        iv_dec = NULL;
        free(enc_out);
        enc_out = NULL;
        free(dec_out);
        dec_out = NULL;
    
        return 0;
    }
    
    #include <stdio.h>
    #include <stdlib.h>
    #include <string.h>
    #include <openssl/aes.h>
    #include <openssl/rand.h>
    
    // a simple hex-print routine. could be modified to print 16 bytes-per-line
    static void hex_print(const void* pv, size_t len)
    {
        const unsigned char * p = (const unsigned char*)pv;
        if (NULL == pv)
            printf("NULL");
        else
        {
            size_t i = 0;
            for (; i<len;++i)
                printf("%02X ", *p++);
        }
        printf("\n");
    }
    
    // main entrypoint
    int main(int argc, char **argv)
    {
        int keylength;
        printf("Give a key length [only 128 or 192 or 256!]:\n");
        scanf("%d", &keylength);
    
        /* generate a key with a given length */
        unsigned char *aes_key = (unsigned char*)malloc(sizeof(unsigned char) * (keylength/8));
        memset(aes_key, 0, keylength/8);
        if (!RAND_bytes(aes_key, keylength/8))
            exit(-1);
    
        size_t inputslength = 0;
        printf("Give an input's length:\n");
        scanf("%lu", &inputslength);
    
        /* generate input with a given length */
        unsigned char *aes_input = (unsigned char*)malloc(sizeof(unsigned char) *inputslength);
        memset(aes_input, 'X', inputslength);
    
        /* init vector */
        unsigned char *iv_enc = (unsigned char*)malloc(sizeof(unsigned char) *AES_BLOCK_SIZE), *iv_dec = (unsigned char*)malloc(sizeof(unsigned char) *AES_BLOCK_SIZE);
        RAND_bytes(iv_enc, AES_BLOCK_SIZE);
        memcpy(iv_dec, iv_enc, AES_BLOCK_SIZE);
    
        // buffers for encryption and decryption
        const size_t encslength = ((inputslength + AES_BLOCK_SIZE) / AES_BLOCK_SIZE) * AES_BLOCK_SIZE;
        unsigned char *enc_out = (unsigned char*)malloc(sizeof(unsigned char) *encslength);
        unsigned char *dec_out = (unsigned char*)malloc(sizeof(unsigned char) *inputslength);
        memset(enc_out, 0, sizeof(enc_out));
        memset(dec_out, 0, sizeof(dec_out));
    
        // so i can do with this aes-cbc-128 aes-cbc-192 aes-cbc-256
        AES_KEY enc_key, dec_key;
        AES_set_encrypt_key(aes_key, keylength, &enc_key);
        AES_cbc_encrypt(aes_input, enc_out, inputslength, &enc_key, iv_enc, AES_ENCRYPT);
    
        AES_set_decrypt_key(aes_key, keylength, &dec_key);
        AES_cbc_encrypt(enc_out, dec_out, encslength, &dec_key, iv_dec, AES_DECRYPT);
    
        printf("original:\t");
        hex_print(aes_input, inputslength);
    
        printf("encrypt:\t");
        hex_print(enc_out, encslength);
    
        printf("decrypt:\t");
        hex_print(dec_out, inputslength);
    
        // free memory here
    
        return 0;
    }