Как подписать PDF-файл с помощью Yubikey 5A программноC++

Программы на C++. Форум разработчиков
Ответить
Anonymous
 Как подписать PDF-файл с помощью Yubikey 5A программно

Сообщение Anonymous »

У меня был случай, когда мне нужно было создать функцию подписи PDF-файлов с помощью ключа безопасности. Для этого я использую Yubikey 5A и его библиотеку yubico-piv-tool. Я собрал код, используя различные ресурсы, но до сих пор не могу получить конечный результат.

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

void signPDF(const char* pdfFilePath, const char* yubikeyPIN) {
// Open PDF file
HPDF_Doc pdf = HPDF_New(error_handler, NULL);
if (!pdf) {
fprintf(stderr, "Error: Cannot create PDF object\n");
return;
}

// Add a page to the document
HPDF_Page page = HPDF_AddPage(pdf);

// Set the font and size
HPDF_Font font = HPDF_GetFont(pdf, "Helvetica", NULL);
HPDF_Page_SetFontAndSize(page, font, 24);

// Write some text
HPDF_Page_BeginText(page);
HPDF_Page_TextOut(page, 50, 700, "Not so Random!");
HPDF_Page_EndText(page);

// Save PDF content to stream
if (HPDF_OK != HPDF_SaveToStream(pdf)) {
fprintf(stderr, "Error: Cannot save PDF to stream\n");
HPDF_Free(pdf);
return;
}

// Get the size of the stream
HPDF_UINT32 contentLen = HPDF_GetStreamSize(pdf);

// Allocate memory for the content
HPDF_BYTE *content = (HPDF_BYTE *)malloc(contentLen);

// Perform signing operation using YubiKey's PIV
ykpiv_state *state;
if (ykpiv_init(&state, 0) != YKPIV_OK) {
fprintf(stderr, "Error: Cannot initialize YubiKey PIV\n");
return;
}

ykpiv_rc res = ykpiv_connect(state, NULL);
if (res != YKPIV_OK) {
fprintf(stderr, "Error: ykpiv_connect failed with code %d\n", res);
return;
}

int tries;
res = ykpiv_verify(state, yubikeyPIN, &tries);
if (res != YKPIV_OK) {
fprintf(stderr, "Error: Cannot authenticate with YubiKey\n");
return;
}

size_t signatureLen = YKPIV_MAX_SIGNATURE_SIZE;
unsigned char signature[YKPIV_MAX_SIGNATURE_SIZE];
res =
ykpiv_sign_data(state, content, contentLen, signature, &signatureLen,
YKPIV_ALGO_ECCP256, YKPIV_KEY_SIGNATURE);
if (res != YKPIV_OK) {
fprintf(stderr, "Error: Cannot sign PDF content.  Error code: %d\n", res);
ykpiv_done(state);
HPDF_Free(pdf);
return;
}

// Save the signed PDF file
if (HPDF_SaveToFile(pdf, "signed_example.pdf") != HPDF_OK) {
fprintf(stderr, "Error: Cannot save signed PDF file.\n");
return;
}

printf("PDF file signed successfully.\n");
}void signPDF(const char* pdfFilePath, const char* yubikeyPIN) {
// Open PDF file
HPDF_Doc pdf = HPDF_New(error_handler, NULL);
if (!pdf) {
fprintf(stderr, "Error: Cannot create PDF object\n");
return;
}

// Add a page to the document
HPDF_Page page = HPDF_AddPage(pdf);

// Set the font and size
HPDF_Font font = HPDF_GetFont(pdf, "Helvetica", NULL);
HPDF_Page_SetFontAndSize(page, font, 24);

// Write some text
HPDF_Page_BeginText(page);
HPDF_Page_TextOut(page, 50, 700, "Not so Random!");
HPDF_Page_EndText(page);

// Save PDF content to stream
if (HPDF_OK != HPDF_SaveToStream(pdf)) {
fprintf(stderr, "Error: Cannot save PDF to stream\n");
HPDF_Free(pdf);
return;
}

// Get the size of the stream
HPDF_UINT32 contentLen = HPDF_GetStreamSize(pdf);

// Allocate memory for the content
HPDF_BYTE *content = (HPDF_BYTE *)malloc(contentLen);

// Perform signing operation using YubiKey's PIV
ykpiv_state *state;
if (ykpiv_init(&state, 0) != YKPIV_OK) {
fprintf(stderr, "Error: Cannot initialize YubiKey PIV\n");
return;
}

ykpiv_rc res = ykpiv_connect(state, NULL);
if (res != YKPIV_OK) {
fprintf(stderr, "Error: ykpiv_connect failed with code %d\n", res);
return;
}

int tries;
res = ykpiv_verify(state, yubikeyPIN, &tries);
if (res != YKPIV_OK) {
fprintf(stderr, "Error: Cannot authenticate with YubiKey\n");
return;
}

size_t signatureLen = YKPIV_MAX_SIGNATURE_SIZE;
unsigned char signature[YKPIV_MAX_SIGNATURE_SIZE];
res =
ykpiv_sign_data(state, content, contentLen, signature, &signatureLen,
YKPIV_ALGO_ECCP256, YKPIV_KEY_SIGNATURE);
if (res != YKPIV_OK) {
fprintf(stderr, "Error: Cannot sign PDF content. Error code: %d\n", res);
ykpiv_done(state);
HPDF_Free(pdf);
return;
}

// Save the signed PDF file
if (HPDF_SaveToFile(pdf, "signed_example.pdf") != HPDF_OK) {
fprintf(stderr, "Error: Cannot save signed PDF file.\n");
return;
}

printf("PDF file signed successfully.\n");
}
По сути, код создает документ с одной страницей (это не совсем важно, поскольку, когда я разберусь с подписью, я смогу загрузить PDF-документ прямо из хранилище) и подписывает его содержимое с помощью закрытого ключа в Yubikey. Но моя проблема в том, что я не могу понять, как добавить этот подписанный контент в правильные диапазоны байтов в PDF.
Я пробовал использовать библиотеку PoDoFo, но, похоже, это необходимо работайте только с заранее доступным закрытым ключом, что сводит на нет всю цель, поскольку ключ в любом случае не следует вынимать из YubiKey. Я пытался разобраться в том, как подписываются PDF-файлы, но создание функциональности с нуля для этого конкретного случая использования кажется слишком сложным.
Что мне можно попробовать дальше? Язык не является проблемой, если решение можно реализовать.

Подробнее здесь: https://stackoverflow.com/questions/783 ... mmatically
Ответить

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

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

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

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

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