Ключевое слово в защите информации
КЛЮЧЕВОЕ СЛОВО
в защите информации
Получить ГОСТ TLS-сертификат для домена (SSL-сертификат)
Добро пожаловать, Гость! Чтобы использовать все возможности Вход. Новые регистрации запрещены.

Уведомление

Icon
Error

Опции
К последнему сообщению К первому непрочитанному
Offline Igor.K.  
#1 Оставлено : 24 июля 2015 г. 17:13:08(UTC)
Igor.K.

Статус: Новичок

Группы: Участники
Зарегистрирован: 10.07.2015(UTC)
Сообщений: 4
Беларусь
Откуда: Минск

Сказал(а) «Спасибо»: 2 раз
Подскажите пожалуйста, в чем может быть причина. уже 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);
Offline Максим Коллегин  
#2 Оставлено : 24 июля 2015 г. 18:18:16(UTC)
Максим Коллегин

Статус: Сотрудник

Группы: Администраторы
Зарегистрирован: 12.12.2007(UTC)
Сообщений: 6,405
Мужчина
Откуда: КРИПТО-ПРО

Сказал «Спасибо»: 37 раз
Поблагодарили: 720 раз в 624 постах
А SignedCms использовать религия не позволяет? https://msdn.microsoft.c...y/ms180952(v=vs.85).aspx
Знания в базе знаний, поддержка в центре поддержки
thanks 1 пользователь поблагодарил Максим Коллегин за этот пост.
Igor.K. оставлено 27.07.2015(UTC)
Offline Kirill Sobolev  
#3 Оставлено : 25 июля 2015 г. 22:01:39(UTC)
Кирилл Соболев

Статус: Сотрудник

Группы: Участники
Зарегистрирован: 25.12.2007(UTC)
Сообщений: 1,733
Мужчина
Откуда: КРИПТО-ПРО

Поблагодарили: 177 раз в 168 постах
Зачем вот этот вызов
Цитата:
Marshal.FreeCoTaskMem(buffer);

перед вызовом CryptVerifyDetachedMessageSignature?
Техническую поддержку оказываем тут
Наша база знаний
thanks 1 пользователь поблагодарил Кирилл Соболев за этот пост.
Igor.K. оставлено 27.07.2015(UTC)
Offline Igor.K.  
#4 Оставлено : 27 июля 2015 г. 16:21:58(UTC)
Igor.K.

Статус: Новичок

Группы: Участники
Зарегистрирован: 10.07.2015(UTC)
Сообщений: 4
Беларусь
Откуда: Минск

Сказал(а) «Спасибо»: 2 раз
Спасибо за ответы. SignedCms использовал, там всё нормально. Просто попробовал через CryptoAPI.
Marshal.FreeCoTaskMem(buffer); перед вызовом CryptVerifyDetachedMessageSignature? не досмотрел.
В общем разобрался уже. При формировании подписи неправильно указал размер исходного сообщения.

Еще раз спасибо.
Offline Igor.K.  
#5 Оставлено : 27 июля 2015 г. 16:34:57(UTC)
Igor.K.

Статус: Новичок

Группы: Участники
Зарегистрирован: 10.07.2015(UTC)
Сообщений: 4
Беларусь
Откуда: Минск

Сказал(а) «Спасибо»: 2 раз
А можно ещё маленький вопрос: при подписи CryptSignMessage(....)
почему при таком указании
SignPara.HashAlgorithm.pszObjId = CryptoApi.CertAlgIdToOID(CryptoApi.CertOIDToAlgId(signingCert.SignatureAlgorithm.Value));
дает ошибку: неправильный криптографический алгоритм, а если явно присвоить зачение = "....."; то тогда нормально отрабатывает.
Значение которое возвращает CryptoApi.CertAlgIdToOID(CryptoApi.CertOIDToAlgId(signingCert.SignatureAlgorithm.Value) такое же как и задаю явно.
Offline Kirill Sobolev  
#6 Оставлено : 27 июля 2015 г. 17:13:53(UTC)
Кирилл Соболев

Статус: Сотрудник

Группы: Участники
Зарегистрирован: 25.12.2007(UTC)
Сообщений: 1,733
Мужчина
Откуда: КРИПТО-ПРО

Поблагодарили: 177 раз в 168 постах
Уверены, что такое же?
А вообще, нельзя устанавливать алгоритм хеширования при подписи в алгоритм подписи сертификата.
Это могут быть в принципе разные алгоритмы, не имеющие друг к другу никакого отношения.
Техническую поддержку оказываем тут
Наша база знаний
Offline Igor.K.  
#7 Оставлено : 27 июля 2015 г. 17:27:10(UTC)
Igor.K.

Статус: Новичок

Группы: Участники
Зарегистрирован: 10.07.2015(UTC)
Сообщений: 4
Беларусь
Откуда: Минск

Сказал(а) «Спасибо»: 2 раз
Значение такое же. Просто если это значение присвоить переменной типа string и затем присвоить саму переменную,
то будет такая же ошибка. А вот если значение явно присвоить переменной типа const string - тогда ошибки нет, отрабатывает.
Почему надо присваивать SignPara.HashAlgorithm.pszObjId именно константу, тогда работает.

[StructLayout(LayoutKind.Sequential)]
public struct CRYPT_SIGN_MESSAGE_PARA
{
public int cbSize;
public int dwMsgEncodingType;
public IntPtr pSigningCert; // PCCERT_CONTEXT
public CRYPT_ALGORITHM_IDENTIFIER HashAlgorithm; // CRYPT_ALGORITHM_IDENTIFIER
public IntPtr pvHashAuxInfo; // void*
public int cMsgCert;
public IntPtr rgpMsgCert; // PCCERT_CONTEXT*
public int cMsgCrl;
public IntPtr rgpMsgCrl; // PCCRL_CONTEXT*
public int cAuthAttr;
public IntPtr rgAuthAttr; // PCRYPT_ATTRIBUTE
public int cUnauthAttr;
public IntPtr rgUnauthAttr; // PCRYPT_ATTRIBUTE
public int dwFlags;
public int dwInnerContentType;
}

[StructLayout(LayoutKind.Sequential)]
public struct CRYPT_ALGORITHM_IDENTIFIER
{
[MarshalAs(UnmanagedType.LPStr)]
public String pszObjId; // LPSTR
public CRYPTOAPI_BLOB Parameters;
}
RSS Лента  Atom Лента
Пользователи, просматривающие эту тему
Guest
Быстрый переход  
Вы не можете создавать новые темы в этом форуме.
Вы не можете отвечать в этом форуме.
Вы не можете удалять Ваши сообщения в этом форуме.
Вы не можете редактировать Ваши сообщения в этом форуме.
Вы не можете создавать опросы в этом форуме.
Вы не можете голосовать в этом форуме.