pinvoking adwapi.dll - cryptDecrypt和cryptEncrypt函数,奇怪的问题

时间:2011-03-20 00:40:41

标签: c# pinvoke smartcard cryptoapi

我正在观察这个函数的奇怪行为,我要加密的字符串包含14个字节,如果我使用函数发送缓冲区的长度= 14,则失败(“内部错误” - 非常具有描述性和最有帮助错误代码),但它在缓冲区长度(和缓冲区本身)大128字节时有效。

我通过制作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是指向加密密钥的指针,第二个参数是null,3rd是“true”(没有更多数据),没有标志,缓冲区字节数组(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'{{1} }> [Sαδ+}的Ct N'安培;??14 b P U1 ??%JQ ??? / MP 5wB ????

?!????

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

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

提前致谢。

2 个答案:

答案 0 :(得分:2)

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

调用CryptDecrypt后,参数pdwDataLen(代码中的locInputLength)将包含已解密的实际数据的长度。如果您只选择locInputLength的前dataCopy个字节,它会为您提供所需内容吗?

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

答案 1 :(得分:0)

是的,那就做到了!像馅饼一样容易!

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

你直接退后一步,从一个略微不同的角度看待事物之前你不会“看到”的其中一件事;)