Hi, I have tried to sign PDF document using latest version of PoDoFo 0.9.6 and openssl has been used for reading the certificate. I have attached the .ccp file which has the code. The PDF file get created, but when it shows "invalid signature' on mouse over the signature field. "Error encountered while BER decoding:Error during signature verification" is shown on clicking the signature in the PDF document.
Can you please help me to fix this issue? I have also attached PDF created with signature from the attached code. Thanks, Susheela
// OpenSSL includes #include <openssl/err.h> #include <openssl/evp.h> #include <openssl/pkcs12.h> #include <openssl/pkcs7.h> #include <openssl/rsa.h> #include <openssl/sha.h> #include "../../src/podofo.h" #include <iostream> using namespace PoDoFo; class Ossl { private: SHA_CTX m_sha_ctx; EVP_PKEY* mp_pkey; // private key X509* mp_x509; // signing certificate STACK_OF(X509)* mp_ca; // certificate chain up to the CA public: Ossl(){} ~Ossl(){} void init(const char * file) { CRYPTO_malloc_init(); ERR_load_crypto_strings(); OpenSSL_add_all_algorithms(); FILE* fp = fopen(file, "rb"); if (fp == NULL) { std::cout << "fp null" << std::endl; return; } PKCS12* p12 = d2i_PKCS12_fp(fp, NULL); fclose(fp); if (p12 == NULL) { std::cout << "p12 null" << std::endl; return; } mp_pkey = NULL; mp_x509 = NULL; mp_ca = NULL; int ok = PKCS12_parse(p12, "123456", &mp_pkey, &mp_x509, &mp_ca); if (ok == 0) { std::cout << "not ok" << std::endl; return; } SHA1_Init(&m_sha_ctx); std::cout << "init ok" << std::endl; } void append(const char* data, int len) { SHA1_Update(&m_sha_ctx, data, len); return; } char * signature() { unsigned char sha_buffer[SHA_DIGEST_LENGTH]; memset((void*) sha_buffer, 0, SHA_DIGEST_LENGTH); SHA1_Final(sha_buffer, &m_sha_ctx); PKCS7* p7 = PKCS7_new(); PKCS7_set_type(p7, NID_pkcs7_signed); PKCS7_SIGNER_INFO* p7Si = PKCS7_add_signature(p7, mp_x509, mp_pkey, EVP_sha1()); PKCS7_add_attrib_content_type(p7Si, OBJ_nid2obj(NID_pkcs7_data)); PKCS7_add0_attrib_signing_time(p7Si, NULL); PKCS7_add1_attrib_digest(p7Si, (const unsigned char*) sha_buffer, SHA_DIGEST_LENGTH); PKCS7_add_certificate(p7, mp_x509); int c = 0; for ( ; c < sk_X509_num(mp_ca); c++) { X509* cert = sk_X509_value(mp_ca, c); PKCS7_add_certificate(p7, cert); } PKCS7_set_detached(p7, 1); PKCS7_content_new(p7, NID_pkcs7_data); PKCS7_SIGNER_INFO_sign(p7Si); int p7Len = i2d_PKCS7(p7, NULL); unsigned char* p7Buf = (unsigned char*) malloc(p7Len); unsigned char *p; p=p7Buf; if (p7Buf != NULL) { int len = i2d_PKCS7(p7, &p); printf("%i", len); std::cout << "p7Buf filled"; } PKCS7_free(p7); //std::cout << "buffer value"<<p7Buf<< std::endl; printf("%x\n", *p); return (char *) p; } }; using namespace PoDoFo; #define CONVERSION_CONSTANT 0.002834645669291339 void CreateSimpleForm( PdfPage* pPage, PdfStreamedDocument* pDoc, const PdfData &signatureData ) { PdfPainter painter; PdfFont* pFont = pDoc->CreateFont( "Courier" ); painter.SetPage( pPage ); painter.SetFont( pFont ); painter.DrawText( 10000 * CONVERSION_CONSTANT, 280000 * CONVERSION_CONSTANT, "PoDoFo Sign Test" ); painter.FinishPage(); PdfSignatureField signField( pPage, PdfRect( 70000 * CONVERSION_CONSTANT, 10000 * CONVERSION_CONSTANT, 50000 * CONVERSION_CONSTANT, 50000 * CONVERSION_CONSTANT ), pDoc ); signField.SetFieldName("PODOFO"); signField.SetSignature(signatureData); signField.SetSignatureReason("Testing signature"); // Set time of signing signField.SetSignatureDate( PdfDate() ); } int main( int argc, char* argv[] ) { PdfPage* pPage; if( argc != 2 ) { printf("Usage: SignTest [output_filename]\n"); printf(" - Create a PDF ready to be signed\n"); return 0; } try { PdfSignOutputDevice signer(argv[1]); // Reserve space for signature signer.SetSignatureSize(1024); PdfStreamedDocument writer( &signer, PoDoFo::ePdfVersion_1_5 ); // Disable default appearance writer.GetAcroForm(ePdfCreateObject, ePdfAcroFormDefaultAppearance_None); pPage = writer.CreatePage( PdfPage::CreateStandardPageSize( ePdfPageSize_A4 ) ); CreateSimpleForm( pPage, &writer, *signer.GetSignatureBeacon()); writer.Close(); // Adjust ByteRange for signature if(signer.HasSignaturePosition()) { signer.AdjustByteRange(); // read data for signature and count it signer.Seek(0); Ossl * ossl = new Ossl(); ossl->init("keystore.p12"); // generate digest and count signature // use NSS, MS Crypto API or OpenSSL // to generate signature in DER format char buff[65536]; size_t len; while( (len = signer.ReadForSignature(buff, 65536))>0 ) { ossl->append(buff, len); } // Paste signature to the file PdfData sigData(ossl->signature()); //std::cout << ossl->signature() << std::endl; signer.SetSignature(sigData); delete ossl; } signer.Flush(); } catch( PdfError & e ) { std::cerr << "Error: An error " << e.GetError() << " ocurred." << std::endl; e.PrintErrorMsg(); return e.GetError(); } return 0; }
sample2.pdf
Description: Adobe PDF document
_______________________________________________ Podofo-users mailing list Podofo-users@lists.sourceforge.net https://lists.sourceforge.net/lists/listinfo/podofo-users