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) 编辑 收藏 举报