首页
社区
课程
招聘
[求助]调用CryptDecrypt出错,GetLastError = 8
发表于: 2013-12-20 11:48 5353

[求助]调用CryptDecrypt出错,GetLastError = 8

2013-12-20 11:48
5353
调用API函数CryptDecrypt时发生错误【00000008】--存储空间不足,无法处理此命令。

C#开发的,算法是RSA,密钥长度是1024bit,密钥是由api生成的,
Provider = "Microsoft Enhanced RSA and AES Cryptographic Provider"
ProviderType = PROV_RSA_AES,值为24

导入代码:
[DllImport(@"advapi32.dll", CharSet = CharSet.Auto, SetLastError = true)]
        [return: MarshalAs(UnmanagedType.Bool)]
        public static extern bool CryptDecrypt(IntPtr hKey, IntPtr hHash, int Final, uint dwFlags,
            byte[] pbData, ref uint pdwDataLen);

调用代码:
CryptDecrypt(hKey, IntPtr.Zero, final, 0, dataBlock, ref dataLen)

hKey是通过CryptGetUserKey取得AT_KEYEXCHANGE的密钥句柄,没报错
dataBlock的实际长度为512字节,有128字节数据
dataLen的值为128
final的值为1

返回false后调用Marshal.GetLastWin32Error()得到值为8,错误描述是通过FormatMessage函数取到的,有可能不对。

错误不是一定会发生的,大部分情况下不会发生,偶然会发生。
请教大牛们,什么情况下会发生CryptDecrypt = 8的错误?是运行环境的问题,还是程序的问题?或者提供一个解决思路也行。

以下是函数的代码,出错时cipherText参数的值为128字节数据,是否正确不确定,没发现值为0的字节。

/// <summary>
        /// 数据解密
        /// </summary>
        /// <param name="hKey">密钥句柄</param>
        /// <param name="cipherText">密文</param>
        /// <param name="plainText">输出参数,明文</param>
        public static void Decrypt(IntPtr hKey, byte[] cipherText, ref byte[] plainText) {
            Util.MethodBegin(hKey, cipherText, plainText);
            MemoryStream plainStream = null;

            try {
                // 取得密钥的解密块长度
                UInt32 blocklen = GetKeyBlocklen(hKey);

                // 计算一次解密的数据字节数
                UInt32 dataLenOnce = 512;
                // 密钥的解密块长度为0表明密钥是流式加密的密钥
                // 如果密钥的解密块长度不为0,则密钥是块式解密的密钥,在最后一次加密前,被解密数据的长度必须为
                // 解密块长度的整数倍
                if (blocklen != 0) {
                    dataLenOnce = dataLenOnce - dataLenOnce % blocklen;
                }

                // 申请一次解密所需的空间资源,密文一定不会比明文长,故不需要申请额外的空间
                byte[] dataBlock = new byte[dataLenOnce];

                UInt32 dataLen = 0;
                UInt32 sourceIndex = 0;
                int final;
                plainStream = new MemoryStream();

                do {
                    // 计算本次解密数据的长度
                    dataLen = (UInt32)cipherText.Length - sourceIndex;
                    if (dataLen > dataLenOnce) {
                        dataLen = dataLenOnce;
                    }

                    // 复制本次解密的密文到缓冲区
                    Array.Copy(cipherText, sourceIndex, dataBlock, 0, dataLen);
                    sourceIndex += dataLen;

                    // 最后一块数据标记,0表示非最后一块数据,1表示是最后一块数据
                    final = (sourceIndex < cipherText.Length) ? 0 : 1;

                    // 解密数据
                    if (!NativeMethods.CryptDecrypt(hKey, IntPtr.Zero, final, 0, dataBlock, ref dataLen)) {
                        int err = Marshal.GetLastWin32Error();
                        Util.MethodTrace(hKey, IntPtr.Zero, final, 0, dataBlock, dataLen);
                        Util.MethodEnd(TraceType.MethodEndNG, err);
                        Util.ThrowWin32Error("CryptDecrypt", err);
                    }

                    // 将解密后的明文数据追加到明文流中
                    plainStream.Write(dataBlock, 0, (int)dataLen);
                } while (final == 0);

                // 取得明文
                plainText = plainStream.ToArray();
            } finally {
                plainStream.Dispose();
            }
            Util.MethodEnd(CommonUtil.TraceType.MethodEndOK, plainText);
        }

[注意]传递专业知识、拓宽行业人脉——看雪讲师团队等你加入!

收藏
免费 0
支持
分享
最新回复 (1)
雪    币: 43
活跃值: (10)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
2
别光看不说话啊,提供个思路也行啊。如果缺少什么信息请说明,我再添加。完整的源代码比较多,也不方便提供,请谅解。
2013-12-20 12:21
0
游客
登录 | 注册 方可回帖
返回
//