Skip to content

Commit

Permalink
modificato il file si firma
Browse files Browse the repository at this point in the history
  • Loading branch information
Samuel Panicucci committed Jun 4, 2014
1 parent 247c1c6 commit 7cfbe30
Show file tree
Hide file tree
Showing 19 changed files with 255 additions and 93 deletions.
2 changes: 2 additions & 0 deletions .gitignore
100644 → 100755
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
*.pyc
affinity
aggiungi-repository
certificate.der
Expand Down Expand Up @@ -43,3 +44,4 @@ dumpasn1-i386
dumpasn1-x86_64
python_cert.der
firmapiu-fortunato
firmapiu.tar.gz
Empty file modified dumpit.py
100644 → 100755
Empty file.
Binary file added file.txt
Binary file not shown.
Empty file modified firmapiu.glade
100644 → 100755
Empty file.
5 changes: 5 additions & 0 deletions firmapiu/Makefile
100644 → 100755
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@ SHARE_DIR = $(DESTDIR)/usr/share/firmapiu

MODULES_DIR = $(SHARE_DIR)/modules
LIBRARY_DIR = $(SHARE_DIR)/library
ICONS_DIR = $(SHARE_DIR)/icons

EXE_CLI = firmapiu-cli
EXE_PY = firmapiu-py
Expand All @@ -31,6 +32,10 @@ install:
install bin/$(EXE_CLI) $(BIN_DIR)
install bin/$(EXE_GUI) $(BIN_DIR)
install bin/$(EXE_PY) $(BIN_DIR)
# install icons
install -d $(ICONS_DIR) $(ICONS_DIR)/tango
install -m644 usr/share/firmapiu/icons/*.png $(ICONS_DIR)
install -m644 usr/share/firmapiu/icons/tango/*.png $(ICONS_DIR)/tango
# install library and config file
install usr/share/firmapiu/modules/*.sh $(MODULES_DIR)
install usr/share/firmapiu/library/*.py $(LIBRARY_DIR)
Expand Down
9 changes: 8 additions & 1 deletion firmapiu/bin/firmapiu-gui
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
#!/usr/bin/python2
#!/usr/bin/python
import commands
import time
from threading import Thread
Expand Down Expand Up @@ -41,6 +41,13 @@ class FirmapiuWindow(Gtk.Window):
image_bottone_verifica.show()
self.bottone_verifica.add(image_bottone_verifica)
self.bottone_verifica.connect("clicked", self.verificat)

self.bottone_verifica = Gtk.Button()
image_bottone_verifica = Gtk.Image()
image_bottone_verifica.set_from_file(self.icon_dir + "verifica96x96.png")
image_bottone_verifica.show()
self.bottone_verifica.add(image_bottone_verifica)
self.bottone_verifica.connect("clicked", self.verificat)

self.bottone_timestamp = Gtk.Button()
image_bottone_timestamp = Gtk.Image()
Expand Down
Empty file modified firmapiu/etc/firmapiu/firmapiurc
100644 → 100755
Empty file.
Empty file modified firmapiu/etc/firmapiu/libraries.xml
100644 → 100755
Empty file.
Empty file modified firmapiu/usr/share/firmapiu/icons/fpiublu1.png
100644 → 100755
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Empty file modified firmapiu/usr/share/firmapiu/icons/tango/system-log-out.png
100644 → 100755
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
118 changes: 95 additions & 23 deletions firmapiu/usr/share/firmapiu/library/SignProvider.py
Original file line number Diff line number Diff line change
@@ -1,8 +1,12 @@
#!/usr/bin/python
import os
import logging
from M2Crypto import Engine, m2 # sudo apt-get install python-m2crypto
from M2Crypto.X509 import load_cert, FORMAT_DER
from M2Crypto.SMIME import SMIME
from M2Crypto import SMIME
from M2Crypto import X509
from M2Crypto.BIO import MemoryBuffer

import SmartcardFetcher
# per l'engine installare sudo apt-get install libengine-pkcs11-openssl


Expand All @@ -14,39 +18,107 @@ def __init__(self, pkcs11_engine='/usr/lib/engines/engine_pkcs11.so', pkcs11_dri
self.pkcs11_engine.ctrl_cmd_string("PIN", pin) # senza il pin l'engine chiede il pin da prompt
self.pkcs11_engine.init()

def get_private_key(self, slot_id):
def get_ds_private_key(self, ds_id):
try:
priv_key = self.pkcs11_engine.load_private_key(slot_id)
priv_key = self.pkcs11_engine.load_private_key('slot_0-id_%s' % ds_id)
return priv_key
except Engine.EngineError:
logging.error("no private key found")
return None

def get_certificate(self, slot_id):
def get_ds_certificate(self, ds_id):
try:
cert = self.pkcs11_engine.load_certificate(slot_id)
cert = self.pkcs11_engine.load_certificate('slot_0-id_%s' % ds_id)
return cert
except Engine.EngineError:
logging.error("no certificate found")
return None

def sign_file_with_certificate(self):
pass

def verify_file_with_certificate(self):
pass
def sign_file_with_ds_certificate(library, pin, filename):
if not os.access(filename, os.R_OK):
logging.error("No file to sign %s found" % filename)
return None
if not os.access(library, os.R_OK):
logging.error("No library file found")
return None

logging.debug("opening file: " + filename)
text = open(filename).read()
logging.debug("convert file in memorybuffer")
text_buffer = MemoryBuffer(text)

sign = SignProvider(pkcs11_driver=library, pin=pin)
smartcard_atr = SmartcardFetcher.get_smartcard_atr()
smartcard_library = SmartcardFetcher.get_smartcard_library(smartcard_atr)
smartcard = SmartcardFetcher.SmartcardFetcher(smartcard_library)

# ottengo l'id per estrarre il certificato dall smartcard
logging.debug("get digital signature id")
ds_id = smartcard.get_ds_id()

# ottengo la chiave privata e il ceritficato utili per firmare
logging.debug("get private key reference")
pkey = sign.get_ds_private_key(ds_id)
logging.debug("get certificate reference")
certificate = sign.get_ds_certificate(ds_id)

signer = SMIME.SMIME()
signer.pkey = pkey
signer.x509 = certificate

# firmo il buffer
pkcs7 = signer.sign(text_buffer)

# creo un buffere di uscita
out = MemoryBuffer()
pkcs7.write_der(out)
# per scriverlo in pem pkcs11.write(out)

p7m_out = open("%s.p7m" % filename, "w")
p7m_out.write(out.read())
return True

def verify_file_with_ds_certificate(library, pin, filename_p7m, is_self_signed=True):
if not os.access(filename_p7m, os.R_OK):
logging.error("No file to sign %s found" % filename_p7m)
return None
if not os.access(library, os.R_OK):
logging.error("No library file found")
return None

sign = SignProvider(pkcs11_driver=library, pin=pin)
smartcard_atr = SmartcardFetcher.get_smartcard_atr()
smartcard_library = SmartcardFetcher.get_smartcard_library(smartcard_atr)
smartcard = SmartcardFetcher.SmartcardFetcher(smartcard_library)

ds_id = smartcard.get_ds_id() # ottengo l'id per estrarre il certificato dall smartcard
certificate = sign.get_ds_certificate(ds_id) # ottengo il certificato

# creo uno store di certificati
store_stack = X509.X509_Stack()
store_stack.push(certificate)

store = X509.X509_Store()
store.add_x509(certificate)

signer = SMIME.SMIME()
signer.set_x509_stack(store_stack)
signer.set_x509_store(store)
#p7, data = SMIME.load_pkcs7(filename_p7m) # carico il file firmato in formato PEM

p7m_buffer = open(filename_p7m).read()
input_bio = MemoryBuffer(p7m_buffer)
p7 = SMIME.PKCS7(m2.pkcs7_read_bio_der(input_bio._ptr()), 1)

data_bio = None
if is_self_signed:
v = signer.verify(p7, data_bio, flags=SMIME.PKCS7_NOVERIFY)
else:
v = signer.verify(p7, data_bio)

print v

if __name__ == "__main__":
sign = SignProvider(pkcs11_driver='/usr/local/lib/libbit4ipki.so', pin='29035896')
certificate = sign.get_certificate('445330')
pkey = sign.get_private_key('445330')
# print certificate
# print priv_key
#x509_obj = load_cert("certificate.der", FORMAT_DER) # carico il certificato in formato DER
# text = open("Resoconto.ods").read()
# text_buffer = MemoryBuffer(text)
# signer = SMIME()
# signer.sign(text_buffer)
# out = MemoryBuffer()
# signature = out.getvalue()
# pkcs11_engine.finish()
# sign_file_with_ds_certificate("/usr/local/lib/libbit4ipki.so", "29035896", "prova.txt")
verify_file_with_ds_certificate("/usr/local/lib/libbit4ipki.so", "29035896", "rfc3161.pdf.p7m")
150 changes: 83 additions & 67 deletions firmapiu/usr/share/firmapiu/library/SmartcardFetcher.py
Original file line number Diff line number Diff line change
@@ -1,61 +1,79 @@
#!/usr/bin/python2
#!/usr/bin/python
import os
import sys
import logging
#import StringIO
import smartcard
import PyKCS11
import libxml2
import sys
#from M2Crypto import X509
from smartcard.util import toHexString

class NoSlotFoundException(Exception):
pass

class SmartcardFetcher(object):
def __init__(self, library_path):
self.library_path = library_path
self.pkcs11_obj = PyKCS11.PyKCS11Lib()
self.pkcs11_obj.load(self.library_path)

def get_slot_list(self):
return self.pkcs11_obj.getSlotList()

def get_slot_info(self, slot):
assert isinstance(slot, int)
return self.pkcs11_obj.getSlotInfo(slot)

def get_token_info(self, slot):
assert isinstance(slot, int)
return self.pkcs11_obj.getTokenInfo(slot)

def dump_ds_certificate(self, slot, outfile):
assert isinstance(slot, int)
assert isinstance(outfile, str)
class NoTokenFoundException(Exception):
pass

session = self.pkcs11_obj.openSession(slot)
all_attributes = PyKCS11.CKA.keys() # tutti gli attrivuti possibili per i token
all_attributes = [e for e in all_attributes if isinstance(e, int)]
objects = session.findObjects() # ottengo i token della smartcard

if not len(objects): # se non sono presenti token
logging.error("nessun token trovato")
return False
class NoDigitalSignaturaFoundException(Exception):
pass

for obj in objects:
attributes = session.getAttributeValue(obj, all_attributes)
attr_dict = dict(zip(all_attributes, attributes))

# cerco nei certificati CKO_CERTIFICATE quelli che contengono DS
if attr_dict[PyKCS11.CKA_CLASS] == PyKCS11.CKO_CERTIFICATE and \
attr_dict[PyKCS11.CKA_TRUSTED] and \
attr_dict[PyKCS11.CKA_TOKEN] and \
attr_dict[PyKCS11.CKA_CERTIFICATE_TYPE] == PyKCS11.CKC_X_509 and \
"DS" in str(attr_dict[PyKCS11.CKA_LABEL]):
# print attr_dict[PyKCS11.CKA_ID]
# faccio un dump della sessione
value = attr_dict[PyKCS11.CKA_VALUE]
cert_file = open(outfile, "wb")
for unicode_val in value:
cert_file.write(chr(unicode_val))
cert_file.close()

return True
class SmartcardFetcher(object):
def __init__(self, library_path, slot_use=-1):
self.library_path = library_path
self.pkcs11_obj = PyKCS11.PyKCS11Lib()
self.pkcs11_obj.load(self.library_path)
if slot_use == -1 :
self.slot_use = self.__get_default_slot()
else:
self.slot_use = slot_use

def __get_default_slot(self):
slots = self.pkcs11_obj.getSlotList()

if not len(slots):
raise NoSlotFoundException()

return slots[0] # di default uso la prima slot

def get_ds_id(self):
session = self.pkcs11_obj.openSession(self.slot_use)
cert_objects = session.findObjects( template=(
(PyKCS11.CKA_CLASS, PyKCS11.CKO_CERTIFICATE),
(PyKCS11.CKA_CERTIFICATE_TYPE, PyKCS11.CKC_X_509),
(PyKCS11.CKA_TOKEN, True),
(PyKCS11.CKA_TRUSTED, True)
)
) # ottengo i token di tipo certificato della smartcard

cert_objects_len = len(cert_objects)

if not cert_objects_len: # se non ho trovato certificati
logging.error("no token found into smartcard")
raise NoTokenFoundException()

ds_id = None
# cerco nei certificati CKO_CERTIFICATE quelli che contengono DS
for cert_obj in cert_objects:
attrs = session.getAttributeValue(cert_obj, (PyKCS11.CKA_LABEL,PyKCS11.CKA_ID))
if "DS" in attrs[0]:
ds_id = ''.join([hex(elem)[2:] for elem in attrs[1]])
# ds_id = ''.join([chr(elem) for elem in attr[1]])
# value = attr_dict[PyKCS11.CKA_VALUE] # ottengo una tupla contenente il DER della smartcard

if ds_id is None:
logging.error("no DS signature found")
raise NoDigitalSignaturaFoundException()

return ds_id

# buffer_der = StringIO.StringIO() # creo un buffer per contenere il certificato in formato DER
# for unicode_val in value:
# buffer_der.write(chr(unicode_val))
# return buffer_der.getvalue()


def get_smartcard_atr():
Expand Down Expand Up @@ -88,18 +106,21 @@ def get_smartcard_atr():

def get_smartcard_library(atr):
"""in base all'atr restituisco quale libreria e' utile usare"""
if not os.path.exists("libraries.xml"):
logging.error("no library xml found")
return None

doc = libxml2.parseFile("libraries.xml") # carico il file xml con le librerie e cerco la libreria relativa all'ATR
library_result = doc.xpathEval("//key[text()='%s']/../@path" % atr) # in base all'atr cerco nel file usando XPATH
if len(library_result) == 0: # se non trovo nessun risultato
logging.error("non ho trovato nessuna libreria")
logging.error("no library found")
return None

library_used = library_result[0].get_content() # ottengo il path della libreria
return library_used


def dump_certificate(filename="certificate.der"):
def dump_digital_signature_id():
atr = get_smartcard_atr() # ottengo l'atr della smartcard
if atr is None:
return 1
Expand All @@ -109,24 +130,19 @@ def dump_certificate(filename="certificate.der"):
return 1

fetcher = SmartcardFetcher(library) # creo la classe per ottenere le info sulla smartcard
slot_list = fetcher.get_slot_list() # ottengo la lista degli slot per la smartcard

logging.debug("test number of slot found")
if not len(slot_list): # se non ci sono slot inserite
logging.error("no slot found")
return 1
else: # di default uso la prima
slot_use = slot_list[0]

if fetcher.dump_ds_certificate(slot_use, filename):
logging.debug("dump del certificato riuscito")
return 0
else:
logging.error("dump del certificato non riuscito")
return 1
print fetcher.get_ds_id()

return 0
# ottengo il buffer in formato DER
# buffer_certificate_der = fetcher.dump_ds_der_certificate(slot_use)
# if buffer_certificate_der is None:
# return 1
#
# # salvo il certificato in formato PEM
# x509_obj = X509.load_cert_string(buffer_certificate_der, X509.FORMAT_DER)
# if not x509_obj.save_pem(filename):
# logging.error("unable to save PEM certificate")
# return 1

if __name__ == "__main__":
if len(sys.argv) == 2:
sys.exit(dump_certificate(sys.argv[1]))
else:
sys.exit(dump_certificate())
sys.exit(dump_digital_signature_id())
Loading

0 comments on commit 7cfbe30

Please sign in to comment.