Как подписать PDF-файл с помощью Hypersecure USB с помощью eMudhra DSC в Python?Python

Программы на Python
Ответить
Anonymous
 Как подписать PDF-файл с помощью Hypersecure USB с помощью eMudhra DSC в Python?

Сообщение Anonymous »

Я пытаюсь подписать PDF-файл цифровой подписью с помощью аппаратного USB-токена (Hypersecure USB с eMudhra DSC) в Python. Цель состоит в том, чтобы создать видимую цифровую подпись в PDF-файле, которую можно будет проверить с помощью стандартных программ просмотра PDF-файлов, таких как Adobe Acrobat. Я использую следующие библиотеки:
PyKCS11 для взаимодействия с аппаратным токеном.
pikepdf для управления PDF-файлом и добавления данных подписи.

Код: Выделить всё

from csv import reader, writer
from pdfrw import PdfReader, PdfWriter
from pdfrw.objects import PdfDict, PdfName, PdfString, PdfArray
import hashlib
import PyKCS11

class TokenSigner:
def __init__(self, token_library_path, pin):
self.pkcs11 = PyKCS11.PyKCS11Lib()
try:
self.pkcs11.load(token_library_path)
print("PKCS11 library loaded successfully.")
except Exception as e:
print(f"Error loading PKCS11 library: {e}")
self.pkcs11 = None

self.session = None
self.token_slot = None
if self.pkcs11:
self.login(pin)

def login(self, pin):
try:
slots = self.pkcs11.getSlotList(tokenPresent=True)
if not slots:
print("No tokens found.")
return
self.token_slot = slots[0]
self.session = self.pkcs11.openSession(self.token_slot,  PyKCS11.CKF_SERIAL_SESSION)
self.session.login(pin)
print("Logged in to token.")
except Exception as e:
print(f"Error during login: {e}")

def get_private_key(self):
try:
private_keys = self.session.findObjects([(PyKCS11.CKA_CLASS, PyKCS11.CKO_PRIVATE_KEY)])
if not private_keys:
print("No private keys found.")
return None
for private_key in private_keys:
key_type = self.session.getAttributeValue(private_key, [PyKCS11.CKA_KEY_TYPE])[0]
if key_type == PyKCS11.CKK_RSA:
print("Found valid RSA private key.")
return private_key
print("No valid RSA private key found.")
except Exception as e:
print(f"Error retrieving private key: {e}")
return None

def sign(self, private_key, data):
try:
print(f"Signing data with private key: {private_key}")
if private_key is None:
print("Private key is None!")
return None

hash_data = hashlib.sha256(data).digest()
print(f"Hash data: {hash_data.hex()}")

mechanism = PyKCS11.Mechanism(PyKCS11.CKM_SHA256_RSA_PKCS, None)
signed_data = self.session.sign(private_key, hash_data, mechanism)
print("Data signed successfully.")
return bytes(signed_data)
except PyKCS11.PyKCS11Error as e:
print(f"Signing error: {e}")
return None

def logout(self):
try:
if self.session:
self.session.logout()
self.session.closeSession()
print("Logged out from token.")
except Exception as e:
print(f"Error logging out: {e}")

from pikepdf import Pdf, Name, Array, String, Dictionary

def sign_pdf(input_pdf_path, output_pdf_path, signature_text, signature_position, token_library_path, pin):
try:
# Initialize the signer
signer = TokenSigner(token_library_path, pin)
if signer is None:
print("Signer initialization failed.")
return

private_key = signer.get_private_key()
if private_key is None:
print("Private key not found.  Exiting.")
return

# Read the PDF and data for signing
with open(input_pdf_path, "rb") as f:
data_to_sign = f.read()

# Sign the data
signed_data = signer.sign(private_key, data_to_sign)
if signed_data is None:
print("Error signing data.")
return

# Open the input PDF
with Pdf.open(input_pdf_path) as pdf:
first_page = pdf.pages[0]

# Define the signature field dictionary
signature_dict = Dictionary(
Type=Name("/Annot"),
Subtype=Name("/Widget"),
FT=Name("/Sig"),
Rect=Array([
signature_position[0], signature_position[1],
signature_position[0] + signature_position[2], signature_position[1] + signature_position[3]
]),
T=String(signature_text),
DA=String("/Helv 0 Tf 0 g"),
V=Dictionary(
Contents=String(signed_data.hex())
)
)

print("\n signature data = ", signature_dict)

# Add the signature field to the annotations
if "/Annots" not in first_page:
first_page.Annots = Array()

first_page.Annots.append(signature_dict)

# Save the updated PDF
pdf.save(output_pdf_path)

print(f"PDF signed successfully and saved to: {output_pdf_path}")

except Exception as e:
print(f"An unexpected error occurred: {e}")

finally:
if signer:
signer.logout()

token_library_path = "HYP2003-Linux-x86_64/redist/libcastle_v2.so.1.0.0"
pin = "12345678"
pdf_path = "sample.pdf"
output_path = "signed_sample_visible.pdf"
signature_text = "JAYESH MAHATO"
signature_position = (100, 50, 200, 50)

sign_pdf(pdf_path, output_path, signature_text, signature_position, token_library_path, pin)
ПОЛУЧЕНИЕ ВЫВОДА КАК:

Код: Выделить всё

