Подскажите пожалуйста, в чем может быть причина. уже 2 недели бьюсь над ней.
На C# подписываю xml файл с помощью CryptSignMessage(...). Если подпись not detached (второй параметр false)
то всё нормально проверяется с помощью VerifyApi(....), а если подпись detached (2-ой параметр true),
то функция VerifyDetachApi() (ниже по тексту) в CryptVerifyDetachedMessageSignature(...)
выдает exception Hresult = - 2146233088 (COR_E_EXCEPTION 0x80131500)
Marshal.GetLastWin32Error() возвращает 0
static bool VerifyApi(byte[] data, byte[] signature)
{
GCHandle pCertContext;
pCertContext = GCHandle.Alloc(IntPtr.Zero, GCHandleType.Pinned);
Byte[] pbSignedMessageBlob = signature;
Int32 cbSignedMessageBlob = signature.Length;
Byte[] pbDecodedMessageBlob = null;
int cbDecodedMessageBlob = 0;
// Initialize the VerifyParams data structure.
CryptoApi.CRYPT_VERIFY_MESSAGE_PARA VerifyParams = new CryptoApi.CRYPT_VERIFY_MESSAGE_PARA();
VerifyParams.cbSize = Marshal.SizeOf(VerifyParams);
VerifyParams.dwMsgAndCertEncodingType = CryptoApi.MY_ENCODING_TYPE;
VerifyParams.hCryptProv = 0;
VerifyParams.pfnGetSignerCertificate = IntPtr.Zero;
VerifyParams.pvGetArg = IntPtr.Zero;
// With two calls to CryptVerifyMessageSignature, verify and decode
// the signed message.
// First, call CryptVerifyMessageSignature to get the length of the
// buffer needed to hold the decoded message.
//
bool res = CryptoApi.CryptVerifyMessageSignature(
ref VerifyParams, // Verify parameters.
0, // Signer index.
pbSignedMessageBlob, // Pointer to signed BLOB.
cbSignedMessageBlob, // Size of signed BLOB.
pbDecodedMessageBlob, // Buffer for decoded message.
ref cbDecodedMessageBlob, // Size of buffer.
pCertContext.AddrOfPinnedObject() // Pointer to signer certificate.
);
if (res == false)
{
throw new Exception("CryptVerifyMessageSignature error", new Win32Exception(Marshal.GetLastWin32Error()));
}
// Allocate memory for the buffer.
//
pbDecodedMessageBlob = new Byte[cbDecodedMessageBlob];
// Call CryptVerifyMessageSignature again to copy the message into
// the buffer.
//
res = CryptoApi.CryptVerifyMessageSignature(
ref VerifyParams, // Verify parameters.
0, // Signer index.
pbSignedMessageBlob, // Pointer to signed BLOB.
cbSignedMessageBlob, // Size of signed BLOB.
pbDecodedMessageBlob, // Buffer for decoded message.
ref cbDecodedMessageBlob, // Size of buffer.
pCertContext.AddrOfPinnedObject() // Pointer to signer certificate.
);
if (res == false)
{
throw new Exception("CryptVerifyMessageSignature error", new Win32Exception(Marshal.GetLastWin32Error()));
}
else
{
return true;
}
}
static bool VerifyDetachApi(byte[] messageData, byte[] signatureData) //, out byte[] p_x509
{
// Verify the message signature.
CryptoApi.CRYPT_VERIFY_MESSAGE_PARA verifyParams;
IntPtr buffer = Marshal.AllocCoTaskMem(Marshal.SizeOf(typeof(byte)) * messageData.Length); // AllocHGlobal
Marshal.Copy(messageData, 0, buffer, messageData.Length);
IntPtr[] rgpbToBeSigned = new IntPtr[1] { buffer };
//rgpbToBeSigned[0] = buffer;
int[] rgcbToBeSigned = new int[1] { messageData.Length };
Marshal.FreeCoTaskMem(buffer);
//p_x509 = null;
GCHandle pCertContext;
verifyParams = new CryptoApi.CRYPT_VERIFY_MESSAGE_PARA();
verifyParams.cbSize = (int)Marshal.SizeOf(verifyParams);
verifyParams.dwMsgAndCertEncodingType = CryptoApi.MY_ENCODING_TYPE; //CryptoConstants.X509_ASN_ENCODING | CryptoConstants.PKCS_7_ASN_ENCODING;
verifyParams.hCryptProv = 0;
verifyParams.pfnGetSignerCertificate = IntPtr.Zero;
verifyParams.pvGetArg = IntPtr.Zero;
pCertContext = GCHandle.Alloc(IntPtr.Zero, GCHandleType.Pinned);
try
{
bool res = CryptoApi.CryptVerifyDetachedMessageSignature(
ref verifyParams, // Verify parameters.
0, // Signer index.
signatureData, // Buffer for decoded message.
signatureData.Length, // Size of buffer.
1,
rgpbToBeSigned, // Pointer to signed BLOB.
rgcbToBeSigned, // Size of signed BLOB.
pCertContext.AddrOfPinnedObject());//pCertContext.AddrOfPinnedObject()
if (!res)
{
throw new Exception("Error while encrypting data [" + Marshal.GetLastWin32Error() + "].");
}
try
{
X509Certificate x509 = new X509Certificate((IntPtr)pCertContext.Target);
}
finally
{
CryptoApi.CertFreeCertificateContext((IntPtr)pCertContext.Target);
}
return res;
}
finally
{
pCertContext.Free();
}
}
[StructLayout(LayoutKind.Sequential)]
public struct CRYPT_VERIFY_MESSAGE_PARA
{
public int cbSize;
public uint dwMsgAndCertEncodingType;
public int hCryptProv;
public IntPtr pfnGetSignerCertificate;
public IntPtr pvGetArg;
}
[DllImport("Crypt32.dll", SetLastError = true)]
public static extern Boolean CryptVerifyMessageSignature(
ref CRYPT_VERIFY_MESSAGE_PARA pVerifyPara,
Int32 dwSignerIndex,
Byte[] pbSignedBlob,
Int32 cbSignedBlob,
Byte[] pbDecoded,
ref Int32 pcbDecoded,
IntPtr ppSignerCert
);
[DllImport("Crypt32.dll", SetLastError = true)]
static internal extern bool CryptVerifyDetachedMessageSignature(
ref CRYPT_VERIFY_MESSAGE_PARA pVerifyPara,
int dwSignerIndex,
byte[] pbDetachedSignBlob,
int cbDetachedSignBlob,
int cToBeSigned,
IntPtr[] rgpbToBeSigned,
int[] rgcbToBeSigned,
IntPtr ppSignerCert);