Вставьте несколько (2 раза) цифровых подписей. Я обнаружил, что в PDF есть 3 информационных словаря. - PullRequest
1 голос
/ 26 апреля 2019

я получил ту же проблему (разработать с podofo в C ++).после вставки нескольких (2 раза) цифровых подписей found я обнаружил, что в файле PDF есть 3 инфо-словаря:

как добавить две цифровые подписи без аннулирования предыдущей?

спасибо!

я открываю файл в блокноте ++, и я нашел другой

the first:  97 0 obj<</Title(? G I S e r C l u bThR\n 2 0 1 4 0 7 2 0) /Author(edison qian) /Keywords(GISerClub) /Creator(? M i c r o s o f t ?  W o r d   2 0 1 3) 
            /CreationDate(D:20150601200942+08'00') /ModDate(D:20150601200942+08'00') /Producer(? M i c r o s o f t ?  W o r d   2 0 1 3) >>

the second: 97 0 obj<</Author(edison qian)/CreationDate(D:20150601200942+08'00')/Creator(? M i c r o s o f t ?  W o r d   2 0 1 3)/Keywords(GISerClub)
            /ModDate(D:20190426155330+08'00')/Producer(? M i c r o s o f t ?  W o r d   2 0 1 3)/Title(? G I S e r C l u bThR\n 2 0 1 4 0 7 2 0)>>

the third:  97 0 obj<</Author(edison qian)/CreationDate(D:20150601200942+08'00')/Creator(? M i c r o s o f t ?  W o r d   2 0 1 3)/Keywords(GISerClub)
            /ModDate(D:20190426155428+08'00')/Producer(? M i c r o s o f t ?  W o r d   2 0 1 3)/Title(? G I S e r C l u bThR\n 2 0 1 4 0 7 2 0)>>

мой код:



    bool pdfSign(PdfMemDocument* document,PdfOutputDevice* outputDevice,PKCS12* p12,RSA* rsa,int npage,PdfRect rect,int min_signature_size,const char* ImgFile/*,PdfDate& sigData*/)
    {
        PdfInfo* pInfo = document->GetInfo();
        TKeyMap itm = pInfo->GetObject()->GetDictionary().GetKeys();
        PdfObject* pobj = pInfo->GetObject()->GetDictionary().GetKey(PdfName("ModDate"));
        PdfString modDate = pobj->GetString();
        string sDate = modDate.GetString();
        string sutf8Date = modDate.GetStringUtf8();

        PdfOutlines* pOutLine = document->GetOutlines();
        TKeyMap itm2 = pOutLine->GetObject()->GetDictionary().GetKeys();

        const char *field_name = NULL;
        bool field_use_existing = false;
        int annot_page = npage;
        //double annot_left = 80.0, annot_top = 70.0, annot_width = 150.0, annot_height = 150.0;
        bool annot_print = true;
        const char *reason = "I agree";

        int result = 0;
        PdfSignatureField *pSignField = NULL;

        try
        {
            PdfSignOutputDevice signer( outputDevice );

            PdfAcroForm* pAcroForm = document->GetAcroForm();
            if( !pAcroForm )
                PODOFO_RAISE_ERROR_INFO( ePdfError_InvalidHandle, "acroForm == NULL" );

            if( !pAcroForm->GetObject()->GetDictionary().HasKey( PdfName( "SigFlags" ) ) || 
                !pAcroForm->GetObject()->GetDictionary().GetKey( PdfName( "SigFlags" ) )->IsNumber() || 
                pAcroForm->GetObject()->GetDictionary().GetKeyAsLong( PdfName( "SigFlags" ) ) != 3 )
            {
                if( pAcroForm->GetObject()->GetDictionary().HasKey( PdfName( "SigFlags" ) ) )
                    pAcroForm->GetObject()->GetDictionary().RemoveKey( PdfName( "SigFlags" ) );

                pdf_int64 val = 3;
                pAcroForm->GetObject()->GetDictionary().AddKey( PdfName( "SigFlags" ), PdfObject( val ) );
            }

            if( pAcroForm->GetNeedAppearances() )
            {
                #if 0 /* TODO */
                update_default_appearance_streams( pAcroForm );
                #endif

                pAcroForm->SetNeedAppearances( false );
            }

            PdfString name;
            PdfObject* pExistingSigField = NULL;

            PdfImage image( document );
            image.LoadFromFile( ImgFile );
            double dimgWidth = image.GetWidth();
            double dimgHeight = image.GetHeight();

            char fldName[96]; // use bigger buffer to make sure sprintf does not overflow
            sprintf( fldName, "PodofoSignatureField%" PDF_FORMAT_INT64, static_cast( document->GetObjects().GetObjectCount() ) );
            name = PdfString( fldName );

            PdfPage* pPage = document->GetPage( annot_page );
            if( !pPage )
                PODOFO_RAISE_ERROR( ePdfError_PageNotFound );

            double dPageHeight = pPage->GetPageSize().GetHeight();
            double dPageWidth = pPage->GetPageSize().GetWidth();

            PdfRect annot_rect;
            annot_rect = PdfRect( rect.GetLeft(), 
                pPage->GetPageSize().GetHeight() - rect.GetBottom() - rect.GetHeight(),
                dimgWidth, 
                dimgHeight );

            PdfAnnotation* pAnnot = pPage->CreateAnnotation( ePdfAnnotation_Widget, annot_rect );
            if( !pAnnot )
                PODOFO_RAISE_ERROR_INFO( ePdfError_OutOfMemory, "Cannot allocate annotation object" );

            if( annot_print )
                pAnnot->SetFlags( ePdfAnnotationFlags_Print );
            else if(  !field_name || !field_use_existing  )
                pAnnot->SetFlags( ePdfAnnotationFlags_Invisible | ePdfAnnotationFlags_Hidden );

            PdfPainter painter;
            try
            {
                painter.SetPage( /*&sigXObject*/pPage );

                /* Workaround Adobe's reader error 'Expected a dict object.' when the stream
                    contains only one object which does Save()/Restore() on its own, like
                    the image XObject. */
                painter.Save();
                painter.Restore();
                draw_annotation( *document, painter, image, annot_rect );

            }
            catch( PdfError & e )
            {
                if( painter.GetPage() )
                {
                    try
                    {
                        painter.FinishPage();
                    }
                    catch( ... )
                    {
                    }
                }
            }

            painter.FinishPage();

            //pSignField = new PdfSignatureField( pAnnot, pAcroForm, document );
            pSignField = new PdfSignatureField( pPage, annot_rect, document );
            if( !pSignField )
                PODOFO_RAISE_ERROR_INFO( ePdfError_OutOfMemory, "Cannot allocate signature field object" );

            PdfRect annotSize( 0.0, 0.0, dimgWidth, dimgHeight );
            PdfXObject sigXObject( annotSize, document );

            pSignField->SetAppearanceStream( &sigXObject );


            // use large-enough buffer to hold the signature with the certificate
            signer.SetSignatureSize( min_signature_size );

            pSignField->SetFieldName( name );
            pSignField->SetSignatureReason( PdfString( reinterpret_cast( reason ) ) );
            pSignField->SetSignatureDate( /*sigData*/PdfDate() );
            pSignField->SetSignature( *signer.GetSignatureBeacon() );
            pSignField->SetBackgroundColorTransparent();
            pSignField->SetBorderColorTransparent();

            // The outPdfFile != NULL means that the write happens to a new file,
            // which will be truncated first and then the content of the srcPdfFile
            // will be copied into the document, follwed by the changes.
            //signer.Seek(0);
            document->WriteUpdate( &signer, true ); 

            if( !signer.HasSignaturePosition() )
                PODOFO_RAISE_ERROR_INFO( ePdfError_SignatureError, "Cannot find signature position in the document data" );

            // Adjust ByteRange for signature
            signer.AdjustByteRange();

            // Read data for signature and count it
            // We seek at the beginning of the file
            signer.Seek( 0 );
            sign_with_signer( signer, g_x509, g_pKey );
            signer.Flush();
        }
        catch( PdfError & e )
        {

        }

        if( pSignField )
            delete pSignField;

    }

