Проверка подписи SAML в python

Мне нужно реализовать аутентификацию в python от третьей стороны с помощью SAML2. Я просмотрел pysaml2 и обнаружил, что это довольно запутанно, и решил дайте M2Crypto шанс после того, как я нашел этот вопрос от Ennael.

Токен SAML, который я получаю, можно найти здесь. Я уже извлек всю необходимую мне информацию из тега Assertion (SSN пользователя, IP-адрес и окно истечения срока действия токенов SAML), но я не могу получить функцию verify_signature из Ennael (и исправленный код из Эзра Нугрохо), чтобы вернуть True. Я также пытался изменить verify_EVP.reset_context(md='sha1') на verify_EVP.reset_context(md='sha256'), но это тоже не сработало.

Я думаю, что моя ошибка должна быть в части signed_info. Что мне передать verify_signature для этой части? Должен ли я предварительно обрабатывать его каким-либо образом? Я искал тег Transform, но не знаю, где искать дальше.

Любая помощь будет оценена. Если кому-то нужен XML перед запутыванием, чтобы проверить и помочь мне, просто напишите мне.

EDIT Это мой код (очень похожий на то, на что я ссылался. Основная функция находится внизу):

def verify_signature(signed_info, cert, signature):
    from M2Crypto import EVP, RSA, X509, m2
    x509 = X509.load_cert_string(base64.decodestring(cert), X509.FORMAT_DER)
    pubkey = x509.get_pubkey().get_rsa()
    verify_EVP = EVP.PKey()
    verify_EVP.assign_rsa(pubkey)
    verify_EVP.reset_context(md='sha1')
    verify_EVP.verify_init()
    verify_EVP.verify_update(signed_info)

    return verify_EVP.verify_final(signature.decode('base64'))

def decode_response(resp):
    return base64.b64decode(resp)

def get_xmldoc(xmlstring):
    return XML(xmlstring)


def get_signature(doc):
    return doc.find('{http://www.w3.org/2000/09/xmldsig#}Signature')


def get_signed_info(signature):
    signed_info = signature.find(
        '{http://www.w3.org/2000/09/xmldsig#}SignedInfo')
    signed_info_str = tostring(signed_info)
    # return parse(StringIO(signed_info_str))
    return signed_info_str


def get_cert(signature):
    ns = '{http://www.w3.org/2000/09/xmldsig#}'
    keyinfo = signature.find('{}KeyInfo'.format(ns))
    keydata = keyinfo.find('{}X509Data'.format(ns))
    certelem = keydata.find('{}X509Certificate'.format(ns))
    return certelem.text


def get_signature_value(signature):
    return signature.find(
        '{http://www.w3.org/2000/09/xmldsig#}SignatureValue').text

def parse_saml(saml):
    dec_resp = decode_response(saml)
    xml = get_xmldoc(dec_resp)

    signature = get_signature(xml)
    signed_info = get_signed_info(signature)
    cert = get_cert(signature)
    signature_value = get_signature_value(signature)

    is_valid = verify_signature(signed_info, cert, signature_value)

ОБНОВЛЕНИЕ. Возможно, мне нужна дополнительная информация от стороннего поставщика услуг аутентификации? Нужен ли мне закрытый ключ для всего этого?


person Sindri Guðmundsson    schedule 18.01.2014    source источник
comment
Вы, вероятно, хотите показать свой код, чтобы кто-то мог вам помочь.   -  person hughdbrown    schedule 19.01.2014
comment
Готово - думал ссылок будет достаточно.   -  person Sindri Guðmundsson    schedule 19.01.2014
comment
вам не нужно ничего от стороннего поставщика, и вам не нужен закрытый ключ для проверки подписи   -  person Oleg Mikheev    schedule 19.01.2014
comment
Ладно, так и думал, но хотел убедиться. Вы хоть понимаете, что я делаю неправильно?   -  person Sindri Guðmundsson    schedule 19.01.2014


Ответы (2)


Я столкнулся с той же проблемой, и мне пришлось разработать для нее модуль: https://github.com/kislyuk/signxml< /а>. Я решил полагаться только на PyCrypto и pyOpenSSL, поскольку M2Crypto менее популярен и плохо поддерживается, что представляет опасность как с точки зрения совместимости (например, PyPy), так и с точки зрения безопасности. Я также использую lxml для канонизации (c14n). Из документов signxml:

from signxml import xmldsig

cert = open("example.pem").read()
key = open("example.key").read()
root = ElementTree.fromstring(data)
xmldsig(root).verify()
person weaver    schedule 22.09.2014
comment
Спасибо, завтра посмотрю и отпишусь как дела! - person Sindri Guðmundsson; 24.09.2014
comment
Спасибо за эту библиотеку/модуль. Я смог использовать его для проверки и подписи xmls. У меня есть еще 2 вопроса - 1) Здесь вроде предполагается, что привязка будет http-post. Есть ли в этой библиотеке какие-либо API для проверки подписи для http-перенаправления? В случае перенаправления SigAlg и Signature не входят в XML-файл ответа SAML, а представляют собой отдельные параметры в перенаправлении. 2) Эта библиотека не позволяет мне проверить самоподписанный сертификат. Могу ли я обойти это? - person ksrini; 24.06.2016

Вам необходимо канонизировать подписанную информацию перед проверкой подписи. Это то, что подразумевает тег преобразования. По сути, поскольку один и тот же XML может быть отформатирован по-разному, необходимо проверить подпись XML в каноническом формате.

person Ezra Nugroho    schedule 21.01.2014
comment
Я использовал ElementC14N.py и попытался канонизировать SignedInfo, но это ничего не изменило. Как видите, в get_signed_info он закомментирован (return parse(StringIO(signed_info_str))). Разве это не правильно? - person Sindri Guðmundsson; 22.01.2014
comment
Согласно вашему утверждению saml в pastebin, используемое преобразование должно быть эксклюзивным для c14n; см. тег: ‹Алгоритм преобразования=w3.org/2001/10/xml -exc-c14n#› ElementC14N.py может это сделать, но убедитесь, что вы используете правильный метод. - person Ezra Nugroho; 22.01.2014