日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當前位置: 首頁 > 编程资源 > 编程问答 >内容正文

编程问答

openssl与cryptoAPI交互AES加密解密

發布時間:2025/3/20 编程问答 33 豆豆
生活随笔 收集整理的這篇文章主要介紹了 openssl与cryptoAPI交互AES加密解密 小編覺得挺不錯的,現在分享給大家,幫大家做個參考.

原文:?http://blog.csdn.net/zhouyuqwert/article/details/7422467


有讀者指出代碼貼兩遍,修改下。



繼上次只有CryptoAPI的加密后,這次要實現openssl的了

動機:利用CryptoAPI制作windows的IE,火狐和chrome加密控件后,這次得加上與Android的加密信息交互

先前有說openssl移植到android的過程,這里就不再提android如何調用openssl了,

? ? ? ? 而那一篇第9條提到的openssl與cryptoAPI兼容的兩種方式感覺實現都不太好用,這里再次提出一種AES加密的實現方式

寫這邊文章的最主要的原因,用過CryptoAPI的都知道,很多東西都封裝了,如果要與其他加密組件交互,得用其他組件來實現CryptoAPI的思路

環境:windows visual studio 2010,openssl windows(x86)動態庫

在CryptoAPI中進行AES加密解密,有一種實現方式是調用CryptDeriveKey通過提供的字節數組的hash值獲取key

先來看下CryptoAPI實現AES,來個簡單點的版本

