After Encryption By CryptoAPI is used last time, OpenSSL is implemented this time.
Motivation: After using CryptoAPI to create windows IE, Firefox, and chrome encryption controls, we need to add encrypted information to interact with Android.
Previously, we mentioned the process of porting OpenSSL to Android. Here we will not mention how Android calls OpenSSL,
The two methods mentioned in Article 9th that are compatible with CryptoAPI do not feel easy to implement. Here, we propose an AES encryption implementation method again.
The main reason for writing this article is that everyone who has used CryptoAPI knows that many things are encapsulated. If you want to interact with other encryption components, you must use other components to implement the idea of CryptoAPI.
Environment: Windows Visual Studio 2010, OpenSSL windows (x86) dynamic library
In CryptoAPI, AES encryption and decryption is implemented by calling cryptderivekey to obtain the key through the hash value of the provided byte array.
Let's take a look at how CryptoAPI implements aes to provide a simple version.
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);}
Here, we will first perform the MD5 Digest for the passed byte array key, and then use the cryptoderivekey to obtain the key used for encryption.
OpenSSL performs this step in the same way. The first step is the MD5 Digest, which is relatively simple.
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;}
Then implement cryptoderivekey. Let's take a look at the description of this function on msdn.
The implementation steps in remarks are as follows:
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.
Very simple English, no translation...
OpenSSL code implementation
// See http://msdn.microsoft.com/en-us/library/aa379916 (V = vs.85 ). aspx remarks step unsigned char * derivedkey (unsigned char * sessionkey/* hash value */, size_t N/* key length */) {/** 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]; elseret [I] = ret2 [I-64];} return ret ;}
The most troublesome issue is solved... the rest will be implemented in the order of implementation of CryptoAPI.
Void openssl_aes_encrypt (string text, unsigned char ** sessionkey_out/* here is mainly used to output the generated symmetric key */, unsigned char * sencryptmsg, Int & Len) {openssl_add_all_algorithms (); // generate the session key * sessionkey_out = (unsigned char *) malloc (md5_size); rand_bytes (* sessionkey_out, md5_size); // generate a random key, after the output, you can use 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; // encrypt evp_cipher_ctx; evp_cipher_ctx_init (& CTX); If (convert (& CTX, evp_get_cipherbynid (convert), 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 + = Hangzhou; offseto + = offsett;} notify (& CTX, sencryptmsg + offseto, & offsett ); offseto + = offsett; cbencryptmsg = offseto;} evp_cipher_ctx_cleanup (& CTX); STD: cout <"OpenSSL encrypt:" <STD: Endl; printbytes (sencryptmsg, cbencryptmsg); Len = cbencryptmsg ;}
After encryption is completed, you can try again. The same key and plain text are the same, and the ciphertext output result is the same.
The following is the decryption of crytpoapi:
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);}
Try to use this method to decrypt the encryption of CryptoAPI and OpenSSL, both of which can output plaintext
The last one is OpenSSL decryption.
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; // decrypt evp_cipher_ctx; evp_cipher_ctx_init (& CTX); If (evp_decryptinit_ex (& CTX, evp_get_cipherbynid (ciphertext), 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;} decrypt (& 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 ;}
Test:
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;}