Get xml-crypto на github
Node.js не всегда имеет подходящие библиотеки для операций Xml. Когда такие библиотеки существуют, они не всегда кроссплатформенные (читай: работа на windows). Я только что опубликовал xml-crypto , первую библиотеку цифровых подписей xml для узла. В качестве бонуса эта библиотека написана на чистом javascript, поэтому она кроссплатформенная.
Что такое цифровая подпись Xml?
Там в ТЛ, др версия здесь . Суть в том, что dig-sig позволяет защитить контент от несанкционированного изменения, сообщая нам, кто создал этот контент и кто-либо изменил его с тех пор. Xml dig-sig — это особый вариант, в котором есть несколько интересных аспектов реализации.
Типичная подпись XML выглядит так:
<Signature xmlns="http://www.w3.org/2000/09/xmldsig#"> <SignedInfo> <CanonicalizationMethod Algorithm="http://www.w3.org/2001/10/xml-exc-c14n#" /> <SignatureMethod Algorithm="http://www.w3.org/2000/09/xmldsig#rsa-sha1" /> <Reference URI="#_0"> <Transforms> <Transform Algorithm="http://www.w3.org/2001/10/xml-exc-c14n#" /> </Transforms> <DigestMethod Algorithm="http://www.w3.org/2000/09/xmldsig#sha1" /> <DigestValue>b5GCZ2xpP5T7tbLWBTkOl4CYupQ=</DigestValue> </Reference> </SignedInfo> <SignatureValue>PI2xGt3XrVcxYZ3...</SignatureValue> <KeyInfo> </KeyInfo> </Signature>
Установка Xml-Crypto
Установить с помощью npm :
npm install xml-crypto
Необходимым условием является наличие openssl и его / bin для системного пути. Я использовал версию 1.0.1c, но она должна работать и на старых версиях.
Подписание документа XML
Используйте этот код:
var SignedXml = require('xml-crypto').SignedXml , FileKeyInfo = require('xml-crypto').FileKeyInfo , fs = require('fs') var xml = "<library>" + "<book>" + "<name>Harry Potter</name>" + "</book>" "</library>" var sig = new SignedXml() sig.addReference("//*[local-name(.)='book']") sig.signingKey = fs.readFileSync("client.pem") sig.computeSignature(xml) fs.writeFileSync("signed.xml", sig.getSignedXml())
Результат будет:
<library> <book Id="_0"> <name>Harry Potter</name> </book> <Signature xmlns="http://www.w3.org/2000/09/xmldsig#"> <SignedInfo> <CanonicalizationMethod Algorithm="http://www.w3.org/2001/10/xml-exc-c14n#" /> <SignatureMethod Algorithm="http://www.w3.org/2000/09/xmldsig#rsa-sha1" /> <Reference URI="#_0"> <Transforms> <Transform Algorithm="http://www.w3.org/2001/10/xml-exc-c14n#" /> </Transforms> <DigestMethod Algorithm="http://www.w3.org/2000/09/xmldsig#sha1" /> <DigestValue>cdiS43aFDQMnb3X8yaIUej3+z9Q=</DigestValue> </Reference> </SignedInfo> <SignatureValue>vhWzpQyIYuncHUZV9W...[long base64 removed]...</SignatureValue> </Signature> </library>
Примечание:
sig.getSignedXml () возвращает исходный документ XML с подписью, выдвинутой как последний дочерний элемент корневого узла (как указано выше). Это предполагает, что вы не подписываете корневой узел, а только подузел (ы), иначе это недопустимо. Если вы подписываете корневой узел, вызовите sig.getSignatureXml (), чтобы получить только часть подписи, и sig.getOriginalXmlWithIds (), чтобы получить исходный xml с атрибутами Id, добавленными в соответствующие элементы (необходимые для проверки).
Проверка подписанного документа
Вы можете использовать любой dom-парсер в своем коде (или ни один, в зависимости от вашего использования). В этом примере используется xmldom, поэтому вы должны сначала установить его:
npm install xmldom
Затем запустите:
var select = require('xml-crypto').xpath.SelectNodes , dom = require('xmldom').DOMParser , SignedXml = require('xml-crypto').SignedXml , FileKeyInfo = require('xml-crypto').FileKeyInfo , fs = require('fs') var xml = fs.readFileSync("signed.xml").toString() var doc = new dom().parseFromString(xml) var signature = select(doc, "/*/*[local-name(.)='Signature' and namespace-uri(.)='http://www.w3.org/2000/09/xmldsig#']")[0] var sig = new SignedXml() sig.keyInfoProvider = new FileKeyInfo("client_public.pem") sig.loadSignature(signature.toString()) var res = sig.checkSignature(xml) if (!res) console.log(sig.validationErrors)
Примечание.
Для xml-crypto api требуется отдельно указать подпись xml («<Signature> … </ Signature>» в loadSignature) и подписанный xml (в checkSignature). Подписанный xml может содержать или не содержать подпись, но вы все равно должны предоставить подпись отдельно.
Поддерживаемые алгоритмы
В первом выпуске всегда используются следующие алгоритмы:
Вы можете расширить xml-crypto с помощью других алгоритмов. Я скоро напишу об этом.
Ключевые форматы
Вам необходимо использовать отформатированные сертификаты .pem как для подписи, так и для проверки. Если у вас есть сертификаты pfx x.509 , есть простой способ конвертировать их в pem. Я напишу пост об этом в ближайшее время.
Код
Get xml-crypto на github