[cpp]?view plaincopy print?
  • void?cryptoAPI_encrypt(string?text,unsigned?char*?pwd,unsigned?char**?encryptText,int?&out_len)??
  • {??
  • ????HCRYPTPROV?hCryptProv?=?NULL;????
  • ????HCRYPTKEY?hKey?=?0;????
  • ????HCRYPTHASH?hHash?=?0;????
  • ????int?dwLength?=?0;????
  • ????
  • ????if(!CryptAcquireContext(&hCryptProv,????
  • ????????NULL,????
  • ????????CSP_NAME,//CSP_NAME????
  • ????????PROV_RSA_AES,????
  • ????????CRYPT_VERIFYCONTEXT))????
  • ????{????
  • ????????DWORD?dwLastErr?=?GetLastError();????
  • ????
  • ????????if(NTE_BAD_KEYSET?==?dwLastErr)?????
  • ????????{????
  • ????????????return;????
  • ????????}????
  • ????????else{????
  • ????????????if(!CryptAcquireContext(&hCryptProv,????
  • ????????????????NULL,????
  • ????????????????CSP_NAME,????
  • ????????????????PROV_RSA_AES,????
  • ????????????????CRYPT_NEWKEYSET))????
  • ????????????{????
  • ????????????????return;????
  • ????????????}????
  • ????????}????
  • ????}????
  • ????if(!CryptCreateHash(hCryptProv,?CALG_MD5,?0,?0,?&hHash))????
  • ????{????
  • ????????return;????
  • ????}????
  • ????
  • ????BYTE?*pPwd?=?pwd;???
  • ??
  • ????if(!CryptHashData(hHash,?pPwd,?16,?0))????
  • ????{????
  • ????????return;????
  • ????}????
  • ??
  • ????if(!CryptDeriveKey(hCryptProv,?CALG_AES_128,?hHash,?CRYPT_EXPORTABLE,?&hKey))????
  • ????{????
  • ????????return;????
  • ????}????
  • ??
  • ????int?len?=?text.length();????
  • ????BYTE?*pData?;????
  • ????pData?=?(BYTE*)malloc(len*4);????
  • ????memcpy(pData,text.c_str(),len);??
  • ????DWORD?dwLen?=?len;????
  • ????
  • ????if(!CryptEncrypt(hKey,?NULL,?true,?0,?pData,?&dwLen,?len*4))????
  • ????{????
  • ????????return;????
  • ????}????
  • ????
  • ????cout?<<"--------------------------"?<<?endl?<<?"cryptoAPI?encrypt"<<endl;??
  • ????printBytes(pData,dwLen);????
  • ????*encryptText?=?pData;??
  • ????out_len?=?dwLen;??
  • ????CryptDestroyHash(hHash);??
  • ????CryptDestroyKey(hKey);??
  • ????CryptReleaseContext(hCryptProv,0);??
  • }??

  • 這里將傳進來的字節數組密鑰先進行MD5摘要后,再通過CryptoDeriveKey來得到最后用來加密的密鑰

    openssl要以同樣的方式做一次這個步驟,首先是MD5摘要,相對比較簡單

    [cpp]?view plaincopy print?
  • unsigned?char*?openssl_md5(unsigned?char*sessionKey,size_t?n)??
  • {??
  • ????unsigned?char?*ret?=?(unsigned?char*)malloc(MD5_DIGEST_LENGTH);??
  • ????MD5(sessionKey,n,ret);??
  • ????return?ret;??
  • }??

  • 然后再來實現CryptoDeriveKey,先來看下 MSDN上對于這個函數的說明

    主要看remarks里面的實現步驟:

    [plain]?view plaincopy print?
  • Let?n?be?the?required?derived?key?length,?in?bytes.?The?derived?key?is?the?first?n?bytes?of?the?hash?value?after?the?hash?computation?has?been?completed?by?CryptDeriveKey.?If?the?hash?is?not?a?member?of?the?SHA-2?family?and?the?required?key?is?for?either?3DES?or?AES,?the?key?is?derived?as?follows:??
  • ??
  • 1.Form?a?64-byte?buffer?by?repeating?the?constant?0x36?64?times.?Let?k?be?the?length?of?the?hash?value?that?is?represented?by?the?input?parameter?hBaseData.?Set?the?first?k?bytes?of?the?buffer?to?the?result?of?an?XOR?operation?of?the?first?k?bytes?of?the?buffer?with?the?hash?value?that?is?represented?by?the?input?parameter?hBaseData.??
  • 2.Form?a?64-byte?buffer?by?repeating?the?constant?0x5C?64?times.?Set?the?first?k?bytes?of?the?buffer?to?the?result?of?an?XOR?operation?of?the?first?k?bytes?of?the?buffer?with?the?hash?value?that?is?represented?by?the?input?parameter?hBaseData.??
  • 3.Hash?the?result?of?step?1?by?using?the?same?hash?algorithm?as?that?used?to?compute?the?hash?value?that?is?represented?by?the?hBaseData?parameter.??
  • 4.Hash?the?result?of?step?2?by?using?the?same?hash?algorithm?as?that?used?to?compute?the?hash?value?that?is?represented?by?the?hBaseData?parameter.??
  • 5.Concatenate?the?result?of?step?3?with?the?result?of?step?4.??
  • 6.Use?the?first?n?bytes?of?the?result?of?step?5?as?the?derived?key.??
  • 非常簡單的英文,不做翻譯了...

    直接上openssl代碼實現

    [cpp]?view plaincopy print?
  • //參見?http://msdn.microsoft.com/en-us/library/aa379916(v=vs.85).aspx?remarks步驟??
  • unsigned?char*?derivedKey(unsigned?char*sessionKey/*hash后的值*/,size_t?n/*密鑰長度*/)??
  • {??
  • ????/**step?1*/??
  • ????unsigned?char*?buffer?=?(unsigned?char*)malloc(64);??
  • ??
  • ????for(int?i?=?0?;?i?<?64;i++)??
  • ????{??
  • ????????buffer[i]?=?0x36;??
  • ????}??
  • ??
  • ????int?k?=?n;??
  • ??
  • ????for(int?i?=?0?;?i?<?k?;?i++)??
  • ????{??
  • ????????buffer[i]?=?buffer[i]?^?sessionKey[i];??
  • ????}??
  • ??
  • ????/*step?2*/??
  • ????unsigned?char*?buffer2?=?(unsigned?char*)malloc(64);??
  • ??
  • ????for(int?i?=?0?;?i?<?64;i++)??
  • ????{??
  • ????????buffer2[i]?=?0x5C;??
  • ????}??
  • ??
  • ????for(int?i?=?0?;?i?<?k?;?i++)??
  • ????{??
  • ????????buffer2[i]?=?buffer2[i]?^?sessionKey[i];??
  • ????}??
  • ????/*step?3*/??
  • ????unsigned?char*?ret1?=?openssl_md5(buffer,64);??
  • ????/*step?4*/??
  • ????unsigned?char*?ret2?=?openssl_md5(buffer2,64);??
  • ??
  • ??
  • ????unsigned?char*?ret?=?(unsigned?char*)malloc(128);??
  • ????for(int?i?=?0?;?i?<?128;i++)??
  • ????{??
  • ????????if(i<64)??
  • ????????????ret[i]?=?ret1[i];??
  • ????????else??
  • ????????????ret[i]?=?ret2[i-64];??
  • ????}??
  • ????return?ret;??
  • }??

  • 最麻煩的地方解決了...剩下再按照CryptoAPI的實現順序實現吧

    [cpp]?view plaincopy print?
  • void?openssl_aes_encrypt(string?text,unsigned?char**?SessionKey_out/*這里主要用作將產生的對稱密鑰輸出*/,unsigned?char*?sEncryptMsg,int?&len)??
  • {??
  • ????OpenSSL_add_all_algorithms();??
  • ????//產生會話密鑰??
  • ????*SessionKey_out?=?(unsigned?char*)malloc(MD5_SIZE);??
  • ????RAND_bytes(*SessionKey_out,MD5_SIZE);//產生隨機密鑰,輸出之后可以給其他方法是用了??
  • ????unsigned?char*?SessionKey?=?openssl_md5(*SessionKey_out,MD5_SIZE);??
  • ??????
  • ????SessionKey?=?derivedKey(SessionKey,MD5_SIZE);??
  • ??
  • ????const?unsigned?char*?sMsg?=?(const?unsigned?char*)text.c_str();??
  • ????int?cbMsg?=?text.length();??
  • ????int?cbEncryptMsg;??
  • ????//加密??
  • ????EVP_CIPHER_CTX?ctx;??
  • ????EVP_CIPHER_CTX_init(&ctx);??
  • ????if(EVP_EncryptInit_ex(&ctx,EVP_get_cipherbynid(NID_aes_128_cbc),NULL,SessionKey,NULL))??
  • ????{??
  • ????????int?offseti=0;//in??
  • ????????int?offseto=0;//out??
  • ????????int?offsett=0;//temp??
  • ????????for(;;)??
  • ????????{??
  • ????????????if(cbMsg-offseti<=MAX_ENCRYPT_LEN)??
  • ????????????{??
  • ????????????????EVP_EncryptUpdate(&ctx,?sEncryptMsg+offseto,?&offsett,?sMsg+offseti,?cbMsg-offseti);??
  • ????????????????offseto+=offsett;??
  • ????????????????break;??
  • ????????????}??
  • ????????????else??
  • ????????????{??
  • ????????????????EVP_EncryptUpdate(&ctx,?sEncryptMsg+offseto,?&offsett,?sMsg+offseti,?MAX_ENCRYPT_LEN);??
  • ????????????????offseti+=MAX_ENCRYPT_LEN;??
  • ????????????????offseto+=offsett;??
  • ????????????}??
  • ????????}??
  • ????????EVP_EncryptFinal_ex(&ctx,?sEncryptMsg+offseto,?&offsett);??
  • ????????offseto+=offsett;??
  • ????????cbEncryptMsg=offseto;??
  • ????}??
  • ????EVP_CIPHER_CTX_cleanup(&ctx);??
  • ????std::cout?<<?"openssl?encrypt:"?<<?std::endl;??
  • ????printBytes(sEncryptMsg,cbEncryptMsg);??
  • ????len?=?cbEncryptMsg;??
  • }??

  • 加密的搞定了,可以嘗試下了,同樣的密鑰和同樣的明文,密文輸出結果是一樣的就對了

    下面是CrytpoAPI的解密:

    [cpp]?view plaincopy print?
  • void?cryptAPI_decrypt(unsigned?char*?text,int?len,unsigned?char*?pwd)??
  • {??
  • ????HCRYPTPROV?hCryptProv?=?NULL;????
  • ????HCRYPTKEY?hKey?=?0;????
  • ????HCRYPTHASH?hHash?=?0;????
  • ????int?dwLength?=?0;????
  • ????
  • ????if(!CryptAcquireContext(&hCryptProv,????
  • ????????NULL,????
  • ????????CSP_NAME,//CSP_NAME????
  • ????????PROV_RSA_AES,????
  • ????????CRYPT_VERIFYCONTEXT))????
  • ????{????
  • ????????DWORD?dwLastErr?=?GetLastError();????
  • ????
  • ????????if(NTE_BAD_KEYSET?==?dwLastErr)?????
  • ????????{????
  • ????????????return;????
  • ????????}????
  • ????????else{????
  • ????????????if(!CryptAcquireContext(&hCryptProv,????
  • ????????????????NULL,????
  • ????????????????CSP_NAME,????
  • ????????????????PROV_RSA_AES,????
  • ????????????????CRYPT_NEWKEYSET))????
  • ????????????{????
  • ????????????????return;????
  • ????????????}????
  • ????????}????
  • ????}????
  • ????
  • ????
  • ????if(!CryptCreateHash(hCryptProv,?CALG_MD5,?0,?0,?&hHash))????
  • ????{????
  • ????????return;????
  • ????}????
  • ????
  • ????BYTE?*pPwd?=?pwd;???
  • ??
  • ????if(!CryptHashData(hHash,?pPwd,?16,?0))????
  • ????{????
  • ????????return;????
  • ????}????
  • ??
  • ????if(!CryptDeriveKey(hCryptProv,?CALG_AES_128,?hHash,?CRYPT_EXPORTABLE,?&hKey))????
  • ????{????
  • ????????return;????
  • ????}????
  • ??
  • ????BYTE?*pData?=?text;????
  • ????DWORD?dwLen?=?len;????
  • ????
  • ????if(!CryptDecrypt(hKey,?NULL,?true,?0,?pData,?&dwLen))????
  • ????{????
  • ????????return;????
  • ????}????
  • ????
  • ????cout?<<"--------------------------"?<<?endl?<<?"cryptoAPI?decrypt"<<endl;??
  • ????char*?plainText?=?(char*)malloc(dwLen?+?1);??
  • ????memcpy(plainText,pData,dwLen);??
  • ????plainText[dwLen]?=?'\0';??
  • ????cout?<<?plainText?<<?endl;??
  • ????CryptDestroyHash(hHash);??
  • ????CryptDestroyKey(hKey);??
  • ????CryptReleaseContext(hCryptProv,0);??
  • }??

  • 嘗試用這個方法解密CryptoAPI的加密和openssl的加密吧,都能輸出明文的

    再來最后一個,openssl的解密

    [cpp]?view plaincopy print?
  • void?openssl_aes_decrypt(unsigned?char*?text,int?len,unsigned?char*?SessionKeyP)??
  • {??
  • ????unsigned?char*?decryptMsg?=?(unsigned?char*)malloc(len);??
  • ??
  • ????OpenSSL_add_all_algorithms();??
  • ??
  • ????unsigned?char*?SessionKey?=?openssl_md5(SessionKeyP,MD5_SIZE);??
  • ??????
  • ????SessionKey?=?derivedKey(SessionKey,MD5_SIZE);??
  • ??
  • ????const?unsigned?char*?sMsg?=?text;??
  • ????int?cbMsg?=?len;??
  • ????int?cbEncryptMsg;??
  • ????//解密??
  • ????EVP_CIPHER_CTX?ctx;??
  • ????EVP_CIPHER_CTX_init(&ctx);??
  • ??????
  • ????if(EVP_DecryptInit_ex(&ctx,EVP_get_cipherbynid(NID_aes_128_cbc),NULL,SessionKey,NULL))??
  • ????{??
  • ????????int?offseti=0;//in??
  • ????????int?offseto=0;//out??
  • ????????int?offsett=0;//temp??
  • ????????for(;;)??
  • ????????{??
  • ????????????if(cbMsg-offseti<=MAX_ENCRYPT_LEN)??
  • ????????????{??
  • ????????????????EVP_DecryptUpdate(&ctx,?decryptMsg+offseto,?&offsett,?sMsg+offseti,?cbMsg-offseti);??
  • ????????????????offseto+=offsett;??
  • ????????????????break;??
  • ????????????}??
  • ????????????else??
  • ????????????{??
  • ????????????????EVP_DecryptUpdate(&ctx,?decryptMsg+offseto,?&offsett,?sMsg+offseti,?MAX_ENCRYPT_LEN);??
  • ????????????????offseti+=MAX_ENCRYPT_LEN;??
  • ????????????????offseto+=offsett;??
  • ????????????}??
  • ????????}??
  • ????????EVP_DecryptFinal_ex(&ctx,?decryptMsg+offseto,?&offsett);??
  • ??
  • ????????offseto+=offsett;??
  • ????????cbEncryptMsg=offseto;??
  • ????}??
  • ????EVP_CIPHER_CTX_cleanup(&ctx);??
  • ????std::cout?<<?"openssl?decrypt:"?<<?std::endl;??
  • ??
  • ??
  • ????char*?ret?=?(char*)malloc(cbEncryptMsg?+?1);??
  • ????memcpy(ret,decryptMsg,cbEncryptMsg);??
  • ????ret[cbEncryptMsg]?=?'\0';??
  • ????std::cout?<<?ret?<<?endl;??
  • }??

  • 測試下:

    [cpp]?view plaincopy print?
  • int?_tmain(int?argc,?_TCHAR*?argv[])??
  • {??
  • ????string?text?=?"texttexttexttexttext";??
  • ????unsigned?char*?key;??
  • ????unsigned?char*?sEncryptMsg?=?(unsigned?char*)malloc(text.size()?+?MD5_SIZE);??
  • ????int?len;??
  • ????openssl_aes_encrypt(text,&key,sEncryptMsg,len);??
  • ??
  • ??
  • ????unsigned?char**?sEncryptMsg_crypto?=?(unsigned?char**)malloc(sizeof(unsigned?char*));??
  • ????int?len_crypto;??
  • ????cryptoAPI_encrypt(text,key,sEncryptMsg_crypto,len_crypto);??
  • ????cout?<<?"-----------------------------"?<<?endl<<"cryptoAPI?decrypt?openssl"<<endl;??
  • ????//cryptAPI_decrypt(sEncryptMsg,len,key);??
  • ??
  • ????cout?<<?"-----------------------------"?<<?endl<<"cryptoAPI?decrypt?cryptoAPI"<<endl;??
  • ????//cryptAPI_decrypt(*sEncryptMsg_crypto,len_crypto,key);??
  • ??
  • ????cout?<<?"-----------------------------"?<<?endl<<"oepnssl?decrypt?openssl"<<endl;??
  • ????//openssl_aes_decrypt(sEncryptMsg,len,key);??
  • ??
  • ????cout?<<?"-----------------------------"?<<?endl<<"oepnssl?decrypt?cryptoAPI"<<endl;??
  • ????//openssl_aes_decrypt(*sEncryptMsg_crypto,len_crypto,key);??
  • ????return?0;??
  • }??



  • 總結

    以上是生活随笔為你收集整理的openssl与cryptoAPI交互AES加密解密的全部內容,希望文章能夠幫你解決所遇到的問題。

    如果覺得生活随笔網站內容還不錯,歡迎將生活随笔推薦給好友。