/** * Copyright 2006 by Know-Center, Graz, Austria * PDF-AS has been contracted by the E-Government Innovation Center EGIZ, a * joint initiative of the Federal Chancellery Austria and Graz University of * Technology. * * Licensed under the EUPL, Version 1.1 or - as soon they will be approved by * the European Commission - subsequent versions of the EUPL (the "Licence"); * You may not use this work except in compliance with the Licence. * You may obtain a copy of the Licence at: * http://www.osor.eu/eupl/ * * Unless required by applicable law or agreed to in writing, software * distributed under the Licence is distributed on an "AS IS" basis, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the Licence for the specific language governing permissions and * limitations under the Licence. * * This product combines work with different licenses. See the "NOTICE" text * file for details on the various modules and licenses. * The "NOTICE" text file is part of the distribution. Any derivative works * that you distribute must include a readable copy of the "NOTICE" text file. * * $Id: BinarySignator_1_0_0.java,v 1.1 2006/08/25 17:07:35 wprinz Exp $ */ package at.knowcenter.wag.egov.egiz.framework.signators; import java.io.IOException; import java.io.InputStream; import java.io.UnsupportedEncodingException; import java.util.ArrayList; import java.util.Iterator; import java.util.List; import at.gv.egiz.pdfas.framework.input.DataSource; import at.gv.egiz.pdfas.framework.input.PdfDataSource; import at.gv.egiz.pdfas.impl.input.CompoundPdfDataSourceImpl; import at.gv.egiz.pdfas.impl.signator.IncrementalUpdateHelper; import at.knowcenter.wag.egov.egiz.PdfAS; import at.knowcenter.wag.egov.egiz.PdfASID; import at.knowcenter.wag.egov.egiz.exceptions.PDFDocumentException; import at.knowcenter.wag.egov.egiz.exceptions.PresentableException; import at.knowcenter.wag.egov.egiz.framework.SignResult; import at.knowcenter.wag.egov.egiz.framework.Signator; import at.knowcenter.wag.egov.egiz.framework.SignatorFactory; import at.knowcenter.wag.egov.egiz.pdf.BinarySignature; import at.knowcenter.wag.egov.egiz.pdf.IncrementalUpdateInformation; import at.knowcenter.wag.egov.egiz.pdf.PositioningInstruction; import at.knowcenter.wag.egov.egiz.pdf.ReplaceInfo; import at.knowcenter.wag.egov.egiz.pdf.StringInfo; import at.knowcenter.wag.egov.egiz.pdf.TablePos; import at.knowcenter.wag.egov.egiz.sig.SignatureData; import at.knowcenter.wag.egov.egiz.sig.SignatureDataImpl; import at.knowcenter.wag.egov.egiz.sig.SignatureFieldDefinition; import at.knowcenter.wag.egov.egiz.sig.SignatureObject; import at.knowcenter.wag.egov.egiz.sig.SignatureTypes; import at.knowcenter.wag.exactparser.ByteArrayUtils; import com.lowagie.text.pdf.PdfPTable; /** * Signs the document binary. * *

* In prepareSign, an Incremental Update is created that contains the Signature * block and the egiz dictionary. For formatting the layout, variable values are * filled with placeholders. After the layout has been fixed, all variable * fields (all holes in the byte ranges) are replaced with 0. This document is * then base64 encoded and signed. *

*

* In finishSign, the variable fields (values, /Cert) are replaced with the * values according to the encoding. *

* * @deprecated moved to new-framework * * @author wprinz */ public class BinarySignator_1_0_0 implements Signator { /** * The Pdf-AS ID of this Signator. */ public static final PdfASID MY_ID = new PdfASID(SignatorFactory.VENDOR, SignatorFactory.TYPE_BINARY, SignatorFactory.VERSION_1_0_0); /** * @see at.knowcenter.wag.egov.egiz.framework.Signator#getMyId() */ public PdfASID getMyId() { return MY_ID; } /** * Default constructor. */ public BinarySignator_1_0_0() { // Default constructor. } /** * @see at.knowcenter.wag.egov.egiz.framework.Signator#prepareSign(byte[], * String, TablePos, boolean) */ public IncrementalUpdateInformation prepareSign(PdfDataSource pdf, String signature_type, TablePos pos, boolean has_SIG_ID) throws PresentableException { try { SignatureObject signature_object = PdfAS.createSignatureObjectFromType(signature_type); signature_object.fillValues((char) BinarySignature.LAYOUT_PLACEHOLDER, has_SIG_ID, false); signature_object.setKZ(getMyId()); PdfPTable pdf_table = PdfAS.createPdfPTableFromSignatureObject(signature_object); PositioningInstruction pi = PdfAS.determineTablePositioning(pos, signature_type, pdf, pdf_table); List all_field_definitions = signature_object.getSignatureTypeDefinition().getFieldDefinitions(); List variable_field_definitions = new ArrayList(); for (int i = 0; i < all_field_definitions.size(); i++) { SignatureFieldDefinition sfd = (SignatureFieldDefinition) all_field_definitions.get(i); if (sfd.placeholder_length > 0) { if (sfd.field_name.equals(SignatureTypes.SIG_ID) && has_SIG_ID == false) { continue; } variable_field_definitions.add(sfd); } } //check if signature block is invisible, and if so and if also signature block is positioned //on a new page, prevent pdf-as to do that, because why should make a new page just for an invisible block //added by rpiazzi if (signature_object.getSignatureTypeDefinition().getInvisibleFieldDefinitions().size()==SignatureTypes.REQUIRED_SIG_KEYS.length) { if (pi.isMakeNewPage()) { int pageNumber = pi.getPage(); pi = new PositioningInstruction(false, pageNumber-1, 0, 0); } } //end added IncrementalUpdateInformation iui = IncrementalUpdateHelper.writeIncrementalUpdate(pdf, pdf_table, signature_type, pi, variable_field_definitions, all_field_definitions, null, null, null); String temp_string = iui.temp_ir_number + " " + iui.temp_ir_generation + " obj"; //$NON-NLS-1$//$NON-NLS-2$ byte[] temp_bytes = temp_string.getBytes("US-ASCII"); //$NON-NLS-1$ int temp_start = ByteArrayUtils.lastIndexOf(iui.signed_pdf, temp_bytes); byte[] stream_bytes = new byte[] { '>', '>', 's', 't', 'r', 'e', 'a', 'm', 0x0A }; int stream_start = ByteArrayUtils.indexOf(iui.signed_pdf, temp_start, stream_bytes); iui.content_stream_start = stream_start + stream_bytes.length; // update the stream indices Iterator it = iui.replaces.iterator(); while (it.hasNext()) { ReplaceInfo ri = (ReplaceInfo) it.next(); Iterator sit = ri.replaces.iterator(); while (sit.hasNext()) { StringInfo si = (StringInfo) sit.next(); si.string_start += iui.content_stream_start; } } // update KZ list indices: it = iui.kz_list.iterator(); while (it.hasNext()) { StringInfo si = (StringInfo) it.next(); si.string_start += iui.content_stream_start; } BinarySignature.markByteRanges(iui); // byte [] old_signed_pdf = iui.signed_pdf; iui.signed_pdf = BinarySignature.prepareDataToSign(iui.signed_pdf, iui.byte_ranges); reduceToIUBlock(iui); iui.signature_data = formSignatureData(iui); return iui; } catch (UnsupportedEncodingException e) { e.printStackTrace(); throw new PDFDocumentException(201, e); } } /** * @see at.knowcenter.wag.egov.egiz.framework.Signator#finishSign(at.knowcenter.wag.egov.egiz.pdf.IncrementalUpdateInformation) */ public SignResult finishSign(IncrementalUpdateInformation iui) throws PresentableException { restoreSignedPdf(iui); // PdfAS.prefixID(iui.signed_signature_object, PdfAS.BINARY_ID); fillReplacesWithValues(iui); BinarySignature.replaceCertificate(iui); BinarySignature.replacePlaceholders(iui); SignResult sign_result = new SignResult(PdfAS.PDF_MIME_TYPE, iui.signed_pdf); return sign_result; } /** * Reads the signature values from the signed signature object and fills the * corresponding value in the Replaces array. * * @param iui * The IncrementalUpdateInformation. */ protected void fillReplacesWithValues(IncrementalUpdateInformation iui) { Iterator it = iui.replaces.iterator(); while (it.hasNext()) { ReplaceInfo ri = (ReplaceInfo) it.next(); ri.value = iui.signed_signature_object.retrieveStringValue(ri.sfd.field_name); } } protected void reduceToIUBlock(IncrementalUpdateInformation iui) { byte[] iu_block = new byte[iui.signed_pdf.length - iui.original_document.getLength()]; System.arraycopy(iui.signed_pdf, iui.original_document.getLength(), iu_block, 0, iu_block.length); iui.signed_pdf = null; iui.sign_iui_block = iu_block; } protected void restoreSignedPdf(IncrementalUpdateInformation iui) { iui.signed_pdf = new byte[iui.original_document.getLength() + iui.sign_iui_block.length]; try { InputStream is = iui.original_document.createInputStream(); is.read(iui.signed_pdf, 0, iui.original_document.getLength()); is.close(); } catch (IOException e) { throw new RuntimeException(e); } System.arraycopy(iui.sign_iui_block, 0, iui.signed_pdf, iui.original_document.getLength(), iui.sign_iui_block.length); } /** * Forms the SignatureData to be used for signing. * * @param iui * The IncrementalUpdateInformation. * @return Returns the SignatureData to be used for signing. */ protected SignatureData formSignatureData(IncrementalUpdateInformation iui) { // String document_text = // BinarySignature.retrieveSignableTextFromData(iui.signed_pdf, // iui.signed_pdf.length); // signed_pdf.length); // // byte[] data; // try // { // data = document_text.getBytes("UTF-8"); //$NON-NLS-1$ // } // catch (UnsupportedEncodingException e) // { // throw new RuntimeException("Very strange: UTF-8 character encoding not // supported.", e); //$NON-NLS-1$ // } DataSource ds = new CompoundPdfDataSourceImpl(iui.original_document, iui.sign_iui_block); SignatureData signature_data = new SignatureDataImpl(ds, PdfAS.PDF_MIME_TYPE); return signature_data; } }