2014-01-18 5 views
2

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

Значок SAML принимаю can be found here. Я уже извлек всю необходимую мне информацию из тега Assertion (имя пользователя SSN, IP и окно выхода токенов SAML), но я не могу получить функцию verify_signature от Ennael (и revised code от Ezra Nugroho), чтобы вернуть True. Я также попытался изменить verify_EVP.reset_context(md='sha1') на verify_EVP.reset_context(md='sha256'), но это тоже не сработало.

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

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

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) 

UPDATE: Возможно ли мне нужно больше информации от сторонний поставщик аутентификации? Мне нужен секретный ключ для любого из этого?

+0

Возможно, вы захотите показать свой код, чтобы кто-то мог вам помочь. – hughdbrown

+0

Готово - думал, ссылок будет достаточно. –

+0

вам не нужно ничего от стороннего провайдера, и вам не нужен секретный ключ для проверки подписей. –

ответ

2

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

from signxml import xmldsig 

cert = open("example.pem").read() 
key = open("example.key").read() 
root = ElementTree.fromstring(data) 
xmldsig(root).verify() 
+0

Спасибо, я посмотрю на завтра и дам вам знать, как это происходит! –

+0

Начиная с signxml v. 0.3.5 моя проверка работает! –

+0

может ли кто-нибудь помочь мне с этим lib? http://stackoverflow.com/questions/33138385/invalid-xml-singnature-using-signxml-python-lib –

1

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

+0

Я использовал [ElementC14N.py] (https://bitbucket.org/effbot/et-2009-provolone/src/tip/elementtree/elementtree/ElementC14N.py) и попытался канонизировать SignedInfo, но он не изменился вещь. Вы можете видеть, что в 'get_signed_info' он закомментирован (' return parse (StringIO (signed_info_str)) '). Это неправильно? –

+0

По вашему утверждению saml в pastebin, используемое преобразование должно быть c14n исключительным; см. тег: «" ElementC14N.py, похоже, в состоянии это сделать, но убедитесь, что вы используют правильный метод. –

Смежные вопросы