Электронная подпись XML

346
20 июня 2017, 22:31

Не могу придти к общему пониманию механизмов подписи xml-документов. Буду благодарен за помощь разобраться)

Ситуация у меня такая:

1) есть удостоверяющий центр, выпущенные сертификаты которого проставляются на серверах в хранилище windows.. в личные, доверенные и так далее..не суть.

При логине в приложение пользователь подписывает случайно сгенерированную строку выбранным им сертификатом. На сервере эта подпись проходит проверку:

CAPICOM.SignedData _signedData = new CAPICOM.SignedData();
_signedData.Verify(signedData, false, CAPICOM_SIGNED_DATA_VERIFY_FLAG.CAPICOM_VERIFY_SIGNATURE_AND_CERTIFICATE);
if (_signedData.Content != data) throw new Exception("Контент подписи не совпадает с полученным контентом");
var _certificate = _signedData.Certificates[1]; // сертификат пользователя

Так мы получаем сертификат пользователя (открытый ключ). Важно то, что подпись пройдет проверку только в том случае, если соответствующий открытый ключ сертификата стоит на сервере в хранилище сертов. Это нам и нужно, пускать только тех, чьи серты мы сами выпускали) Здесь вроде понятно.

2) теперь нужно, чтобы эти же пользователи подписывали своими сертами xml-и. Моё ПО на клиенте генерит сами xml-и и подписывает их указанным пользователем сертификатом:

public static void SignXml(XmlDocument xmlDoc, /*RSA*/AsymmetricAlgorithm Key)
{
            SignedXml signedXml = new SignedXml(xmlDoc);
            signedXml.SigningKey = Key;
            Reference reference = new Reference();
            reference.Uri = "";//подпись всего xml-документа
            XmlDsigEnvelopedSignatureTransform env = new XmlDsigEnvelopedSignatureTransform();
            reference.AddTransform(env);
            signedXml.AddReference(reference);
            KeyInfo keyInfo = new KeyInfo();
            keyInfo.AddClause(CryptService.GetKeyInfoClause(Key)); // RSA or GOST
            signedXml.KeyInfo = keyInfo;
            signedXml.ComputeSignature();
            XmlElement xmlDigitalSignature = signedXml.GetXml();
            xmlDoc.DocumentElement.AppendChild(xmlDoc.ImportNode(xmlDigitalSignature, true));
}

Далее подписанный xml отправляется на сервер, где проходит проверку подписи:

            XmlDocument doc = new XmlDocument();
            doc.PreserveWhitespace = true;
            doc.Load(path);
            SignedXml sx = new SignedXml(doc);
            XmlNodeList nodeList = doc.GetElementsByTagName("Signature");
            sx.LoadXml((XmlElement)nodeList[0]);
            return sx.CheckSignature();

Код работает, но у меня возникают вопросы с пониманием: в таком случае можно подписать xml абсолютно любым сертификатом, не выпущенным нашим УЦ, и так как инфа об открытом ключе хранится в самом подписанном xml, подпись проходит проверку. Этот вариант мне не подходит. У метода CheckSignature есть перегрузка с параметром типа AsymmetricAlgorithm, который проверит сертификат подписи на существование в хранилище, проверит его валидность, срок действия и так далее. Это мне и нужно, но я не знаю заранее какой из пользователей прислал подписанный xml.

Скажите пожалуйста: как проверять подпись xml или как её правильно создавать, чтобы проверку подписи проходили только те xml-и, которые подписаны только нашими сертификатами (которые установлены в хранилище)?

P.s. и в чем вообще смысл держать в xml и саму подпись, и открытый ключ для расшифровки подписи? Если при подписи убрать строку signedXml.KeyInfo = keyInfo;, то xml проверку подписи не проходит.

Answer 1

На сервере можно извлечь сертификат из элемента подписи KeyInfo и проверить его валидность. Сертификат однозначно идентифицирует клиента, который прислал xml:

var keyInfo = sx.KeyInfo.OfType<KeyInfoX509Data>().First();
var cert = (X509Certificate2)keyInfo.Certificates[0];    
bool isValid = cert.Verify();

Либо воспользоваться перегрузкой метода CheckSignature, он вместе с подписью проверит и валидность сертификата:

return sx.CheckSignature(cert, false);
READ ALSO
Как передать string в textbox?

Как передать string в textbox?

Доброго времени суток! Имеется POST запрос, в котором есть username=" + username + " password = " + password + "

217
JSON Использование

JSON Использование

Подскажите как возможно получить и записать значения json в файле

199
Visual Studio is busy asp.net mvc

Visual Studio is busy asp.net mvc

При добавлении записи в бд, из контролера возвращается PartialView, который должен просто выводить все объекты в html-список

335
Сервер - Клиент. Рейтинг

Сервер - Клиент. Рейтинг

Подскажите, пожалуйста, как разумнее\правильнее изменять информацию в файлах на сервере с компьютера клиента?

222