Skip to content

Instantly share code, notes, and snippets.

@daniel-hartmann
Created September 23, 2014 14:33
Show Gist options
  • Save daniel-hartmann/be147446573878b8b4d1 to your computer and use it in GitHub Desktop.
Save daniel-hartmann/be147446573878b8b4d1 to your computer and use it in GitHub Desktop.
Code to get private key and certificate from eCNPJ - smart card, certificado A3
#!/usr/bin/env python
# Copyright (C) 2014 Daniel Hartmann (daniel@simbio.com.br)
#
# This file is free software; you can redistribute it and/or modify it
# under the terms of the GNU General Public License as published by
# the Free Software Foundation; either version 2 of the License, or
# (at your option) any later version.
#
# This program is distributed in the hope that it will be useful, but
# WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
# General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with this program; if not, write to the Free Software
# Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
import PyKCS11
import platform
import sys
import base64
import logging
from PyKCS11.LowLevel import CKA_ID, CKA_LABEL, CKA_CLASS, CKO_PRIVATE_KEY, CKO_CERTIFICATE, CKK_RSA, CKA_KEY_TYPE, CKA_VALUE
LIB = '/usr/local/lib/libaetpkss.dylib'
PIN = '999999'
all_attributes = PyKCS11.CKA.keys()
# remove the CKR_ATTRIBUTE_SENSITIVE attributes since we can't get
all_attributes.remove(PyKCS11.LowLevel.CKA_PRIVATE_EXPONENT)
all_attributes.remove(PyKCS11.LowLevel.CKA_PRIME_1)
all_attributes.remove(PyKCS11.LowLevel.CKA_PRIME_2)
all_attributes.remove(PyKCS11.LowLevel.CKA_EXPONENT_1)
all_attributes.remove(PyKCS11.LowLevel.CKA_EXPONENT_2)
all_attributes.remove(PyKCS11.LowLevel.CKA_COEFFICIENT)
all_attributes = [e for e in all_attributes if isinstance(e, int)]
class card_data(object):
def __init__(self, lib=LIB):
self.pkcs11 = PyKCS11.PyKCS11Lib()
self.pkcs11.load(lib)
self.token_slot = None
slots = self.pkcs11.getSlotList()
for slot_index in slots:
slot = self.pkcs11.getSlotInfo(slot_index)
if 'CKF_TOKEN_PRESENT' in slot.flags2text():
self.token_slot = slot_index
break
if not self.token_slot:
raise Exception('Couldn\'t find token slot. Make sure your smart card is inserted.')
def login(self, pin=PIN):
self.session = self.pkcs11.openSession(self.token_slot)
self.session.login(pin)
def logout(self):
if self.session:
self.session.logout()
def _intarray2bytes(self, x):
return ''.join(chr(i) for i in x)
def _find_object(self, session, template):
objects = session.findObjects(template)
for o in objects:
logging.debug("Found pkcs11 object: %s" % o)
return o
return None
def _get_object_attributes(self, session, o):
attributes = session.getAttributeValue(o, all_attributes)
return dict(zip(all_attributes, attributes))
def get_key_and_cert(self):
if not self.session:
raise Exception('You must login to get key and certificate')
key = self._find_object(self.session, [(CKA_CLASS, CKO_PRIVATE_KEY), (CKA_KEY_TYPE, CKK_RSA)])
if key is None:
return None, None
key_a = self._get_object_attributes(self.session, key)
cert = self._find_object(self.session, [(CKA_ID, key_a[CKA_ID]), (CKA_CLASS, CKO_CERTIFICATE)])
cert_pem = None
if cert is not None:
cert_a = self._get_object_attributes(self.session, cert)
cert_pem = self._cert_der2pem(self._intarray2bytes(cert_a[CKA_VALUE]))
logging.debug(cert)
return key, cert_pem
def _cert_der2pem(self, der):
x = base64.standard_b64encode(der)
r = "-----BEGIN CERTIFICATE-----\n"
while len(x) > 64:
r += x[0:64]
r += "\n"
x = x[64:]
r += x
r += "\n"
r += "-----END CERTIFICATE-----"
return r
if __name__ == '__main__':
ecnpj = card_data()
ecnpj.login(PIN)
key, cert_pem = ecnpj.get_key_and_cert()
#print key
#print cert_pem
ecnpj.logout()
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment