Не могу придти к общему пониманию механизмов подписи 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 проверку подписи не проходит.
На сервере можно извлечь сертификат из элемента подписи 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);
Айфон мало держит заряд, разбираемся с проблемой вместе с AppLab
Перевод документов на английский язык: Важность и ключевые аспекты
Доброго времени суток! Имеется POST запрос, в котором есть username=" + username + " password = " + password + "
При добавлении записи в бд, из контролера возвращается PartialView, который должен просто выводить все объекты в html-список
Подскажите, пожалуйста, как разумнее\правильнее изменять информацию в файлах на сервере с компьютера клиента?