导航

AES学习

 

./a.out 11 hello,world
thisLen 11
cipherText: 
14 140 39 184 128 166 91 84 250 32 158 
thisLen 5
decryptedText: hello


gcc aes_ctr.c -lssl -lcrypto

 

aes可以一起加密,分开解密,验证如下

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

static void 
handleErrors(void)
{
    ERR_print_errors_fp(stderr);
    abort();
}

static int 
encrypt(unsigned char *plaintext, int plaintext_len, unsigned char *key,
            unsigned char *iv, unsigned char *ciphertext)
{
    EVP_CIPHER_CTX *ctx;

    int len;

    int ciphertext_len;

    /* Create and initialise the context */
    if (!(ctx = EVP_CIPHER_CTX_new()))
        handleErrors();

    /* Initialise the encryption operation. IMPORTANT - ensure you use a key
     * and IV size appropriate for your cipher
     * In this example we are using 256 bit AES (i.e. a 256 bit key). The
     * IV size for *most* modes is the same as the block size. For AES this
     * is 128 bits */
    if (1 != EVP_EncryptInit_ex(ctx, EVP_aes_128_ctr(), NULL, key, iv))
        handleErrors();

    /* Provide the message to be encrypted, and obtain the encrypted output.
     * EVP_EncryptUpdate can be called multiple times if necessary
     */
    if (1 != EVP_EncryptUpdate(ctx, ciphertext, &len, plaintext, plaintext_len))
        handleErrors();
    ciphertext_len = len;

    /* Finalise the encryption. Further ciphertext bytes may be written at
     * this stage.
     */
    if (1 != EVP_EncryptFinal_ex(ctx, ciphertext + len, &len))
        handleErrors();
    ciphertext_len += len;

    /* Clean up */
    EVP_CIPHER_CTX_free(ctx);

    return ciphertext_len;
}

static int 
decrypt(unsigned char *ciphertext, int ciphertext_len, unsigned char *key,
            unsigned char *iv, unsigned char *plaintext)
{
    EVP_CIPHER_CTX *ctx;

    int len;

    int plaintext_len;

    /* Create and initialise the context */
    if (!(ctx = EVP_CIPHER_CTX_new()))
        handleErrors();

    /* Initialise the decryption operation. IMPORTANT - ensure you use a key
     * and IV size appropriate for your cipher
     * In this example we are using 256 bit AES (i.e. a 256 bit key). The
     * IV size for *most* modes is the same as the block size. For AES this
     * is 128 bits */
    if (1 != EVP_DecryptInit_ex(ctx, EVP_aes_128_ctr(), NULL, key, iv))
        handleErrors();

    /* Provide the message to be decrypted, and obtain the plaintext output.
     * EVP_DecryptUpdate can be called multiple times if necessary
     */
    if (1 != EVP_DecryptUpdate(ctx, plaintext, &len, ciphertext, ciphertext_len))
        handleErrors();
    plaintext_len = len;

    /* Finalise the decryption. Further plaintext bytes may be written at
     * this stage.
     */
    if (1 != EVP_DecryptFinal_ex(ctx, plaintext + len, &len))
        handleErrors();
    plaintext_len += len;

    /* Clean up */
    EVP_CIPHER_CTX_free(ctx);

    return plaintext_len;
}

/* 256/8 = 32 */
static unsigned char sKey[32];
/* 128/8 = 16 */
static unsigned char sIv[16];

unsigned char *key = (unsigned char *)"01234567890123456789012345678901";
unsigned char *iv = (unsigned char *)"0123456789012345";
void aesCtrSet(char *key, char *iv)
{
    memcpy(sKey, key, 32);
    memcpy(sIv, iv, 16);
}



int
aesCtrEncrypt(unsigned char *plainText, unsigned char *cipherText, int len)
{
    int thisLen;

    thisLen = encrypt(plainText, len, sKey, sIv, cipherText);

    printf("thisLen %d\n", thisLen);
    printf("cipherText: \n");
    for (int i = 0; i < thisLen; i++)
        printf("%d ", cipherText[i]);
    printf("\n");

}

