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