C語言使用openSSL庫AES模塊實現(xiàn)加密功能詳解
本文實例講述了C語言使用openSSL庫AES模塊實現(xiàn)加密功能。分享給大家供大家參考,具體如下:
概述
在密碼學(xué)里面一共有3中分類:
1.對稱加密/解密
對稱加密比較常見的有DES/AES。加密方和解密方都持有相同的密鑰。對稱的意思就是加密和解密都是用相同的密鑰。
2.非對稱加密/解密
常見的加密算法DSA/RSA。如果做過Google Pay的話,應(yīng)該不會陌生。非對稱意味著加密和解密使用的密鑰不是相同的。這種應(yīng)用的場合是需要保持發(fā)起方的權(quán)威性,比如Google中一次支付行為,只能Google通過私鑰來加密產(chǎn)出來,但是大家都能通過公鑰來認證這個是真的。打個更加淺顯的比方:私鑰可以理解成美聯(lián)儲的印鈔機,公鑰可以理解成在民間無數(shù)的美元驗鈔機。
還有一個場合也是https使用證書方式登錄的時候,也是使用的雙向的非對稱加密模式來做的。
3.離散
這種只能被稱為驗簽,而不是加密。因為這類算法只能一個方向(將輸入數(shù)據(jù)離散到某個特定的數(shù)字,反向解密是無法做到的。)。最常見的算法就是MD5。在寫php的時候大量的使用這種驗簽來做認證。他可以將字符串離散成32byte的16進制的數(shù)字。
本次使用AES CBC方式來加密。CBC模式加密是SSL的通訊標(biāo)準(zhǔn),所以在做游戲的時候經(jīng)常會使用到。openSSL的基本用法可以參考這個
兩個細節(jié)
這種加密的需要了解下面兩個細節(jié):
1.加密的內(nèi)存塊一般按照16字節(jié)(這個也可以調(diào)整)對齊;當(dāng)原始內(nèi)存塊沒有對齊字節(jié)數(shù)的時候,需要填充;
2.加密解密不會引發(fā)內(nèi)存的膨脹或者縮??;
最近在使用Python,Java,c#都去看過AES的接口,最輕松的是c#,java。當(dāng)使用C來寫,才能明顯感受到在這些操作過程中,有多少次內(nèi)存的分配,多少的內(nèi)存拼接。啥事都有成本,封裝良好的語言損失掉的效率可能來自于這些便利。
準(zhǔn)備知識
函數(shù)接口
int AES_set_encrypt_key(const unsigned char *userKey, const int bits, AES_KEY *key); int AES_set_decrypt_key(const unsigned char *userKey, const int bits, AES_KEY *key); // 設(shè)置加密key AES_KEY aes; AES_set_encrypt_key(key,128,&aes);// 這里填寫的128是bit位,128bit=(128/8)bytes=16bytes,這個換算和32bit對應(yīng)int為內(nèi)存指針的原理一樣。 // 初始化自己的key char key[16]; // 加密函數(shù) void AES_cbc_encrypt(const unsigned char *in, unsigned char *out, size_t length, const AES_KEY *key, unsigned char *ivec, const int enc); # define AES_BLOCK_SIZE 16 // aes.h 71 lines # define AES_ENCRYPT 1 // aes.h 63 lines # define AES_DECRYPT 0 // aes.h 64 lines // 定義一個加密的初始化向量 unsigned char iv[AES_BLOCK_SIZE]; // 加密 AES_cbc_encrypt(raw_buf,encrypt_buf,buf_size,&aes,iv,AES_ENCRYPT); // 解密 AES_cbc_encrypt(raw_buf,encrypt_buf,buf_size,&aes,iv,AES_DECRYPT);
字串轉(zhuǎn)換
// 16進制的字串轉(zhuǎn)換成16byte存儲起來 // hex string to byte in c const char hexstring[] = "deadbeef10203040b00b1e50", *pos = hexstring; unsigned char val[12]; size_t count = 0; /* WARNING: no sanitization or error-checking whatsoever */ for(count = 0; count < sizeof(val)/sizeof(val[0]); count++) { sscanf(pos, "%2hhx", &val[count]); pos += 2; } printf("0x"); for(count = 0; count < sizeof(val)/sizeof(val[0]); count++) printf("%02x", val[count]); printf("\n");
padding算法
char *raw_buf = ...; int raw_size = ...; char *final_buf = NULL; int pidding_size = AES_BLOCK_SIZE - (raw_size % AES_BLOCK_SIZE); int i; final_buf = (char *)malloc(raw_size+pidding_size); if (pidding_size!=0) { memcpy( final_buf, raw_buf, raw_size); for (i =raw_size;i < (raw_size+pidding_size); i++ ) { // zero padding算法: final_buf[i] = 0; or // PKCS5Padding算法 final_buf[i] = pading; } }
完整的代碼
c語言代碼
// main.c #include <aes.h> #include <stdio.h> #include <string.h> #include <assert.h> #include <stdlib.h> unsigned char* str2hex(char *str) { unsigned char *ret = NULL; int str_len = strlen(str); int i = 0; assert((str_len%2) == 0); ret = (char *)malloc(str_len/2); for (i =0;i < str_len; i = i+2 ) { sscanf(str+i,"%2hhx",&ret[i/2]); } return ret; } char *padding_buf(char *buf,int size, int *final_size) { char *ret = NULL; int pidding_size = AES_BLOCK_SIZE - (size % AES_BLOCK_SIZE); int i; *final_size = size + pidding_size; ret = (char *)malloc(size+pidding_size); memcpy( ret, buf, size); if (pidding_size!=0) { for (i =size;i < (size+pidding_size); i++ ) { ret[i] = 0; } } return ret; } void printf_buff(char *buff,int size) { int i = 0; for (i=0;i<size;i ++ ) { printf( "%02X ", (unsigned char)buff[i] ); if ((i+1) % 8 == 0) { printf("\n"); } } printf("\n\n\n\n"); } void encrpyt_buf(char *raw_buf, char **encrpy_buf, int len ) { AES_KEY aes; unsigned char *key = str2hex("8cc72b05705d5c46f412af8cbed55aad"); unsigned char *iv = str2hex("667b02a85c61c786def4521b060265e8"); AES_set_encrypt_key(key,128,&aes); AES_cbc_encrypt(raw_buf,*encrpy_buf,len,&aes,iv,AES_ENCRYPT); free(key); free(iv); } void decrpyt_buf(char *raw_buf, char **encrpy_buf, int len ) { AES_KEY aes; unsigned char *key = str2hex("8cc72b05705d5c46f412af8cbed55aad"); unsigned char *iv = str2hex("667b02a85c61c786def4521b060265e8"); AES_set_decrypt_key(key,128,&aes); AES_cbc_encrypt(raw_buf,*encrpy_buf,len,&aes,iv,AES_DECRYPT); free(key); free(iv); } int main(int argn, char *argv[] ) { char *raw_buf = NULL; char *after_padding_buf = NULL; int padding_size = 0; char *encrypt_buf = NULL; char *decrypt_buf = NULL; // 1 raw_buf = (char *)malloc(17); memcpy(raw_buf,"life's a struggle",17); printf("------------------raw_buf\n"); printf_buff(raw_buf,17); // 2 after_padding_buf = padding_buf(raw_buf,17,&padding_size); printf("------------------after_padding_buf\n"); printf_buff(after_padding_buf,padding_size); // 3 encrypt_buf = (char *)malloc(padding_size); encrpyt_buf(after_padding_buf,&encrypt_buf, padding_size); printf("------------------encrypt_buf\n"); printf_buff(encrypt_buf,padding_size); // 4 decrypt_buf = (char *)malloc(padding_size); decrpyt_buf(encrypt_buf,&decrypt_buf,padding_size); printf("------------------decrypt_buf\n"); printf_buff(decrypt_buf,padding_size); free(raw_buf); free(after_padding_buf); free(encrypt_buf); free(decrypt_buf); return 0; }
編譯scons腳本:
# SConstruct import glob env = Environment() env["CPPPATH"] = [ '/usr/include/openssl' ] env['LIBPATH'] = [ '/home/abel/lib/openssl-1.0.2f' ] env['CPPDEFINES'] = ['LINUX', '_DEBUG' ] env['CCFLAGS'] = '-g -std=gnu99' env['LIBS'] = [ 'm', 'crypto', 'dl' ] env.Program( target = "./test_aes", source = ( glob.glob( './*.c' ) ) )
輸出結(jié)果:
:!./test_aes ------------------raw_buf 6C 69 66 65 27 73 20 61 20 73 74 72 75 67 67 6C 65 ------------------after_padding_buf 6C 69 66 65 27 73 20 61 20 73 74 72 75 67 67 6C 65 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 ------------------encrypt_buf DB 63 28 C5 2C 6A 3F 1B FD 4B C5 47 94 4E 24 9D D2 15 4C F2 6B 3B 1D C0 E7 D2 7B D6 1E 78 60 EA ------------------decrypt_buf 6C 69 66 65 27 73 20 61 20 73 74 72 75 67 67 6C 65 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
總結(jié)
代碼中還是有很多地方都是直接malloc內(nèi)存出來,這些點都能扣得更加細。在每次加密調(diào)用的時候IV內(nèi)存將會改變。
PS:關(guān)于加密解密感興趣的朋友還可以參考本站在線工具:
文字在線加密解密工具(包含AES、DES、RC4等):
http://tools.jb51.net/password/txt_encode
MD5在線加密工具:
http://tools.jb51.net/password/CreateMD5Password
在線散列/哈希算法加密工具:
http://tools.jb51.net/password/hash_encrypt
在線MD5/hash/SHA-1/SHA-2/SHA-256/SHA-512/SHA-3/RIPEMD-160加密工具:
http://tools.jb51.net/password/hash_md5_sha
在線sha1/sha224/sha256/sha384/sha512加密工具:
http://tools.jb51.net/password/sha_encode
希望本文所述對大家C語言程序設(shè)計有所幫助。
欄 目:C語言
本文標(biāo)題:C語言使用openSSL庫AES模塊實現(xiàn)加密功能詳解
本文地址:http://mengdiqiu.com.cn/a1/Cyuyan/1549.html
您可能感興趣的文章
- 04-02c語言函數(shù)調(diào)用后清空內(nèi)存 c語言調(diào)用函數(shù)刪除字符
- 04-02c語言的正則匹配函數(shù) c語言正則表達式函數(shù)庫
- 04-02func函數(shù)+在C語言 func函數(shù)在c語言中
- 04-02c語言中對數(shù)函數(shù)的表達式 c語言中對數(shù)怎么表達
- 04-02c語言用函數(shù)寫分段 用c語言表示分段函數(shù)
- 04-02c語言編寫函數(shù)冒泡排序 c語言冒泡排序法函數(shù)
- 04-02c語言沒有round函數(shù) round c語言
- 04-02c語言分段函數(shù)怎么求 用c語言求分段函數(shù)
- 04-02C語言中怎么打出三角函數(shù) c語言中怎么打出三角函數(shù)的值
- 04-02c語言調(diào)用函數(shù)求fibo C語言調(diào)用函數(shù)求階乘


閱讀排行
本欄相關(guān)
- 04-02c語言函數(shù)調(diào)用后清空內(nèi)存 c語言調(diào)用
- 04-02func函數(shù)+在C語言 func函數(shù)在c語言中
- 04-02c語言的正則匹配函數(shù) c語言正則表達
- 04-02c語言用函數(shù)寫分段 用c語言表示分段
- 04-02c語言中對數(shù)函數(shù)的表達式 c語言中對
- 04-02c語言編寫函數(shù)冒泡排序 c語言冒泡排
- 04-02c語言沒有round函數(shù) round c語言
- 04-02c語言分段函數(shù)怎么求 用c語言求分段
- 04-02C語言中怎么打出三角函數(shù) c語言中怎
- 04-02c語言調(diào)用函數(shù)求fibo C語言調(diào)用函數(shù)求
隨機閱讀
- 01-10delphi制作wav文件的方法
- 08-05dedecms(織夢)副欄目數(shù)量限制代碼修改
- 01-11Mac OSX 打開原生自帶讀寫NTFS功能(圖文
- 08-05DEDE織夢data目錄下的sessions文件夾有什
- 01-10使用C語言求解撲克牌的順子及n個骰子
- 01-10C#中split用法實例總結(jié)
- 01-11ajax實現(xiàn)頁面的局部加載
- 04-02jquery與jsp,用jquery
- 01-10SublimeText編譯C開發(fā)環(huán)境設(shè)置
- 08-05織夢dedecms什么時候用欄目交叉功能?