CryptSignMessage返回错误大小导致二次调用失败问题求助
使用JNA调用Crypt32.dll的CryptSignMessage函数遇到缓冲区大小异常问题
接口定义
我们通过JNA定义了访问本地库Crypt32.dll的接口:
public interface IWinCrypt extends StdCallLibrary { IWinCrypt WIN_CRYPT_LIB = Native.load("Crypt32", IWinCrypt.class, W32APIOptions.DEFAULT_OPTIONS); /** * 对指定内容生成哈希、签名哈希,并将原始消息内容和签名哈希一起编码。 * * @param cryptSignMessagePara 包含签名参数的结构体。 * @param fDetachedSignature 如果是分离式签名则为TRUE,否则为FALSE。 * @param cToBeSigned rgpbToBeSigned和rgcbToBeSigned数组的元素数量。 * @param rgpbToBeSigned 指向待签名内容缓冲区的指针数组。 * @param rgcbToBeSigned rgpbToBeSigned中各内容缓冲区的字节大小数组。 * @param pbSignedBlob 接收编码后签名哈希的缓冲区指针。 * @param pcbSignedBlob 指向DWORD类型变量的指针,指定pbSignedBlob缓冲区的字节大小。 * @return 成功返回true,失败返回false */ boolean CryptSignMessage(WinCryptDataTypeMapping.CryptSignMessagePara.ByReference cryptSignMessagePara, boolean fDetachedSignature, int cToBeSigned, PointerByReference rgpbToBeSigned, IntByReference rgcbToBeSigned, Pointer pbSignedBlob, IntByReference pcbSignedBlob); }
调用流程
参考官方示例流程,先传入null作为签名Blob指针获取所需缓冲区大小:
final Memory ptr = new Memory(message.length); ptr.write(0, message, 0, message.length); final PointerByReference aMessage = new PointerByReference(ptr); final IntByReference pMessageLen = new IntByReference(message.length); final IntByReference pSignLen = new IntByReference(); IWinCrypt.WIN_CRYPT_LIB.CryptSignMessage(signMessagePara, true, 1, aMessage, pMessageLen, null, pSignLen)
随后根据返回的大小分配内存,再次调用函数:
final Memory signature = new Memory(pSignLen.getValue()); IWinCrypt.WIN_CRYPT_LIB.CryptSignMessage(signMessagePara, true, 1, aMessage, pMessageLen, signature, pSignLen)
问题现象
第二次调用始终失败,错误信息为com.sun.jna.platform.win32.Win32Exception: More data is available.,提示需要更大的缓冲区空间。测试发现首次调用返回的大小为2019字节,第二次调用失败后pSignLen被更新为2081字节。
环境信息
- 操作系统:Windows Server 2019
- Java版本:Java 8、Java 11均出现该问题
- JVM位数:64位
- JNA版本:5.0.0及以上多个版本均测试过
内容的提问来源于stack exchange,提问作者Suhas .N
相关产品推荐
相关产品推荐