int
aesCtrDecrypt(unsigned char *cipherText, unsigned char *decryptedText, int len)
{
    int thisLen;

    thisLen = decrypt(cipherText, len, sKey, sIv, decryptedText);

    printf("thisLen %d\n", thisLen);
    printf("decryptedText: %s\n", decryptedText);
#if 0
    for (int i = 0; i < thisLen; i++)
        printf("%d ", decryptedText[i]);
    printf("\n");
#endif
}


int main(int argc, char **argv)
{
    int len = atoi(argv[1]);
    unsigned char p[len];
    aesCtrEncrypt(argv[2], p, len);

    unsigned char p2[5];
    aesCtrDecrypt(p, p2, 5);
    return 0;

}

 

------------------

实现里需要的key和iv可以使用openssl命令生成

未验证

https://superuser.com/questions/455463/openssl-hash-function-for-generating-aes-key

--------

AES官网

https://www.openssl.org/source/

----------------------

源码出处

https://wiki.openssl.org/index.php/EVP_Symmetric_Encryption_and_Decryption#Decrypting_the_Message

参照源码出处

https://blog.csdn.net/yasi_xi/article/details/13997337

这里有说到解密后的长度和加密前的长度不一致,有说是和mode有关

我使用源码加密17位数据,加密后的长度仍是17位,即这里没改。链接里是照搬StackOverflow的答案,但我判断不出来哪个是正确的。

 如cbc有不一致问题

https://blog.csdn.net/you_lan_hai/article/details/50992719

https://blog.csdn.net/mao834099514/article/details/54945776

StackOverflow链接

https://stackoverflow.com/questions/3283787/size-of-data-after-aes-cbc-and-aes-ecb-encryption

---------

openssl资料

https://blog.csdn.net/shuanyancao/article/details/8985963

参照源码,上手

https://blog.csdn.net/it_liuwei/article/details/80620740

https://blog.csdn.net/weixin_43844907/article/details/105041589

--------------------------

休息日也在弄这个。

我读书的时候没关注过库,更别提openssl的库了。今天发现,别人读研的时候学习的这个。我需要几天来把这个东西拿着用?。。。。

md5我用的rfc自带的源码,下了openssl的源码才发现,openssl也提供md5,emmm,MD5的实现太顺利了。

我想要用的是openssl的API,openssl还提供了指令。openssl是非常强大的。最优的解决方案是自己实现和学习openssl,即使是自己实现,我也希望能学习openssl,开源的总对人有吸引力。

找了两本书,一本全一些,但是讲的是指令。

下了openssl的源码,aes目录下,有cbc,cfb,ecb,ofb,但是没有看到ctr。

modes目录下有ctr128,只看到了encrypt

------------------------------------------

 

分组密码只能加密固定长度的明文。

若明文长度不固定,使用迭代方式得到固定长度。

分组密码的迭代方式为分组密码的模式。

模式可以为:ECB,CBC,CFB,OFB,CTR。

CBC,Cipher Block Chaining,密文分组链接模式。

CTR,CounTeR,计数器模式。

-----------------------

 

AES - Advanced Encryption Standard

高级加密标准

其算法为Rijndael

分组标准长度为128b,即16个字节,密钥长度可选为128b,192b,256b,即16B,24B,32B三种。

Rijndael由多轮构成,每一轮由4个步骤:SubBytes,ShiftRows,MixColumns,AddRoundKey。

轮数由分组长度和密钥长度决定,

 

SubBytes 字节代换

每个字节取值0-255,有256种可能。提供一张替换表,采用一一对应,对原分组的16个字节进行替换。

 

ShiftRows 行移位

将16个字节划分为4行,每行进行平移。

 

MixColumns 列混合

16个字节划分为4行后,同样也有4列。

对每列进行比特运算。

 

AddRoundKey 轮密钥加

处理过后的数据,与轮密钥进行异或运算。

 

 

 

https://www.jb51.net/article/193493.htm

 

https://book.douban.com/subject/2678340/

 

https://book.douban.com/subject/1434818/

 

https://book.douban.com/subject/2678341/

 

https://www.zhihu.com/question/36289177/answer/66944812

 

https://blog.dynox.cn/?p=1562

 

这个是一个源码实现,提供cbc和ecb模式的实现

 

https://github.com/matt-wu/AES/

还可以是openssl的aes

posted on 2021-05-08 16:13  toughcactus  阅读(118)  评论(0编辑  收藏  举报