调用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);
}
[注意]传递专业知识、拓宽行业人脉——看雪讲师团队等你加入!