На одном из идущих в настоящее время проектов решалась задача подписания (наложения ЭП - электронной подписи) XML документов, а именно SOAP-пакетов. Рекомендованным форматом был
OASIS Standard 200401 с профилем
X.509 Certificate Token Profile. Эти документы описывают применение созданного www-консорциумом (W3C) формата электронных подписей XML (XMLDSig - XML Digital Signature) в SOAP-сообщениях. XML-подписи, как и другие виды ЭП, поддерживают аутентификацию, целостность
данных и неотрекаемость от подписания данных.
Отмечу несколько особенностей формата XMLDSig:
1. Объектом подписания может служить не весь XML-документ, а только его часть, т.е. определённый узел. Согласно OASIS Standard 200401 подписываемым объектом является тело (узел Body) SOAP-сообщения.
2. Различные части XML-документа могут быть подписаны несколькими исполнителями.
3. XML-подпись может находиться на разных уровнях по отношению к подписываемому объекту:
4. Для проверки действительности ЭП необходим доступ к объекту подписания.
В общем случае сообщение состоит из заголовка и тела: Header и Body. Header содержит метаданные, а Body данные. XML-подпись помещается в узел Header.
Для решения задачи были использованы ГОСТ Р 34.11-94 — российский криптографический стандарт вычисления хеш-функции и ГОСТ Р 34.10-2001 - стандарт электронной подписи.
В силу гибкости правил составления XML, одна и та же структура документа и одна и та же часть информации могут быть представлены различными XML-документами. Рассмотрим два документа:
С логической точки зрения они равнозначны, то есть имеют одинаковую XML-схему. Но XML-файлы этих листингов не содержат одну и ту же последовательность символов, что повлечёт разные результаты, например, при получении значения хэша.
Во избежание подобных разночтений были приняты строгие правила форматирования и требования к содержанию XML-сообщений. Процесс приведения XML-документов к унифицированному (каноническому) виду называют каноникализацией (англ. Canonicalization). Примерами правил может быть применение определённой схемы кодирования (UTF-8), нормализация значений атрибутов, использование двойдых кавычек для значений атрибутов, определённый порядок атрибутов и объявлений пространств имён, и др. Каноникализация XML бывает нескольких видов, которые отличаются составом правил. Побробнее о процессе каноникализации можно прочитать в официальной спецификации W3C (русскоязычные статьи на эту тему можно найти здесь и здесь)
Для реализации подписания XML в DIRECTUM была написана COM-библиотека, внутри которорй описаны 3 класса: Hasher, Signer и XMLCanonicalizer для получения хэша, значения ЭП и каноникализации XML-документов соответственно.
Для функционирования библиотеки требуется Crypto PRO CSP (тестировалась на версии Crypto PRO CSP 3.6.6497 KC2) и .NET (минимально 2.0).
Регистрация библиотеки выполняется выполнением следующей команды:
> regasm.exe "путь к dll" /codebase /tlb
Содержит поля Content (тип 'строка') и HashValueAsBase64 (тип 'строка'), а также метод для вычисления значения хэш-функции Hash(). Для вычисления необходимо означить Content, вызвать метод Hash(), в результате которого в поле HashValueAsBase64 запишется значение хэш-функции в Base64.
Содержит поля Content (тип 'строка'), ContainerName (тип 'строка'), CertificateAsPEM (тип 'строка'), BESignatureValueAsBase64 (тип 'строка'), метод Sign(). После инициализации объекта необходимо означить Content (данные для подписания), ContainerName (имя контейнера закрытого ключа сертификата), вызвать метод Sign(). После чего в поле CertificateAsPEM попадёт соответствующий закрытому ключу сертификат в Base64, а в поле BESignatureValueAsBase64 значение подписи в виде Base64-строки.
Содержит поля XMLContent (тип 'строка'), CanonicalXML (тип 'строка'), метод C14NExc(). Для получения канонической формы XML нужно означить XMLContent, вызвать C14NExc(), получить результат из поля CanonicalXML.
Создание подписи выглядит следующим образом: сначала формируется основа soap-пакета, узлы Header и Body. Body заполняется данными и добавляется атрибут wsu:ID="Body" - идентификатор подписываемых данных.
Далее нужно подготовить структуру Security и включить её в Header.
Заполнение структуры Security происходит в следующем порядке:
Для того, чтобы проверить сформированную таким образом ЭП необходимо проделать все действия в обратном порядке, а именно:
XML-документ до подписания: SOAPEnvelope.xml (266,00 байт)
Подписанный XML-документ: SignedSOAPEnvelope.xml (3,32 Кб)
Примеры подписания XML на ISBL (сценарий): dev.zip (5,95 Кб)
Для постоянного использования код, выполняющий типовое подписание готового SOAP-конверта, вынесен в функцию SignSOAP().
Для подписания используется сертификат из личного хранилища сертификатов текущего пользователя.
Cертификат для тесподписания можно получить на тестовом центре сертификации КриптоПРО.
Библиотека SIRCrypt: SIRCrypt.zip (7,42 Кб)
Дима, это невероятно круто! Плюсую за данную разработку!
Монструозно!
Где можно ознакомится подробно с библиотеками(описание функций и т.д.)?
Здравствуйте!Как использовать данную библиотеку в Delphi?
Разобрался...Только почему то
CanonicalXML возвращает результат - байтовый а не строка
function SirCryptSigner(const Content: WideString; const Container: WideString;const enc :boolean; out CertPem: WideString): WideString;
Var
p,s:Pointer;
v,c:Variant;
obj:OleVariant;
Pair: TStringStream;
begin
//https://club.directum.ru/post/546
{Ñîäåðæèò ïîëÿ Content (òèï 'ñòðîêà'), ContainerName (òèï 'ñòðîêà'), CertificateAsPEM (òèï 'ñòðîêà'), BESignatureValueAsBase64 (òèï 'ñòðîêà'), ìåòîä Sign().
Ïîñëå èíèöèàëèçàöèè îáúåêòà íåîáõîäèìî îçíà÷èòü Content (äàííûå äëÿ ïîäïèñàíèÿ), ContainerName (èìÿ êîíòåéíåðà çàêðûòîãî êëþ÷à ñåðòèôèêàòà), âûçâàòü ìåòîä Sign().
Ïîñëå ÷åãî â ïîëå CertificateAsPEM ïîïàä¸ò ñîîòâåòñòâóþùèé çàêðûòîìó êëþ÷ó ñåðòèôèêàò â Base64, à â ïîëå BESignatureValueAsBase64 çíà÷åíèå ïîäïèñè â âèäå Base64-ñòðîêè.}
try
Pair:=TStringStream.Create('');
obj:=CreateOleObject('SirCrypt.Signer');
obj.Content:=Content;
obj.ContainerName:=Container ;
// obj.CertificateAsPEM:=CertPem;
obj.Sign;
CertPem:=Base64EnCodeStr(obj.CertificateAsPEM) ;
//ShowMessage(By);
v:={Base64EnCodeStr}(obj.BESignatureValueAsBase64);
c:= obj.CertificateAsPEM ;
s:=@c ;
p:=@v;
Pair.WriteBuffer(p,(Length(v)+SizeOf(v))*16);
if enc then
Result:=Base64EncodeStr(Pair.DataString)//WideString((obj.BESignatureValueAsBase64)) ;
else
Result:=Trim(WideString(Pair.DataString));
//Pair.WriteBuffer(p,(Length(v)+SizeOf(v))*16);
Pair.WriteBuffer(s,(Length(v)+SizeOf(c))*16);
CertPem:=Base64EncodeStr(Pair.DataString);
// ShowMessage(Base64DecodeStr(String(v)) ) ;
//Èñòî÷íèê: http://ezp20.ru/ecp-xml
// obj.Free;
Pair.Free;
except
Result:='';
ShowMessage('Class Signer не зарегистрирован!');
end;
end;
Хорошая библиотека, пока не пришел ГОСТ 2012. Жаль, что она не переделана под сегодняшние нужды
переделай ..)) Родина тебя не забудет
Авторизуйтесь, чтобы написать комментарий