0

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 :

  1. Certificate and
  2. Public key (since private key cannot be extracted)

from the card and then use these 2 things to create a HTTPs connection (example here) . So far I am able to extract certificate in pem format. But i cant find a way to extract key in pem format till now. I used PyKCS11 to read the card. 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))

session = pkcs11.openSession(0, CKF_SERIAL_SESSION | CKF_RW_SESSION)
session.login('123456')
result = []
result_pem = []



# find public key and print modulus
pubKey = session.findObjects([(CKA_CLASS, CKO_PUBLIC_KEY)])[0]
modulus = session.getAttributeValue(pubKey, [CKA_MODULUS])[0]
print("\nmodulus: {}".format(binascii.hexlify(bytearray(modulus))))

#find certificates
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)
print(result)

So here are my questions: 1. Is my approach right?

  1. If yes, then how to extract public key in pem format?

  2. How this smart card authentication actually works on client side and server side?

Anudocs
  • 686
  • 1
  • 13
  • 54
  • Please check if this answer https://stackoverflow.com/a/55757349/9659885 is of any help... your host (server) may use python to verify signed token received from browser extension discussed in this answer. – Bharat Vasant Mar 07 '20 at 15:25

1 Answers1

1

Public key extraxction

If you already have exported the certificate, it is probably easier to extract the public key from there, instead of from the smartcard. You can use openssl for that:

openssl x509 -in cert.pem -pubkey -out pubkey.pem -noout

Authentication

What you are trying to achieve is to open a TLS connection with mutual authentication using a client certificate. If you do this, the private key of your client certificate signs parts of the handshake to authenticate itself towards the server.

Extracting the certificate and the public key from the smartcard won't help you here. You need to find a library, which allows you to use your private key straight from your PKCS#11 token.

mat
  • 1,645
  • 15
  • 36
  • Thanks for confirmation. Unfortunately I couldnt find a python3.x library which allows you to use your private key straight from your PKCS#11 token. There is ´M2crypto´ but it supports only Python2.x . Seems like it is impossible to do in python. Can you suggest any other programming language where it is easy to implement ? – Anudocs Feb 19 '20 at 08:45
  • I'm not aware of any current off-the-shelf solutions either. I have done it using C# in the past, but that required some custom extensions. Openssl ist definitely able to do it, but that can't be called "easy". – mat Feb 19 '20 at 09:31
  • Ok. I will go after openssl. If, in any case, you know any good article about how to implement this in openssl then please let me know. – Anudocs Feb 19 '20 at 09:36