Я пытаюсь проверить подпись XML-сообщения с заданным открытым ключом в Python, который отлично проверяется в коде PHP с помощью openssl.
Вот PHP-код, который работает нормально.
$pubKey = openssl_pkey_get_public(file_get_contents("public_key.pem"));
$xmlDoc = new DOMDocument();
$xmlDoc->load("message.xml");
$signedInfo=$xmlDoc->getElementsByTagName("SignedInfo")->item(0)->C14N(true, true);
$signature = base64_decode($xmlDoc->documentElement->getElementsByTagName("SignatureValue")->item(0)->nodeValue);
$ok = openssl_verify($signedInfo, $signature, $pubKey, OPENSSL_ALGO_SHA1);
Я нашел разные библиотеки в Python для достижения этой цели, но ни одна из них не проходит проверку. Я перечислил библиотеки и проблемы, с которыми я столкнулся. Есть ли другие предпочтительные способы достижения этого?
<сильный>1. pyOpenSSL
Выдается следующее сообщение: [('подпрограммы rsa', 'INT_RSA_VERIFY', 'неправильная длина подписи')]
import OpenSSL.crypto as c
from StringIO import StringIO
import xml.etree.ElementTree as xml_et
from myapp import settings
namespace = "{http://www.w3.org/2000/09/xmldsig#}"
xml_bytes = open(settings.STATIC_ROOT + '/file/test.xml', 'rt').read()
response_xml = xml_et.fromstring(xml_bytes.encode('utf-8'))
signature_elem = response_xml.find(namespace + 'Signature')
signature_value = signature_elem.find(namespace + 'SignatureValue').text
signed_info_output = StringIO()
signed_info_tree = xml_et.ElementTree(signature_elem.find(namespace + 'SignedInfo'))
signed_info_tree.write_c14n(signed_info_output)
signed_info = signed_info_output.getvalue()
# load certificate
cert = c.load_certificate(c.FILETYPE_PEM, open(settings.STATIC_ROOT + '/file/public.cert', 'rt').read())
# verify signature
try:
c.verify(cert, signature_value, signed_info, 'sha1')
print 'success'
except Exception, e:
print 'fail'
<сильный>2. М2Крипто
Пытался установить M2Crypto, но не удалось найти заголовочный файл openssl/err.h. Итак, я установил openssl 1.1.0e и скопировал каталоги lib и include в каталог C:/pkg, и он выдает другую ошибку, например: SWIG/_m2crypto_wrap.c(3754): ошибка C2065: «CRYPTO_NUM_LOCKS»: необъявленный идентификатор И найден предварительно скомпилированный Установщик M2Crypto msi, но во время выполнения выдает следующую ошибку: ImportError: Ошибка загрузки DLL: указанный модуль не найден.
Эта библиотека кажется устаревшей и недостаточно доступной документации.
<сильный>3. signxml
Пока это единственная библиотека, которая у меня частично работает. Проверка XML работает нормально, но выдает ошибку на знаке: ValueError: Не удалось десериализовать данные ключа.
from xml.etree import ElementTree
from signxml import XMLSigner, XMLVerifier
from myapp import settings
cert = open(settings.STATIC_ROOT + '/file/public.cert', 'rt').read()
key = open(settings.STATIC_ROOT + '/file/public.key', 'rt').read()
root = ElementTree.fromstring('<xml1>12</xml1>')
signed_root = XMLSigner().sign(root, key=key, cert=cert)
verified_data = XMLVerifier().verify(signed_root).signed_xml
print verified_data