生活随笔
收集整理的这篇文章主要介绍了
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, 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?
unsigned char * derivedKey(unsigned char *sessionKey , size_t n ) { 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]; } 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]; } unsigned char * ret1 = openssl_md5(buffer,64); 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; int offseto=0; int offsett=0; 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, 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; int offseto=0; int offsett=0; 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; cout << "-----------------------------" << endl<< "cryptoAPI decrypt cryptoAPI" <<endl; cout << "-----------------------------" << endl<< "oepnssl decrypt openssl" <<endl; cout << "-----------------------------" << endl<< "oepnssl decrypt cryptoAPI" <<endl; return 0; }
总结
以上是生活随笔 为你收集整理的openssl与cryptoAPI交互AES加密解密 的全部内容,希望文章能够帮你解决所遇到的问题。
如果觉得生活随笔 网站内容还不错,欢迎将生活随笔 推荐给好友。