Ответ 1
Хотя DSA и ECDSA связаны между собой, они не совпадают. Почему бы не попробовать ECDsaCryptoServiceProvider
? Обратите внимание, что поддержка ECDSA для эллиптических кривых включает только кривые NIST.
Зная немного о криптографии, у меня большие проблемы с тем, что кажется простой задачей.
У меня есть сертификат .pem, байты данных и подпись этих данных. Я хочу проверить, изменил ли кто-либо данные, сопоставив его с сигнатурой.
Моя попытка:
private bool VerifySignature(byte[] data, byte[] signature)
{
try
{
X509Certificate certificate = new X509Certificate("cert_filename.pem");
if (certificate == null)
return false;
DSACryptoServiceProvider dsa = (DSACryptoServiceProvider)certificate.PublicKey.Key;
return dsa.VerifyData(data, signatureData);
}
catch
{
return false;
}
}
Но это дает мне ошибку
'Алгоритм ключа сертификатов не поддерживается' (System.NotSupportedException).
В загруженном сертификате говорится, что алгоритм подписи является "sha1ecdsa".
Я пытаюсь проверить данные только подписи. Что мне здесь не хватает? Я бы хотел сделать это без каких-либо внешних решений, поскольку это кажется действительно тривиальной задачей.
Обновление: я пытаюсь достичь такой же функциональности, как в следующем Java-коде:
private boolean verify(byte[] data, byte[] signature)
{
boolean isLicenseCorrect = false;
Signature sig = Signature.getInstance("SHA1WithECDSA");
sig.initVerify(certificate.getPublicKey());
sig.update(data);
return sig.verify(signature);
}
Хотя DSA и ECDSA связаны между собой, они не совпадают. Почему бы не попробовать ECDsaCryptoServiceProvider
? Обратите внимание, что поддержка ECDSA для эллиптических кривых включает только кривые NIST.
.NET 4.6.1 добавлена улучшенная поддержка ECDSA. Хотя я не поклонник вашего catch-all-and-return-false, я буду держать его здесь для сравнения:
private bool VerifySignature(byte[] data, byte[] signature)
{
try
{
// new cannot return null, so no point in a null check. It would have thrown.
using (X509Certificate certificate = new X509Certificate("cert_filename.pem"))
using (ECDsa ecdsa = certificate.GetECDsaPublicKey())
using (RSA rsa = certificate.GetRSAPublicKey())
// Improved DSA is 4.6.2
{
// You said the cert was ECDSA-SHA1, but that doesn't mean the original data was.
// I assumed it was.
if (ecdsa != null)
return ecdsa.VerifyData(data, signature, HashAlgorithmName.SHA1);
if (rsa != null)
return rsa.VerifyData(data, signature, HashAlgorithmName.SHA1, RSASignaturePadding.Pkcs1);
return false;
}
}
catch
{
return false;
}
}
Обратите внимание, что в .NET 4.6 базовый класс RSA имеет определенные методы Sign/Verify, а в 4.6.1 базовый класс ECDsa получил аналогичную обработку. Новый код не должен говорить о типах * CryptoServiceProvider, если не загружать уже существующие именованные ключи.
Также стоит отметить, что методы PublicKey Get [Algorithm] возвращают null
, когда открытый ключ не относится к типу алгоритма, поэтому проверка нулей оправдана.