CryptEncrypt function
Applies to: desktop apps only
The CryptEncrypt function encrypts data. The algorithm used to encrypt the data is designated by the key held by the CSP module and is referenced by the hKey parameter.
Important changes to support Secure/Multipurpose Internet Mail Extensions (S/MIME) email interoperability have been made to CryptoAPI that affect the handling of enveloped messages. For more information, see the Remarks section of CryptMsgOpenToEncode.
Important The CryptEncrypt function is not guaranteed to be thread safe and may return incorrect results if invoked simultaneously by multiple callers.
Syntax
BOOL WINAPI CryptEncrypt( __in HCRYPTKEY hKey, __in HCRYPTHASH hHash, __in BOOL Final, __in DWORD dwFlags, __inout BYTE *pbData, __inout DWORD *pdwDataLen, __in DWORD dwBufLen );
Parameters
- hKey [in]
-
A handle to the encryption key. An application obtains this handle by using either the CryptGenKey or the CryptImportKey function.
The key specifies the encryption algorithm used.
- hHash [in]
-
A handle to a hash object. If data is to be hashed and encrypted simultaneously, a handle to a hash object can be passed in the hHash parameter. The hash value is updated with the plaintext passed in. This option is useful when generating signed and encrypted text.
Before calling CryptEncrypt, the application must obtain a handle to the hash object by calling the CryptCreateHash function. After the encryption is complete, the hash value can be obtained by using the CryptGetHashParam function, or the hash can be signed by using the CryptSignHash function.
If no hash is to be done, this parameter must be NULL.
- Final [in]
-
A Boolean value that specifies whether this is the last section in a series being encrypted. Final is set to TRUE for the last or only block and to FALSE if there are more blocks to be encrypted. For more information, see Remarks.
- dwFlags [in]
-
The following dwFlags value is defined but reserved for future use.
Value Meaning - CRYPT_OAEP
Use Optimal Asymmetric Encryption Padding (OAEP) (PKCS #1 version 2). This flag is only supported by the Microsoft Enhanced Cryptographic Provider with RSA encryption/decryption.
Windows 2000: This flag is not supported. - pbData [in, out]
-
A pointer to a buffer that contains the plaintext to be encrypted. The plaintext in this buffer is overwritten with the ciphertext created by this function.
The pdwDataLen parameter points to a variable that contains the length, in bytes, of the plaintext. The dwBufLen parameter contains the total size, in bytes, of this buffer.
If this parameter contains NULL, this function will calculate the required size for the ciphertext and place that in the value pointed to by the pdwDataLen parameter.
- pdwDataLen [in, out]
-
A pointer to a DWORD value that , on entry, contains the length, in bytes, of the plaintext in the pbData buffer. On exit, this DWORD contains the length, in bytes, of the ciphertext written to the pbData buffer.
If the buffer allocated for pbData is not large enough to hold the encrypted data, GetLastError returns ERROR_MORE_DATA and stores the required buffer size, in bytes, in the DWORD value pointed to by pdwDataLen.
If pbData is NULL, no error is returned, and the function stores the size of the encrypted data, in bytes, in the DWORD value pointed to by pdwDataLen. This allows an application to determine the correct buffer size.
When a block cipher is used, this data length must be a multiple of the block size unless this is the final section of data to be encrypted and the Final parameter is TRUE.
- dwBufLen [in]
-
Specifies the total size, in bytes, of the input pbData buffer.
Note that, depending on the algorithm used, the encrypted text can be larger than the original plaintext. In this case, the pbData buffer needs to be large enough to contain the encrypted text and any padding.
As a rule, if a stream cipher is used, the ciphertext is the same size as the plaintext. If a block cipher is used, the ciphertext is up to a block length larger than the plaintext.
Return value
If the function succeeds, the function returns nonzero (TRUE).
If the function fails, it returns zero (FALSE). For extended error information, call GetLastError.
The error codes prefaced by NTE are generated by the particular CSP being used. Some possible error codes follow.
| Value | Description |
|---|---|
|
One of the parameters specifies a handle that is not valid. |
|
One of the parameters contains a value that is not valid. This is most often a pointer that is not valid. |
|
The hKey session key specifies an algorithm that this CSP does not support. |
|
The data to be encrypted is not valid. For example, when a block cipher is used and the Final flag is FALSE, the value specified by pdwDataLen must be a multiple of the block size. |
|
The dwFlags parameter is nonzero. |
|
The hHash parameter contains a handle that is not valid. |
|
An attempt was made to add data to a hash object that is already marked "finished." |
|
The hKey parameter does not contain a valid handle to a key. |
|
The size of the output buffer is too small to hold the generated ciphertext. |
|
The CSP context that was specified when the key was created cannot be found. |
|
The application attempted to encrypt the same data twice. |
|
The function failed in some unexpected way. |
|
The CSP ran out of memory during the operation. |
Remarks
If a large amount of data is to be encrypted, it can be done in sections by calling CryptEncrypt repeatedly. The Final parameter must be set to TRUE on the last call to CryptEncrypt, so that the encryption engine can properly finish the encryption process. The following extra actions are performed when Final is TRUE:
- If the key is a block cipher key, the data is padded to a multiple of the block size of the cipher. If the data length equals the block size of the cipher, one additional block of padding is appended to the data. To find the block size of a cipher, use CryptGetKeyParam to get the KP_BLOCKLEN value of the key.
- If the cipher is operating in a chaining mode, the next CryptEncrypt operation resets the cipher's feedback register to the KP_IV value of the key.
- If the cipher is a stream cipher, the next CryptEncrypt resets the cipher to its initial state.
There is no way to set the cipher's feedback register to the KP_IV value of the key without setting the Final parameter to TRUE. If this is necessary, as in the case where you do not want to add an additional padding block or change the size of each block, you can simulate this by creating a duplicate of the original key by using the CryptDuplicateKey function, and passing the duplicate key to the CryptEncrypt function. This causes the KP_IV of the original key to be placed in the duplicate key. After you create or import the original key, you cannot use the original key for encryption because the feedback register of the key will be changed. The following pseudocode shows how this can be done.
// Set the IV for the original key. Do not use the original key for
// encryption or decryption after doing this because the key's
// feedback register will get modified and you cannot change it.
CryptSetKeyParam(hOriginalKey, KP_IV, newIV)
while(block = NextBlock())
{
// Create a duplicate of the original key. This causes the
// original key's IV to be copied into the duplicate key's
// feedback register.
hDuplicateKey = CryptDuplicateKey(hOriginalKey)
// Encrypt the block with the duplicate key.
CryptEncrypt(hDuplicateKey, block)
// Destroy the duplicate key. Its feedback register has been
// modified by the CryptEncrypt function, so it cannot be used
// again. It will be re-duplicated in the next iteration of the
// loop.
CryptDestroyKey(hDuplicateKey)
}
The Microsoft Enhanced Cryptographic Provider supports direct encryption with RSA public keys and decryption with RSA private keys. The encryption uses PKCS #1 padding. On decryption, this padding is verified. The length of plaintext data that can be encrypted with a call to CryptEncrypt with an RSA key is the length of the key modulus minus eleven bytes. The eleven bytes is the chosen minimum for PKCS #1 padding. The ciphertext is returned in little-endian format.
Examples
For examples that use this function, see Example C Program: Encrypting a File and Example C Program: Decrypting a File.
Requirements
|
Minimum supported client | Windows 2000 Professional |
|---|---|
|
Minimum supported server | Windows 2000 Server |
|
Header |
|
|
Library |
|
|
DLL |
|
See also
- Data Encryption and Decryption Functions
- CryptCreateHash
- CryptDecrypt
- CryptGenKey
- CryptGetHashParam
- CryptGetKeyParam
- CryptImportKey
- CryptMsgOpenToEncode
- CryptSignHash
Send comments about this topic to Microsoft
Build date: 3/6/2012
I overcame this problem by making a size 128 byte array and I copied the 14 bytes from the plain text (that I wish to encrypt),
When I decrypt those bytes, I must once again give the function the whole 128 byte array (which now has every byte encrypted, even the ones from #13-#127 (which I guess is to be expected)). Luckily for me the first 14 bytes get decrypted as they should, the rest is gibberish.
I would like to know why the encrypt method fails if the incoming buffer isnt 128 byte large, and also why decrypt function also requires a 128 byte array, is it some padding thing?
This is how I call the encrypt function:
System.Text.ASCIIEncoding encoding = new System.Text.ASCIIEncoding(); // encoding type
byte[] buff = new byte[128]; // this is my buffer array, instantiated and initiated
string String2Encrypt = "Testing"; // this is the string I need encrypted
byte[] tempo = encoding.GetBytes(String2Encrypt); // getting bytes from string
Buffer.BlockCopy(tempo, 0, buff, 0, tempo.Length); // copying the small array into the large one
uint inputlength = Convert.ToUInt32(tempo.Length); // getting the size of the small array
bool DidIt = UnsafeNativeMethods.CryptEncrypt(MyKey, IntPtr.Zero, 1, 0, buff, ref inputlength, outputdatalength); // calling the function
// in this case, the MyKey is pointer to a crypto key, 2nd argument is null, 3rd is "true" (no more data), no flags, buffer byte array (128), Testing.Length in this case it is 7, 128
This is how I decrypt it:
IntPtr UserKeyLocal = MyUserKey; // taking an argument (MyUserKey) and "filling" the local variable, not really relevant
byte[] dataCopy = new byte[buff.Length]; // init and insta the datacopy array (128 byte)
Buffer.BlockCopy(buff, 0, dataCopy, 0, (int)buff.Length); // copying the argument array into a local version (I used this for testing to go around another problem), irrelevant
uint locinputlength = inputlength; // another argument made local
bool DidIT = UnsafeNativeMethods.CryptDecrypt(UserKeyLocal, IntPtr.Zero, true, 0, dataCopy, ref locinputlength); // calling the function
The result would look like this:
Testing?R????7?q???????????????????????????????????????????????????????????????????????????????????????????????????????????????????????
Its almost working as intended but I need to be able to get ONLY the "Testing" part of the string without using tricks like substringing.
What I am trying to do (maybe there is an alternative way) is this; I have a binary (file) that has in it "Testing" encrypted by a public key I got from a certificate which I exported form a SmartCard.
I need to verify (decrypt) this file by using my SmartCard (I am using its propriety CSP) with the private key. As you can see, it ALMOST works.
Thanks in advance.
- 3/20/2011
- Bruno Bozic
Important The CryptEncrypt function is not guaranteed to be thread safe and may return incorrect results if invoked simultaneously by multiple callers.
, doesn't make any sense, unless you meant to say that CryptEncrypt isn't thread safe when invoked by multiple callers with the same hKey or hHash or pbData or pwdDataLen or any combination of these. As written, it sounds like there may be only one encryption going on at any given time within a process.
- 3/18/2011
- A.M._