2011-03-20 54 views
0

我正在观察这个函数的奇怪行为,我想加密的字符串包含14个字节,如果我使用函数发送缓冲区= 14的长度,它会失败(“一个内部错误” - 非常具有描述性和最有用的错误代码),但是它在缓冲区长度(和缓冲区本身)为128个字节时有效。pinvoking adwapi.dll - cryptDecrypt和cryptEncrypt函数,奇怪的问题

我通过制作大小为128字节数组克服了这个问题,我复制从明文的14个字节(即我希望加密),

当我解密这些字节,我必须再次给功能整个128字节的数组(现在每个字节都加密了,即使是#13-#127(我猜也是这样))。幸运的是,前14个字节是应该解密的,其余的都是乱码。

我想知道为什么加密方法失败,如果传入的缓冲区不是128字节大,而且为什么解密函数也需要128字节的数组,这是一些填充的东西?

这是我如何调用加密函数:

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 

//在这种情况下,是的myKey指针指向一个加密密钥的,第二个参数为空,第三是“真”(没有更多的数据) ,没有任何标志,缓冲器的字节数组(128),Testing.Length在这种情况下,如图7所示,128

这是我如何对其进行解密:

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 

其结果将是这样的: 测试·R ???? 7] Q ????? $ ?? UJ ??米%3 B 48 E'一?74P?)?N9 ??瓦特?R * O)E' i?+?> [?S ???} Ct?n? & ?? b?P!?u1 ??%?JQ ??? /?mP?5wB?

它几乎按预期工作,但我需要能够只使用字符串的“测试”部分,而不使用子串处理技巧。

我想要做什么(也许有另一种方法)是这样的;我有一个二进制文件(文件),它具有“测试”,通过从我从智能卡导出的证书中获得的公钥加密。 我需要通过使用我的智能卡(我正在使用其专用CSP)和私钥来验证(解密)此文件。正如你所看到的,它几乎可以工作。

在此先感谢。

+0

类似的问题:http://stackoverflow.com/questions/1591070/cryptencrypt-API – Kimberly 2011-03-20 03:01:09

回答

2

我认为缓冲区必须是128字节的原因是正在使用分组密码。在这种情况下,缓冲区长度必须是块大小的倍数。对于数据块缓冲区,缓冲区可能需要大于数据的大小,以便可以将加密或解密的数据写入其中(长度(加密)!=长度(明文))。

调用CryptDecrypt后,参数pdwDataLen(代码中的locInputLength)将包含被解密的实际数据的长度。如果你只采用dataCopy的第一个locInputLength字节,它会给你你需要的吗?

参考文献: http://msdn.microsoft.com/en-us/library/aa379913(VS.85).aspx http://msdn.microsoft.com/en-us/library/aa379924(VS.85).aspx

0

是啊,这做到了!易如反掌!

  byte[] buffer = new byte[locinputlength]; 
      Buffer.BlockCopy(dataCopy, 0, buffer, 0, (int)locinputlength); 
      return buffer; 

其中的一个东西,你只是不“看”,直到你退一步一点,看看从略有不同的视角的事;)