Здравствуйте!
Помогите пожалуйста разобраться.
Даю вводную.
1. На сервер приложений приходит неподписанная xml-ка.
Я считаю от нее хэш по ГОСТ3411, сохраняю эту xml в месте с вычисленным хешом к себе в БД.
В качестве ответа sender получает id добавленного документа(та самая xml-ка) + вычисленный хэш.
2. Затем sender передаёт мне id документа, который был добавлен(см. пункт 1) + xmблок <Signature> вида(соответствует ранее присланной неподписанной xml-ке):
<Signature>
<SignedInfo>
<CanonicalizationMethod>...</CanonicalizationMethod>
<SignatureMethod>...</SignatureMethod>
<Reference URI="...">
<Transforms>...</Transforms>
<DigestMethod>...</DigestMethod>
<DigestValue>хэш от тела документа</DigestValue>
</Reference>
</SignedInfo>
<SignatureValue>base64 блок - закодированный хэш содержимого узла SignedInfo</SignatureValue>
<KeyInfo>блок с сертификатом остается как был</KeyInfo>
</Signature>
То есть присылают только блок <Signature>, тело самой неподписанной xml-ки у меня уже есть в БД.
3. Мне требуется проделать вот что :
a. Пересчитать хэш элемента SignedInfo
b. Расшифровать содержимое SignatureValue на открытом ключе из KeyInfo
c. Проверить совпадение значений п.1 и п.2
d. Если совпадение есть, взять хэш исходного документа из временной таблицы по idDoc
e. Сравнить со значением из первого узла Reference->DigestValue
Застрял на пункте b (Расшифровать содержимое SignatureValue на открытом ключе из KeyInfo).
Не получается передать PublicKey из <KeyInfo> в объект Gost3410CryptoServiceProvider.
Получаю System.NullReferenceException {"Ссылка на объект не указывает на экземпляр объекта."}
StackTrace:
в CryptoPro.Asn1.GostR3410_2001_PKISyntax.GostR3410_2001_PublicKeyParameters.Encode(Asn1BerEncodeBuffer buffer, Boolean explicitTagging)
в Com.Objsys.Asn1.Runtime.Asn1Type.Encode(Asn1BerEncodeBuffer buffer)
в CryptoPro.Sharpei.cpAsnUtils.EncodeParameters(Gost3410CspObject cspObject)
в CryptoPro.Sharpei.COMCryptography.EncodePublicBlob(Gost3410CspObject cspObject)
в CryptoPro.Sharpei.COMCryptography.ImportPublicKey(SafeProvHandleCP hCSP, CspProviderFlags flags, Gost3410CspObject pubKey, SafeKeyHandleCP& hKey)
в CryptoPro.Sharpei.Gost3410CryptoServiceProvider.ImportParameters(Gost3410Parameters parameters)
в CryptoPro_TestApp.Program.Main(String[] args) в ...
в System.AppDomain._nExecuteAssembly(RuntimeAssembly assembly, String[] args)
в Microsoft.VisualStudio.HostingProcess.HostProc.RunUsersAssembly()
в System.Threading.ExecutionContext.RunInternal(ExecutionContext executionContext, ContextCallback callback, Object state, Boolean preserveSyncCtx)
в System.Threading.ExecutionContext.Run(ExecutionContext executionContext, ContextCallback callback, Object state, Boolean preserveSyncCtx)
в System.Threading.ExecutionContext.Run(ExecutionContext executionContext, ContextCallback callback, Object state)
в System.Threading.ThreadHelper.ThreadStart()
Соответствующий кусок кода как z пытаюсь это сделать:
var xdoc = XDocument.Parse(File.ReadAllText(@"D:\unsigned_xml.txt", Encoding.UTF8));
var signatureValueElem = xdoc.Descendants().FirstOrDefault(el1 => el1.Name.LocalName.Equals("SignatureValue"));
byte[] signatureValueBytes = Convert.FromBase64String(signatureValueElem.Value);
//Создаем новый Гост-34.10 CSP.
var Gost = new Gost3410CryptoServiceProvider();
var certStrBase64 = xdoc.Descendants().FirstOrDefault(el1 => el1.Name.LocalName.Equals("Signature")).FirstElement("KeyInfo").
FirstElement("X509Data").Elements().Where(it => it.Name.LocalName.Equals("X509Certificate")).
FirstOrDefault().Value.Replace("-----BEGIN CERTIFICATE-----", null).Replace(
"-----END CERTIFICATE-----", null).Trim();
var certX509 = new X509Certificate2(Convert.FromBase64String(certStrBase64));
var pubKeyParam = new Gost3410Parameters {PublicKey = certX509.GetPublicKey()};
Gost.ImportParameters(pubKeyParam); //!!!!! Здесь происходит исключение System.NullReferenceException.
//Поле PublicKey - задано. Остальные поля DigestParamSet, EncryptionParamSet, PrivateKey, PublicKeyParamSet == null
//Проверяем правильность подписи и выводим результат.
bool b = GostVerifyHash(hashSignedInfo, signatureValueBytes, Gost, "Gost3411");
if (b)
{
Console.WriteLine("Подпись вычислена верно.");
}
else
{
Console.WriteLine("Подпись вычислена неверно.");
}
//////////////////////////////////////////////////////////////////////////
static bool GostVerifyHash(byte[] HashValue, byte[] SignedHashValue, AsymmetricAlgorithm key, string HashAlg)
{
try
{
//Создаем форматтер подписи с закрытым ключом из переданного
//функции криптопровайдера.
GostSignatureDeformatter Deformatter = new GostSignatureDeformatter(key);
//Deformatter.SetKey();
//Устанавливаем хэш-алгоритм.
Deformatter.SetHashAlgorithm(HashAlg);
//Проверяем подпись и возвращаем результат.
return Deformatter.VerifySignature(HashValue, SignedHashValue);
}
catch (CryptographicException e)
{
Console.WriteLine(e.Message);
return false;
}
}
Подскажите пожалуйста что мне нужно сделать чтобы расшифровать содержимое SignatureValue на открытом ключе из KeyInfo.
В правильно ли я направлении вообще иду..
Буду очень признателен.
Отредактировано пользователем 9 июля 2014 г. 15:36:12(UTC)
| Причина: Не указана