pykcs_pdf_sign.py 3.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103
  1. '''Created Oct 12, 2021 Levi'''
  2. #!/home/deeejas/.virtualenvs/python3.12/bin/python3
  3. # *-* coding: utf-8 *-*
  4. import datetime
  5. import os
  6. import platform
  7. import keyring
  8. from keyring import backends
  9. import PyKCS11 as PK11
  10. from PyKCS11.LowLevel import (CKA_CLASS, CKO_CERTIFICATE,
  11. CKA_VALUE, CKA_ID, CKO_PRIVATE_KEY,
  12. CKM_SHA256_RSA_PKCS)
  13. from endesive import pdf, hsm
  14. if platform.system() == 'Linux':
  15. keyring.backend._load_plugins()
  16. keyring.set_keyring(backends.SecretService.Keyring())
  17. dllpath = os.getenv('PKCS11_MODULE')
  18. class Signer(hsm.HSM):
  19. def certificate(self):
  20. slot = self.pkcs11.getSlotList(tokenPresent=True)[0]
  21. inf = self.pkcs11.getTokenInfo(slot)
  22. self.LABEL = inf.label.strip()
  23. # print(self.pkcs11.getTokenInfo(2))
  24. # print(self.pkcs11.getSlotInfo(1))
  25. self.login(self.LABEL, keyring.get_password('sig', 'token')) # WF PROXKey is token name.
  26. keyid = [0x38, 0x7b, 0x4b, 0x49, 0xe2, 0xe7, 0x10, 0x4f, 0x60, 0x15, 0xc1, 0x42, 0x38, 0x6c, 0x3d, 0x41, 0x43, 0x5e, 0x91, 0x9b]
  27. keyid = bytes(keyid)
  28. try:
  29. pk11objects = self.session.findObjects([(CKA_CLASS, CKO_CERTIFICATE)])
  30. all_attributes = [
  31. # PK11.CKA_SUBJECT,
  32. CKA_VALUE,
  33. # PK11.CKA_ISSUER,
  34. # PK11.CKA_CERTIFICATE_CATEGORY,
  35. # PK11.CKA_END_DATE,
  36. CKA_ID,
  37. ]
  38. for pk11object in pk11objects:
  39. try:
  40. attributes = self.session.getAttributeValue(pk11object, all_attributes)
  41. except PK11.PyKCS11Error as _:
  42. continue
  43. attrDict = dict(list(zip(all_attributes, attributes)))
  44. cert = bytes(attrDict[CKA_VALUE])
  45. # if keyid == bytes(attrDict[PK11.CKA_ID]):
  46. return bytes(attrDict[CKA_ID]), cert
  47. finally:
  48. self.logout()
  49. # self.closeSession()
  50. return None, None
  51. def sign(self, keyid, data, mech):
  52. self.login(self.LABEL, keyring.get_password('sig', 'token'))
  53. try:
  54. privKey = self.session.findObjects([(CKA_CLASS, CKO_PRIVATE_KEY), (CKA_ID, keyid)])[0]
  55. mech = getattr(PK11, 'CKM_%s_RSA_PKCS' % mech.upper())
  56. sig = self.session.sign(privKey, data, PK11.Mechanism(CKM_SHA256_RSA_PKCS, None))
  57. return bytes(sig)
  58. finally:
  59. self.logout()
  60. def signer(fname, reasen, folder='pdf/'):
  61. date = datetime.datetime.utcnow() # - datetime.timedelta(hours=12)
  62. date = date.strftime('%Y%m%d%H%M%S+00\'00\'')
  63. dct = {
  64. 'sigflags': 3,
  65. 'sigpage': 0,
  66. 'sigbutton': True,
  67. 'contact': 'Levente Marton <levente.marton@mzk.ro>',
  68. 'location': 'Romania Cluj Napoca',
  69. 'signingdate': date.encode(),
  70. 'reason': f'{reasen}',
  71. 'signature': f'Digitally signed by\n\
  72. Levente Marton\n\
  73. Date: {datetime.datetime.now()}',
  74. 'signaturebox': (5, 5, 150, 100),
  75. }
  76. clshsm = Signer(dllpath)
  77. # fname = fname
  78. with open(folder + fname, 'rb') as datau:
  79. datau = datau.read()
  80. datas = pdf.cms.sign(datau, dct,
  81. None, None,
  82. [],
  83. 'sha256',
  84. clshsm,
  85. )
  86. fname = fname.replace('.pdf', '_signed.pdf')
  87. with open(folder + fname, 'wb') as fp:
  88. fp.write(datau)
  89. fp.write(datas)
  90. if __name__ == '__main__':
  91. for file in filter(lambda f: f.endswith('.pdf'), os.listdir('pdf')):
  92. signer(file, reasen='signature')