я использую код выше два раза и первую подписьявляется недействительным.как добавить две цифровые подписи без аннулирования предыдущей?

1 Ответ

0 голосов
/ 29 апреля 2019

Рисование справа PdfCanvas

После анализа примера в формате pdf выяснилась причина, по которой ваша вторая подпись аннулировала вашу первую подпись: в процессе подписания вы изменяете содержимое страницы с помощью виджетааннотация подписи.

Но изменение содержимого любой страницы лишает законной силы любую предыдущую подпись!Ср этот ответ для получения подробной информации о разрешенных и запрещенных изменениях подписанных документов.

Действительно:

PdfPainter painter;

try
{
    painter.SetPage( /*&sigXObject*/pPage );

    /* Workaround Adobe's reader error 'Expected a dict object.' when the stream
        contains only one object which does Save()/Restore() on its own, like
        the image XObject. */
    painter.Save();
    painter.Restore();
    draw_annotation( *document, painter, image, annot_rect );
}

Видимо, вы здесь что-то меняете в самом контенте страницы.Когда этот код выполняется при применении второй подписи, первая подпись становится недействительной.

Вы подтвердили в комментарии:

я использую '& sigXObject' вместо 'pPage', все две подписи работают!но красная печать исчезла

Использование правильных координат

Что касается вашего наблюдения, что красная печать исчезла : вы используете неправильные координаты для рисования изображения наВнешний вид аннотации!

Вы используете координаты для системы координат страницы, но вы должны использовать координаты в системе координат, заданной ограничительной рамкой внешнего вида.

Таким образом, ваш

painter.DrawImage( annot_rect.GetLeft(), annot_rect.GetBottom(), &image );

не так, вместо этого попробуйте что-то вроде

painter.DrawImage( 0, 0, &image );

, поскольку ограничивающая рамка вашего внешнего вида -

[ 0 0 151 151 ]
...