RSA + SHA256 может и будет работать ...
Ваш более поздний пример может работать не все время, он должен использовать OID хеш-алгоритма, а не его имя.Согласно первому примеру, это получается из вызова на CryptoConfig.MapNameToOID(AlgorithmName)
, где AlgorithmName
- это то, что вы предоставляете (т. Е. «SHA256»).
Сначала вам понадобитсяэто сертификат с закрытым ключом.Обычно я читаю мой из хранилища LocalMachine или CurrentUser, используя файл открытого ключа (.cer
) для идентификации закрытого ключа, а затем перечисляю сертификаты и сопоставляю их по хэшу ...
X509Certificate2 publicCert = new X509Certificate2(@"C:\mycertificate.cer");
//Fetch private key from the local machine store
X509Certificate2 privateCert = null;
X509Store store = new X509Store(StoreLocation.LocalMachine);
store.Open(OpenFlags.ReadOnly);
foreach( X509Certificate2 cert in store.Certificates)
{
if (cert.GetCertHashString() == publicCert.GetCertHashString())
privateCert = cert;
}
вы получите там, как только вы получили сертификат с закрытым ключом, мы должны восстановить его.Это может потребоваться из-за способа, которым сертификат создает свой закрытый ключ, но я не совсем уверен, почему.В любом случае, мы делаем это, сначала экспортируя ключ, а затем повторно импортируя его, используя любой промежуточный формат, который вам нравится, самый простой - xml:
//Round-trip the key to XML and back, there might be a better way but this works
RSACryptoServiceProvider key = new RSACryptoServiceProvider();
key.FromXmlString(privateCert.PrivateKey.ToXmlString(true));
Как только это будет сделано, мы теперь можем подписать часть данных какследует:
//Create some data to sign
byte[] data = new byte[1024];
//Sign the data
byte[] sig = key.SignData(data, CryptoConfig.MapNameToOID("SHA256"));
Наконец, проверка может быть проведена непосредственно с открытым ключом сертификата без необходимости восстановления, как мы делали с закрытым ключом:
key = (RSACryptoServiceProvider)publicCert.PublicKey.Key;
if (!key.VerifyData(data, CryptoConfig.MapNameToOID("SHA256"), sig))
throw new CryptographicException();