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;
}

Attachment: sample2.pdf
Description: Adobe PDF document

_______________________________________________
Podofo-users mailing list
Podofo-users@lists.sourceforge.net
https://lists.sourceforge.net/lists/listinfo/podofo-users

Reply via email to