Reputation: 686
So I have a credit card looking like smart card with a chip. This card logins on a website after the card is inserted into the card reader.
Now I have to write a program in python which can read the card and login on that website. After research on internet I found out that I need to extract certificate from the card and then use it to create a HTTPS connection . So far I am able to extract certificate in pem format. I used PyKCS11
to extract the certificate. Below is my code:
from asn1crypto import pem, x509
from PyKCS11 import *
import binascii
pkcs11 = PyKCS11Lib()
pkcs11.load(r'C:\Windows\System32\XXXX.dll')
print(pkcs11.getSlotList(tokenPresent=False))
slot = pkcs11.getSlotList(tokenPresent=False)[0]
print(pkcs11.getTokenInfo(slot))
# get slot value via pkcs11.getSlotList(tokenPresent=False). Usually it's 0
session = pkcs11.openSession(0, CKF_SERIAL_SESSION | CKF_RW_SESSION)
session.login('123456')
result = []
result_pem = []
certs = session.findObjects([(CKA_CLASS, CKO_CERTIFICATE)])
for cert in certs:
cka_value, cka_id = session.getAttributeValue(cert, [CKA_VALUE, CKA_ID])
cert_der = bytes(cka_value)
cert = x509.Certificate.load(cert_der)
# Write out a PEM encoded value
cert_pem = pem.armor('CERTIFICATE', cert_der)
result.append(cert)
result_pem.append(cert_pem)
with open('cert.pem','wb') as f:
f.write(cert_pem)
Now i am sending a HTTPS request with extracted card's certificate and card's PIN. Below is my code:
import http.client
import json
import ssl
# Defining certificate related stuff and host of endpoint
certificate_file = r'C:\Users\XXXXX\Documents\Reporting Tool\cert.pem'
certificate_secret= '123456'
host = "example.com"
# Defining parts of the HTTP request
request_url='/login.form'
request_headers = {
'user-Agent' : 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/79.0.3945.79 Safari/537.36'
}
request_body_dict={
'login-form-type': 'cert'
}
# Define the client certificate settings for https connection
context = ssl.SSLContext(ssl.PROTOCOL_SSLv23)
context.load_cert_chain(certfile=certificate_file, password=certificate_secret) ##gives error
The last line of this code throws error:
Exception has occurred: SSLError
[SSL] PEM lib (_ssl.c:3845)
So here are my questions:
Upvotes: 1
Views: 2486
Reputation: 139
I'm also looking into client authentication through a certificate stored on a card. Initially I also found PyKCS11 for accessing certificates on the card, but also failed to authenticate with the server after adding the certificate to a Python ssl.SSLContext
.
The reason for this is that the the certificate from the card can't be used for SSL/TLS authentication without the private key. The private key is also stored on the card, but can't be extracted from it. Rather one uses a library provided by the hardware provider of the card to encrypt messages using the private key directly on the card. This way the private key never leaves the card and can't be compromised. See Authenticate SSL Web Request Using PKCS#11 HSM and PKCS#11 TLS Authentication on stackoverflow.
M2Crypto
seems to be able load an pkcs11 engine (provided by your card provider or an open-source alternative like OpenSC) and "load" the private key which can be passed to a M2Crypto.SSL.Context
. I believe this uses the hardware cryptography module when it needs to encrypt some message with the private key. Have a look at this answer for a rough idea of how to set this up in code.
I hope this helps at least a little bit, and I'll come back and update this answer if I find out more.
Upvotes: 1