The key transport algorithm is a little more difficult to process, and it may not serve its purpose (I see, you noticed that CAPI should support RSAencryption , trust me, I do too). It looks like you found that alaready discovered the main part of your problem - The generated message appears, but your method makes it necessary to use CryptEncryptMessage , which will not work well / at all in the end.
Step 1 - Learn the Code
CRYPT_ENCRYPT_MESSAGE_PARA EncryptMessageParams; EncryptMessageParams.cbSize = sizeof(CMSG_ENVELOPED_ENCODE_INFO); EncryptMessageParams.dwMsgEncodingType = PKCS_7_ASN_ENCODING; EncryptMessageParams.ContentEncryptionAlgorithm.pszObjId = szOID_NIST_AES256_CBC; EncryptMessageParams.ContentEncryptionAlgorithm.Parameters.cbData = 0; EncryptMessageParams.ContentEncryptionAlgorithm.Parameters.pbData = 0; EncryptMessageParams.hCryptProv = NULL; EncryptMessageParams.pvEncryptionAuxInfo = NULL; EncryptMessageParams.dwFlags = 0; EncryptMessageParams.dwInnerContentType = 0; BYTE pbEncryptedBlob[640000]; DWORD pcbEncryptedBlob = 640000; BOOL retval = CryptEncryptMessage(&EncryptMessageParams, cRecipientCert, pRecipCertContextArray, pbMsgText, dwMsgTextSize, pbEncryptedBlob, &pcbEncryptedBlob);
Pretty simple, right? Although effective, this is not really a problem. If you look at this:
EncryptMessageParams.dwFlags = 0; EncryptMessageParams.dwInnerContentType = 0;
You will see that it is predefined, but only used in the definition of retval . However, I could definitely see this as micro-optimization, and not very useful if we are going to rewrite the code. However, I outlined the basic steps to integrate this without completely repeating the code (so that you can continue to use the same parameters):
Step 2 - Editing Parameters
As @owlstead notes in his comments, the Crypto API is not very user friendly. However, you did a great job with limited resources. What would you like to add is the Cryptographic Enumeration Provider to narrow your keys. Make sure you are using Microsoft Base Cryptographic Provider version 1.0 or Microsoft Enhanced Cryptographic Provider version 1.0 for effective use. Otherwise, you need to add a function like this:
DWORD cbName; DWORD dwType; DWORD dwIndex; CHAR *pszName = NULL; (regular crypt calls here)
This is mainly used to prevent the NTE_BAD_FLAGS error, although technically you can avoid this with a lower level declaration. If you want, you can also create a completely new hash (although this is only necessary if the above implementation does not scale to the required time / speed ratio):
DWORD dwBufferLen = strlen((char *)pbBuffer)+1*(0+5); HCRYPTHASH hHash; HCRYPTKEY hKey; HCRYPTKEY hPubKey; BYTE *pbKeyBlob; BYTE *pbSignature; DWORD dwSigLen; DWORD dwBlobLen; (use hash as normal w/ crypt calls and the pbKeyBlobs/Signatures)
Be sure to run this snippet before moving on. You can do so easily:
if(CryptAcquireContext(&hProv, NULL, NULL, PROV_RSA_FULL, 0)) { printf("CSP context acquired.\n"); }
If you are documenting or releasing, you might want to add void MyHandleError(char *s) to catch the error so that someone who edits but cannot can catch it quickly.
By the way, when you first start, you will need to create a new set, because there is no default value. Below is a nice single line line that can be inserted into if :
CryptAcquireContext(&hCryptProv, NULL, NULL, PROV_RSA_FULL, CRYPT_NEWKEYSET)
Remember that synchronizing server resources will not be as effective as the replication proposed in the first step. Here is what I will explain below:
Step 3 - Transcoding and Retransmission
As a programmer, re-encoding may seem like a waste of time, but it can ultimately help you. Remember that you still have to encode user parameters when encoding / synchronizing; I am not going to give you all the code as a child. This should be enough to show you the basic outline.
I definitely assume that you are trying to access the current user's container inside a specific CSP ; Otherwise, I do not see this. If not, you can make some basic changes to suit your needs.
Remember that we will bypass CryptEncryptMessage with a CryptReleaseContext , which directly releases the handle received by the CryptAcquireContext function. The Microsoft CAC standard is below:
BOOL WINAPI CryptAcquireContext( _Out_ HCRYPTPROV *phProv, _In_ LPCTSTR pszContainer, _In_ LPCTSTR pszProvider, _In_ DWORD dwProvType, _In_ DWORD dwFlags );
Please note that Microsoft scolds you if you use the user interface:
If the CSP must display an interface for operation, the call fails, and the error code NTE_SILENT_CONTEXT is set as the last error. In addition, if calls are made to CryptGenKey with the CRYPT_USER_PROTECTED flag with the context that was obtained using the CRYPT_SILENT flag, the calls fail, and CSP sets NTE_SILENT_CONTEXT.
This is mainly server code, and ERROR_BUSY will definitely be displayed to new users when there are multiple connections, especially with high latency. Above 300 ms, it will just call NTE_BAD_KEYSET_PARAM or a similar call because of a timeout without getting the proper error. (Transmission problems, is anyone with me?)
If you are not worried about several DLLs (which this does not support due to NTE_PROVIDER_DLL_FAIL errors), the basic setting for accessing crypt client services will be as shown below (copied directly from Microsoft examples):
if (GetLastError() == NTE_BAD_KEYSET) { if(CryptAcquireContext( &hCryptProv, UserName, NULL, PROV_RSA_FULL, CRYPT_NEWKEYSET)) { printf("A new key container has been created.\n"); } else { printf("Could not create a new key container.\n"); exit(1); } } else { printf("A cryptographic service handle could not be " "acquired.\n"); exit(1); }
As simple as it sounds, you definitely don't want to get hung up on this key exchange algorithm (or whatever you do with it). If you do not use symmetric session keys (Diffie-Hellman / KEA), you can use the key exchange pair to encrypt session keys so that they can be safely stored and exchanged with other users.
Someone named John Howard wrote a good Hyper-V Remote Control Configuration Utility (HVRemote), which is a large compilation of the technologies described here. In addition to using the basic crypts and keys, they can be used to allow ANONYMOUS LOGON DCOM remote access ( cscript hvremote.wsf to be specific). You can see many functions and methods in your latest crypts (you'll have to narrow down your request) on your blog:
http://blogs.technet.com/b/jhoward/
If you need more help with the basics, just leave a comment or ask for a private chat.
Conclusion
Although it is quite simple when you understand the basic server-side hashing methods and how the client captures crypts, you will question why you even tried encryption during the transfer. However, without client encryption, encryption will certainly be the only safe way to transfer what has already been hashed.
Although you can argue that packets can be decrypted and removed with salts, keep in mind that both inbound and outbound should be processed and stored in the correct time and order necessary for the re-hash client.