Проверка запроса Alexa в python

Я работаю над сервисом, который будет обрабатывать голосовые намерения Alexa. Мне нужно проверять подпись каждого запроса, и мне это почти удается. Единственная часть, которая не работает, — это проверка цепочки сертификатов.

Из документация Я знаю, что:

Эта цепочка сертификатов по порядку состоит из (1) сертификата подписи Amazon и (2) одного или нескольких дополнительных сертификатов, которые создают цепочку доверия к сертификату корневого центра сертификации (ЦС).

Мой код выглядит так:

certificates = pem.parse_file("chain.pem")
store = crypto.X509Store()
for cert in certificates[:-1]:
    loaded_cert = crypto.load_certificate(crypto.FILETYPE_PEM,
                                          cert.as_bytes())
    store.add_cert(loaded_cert)

intermediate_cert = crypto.load_certificate(
    crypto.FILETYPE_PEM,
    certificates[-1].as_bytes()
)
# Create a certificate context
store_ctx = crypto.X509StoreContext(store, intermediate_cert)

# Verify the certificate
store_ctx.verify_certificate()

Я получаю следующую ошибку:

OpenSSL.crypto.X509StoreContextError: [20, 0, 'unable to get local issuer certificate']

Я не знаю, что я сделал не так, может быть, есть кто-то, кто уже реализовал это и может подсказать.


person Vitalie Maldur    schedule 23.05.2017    source источник
comment
У вас есть сертификат ЦС?   -  person Mihai    schedule 24.05.2017
comment
Нет. Я не знаю, где его взять.   -  person Vitalie Maldur    schedule 24.05.2017
comment
@VitalieMaldur Вы можете попробовать letsencrypt.org для получения сертификатов.   -  person Yaman Jain    schedule 25.05.2017
comment
@stovfl Я использую команду pyopenssl==17.0.0, а openssl version возвращает OpenSSL 0.9.8zh 14 Jan 2016   -  person Vitalie Maldur    schedule 26.05.2017


Ответы (2)


Сначала и один раз получите CA Issuer for all Certificate в 'chain.pem':

for cert in pem.parse_file("chain.pem"):
    CA_cert = crypto.load_certificate(crypto.FILETYPE_PEM, cert.as_bytes())
    print('CA_cert:\nissuer :{}\nsubject:{}'.
        format(CA_cert.get_subject(), CA_cert.get_issuer()))

Вывод, например:

CA_cert:
issuer :<X509Name object '/C=US/O=thawte, Inc./OU=Certification Services Division/OU=(c) 2006 thawte, Inc. - For authorized use only/CN=thawte Primary Root CA'>
subject:<X509Name object '/C=US/O=thawte, Inc./OU=Certification Services Division/OU=(c) 2006 thawte, Inc. - For authorized use only/CN=thawte Primary Root CA'>

Показанный пример сертификата является самоподписанным сертификатом.


Добавьте всех показанных эмитентов в CA_store, затем выполните .verify_certificate для всех сертификатов в 'chain.pem'.

CA_store = crypto.X509Store()
for _pem in ['issuer_1.pem', 'issuer_2.pem']:
    for cert in pem.parse_file(_pem):
        CA_store.add_cert(
            crypto.load_certificate(crypto.FILETYPE_PEM, cert.as_bytes())
        )

for cert in pem.parse_file("chain.pem"):
    try:
        crypto.X509StoreContext(CA_store,
                                crypto.load_certificate(crypto.FILETYPE_PEM, cert.as_bytes())
                                ).verify_certificate()
    except X509StoreContextError as exp:
        cert = exp.certificate
        print('X509StoreContextError:{}\ncertificate\n\tissuer :{}\n\tsubject:{}'.
            format(exp.args, cert.get_issuer(), cert.get_subject()))

Протестировано с Python: 3.4.2 - OpenSSL: 17.0.0 - криптография: 1.8.2 - cffi: 1.10.0

person stovfl    schedule 26.05.2017

Согласно документации OpenSSL.crypto.X509Store,

Хранилище X.509, будучи только описанием, не может использоваться само по себе для проверки сертификата. Чтобы выполнить фактический процесс проверки, см. X509StoreContext.

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

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

person A STEFANI    schedule 26.05.2017