PKCS11 library loaded successfully. Logged in to token. Found valid
RSA private key.  Signing data with private key:
CKA_ALWAYS_AUTHENTICATE: False CKA_ALWAYS_SENSITIVE: True CKA_CLASS:
CKO_PRIVATE_KEY CKA_DECRYPT: True CKA_DERIVE: False CKA_END_DATE: ()
CKA_EXTRACTABLE: False CKA_ID: (122, 171, 175, 175, 25, 237, 96, 58,
207, 130, 173, 148, 193, 195, 74, 94, 121, 110, 10, 31)
CKA_KEY_TYPE:    CKK_RSA CKA_LABEL:
48055270-5655-4074-92f5-5f043e5b7908 CKA_LOCAL:    True
CKA_MODIFIABLE: True CKA_MODULUS: (157, 159, 241, 25, 154, 190,
52, 253, 254, 145, 218, 252, 211, 2, 17, 85, 223, 229, 71, 192, 8,
62, 249, 36, 2, 41, 176, 194, 172, 106, 202, 61, 94, 96, 77, 48, 72,
93, 167, 128, 128, 175, 108, 104, 225, 68, 26, 216, 171, 110, 230,
91, 243, 102, 158, 92, 93, 20, 42, 182, 199, 212, 53, 3, 248, 60,
42,    242, 185, 150, 13, 97, 238, 226, 93, 109, 215, 61, 228, 56,
16, 204,    101, 9, 126, 237, 88, 12, 158, 154, 234, 250, 23, 201,
148, 183, 167,    93, 222, 247, 219, 232, 247, 196, 175, 34, 197,
136, 181, 50, 235,    106, 139, 92, 88, 0, 176, 30, 137, 113, 174,
66, 124, 15, 120, 21,    77, 248, 194, 49, 47, 76, 76, 174, 204,
141, 94, 213, 161, 96, 240,    123, 70, 86, 109, 231, 242, 183, 10,
108, 10, 148, 40, 125, 197, 187,    130, 57, 82, 65, 16, 100, 158,
114, 102, 0, 232, 247, 8, 47, 58, 175,    155, 86, 255, 35, 96, 213,
34, 37, 255, 189, 162, 143, 54, 92, 147,    57, 43, 167, 44, 157,
128, 231, 196, 72, 13, 218, 71, 18, 153, 122,    39, 226, 86, 173,
201, 142, 102, 63, 142, 238, 234, 27, 77, 186, 98,    143, 105, 218,
57, 118, 37, 227, 72, 150, 192, 134, 139, 91, 72, 37,    26, 164,
205, 78, 182, 130, 142, 177, 49, 189, 213, 130, 9, 219, 0,    87,
23, 223, 80, 100, 233, 176, 69, 155) CKA_NEVER_EXTRACTABLE: True
CKA_PRIVATE: True CKA_PUBLIC_EXPONENT: (1, 0, 1) CKA_SENSITIVE: True
CKA_SIGN: True CKA_SIGN_RECOVER: True CKA_START_DATE: ()
CKA_SUBJECT:    () CKA_TOKEN: True CKA_UNWRAP: True
CKA_WRAP_WITH_TRUSTED: False Hash    data:
d5ddf867002b9541fcc6ea8169a85ca2a741b6afa36448d2b389cdfc0e80bd5b
Data    signed successfully.

signature data =  pikepdf.Dictionary(Type="/Annot")({   "/DA":    "/Helv 0 Tf 0 g",   "/FT": "/Sig",   "/Rect": [ 100, 50, 300, 100 ],
"/Subtype": "/Widget",   "/T": "JAYESH MAHATO",   "/Type": "/Annot",
"/V": {
"/Contents": "7d5653390f44bf06377b2ae5264538a3d0d4e9c524d33374ce8b6ad03033ea0354de6fde1d07fbded86679b4f2ebe29a0ffb139eb47ad5c7cd04b7486a671a783936c77fde54a871a00afb818e7acf7140c1570be07597c906d7d138645d3e011fcb9da1c788ba3cc79b31029fc7de1a53cadd50983ddcbb160c7fd78f5e968a53074217f56b85f2f23292f133a9086346c33fe68f13c8c41ab8c2fbbc45bb51648553ba68e9c76bd11e3e7616a67c5bde5f09f55639c8a5f38dcf3b96e5b02eb53c1af4bd3e4ff88db36d204e00cf78867967a7c577a910576e5bf68aec8966a1f18546016fc09c56c388a50ed9ad954608bf07c0c23ff549e10477138e413e"
} }) PDF signed successfully and saved to: signed_sample_visible.pdf
Logged out from token.
Результаты моего сценария показывают, что процесс подписания завершается успешно, и подписанный PDF-файл сохраняется. Однако:
Полученный PDF-файл не содержит видимой подписи.
Средства просмотра PDF-файлов не могут проверить цифровую подпись.
Словарные данные для подписи добавляются в аннотации PDF, но подпись не работает должным образом. Похоже, что данные цифровой подписи либо неполны, либо внедрены неправильно.
Ключевые моменты:
USB-токен успешно распознан, и я может получить закрытый ключ с помощью PyKCS11.
Данные хешируются и подписываются с помощью CKM_SHA256_RSA_PKCS.
Видимая аннотация добавляется в PDF-файл, но цифровая подпись не работает.
Среда:
Версия Python: (укажите версию, например, Python 3.8)
Библиотеки: PyKCS11, pikepdf, hashlib
Аппаратное обеспечение: Hypersecure USB-токен с eMudhra DSC.
Любая помощь, рекомендации или рабочие примеры будем очень признательны.

Подробнее здесь: https://stackoverflow.com/questions/793 ... -in-python
Ответить

Быстрый ответ

Изменение регистра текста: 
Смайлики
:) :( :oops: :roll: :wink: :muza: :clever: :sorry: :angel: :read: *x)
Ещё смайлики…
   
К этому ответу прикреплено по крайней мере одно вложение.

Если вы не хотите добавлять вложения, оставьте поля пустыми.

Максимально разрешённый размер вложения: 15 МБ.

Вернуться в «Python»