2016-12-28 17 views
0

Функции CryptVerifyMessageSignature и CryptDecryptMessage позволяют мне проверить правильность сигнатуры S/MIME (или дешифровать зашифрованные данные в CryptDecryptMessage), а также вернуть сертификат, который использовался для подписания (или шифрования). Однако нет информации о том, какие алгоритмы были фактически использованы для подписи и шифрования. Как я могу получить эту информацию?Как определить алгоритм хеширования и шифрования сообщения S/MIME с помощью Win32 CryptoAPI?

Я использую C#, но любые примеры C/C++ или подсказки также приветствуются.

Edit: проверки подписи фрагмент кода (весь код очень большой, чтобы включить его здесь) предоставляется по запросу

IntPtr pbDetachedSignBlob = IntPtr.Zero; 
uint cbDetachedSignBlob = (uint)signatureBytes.Length; 
IntPtr pbContent = IntPtr.Zero; 
uint cbContent = (uint)data.Length; 

pbDetachedSignBlob = Marshal.AllocHGlobal((int)cbDetachedSignBlob); 
Marshal.Copy(signatureBytes, 0, pbDetachedSignBlob, (int)cbDetachedSignBlob); 
pbContent = Marshal.AllocHGlobal((int)cbContent); 
Marshal.Copy(data, 0, pbContent, (int)cbContent); 
IntPtr[] messageArray = { pbContent }; 
uint[] messageSizeArray = { cbContent }; 

GCHandle messageArrayHandle = GCHandle.Alloc(messageArray, GCHandleType.Pinned); 
IntPtr messageArrayPtr = (IntPtr)messageArrayHandle.AddrOfPinnedObject(); 

int ret = CryptoApiFuncs.MessageFuncs.CryptVerifyDetachedMessageSignature(pVerifyPara, 0, pbDetachedSignBlob, cbDetachedSignBlob, 1, messageArrayPtr, ref messageSizeArray[0], ref pSignerCert); 
+0

может вы делитесь код, который вы используете для? –

+1

@CiroCorvino Я добавил код, хотя я не уверен, как это помогает. У меня нет проблем с этим кодом, он работает нормально. Это просто другое дело. – Alex

ответ

0

АНИ вы используете, проводить проверки достоверности цифровой подписи, которая идет с документами и и т. д. Эта проверка выполняется в отношении сертификата, информация которого содержится в структуре CERT_CONTEXT (pSignerCert), в которую, в свою очередь, входит структура CERT_INFO().

В CERT_CONTEXT вы можете найти информацию о стандартном сертифицированном типе кодирования (X509_ASN_ENCODING или PKCS_7_ASN_ENCODING).

В CERT_INFO вы можете найти CRYPT_ALGORITHM_IDENTIFIER и другие более подробные информации.

Для в документации о CryptVerifyDetachedMessageSignature APIs и родственные структуры:

EDIT:

Система цифровой подписи обычно работает создание хэша данных для входа (SHA1 минимального уровень старых сертификатов стандарта, в настоящее время новых certicates начать с уровня SHA256 ..), то этот хэш получить шифруются с частным ключ с использованием алгоритма асимметричной криптографии (RSA).

Когда сообщение получено, оно расшифровывается с открытым ключом, содержащимся в открытом сертификате, а затем дата получает хешированный с правильным алгоритмом, объявленным в сертификате (с программной точки зрения, см. Структуру полей по), и если эти два хэша (один в том же сертификате, который идет с данными, а другой, рассчитанный на клиенте, который проверяет цифровую подпись), соответствуют, то проверяется, что данные не повреждены или не изменены кем-либо кроме автора, и если сертификат выпущен действующим органом по сертификации, то автор также идентифицируется уверенным образом.

+0

Это информация у меня уже есть. Как я писал в сообщении, у меня нет проблем с получением сертификатов, используемых для подписи и шифрования. Я не могу найти алгоритм, используемый для этого. Вы упомянутый CRYPT_ALGORITHM_IDENTIFIER соответствует алгоритму, используемому для подписи самого сертификата, а не данных, подписанных ключом этого сертификата. Например, у меня есть сообщение, которое подписывается с SHA1 alg, а сам сертификат подписан с SHA256 alg. – Alex

+0

информация (открытый ключ и алгоритм) о подписи данных с помощью закрытого ключа, который вы можете найти в поле CERT_INFO: CERT_PUBLIC_KEY_INFO SubjectPublicKeyInfo, который, в свою очередь, сообщает информацию об алгоритме всегда в структуре CRYPT_ALGORITHM_IDENTIFIER. Я упомянул о другой более подробной информации ... –

+0

Опять же, все, что вы упомянули, касается сертификата. Мне не нужна эта информация, я уже извлек все из CERT_CONTEXT, CERT_INFO и CERT_PUBLIC_KEY_INFO. Я знаю об этих структурах, и у меня уже есть вся информация от них. Теперь мне нужна информация об алгоритме, который использовался для подписи сообщения. Он не содержится в сертификате (например, я могу использовать тот же сертификат для подписывания с использованием разных алгоритмов). – Alex

1

Не удалось найти способ сделать это напрямую через CryptoAPI, но сумел сделать это с System.Security.Cryptography.Pkcs.SignedCms класса:

SignedCms cms = new SignedCms(new ContentInfo(data)); 
cms.Decode(signature); 
string algName = cms.SignerInfos[0].DigestAlgorithm.FriendlyName; 

где данные байтов сообщения проверяется и подпись - это отложенные байты подписи.

Код продукции также должен быть готов к ожиданию не-одиночных значений в коллекции SignerInfos, но пример кода показывает идею.

Точно так же, EnvelopedCms класс предоставляет сведения о алгоритм шифрования сообщения:

EnvelopedCms cms = new EnvelopedCms(); 
cms.Decode(data); 
string s = cms.ContentEncryptionAlgorithm.Oid.FriendlyName;