Search code examples
pythonsmartcardwincryptpyscard

How to read certificate from smart card via python?


I have a Smart Card (actually USB Token) with some certificate and keys written on it. Now I need to retrieve this certificate using python on Windows. How can it be achieved?

I had a look on pyscard package but it seems too low-level and probably not a most simple way of doing this. But if you know that low-level answer then your help will be appreciated.
Seems like CryptAcquireContext function from pywin32 (win32crypt) allow me to use private key from smart card for encryption purposes but I cannot get the certificate itself.

Do you have any suggestions?


Solution

  • Found an answer myself though. Hope it will help someone:
    Usually smart card manufacturers provide a library (.so or .dll) implementing PKCS#11 standard.
    There are several solutions which you can use to communicate with your smart card via this library. Such as: pkcs11-tool (CLI interface), PyKCS11 (python wrapper).

    Here is an example how it could be achieved with PyKCS11:

    from asn1crypto import x509
    from PyKCS11 import *
    
    pkcs11 = PyKCS11Lib()
    pkcs11.load('<MANUFACTURER_LIBRARY_PATH>')
    # get slot value via pkcs11.getSlotList(tokenPresent=False). Usually it's 0
    session = pkcs11.openSession(slot, CKF_SERIAL_SESSION | CKF_RW_SESSION)
    session.login('<SMART_CARD_PIN_CODE>')
    result = []
    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)
        result.append(cert)
    print(result)
    

    This way I was able to list certificates on smart card both on Linux and Windows