From 91d21a80ac10336c5692d2f222dec93ec8c48f3e Mon Sep 17 00:00:00 2001 From: Oleg Korshul Date: Wed, 21 Jan 2026 18:11:03 +0300 Subject: [PATCH] Add support sign params --- .../xmlsec/src/src/Certificate_openssl.h | 6 +++ X2tConverter/src/lib/common.h | 43 ++++++++++++++++ X2tConverter/src/lib/pdf_image.h | 51 +++++++++++++++++++ X2tConverter/test/qmake/main.cpp | 36 +++++++++++++ 4 files changed, 136 insertions(+) diff --git a/DesktopEditor/xmlsec/src/src/Certificate_openssl.h b/DesktopEditor/xmlsec/src/src/Certificate_openssl.h index 9d8ee137ad..11c09e5bf5 100644 --- a/DesktopEditor/xmlsec/src/src/Certificate_openssl.h +++ b/DesktopEditor/xmlsec/src/src/Certificate_openssl.h @@ -605,6 +605,12 @@ public: evp = EVP_sha512(); else if (m_alg == OOXML_HASH_ALG_ECDSA_384) evp = EVP_sha384(); + else if (m_alg == OOXML_HASH_ALG_SHA256) + evp = EVP_sha256(); + else if (m_alg == OOXML_HASH_ALG_SHA384) + evp = EVP_sha384(); + else if (m_alg == OOXML_HASH_ALG_SHA512) + evp = EVP_sha512(); if (!PKCS7_sign_add_signer(pkcs7, m_cert, m_key, evp, 0)) { diff --git a/X2tConverter/src/lib/common.h b/X2tConverter/src/lib/common.h index 47a901dbbf..785e694bc8 100644 --- a/X2tConverter/src/lib/common.h +++ b/X2tConverter/src/lib/common.h @@ -39,8 +39,44 @@ #include "../../../DesktopEditor/graphics/pro/Fonts.h" +#include "../../../DesktopEditor/common/SystemUtils.h" + +#include "../../../DesktopEditor/xmlsec/src/include/CertificateCommon.h" +#include "../../../DesktopEditor/xmlsec/src/include/OOXMLSigner.h" + namespace NExtractTools { + namespace NSSign + { + ICertificate* loadCertificate(InputParams& params) + { + std::wstring keyPath = params.getSigningKeyStorePath(); + if (keyPath.empty()) + return NULL; + + ICertificate* certificate = NSCertificate::FromFiles(keyPath, "", L"", ""); + if (!certificate) + { + std::string keyPass = NSSystemUtils::GetEnvVariableA(L"SIGNING_KEYSTORE_PASSPHRASE"); + if (!keyPass.empty()) + certificate = NSCertificate::FromFiles(keyPath, keyPass, L"", ""); + } + return certificate; + } + + int ooxmlSign(const std::wstring& folder, InputParams& params) + { + ICertificate* certificate = loadCertificate(params); + if (!certificate) + return 1; + + COOXMLSigner oOOXMLSigner(folder, certificate); + int error = oOOXMLSigner.Sign(); + RELEASEOBJECT(certificate); + return error; + } + } + // COMMON FUNCTIONS NSFonts::IApplicationFonts* createApplicationFonts(InputParams& params) { @@ -169,6 +205,8 @@ namespace NExtractTools // compress ooxml directory to archive and encrypt if needed. _UINT32 dir2zipMscrypt(const std::wstring& sFrom, const std::wstring& sTo, InputParams& params, ConvertParams& convertParams) { + NSSign::ooxmlSign(sFrom, params); + _UINT32 nRes = S_OK; if (params.hasSavePassword()) { @@ -189,6 +227,7 @@ namespace NExtractTools // Copy file sFromDir or sFromFile => sToDir/sToFile (compress directory, if sFromFile is empty) _UINT32 CopyOOXOrigin(const std::wstring& sToDir, const std::wstring& sFromDir, const std::wstring& sToFile, const std::wstring& sFromFile) { + // TODO: SIGN? std::wstring sDstFile = combinePath(sToDir, sToFile); if (sFromFile.empty()) return dir2zip(sFromDir, sDstFile); @@ -267,6 +306,8 @@ namespace NExtractTools _UINT32 nRes = func(sFrom, sUnpackedResult, params, convertParams); if (SUCCEEDED_X2T(nRes)) { + NSSign::ooxmlSign(sUnpackedResult, params); + COfficeUtils oCOfficeUtils(NULL); nRes = (S_OK == oCOfficeUtils.CompressFileOrDirectory(sUnpackedResult, sTo, true)) ? 0 : AVS_FILEUTILS_ERROR_CONVERT; } @@ -455,6 +496,7 @@ namespace NExtractTools } else { + NSSign::ooxmlSign(sOOXMLDir, params); COfficeUtils oCOfficeUtils(NULL); hRes = (S_OK == oCOfficeUtils.CompressFileOrDirectory(sOOXMLDir, sTo, false)) ? 0 : AVS_FILEUTILS_ERROR_CONVERT; } @@ -463,6 +505,7 @@ namespace NExtractTools { if (!params.getDontSaveAdditional()) { + // TODO: Sign? copyOrigin(sFrom, *params.m_sFileTo); } return AVS_FILEUTILS_ERROR_CONVERT_DRM; diff --git a/X2tConverter/src/lib/pdf_image.h b/X2tConverter/src/lib/pdf_image.h index 49ac4cf2fb..9e3d030224 100644 --- a/X2tConverter/src/lib/pdf_image.h +++ b/X2tConverter/src/lib/pdf_image.h @@ -44,6 +44,38 @@ #include "common.h" +namespace NExtractTools +{ + static int pdfSign(const std::wstring& file, NSFonts::IApplicationFonts* fonts, InputParams& params, ConvertParams& convertParams) + { + ICertificate* certificate = NSSign::loadCertificate(params); + if (!certificate) + return 1; + + std::wstring pdfTemp = combinePath(convertParams.m_sTempDir, L"pdf_sign.pdf"); + NSFile::CFileBinary::Move(file, pdfTemp); + + CPdfFile pdfFile(fonts); + pdfFile.SetTempDirectory(convertParams.m_sTempDir); + std::wstring password = params.getSavePassword(); + + if (!pdfFile.LoadFromFile(pdfTemp, L"", password.c_str(), password.c_str())) + return 2; + + if (!pdfFile.EditPdf(file)) + return 2; + + if (!pdfFile.EditPage(0)) + return 2; + + pdfFile.Sign(0, 0, 0, 0, L"", certificate); + pdfFile.Close(); + + RELEASEOBJECT(certificate); + return 0; + } +} + namespace NExtractTools { _UINT32 bin2pdf(const std::wstring& sFrom, const std::wstring& sTo, InputParams& params, ConvertParams& convertParams) @@ -76,6 +108,12 @@ namespace NExtractTools { nRet = S_OK == pdfWriter.OnlineWordToPdf(sFrom, sTo, &oBufferParams) ? 0 : AVS_FILEUTILS_ERROR_CONVERT; } + + if (0 == nRet) + { + pdfSign(sTo, pApplicationFonts, params, convertParams); + } + RELEASEOBJECT(pApplicationFonts); return nRet; } @@ -245,6 +283,12 @@ namespace NExtractTools int nReg = (convertParams.m_bIsPaid == false) ? 0 : 1; nRes = (S_OK == pdfWriter.OnlineWordToPdfFromBinary(sPdfBinFile, sTo, &oBufferParams)) ? nRes : AVS_FILEUTILS_ERROR_CONVERT; + + if (0 == nRes) + { + pdfSign(sTo, pApplicationFonts, params, convertParams); + } + RELEASEOBJECT(pApplicationFonts); } // удаляем sPdfBinFile, потому что он не в Temp @@ -1040,7 +1084,14 @@ namespace NExtractTools convertParams.m_sPrintPages = sPages; nRes = PdfDjvuXpsToRenderer(&pReader, &pdfWriter, sFrom, nFormatFrom, sTo, params, convertParams, pApplicationFonts); if (SUCCEEDED_X2T(nRes)) + { nRes = S_OK == pdfWriter.SaveToFile(sTo) ? 0 : AVS_FILEUTILS_ERROR_CONVERT; + + if (0 == nRes) + { + pdfSign(sTo, pApplicationFonts, params, convertParams); + } + } RELEASEOBJECT(pReader); } } diff --git a/X2tConverter/test/qmake/main.cpp b/X2tConverter/test/qmake/main.cpp index 56e7c4bc93..336962e4b4 100644 --- a/X2tConverter/test/qmake/main.cpp +++ b/X2tConverter/test/qmake/main.cpp @@ -1,9 +1,34 @@ +#ifdef _WIN32 +#include +#endif + #include "../../../DesktopEditor/common/Directory.h" #include "../../../DesktopEditor/common/StringBuilder.h" #include "../../../DesktopEditor/fontengine/ApplicationFontsWorker.h" #include "../../../Common/OfficeFileFormatChecker.h" #include "../../src/dylib/x2t.h" +static void SetEnvValueA(const std::string& sName, const std::string& sValue) +{ +#ifdef WIN32 + std::wstring sNameW = UTF8_TO_U(sName); + std::wstring sValueW = UTF8_TO_U(sValue); + + _wputenv_s(sNameW.c_str(), sValueW.c_str()); +#else + static char buffer[100000]; // on all process + static int offset = 0; + + std::string tmp = sName + "=" + sValue; + size_t len = tmp.length(); + + memcpy(buffer + offset, tmp.c_str(), sizeof(char) * len); + buffer[offset + len] = '\0'; + putenv(buffer + offset); + offset += (len + 1); +#endif +} + void CheckFonts(const std::wstring& fontsDir, bool isUseSystem = true, const std::vector& addtitionalFontsDirs = {}) { CApplicationFontsWorker fonts_worker; @@ -159,6 +184,17 @@ int main(int argc, char** argv) oBuilder.WriteString(L""); } + if (false) + { + // if need disable js engine cache + oBuilder.WriteString(L""); + + oBuilder.WriteEncodeXmlString(curr_dir + wsep + L"certificate.pfx"); + SetEnvValueA("SIGNING_KEYSTORE_PASSPHRASE", "123"); + + oBuilder.WriteString(L""); + } + oBuilder.WriteString(L""); // writing xml data into file