I work on a service that will handle Alexa voice intents. I need to verify the signature of each request and I almost succeed. The only part that is not working is the validation of certificates chain.
From the documentation I know that:
This certificate chain is composed of, in order, (1) the Amazon signing certificate and (2) one or more additional certificates that create a chain of trust to a root certificate authority (CA) certificate.
My code looks like this:
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()
I receive the following error:
OpenSSL.crypto.X509StoreContextError: [20, 0, 'unable to get local issuer certificate']
I don't know what I did wrong, maybe there is someone who already implemented this and can drop a hint.
The Alexa Skills Kit SDK for Python simplifies the development of the back-end cloud service for your Alexa skill. A part of the Alexa Skills Kit, the SDK reduces the amount of code you need to write to process Alexa requests and responses and to handle other common skill tasks.
The Request module is one of the most popular NPM module for making HTTP requests. It supports both HTTP and HTTPS and follows redirects by default.
One simple way to debug this issue is copying the input JSON from Alexa skill simulator and paste it in the lambda's configure test events. Now run test and it'll generate all the error logs in the lambda itself, for your easy reference.
First and once get the CA Issuer for all Certificate in '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()))
Output, for example:
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'>
This shown example Certificate is a self signed certificate.
Add all shown issuer to CA_store
, then do .verify_certificate
for all Certificate in '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()))
Tested with Python:3.4.2 - OpenSSL:17.0.0 - cryptography:1.8.2 - cffi:1.10.0
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With