问题
I am observing wierd behaviour of this function, the string that I want to encrypt contains 14 bytes, if I use the function to send lenght of buffer = 14, it fails ("an internal error" - very descriptive and most helpful error code), but it works when the buffer length (and the buffer itself) is 128 bytes large.
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?????$??uj??m%?b??e?a?74p?)?n9??w?R*O)E?i?+?
>[?S???}Ct?n?&??b?P!?u1??%?JQ???/?mP?5wB????
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.
回答1:
I think the reason the buffer must be 128 bytes is that a block cipher is being used. In that case, the buffer length must be a multiple of the block size. With a block ciper, the buffer may need to be larger than the size of the data anyway, so that the encrypted or decrypted data can be written to it (length(encrypted) != length(plaintext)).
After you call CryptDecrypt, the parameter pdwDataLen
(locInputLength
in your code) will contain the length of the actual data that was decrypted. If you take only the first locInputLength
bytes of dataCopy
, does it give you what you need?
References: http://msdn.microsoft.com/en-us/library/aa379913(VS.85).aspx http://msdn.microsoft.com/en-us/library/aa379924(VS.85).aspx
回答2:
Yup, that did it! easy as pie!
byte[] buffer = new byte[locinputlength];
Buffer.BlockCopy(dataCopy, 0, buffer, 0, (int)locinputlength);
return buffer;
One of those things you just dont "see" until you step back a little and look at the thing from a slightly different perspective ;)
来源:https://stackoverflow.com/questions/5365965/pinvoking-adwapi-dll-cryptdecrypt-and-cryptencrypt-functions-weird-problem