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 [email protected] https://lists.sourceforge.net/lists/listinfo/podofo-users
