/** * 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. */ package at.gv.egiz.pdfas.impl.api; import java.io.File; import java.io.UnsupportedEncodingException; import java.text.MessageFormat; import java.util.ArrayList; import java.util.Iterator; import java.util.List; import java.util.Properties; import java.util.Vector; import org.apache.commons.lang.math.NumberUtils; import org.apache.commons.logging.Log; import org.apache.commons.logging.LogFactory; import at.gv.egiz.pdfas.api.PdfAs; import at.gv.egiz.pdfas.api.analyze.AnalyzeParameters; import at.gv.egiz.pdfas.api.analyze.AnalyzeResult; import at.gv.egiz.pdfas.api.commons.Constants; import at.gv.egiz.pdfas.api.commons.DynamicSignatureLifetimeEnum; import at.gv.egiz.pdfas.api.commons.DynamicSignatureProfile; import at.gv.egiz.pdfas.api.commons.DynamicSignatureProfileImpl; import at.gv.egiz.pdfas.api.commons.SignatureInformation; import at.gv.egiz.pdfas.api.exceptions.PdfAsException; import at.gv.egiz.pdfas.api.sign.SignParameters; import at.gv.egiz.pdfas.api.sign.SignResult; import at.gv.egiz.pdfas.api.sign.SignatureDetailInformation; import at.gv.egiz.pdfas.api.verify.VerifyAfterAnalysisParameters; import at.gv.egiz.pdfas.api.verify.VerifyAfterReconstructXMLDsigParameters; import at.gv.egiz.pdfas.api.verify.VerifyParameters; import at.gv.egiz.pdfas.api.verify.VerifyResult; import at.gv.egiz.pdfas.api.verify.VerifyResults; import at.gv.egiz.pdfas.api.xmldsig.ExtendedSignatureInformation; import at.gv.egiz.pdfas.api.xmldsig.ReconstructXMLDsigAfterAnalysisParameters; import at.gv.egiz.pdfas.api.xmldsig.ReconstructXMLDsigParameters; import at.gv.egiz.pdfas.api.xmldsig.ReconstructXMLDsigResult; import at.gv.egiz.pdfas.api.xmldsig.XMLDsigData; import at.gv.egiz.pdfas.commandline.CommandlineConnectorChooser; import at.gv.egiz.pdfas.exceptions.ErrorCode; import at.gv.egiz.pdfas.exceptions.framework.PlaceholderExtractionException; import at.gv.egiz.pdfas.framework.ConnectorParameters; import at.gv.egiz.pdfas.framework.DataSourceHolder; import at.gv.egiz.pdfas.framework.config.SettingsHelper; import at.gv.egiz.pdfas.framework.input.ExtractionStage; import at.gv.egiz.pdfas.framework.input.PdfDataSource; import at.gv.egiz.pdfas.framework.signator.Signator; import at.gv.egiz.pdfas.framework.signator.SignatorInformation; import at.gv.egiz.pdfas.framework.vfilter.VerificationFilterParameters; import at.gv.egiz.pdfas.impl.api.analyze.AnalyzeResultImpl; import at.gv.egiz.pdfas.impl.api.commons.DataSinkAdapter; import at.gv.egiz.pdfas.impl.api.commons.PdfDataSourceAdapter; import at.gv.egiz.pdfas.impl.api.commons.SignatureInformationAdapter; import at.gv.egiz.pdfas.impl.api.commons.SignatureProfileImpl; import at.gv.egiz.pdfas.impl.api.commons.TextDataSourceAdapter; import at.gv.egiz.pdfas.impl.api.sign.ActualSignaturePositionAdapter; import at.gv.egiz.pdfas.impl.api.sign.SignResultImpl; import at.gv.egiz.pdfas.impl.api.sign.SignatureDetailInformationImpl; import at.gv.egiz.pdfas.impl.api.verify.VerifyResultAdapter; import at.gv.egiz.pdfas.impl.api.verify.VerifyResultsImpl; import at.gv.egiz.pdfas.impl.input.DelimitedPdfDataSource; import at.gv.egiz.pdfas.impl.vfilter.VerificationFilterParametersImpl; import at.gv.egiz.pdfas.impl.xmldsig.XMLDsigReconstructor; import at.gv.egiz.pdfas.placeholder.SignaturePlaceholderContext; import at.gv.egiz.pdfas.placeholder.SignaturePlaceholderData; import at.gv.egiz.pdfas.placeholder.SignaturePlaceholderExtractor; import at.gv.egiz.pdfas.utils.ConfigUtils; import at.knowcenter.wag.egov.egiz.PdfAS; import at.knowcenter.wag.egov.egiz.PdfASID; import at.knowcenter.wag.egov.egiz.cfg.OverridePropertyHolder; import at.knowcenter.wag.egov.egiz.cfg.SettingsReader; import at.knowcenter.wag.egov.egiz.exceptions.ConnectorException; import at.knowcenter.wag.egov.egiz.exceptions.OutOfMemoryException; import at.knowcenter.wag.egov.egiz.exceptions.PDFDocumentException; import at.knowcenter.wag.egov.egiz.exceptions.PresentableException; import at.knowcenter.wag.egov.egiz.exceptions.SettingsException; import at.knowcenter.wag.egov.egiz.exceptions.SignatorFactoryException; import at.knowcenter.wag.egov.egiz.exceptions.SignatureException; import at.knowcenter.wag.egov.egiz.framework.SignatorFactory; import at.knowcenter.wag.egov.egiz.pdf.AdobeSignatureHelper; import at.knowcenter.wag.egov.egiz.pdf.BinarySignatureHolder; import at.knowcenter.wag.egov.egiz.pdf.NoSignatureHolder; import at.knowcenter.wag.egov.egiz.pdf.ObjectExtractor; import at.knowcenter.wag.egov.egiz.pdf.SignatureHolder; import at.knowcenter.wag.egov.egiz.pdf.TablePos; import at.knowcenter.wag.egov.egiz.pdf.TextualSignatureHolder; import at.knowcenter.wag.egov.egiz.sig.SignatureData; import at.knowcenter.wag.egov.egiz.sig.SignatureDataImpl; import at.knowcenter.wag.egov.egiz.sig.SignatureResponse; import at.knowcenter.wag.egov.egiz.sig.SignatureTypeDefinition; import at.knowcenter.wag.egov.egiz.sig.SignatureTypes; import at.knowcenter.wag.egov.egiz.sig.connectors.Connector; import at.knowcenter.wag.egov.egiz.sig.connectors.bku.SignSignatureObject; /** * Implementation of the {@link PdfAs} interface. * * @author wprinz */ public class PdfAsObject implements PdfAs { //23.11.2010 changed by exthex - added methods for reconstructXMLDsig /** * The log. */ private static Log log = LogFactory.getLog(PdfAsObject.class); private static final String ENABLE_PLACEHOLDER_SEARCH_KEY = "enable_placeholder_search"; /** * Configuration key for minimal signature block width threshold. Any width below this certain value will lead to a warning log entry." */ private static final String SIGNATURE_BLOCK_WIDTH_THRESHOLD_FOR_WARNING_KEY = "signature_block_width_warning_threshold"; /** * Minimal signature block width. If a width below that value is defined (by parameter, by placeholder or by configuration) a warning log entry is created. */ public static final float DEFAULT_SIGNATURE_BLOCK_WIDTH_THRESHOLD = 150; /** * This constructor is for internal use only - use * {@link at.gv.egiz.pdfas.PdfAsFactory} instead. * Note: IAIK JCE and IAIK ECC security providers are automatically registered. * * @param workDirectory * The work directory. * @throws PdfAsException * Thrown, if the configuration cannot be processed. */ public PdfAsObject(File workDirectory) throws PdfAsException { this(workDirectory, SettingsReader.REGISTER_IAIK_PROVIDERS_ON_DEFAULT); } /** * This constructor is for internal use only - use * {@link at.gv.egiz.pdfas.PdfAsFactory} instead. * * @param workDirectory * The work directory. * @param registerProvider true: automatically registers IAIK JCE and ECC Provider; * false: providers will NOT be automatically registered, providers * needed have to be registered by the API user * @throws PdfAsException * Thrown, if the configuration cannot be processed. */ public PdfAsObject(File workDirectory, boolean registerProvider) throws PdfAsException { String path = workDirectory != null ? workDirectory.getPath() : null; SettingsReader.initialize(path, path); reloadConfig(registerProvider); } /** * This constructor is for internal use only - use * {@link at.gv.egiz.pdfas.PdfAsFactory} instead. * Note: IAIK JCE and IAIK ECC security providers are automatically registered. * * @throws PdfAsException * Thrown, if the configuration cannot be processed. */ public PdfAsObject() throws PdfAsException { this(null); } /** * @see at.gv.egiz.pdfas.api.PdfAs#reloadConfig() */ public void reloadConfig() throws PdfAsException { ConfigUtils.initializeLogger(); SettingsReader.createInstance(); SignatureTypes.createInstance(); } /** * @param registerProvider true: automatically registers IAIK JCE and ECC Provider; * false: providers will NOT be automatically registered, providers * needed have to be registered by the API user * @see at.gv.egiz.pdfas.api.PdfAs#reloadConfig() */ private void reloadConfig(boolean registerProvider) throws PdfAsException { ConfigUtils.initializeLogger(); SettingsReader.createInstance(registerProvider); SignatureTypes.createInstance(); } /** * @see at.gv.egiz.pdfas.api.PdfAs#getProfileInformation() */ public List getProfileInformation() throws PdfAsException { log.debug("Collecting profile information."); final String MOA_SIGN_KEY_IDENTIFIER_KEY = "moa.sign.KeyIdentifier"; SettingsReader settings = SettingsReader.getInstance(); final String defaultMoaKeyIdentifiert = settings.getSetting(MOA_SIGN_KEY_IDENTIFIER_KEY, null); SignatureTypes types = SignatureTypes.getInstance(); List profiles = types.getSignatureTypeDefinitions(); List profileInformation = new ArrayList(profiles.size()); String default_type = settings.getValueFromKey(SignatureTypes.DEFAULT_TYPE); Iterator it = profiles.iterator(); while (it.hasNext()) { SignatureTypeDefinition profile = (SignatureTypeDefinition) it.next(); final String profileId = profile.getType(); log.debug("Processing profile \"" + profileId + "\"."); final String moaKeyIdentifier = settings.getSetting("sig_obj." + profileId + "." + MOA_SIGN_KEY_IDENTIFIER_KEY, defaultMoaKeyIdentifiert); final String profileDescription = settings.getSetting("sig_obj." + profileId + "." + SignatureTypes.SIG_DESCR, null); boolean isDefault = (default_type != null && default_type.equals(profileId)); // modified by tknall SignatureProfileImpl signatureProfile = new SignatureProfileImpl(profileId, profileDescription, moaKeyIdentifier, isDefault); // start - added by tknall // signature entries relevant to the search algorithm Properties signatureEntries = new Properties(); // search for table entries String parentPropertyKey = "sig_obj." + profileId + ".table"; log.debug("Looking for subkeys of \"" + parentPropertyKey + "\"."); Vector keysVector = settings.getSettingKeys(parentPropertyKey); if (keysVector != null) { Iterator keyIt = keysVector.iterator(); while (keyIt.hasNext()) { String subKey = (String) keyIt.next(); if (subKey != null && subKey.length() > 0) { String fullKey = parentPropertyKey + "." + subKey; String value = settings.getValueFromKey(fullKey); int lastIndex = fullKey.lastIndexOf("."); if (lastIndex != -1) { String endsWith = fullKey.substring(lastIndex + 1); if (value != null && value.length() > 0) { if (NumberUtils.isDigits(endsWith)) { signatureEntries.setProperty(fullKey, value); } else { log.debug("Ignoring table entry \"" + fullKey + "\" because it does not end with a digit. Therefore it is not relevant for the seach algorithm."); } } else { log.warn("Problem detected with key \"" + fullKey + "\". The value is empty."); } } } } } // search for table entries parentPropertyKey = "sig_obj." + profileId + ".key"; log.debug("Looking for subkeys of \"" + parentPropertyKey + "\"."); keysVector = settings.getSettingKeys(parentPropertyKey); if (keysVector != null) { Iterator keyIt = keysVector.iterator(); while (keyIt.hasNext()) { String subKey = (String) keyIt.next(); if (subKey != null && subKey.length() > 0) { String fullKey = parentPropertyKey + "." + subKey; String value = settings.getValueFromKey(fullKey); if (value != null && value.length() > 0) { signatureEntries.setProperty(fullKey, value); } else { log.warn("Problem detected with key \"" + fullKey + "\". The value is empty."); } } } } // set properties signatureProfile.setSignatureBlockEntries(signatureEntries); // stop - added by tknall profileInformation.add(signatureProfile); } return profileInformation; } /** * @see at.gv.egiz.pdfas.api.PdfAs#sign(at.gv.egiz.pdfas.api.sign.SignParameters) */ public SignResult sign(SignParameters signParameters) throws PdfAsException { CheckHelper.checkSignParameters(signParameters, false); try { SignatureDetailInformation signatorInfo = prepareSign(signParameters); return sign(signParameters, signatorInfo); } catch (java.lang.OutOfMemoryError e) { throw new OutOfMemoryException(ErrorCode.OUT_OF_MEMORY_ERROR, "Insufficient memory allocated to virtual machine. Start Java with parameters \"-Xms128m -Xmx786m -XX:MaxPermSize=256m\".", e); } } /** * @see at.gv.egiz.pdfas.api.PdfAs#verify(at.gv.egiz.pdfas.api.verify.VerifyParameters) */ public VerifyResults verify(VerifyParameters verifyParameters) throws PdfAsException { CheckHelper.checkVerifyParameters(verifyParameters); AnalyzeParameters ap = new AnalyzeParameters(); fillAnalyzeParametersWithVerifyParameters(ap, verifyParameters); AnalyzeResult analyzeResult = analyze(ap); if (verifyParameters.getSignatureToVerify() != Constants.VERIFY_ALL) { if (verifyParameters.getSignatureToVerify() >= analyzeResult.getSignatures().size()) { throw new SignatureException(312, "The selected signature to be verified doesn't exist. " + verifyParameters.getSignatureToVerify()); } Object stv = analyzeResult.getSignatures().get(verifyParameters.getSignatureToVerify()); List selectedSignature = new ArrayList(1); selectedSignature.add(stv); analyzeResult = new AnalyzeResultImpl(selectedSignature); } VerifyAfterAnalysisParameters vaap = new VerifyAfterAnalysisParameters(); vaap.setAnalyzeResult(analyzeResult); fillVerifyAfterAnalysisParametersWithVerifyParameters(vaap, verifyParameters); VerifyResults res = verify(vaap); return res; } /** * Copies all adequate parameters from the {@link VerifyParameters} to the * {@link AnalyzeParameters}. * * @param ap * The {@link AnalyzeParameters}. * @param vp * The {@link VerifyParameters}. */ protected void fillAnalyzeParametersWithVerifyParameters(AnalyzeParameters ap, VerifyParameters vp) { ap.setDocument(vp.getDocument()); ap.setVerifyMode(vp.getVerifyMode()); ap.setReturnNonTextualObjects(vp.isReturnNonTextualObjects()); } protected void fillAnalyzeParametersWithReconstructXMLDsigParameters(AnalyzeParameters ap, ReconstructXMLDsigParameters rxp) { ap.setDocument(rxp.getDocument()); ap.setVerifyMode(rxp.getVerifyMode()); ap.setReturnNonTextualObjects(rxp.isReturnNonTextualObjects()); } /** * Copies all adequate parameters from the {@link VerifyParameters} to the * {@link VerifyAfterAnalysisParameters}. * * @param vaap * The {@link VerifyAfterAnalysisParameters}. * @param vp * The {@link VerifyParameters}. */ protected void fillVerifyAfterAnalysisParametersWithVerifyParameters(VerifyAfterAnalysisParameters vaap, VerifyParameters vp) { vaap.setSignatureDevice(vp.getSignatureDevice()); vaap.setVerificationTime(vp.getVerificationTime()); vaap.setReturnHashInputData(vp.isReturnHashInputData()); } protected void fillReconstructXMLDsigAfterAnalysisParametersWithVerifyAfterAnalysisParameters( ReconstructXMLDsigAfterAnalysisParameters reconstructParams, VerifyAfterAnalysisParameters verifyAfterAnalysisParameters) { reconstructParams.setAnalyzeResult(verifyAfterAnalysisParameters.getAnalyzeResult()); reconstructParams.setSignatureDevice(verifyAfterAnalysisParameters.getSignatureDevice()); } /** * @see at.gv.egiz.pdfas.api.PdfAs#analyze(at.gv.egiz.pdfas.api.analyze.AnalyzeParameters) */ public AnalyzeResult analyze(AnalyzeParameters analyzeParameters) throws PdfAsException { CheckHelper.checkAnalyzeParameters(analyzeParameters); VerificationFilterParameters parametersConfig = SettingsHelper.readVerificationFilterParametersFromSettings(); boolean binaryOnly = parametersConfig.extractBinarySignaturesOnly(); if (analyzeParameters.getVerifyMode().equals(Constants.VERIFY_MODE_BINARY_ONLY)) { binaryOnly = true; } boolean assumeOnlySB = parametersConfig.assumeOnlySignatureUpdateBlocks(); if (analyzeParameters.getVerifyMode().equals(Constants.VERIFY_MODE_SEMI_CONSERVATIVE)) { assumeOnlySB = true; } if (analyzeParameters.getVerifyMode().equals(Constants.VERIFY_MODE_FULL_CONSERVATIVE)) { assumeOnlySB = false; } VerificationFilterParameters parameters = new VerificationFilterParametersImpl(binaryOnly, assumeOnlySB, parametersConfig.scanForOldSignatures()); at.gv.egiz.pdfas.framework.input.DataSource inputDataSource = null; if (analyzeParameters.getDocument().getMimeType().equals("application/pdf")) { inputDataSource = new PdfDataSourceAdapter(analyzeParameters.getDocument()); } else { try { inputDataSource = new TextDataSourceAdapter(analyzeParameters.getDocument()); } catch (UnsupportedEncodingException e) { throw new PresentableException(ErrorCode.DOCUMENT_CANNOT_BE_READ, "The characterEncoding is not supported." + analyzeParameters.getDocument().getCharacterEncoding(), e); } } assert inputDataSource != null; try { ExtractionStage es = new ExtractionStage(); DataSourceHolder dsh = new DataSourceHolder(inputDataSource); List signature_holders = es.extractSignatureHolders(dsh, parameters); // List sigInfs = new ArrayList(signature_holders.size()); List sigInfs = new ArrayList(); List noSigs = new ArrayList(); Iterator it = signature_holders.iterator(); while (it.hasNext()) { SignatureHolder sh = (SignatureHolder)it.next(); if(sh instanceof NoSignatureHolder) { noSigs.add(sh); } else { SignatureInformation si = new SignatureInformationAdapter(sh); sigInfs.add(si); if (analyzeParameters.isReturnNonTextualObjects()) { si.setNonTextualObjects(doExtractNonTexualObjects(sh, (PdfDataSource) dsh.getDataSource())); } } } return new AnalyzeResultImpl(sigInfs, noSigs, parameters.hasBeenCorrected()); } catch (java.lang.OutOfMemoryError e) { throw new OutOfMemoryException(ErrorCode.OUT_OF_MEMORY_ERROR, "Insufficient memory allocated to virtual machine. Start Java with parameters \"-Xms128m -Xmx786m -XX:MaxPermSize=256m\".", e); } } private List doExtractNonTexualObjects(SignatureHolder sh, PdfDataSource pdfDataSource) { if (sh == null) return null; if (sh instanceof BinarySignatureHolder) { BinarySignatureHolder bsh = (BinarySignatureHolder)sh; return ObjectExtractor.extractNonTextInfo(bsh.getSignedPdf()); } else if (sh instanceof TextualSignatureHolder) { TextualSignatureHolder tsh = (TextualSignatureHolder)sh; if (tsh.getUiBlockEndPos() == 0) { log.warn("uiblockendpos not available. Extract objects from final pdf document"); return ObjectExtractor.extractNonTextInfo(pdfDataSource); } DelimitedPdfDataSource dpds = new DelimitedPdfDataSource(pdfDataSource, tsh.getUiBlockEndPos()); return ObjectExtractor.extractNonTextInfo(dpds); } else { return null; } } /** * @see at.gv.egiz.pdfas.api.PdfAs#verify(at.gv.egiz.pdfas.api.verify.VerifyAfterAnalysisParameters) */ public VerifyResults verify(VerifyAfterAnalysisParameters verifyAfterAnalysisParameters) throws PdfAsException { CheckHelper.checkVerifyAfterAnalysisParameters(verifyAfterAnalysisParameters); List signatures = verifyAfterAnalysisParameters.getAnalyzeResult().getSignatures(); // added by tknall if (signatures == null || signatures.isEmpty()) { throw new PDFDocumentException(ErrorCode.DOCUMENT_NOT_SIGNED, "PDF document not signed."); //$NON-NLS-1$ } ReconstructXMLDsigAfterAnalysisParameters rxaap = new ReconstructXMLDsigAfterAnalysisParameters(); fillReconstructXMLDsigAfterAnalysisParametersWithVerifyAfterAnalysisParameters(rxaap, verifyAfterAnalysisParameters); ReconstructXMLDsigResult reconstructResult = reconstructXMLDSIG(rxaap); VerifyAfterReconstructXMLDsigParameters varxp = new VerifyAfterReconstructXMLDsigParameters(); fillVerifyAfterReconstructXMLDsigParametersWithVerifyAfterAnalysisParameters(varxp, verifyAfterAnalysisParameters); varxp.setReconstructXMLDsigResult(reconstructResult); return verify(varxp); } protected void fillVerifyAfterReconstructXMLDsigParametersWithVerifyAfterAnalysisParameters( VerifyAfterReconstructXMLDsigParameters varxp, VerifyAfterAnalysisParameters verifyAfterAnalysisParameters) { varxp.setReturnHashInputData(verifyAfterAnalysisParameters.isReturnHashInputData()); varxp.setSignatureDevice(verifyAfterAnalysisParameters.getSignatureDevice()); varxp.setVerificationTime(verifyAfterAnalysisParameters.getVerificationTime()); varxp.setVerifySignatureIndex(verifyAfterAnalysisParameters.getVerifySignatureIndex()); } /** * @see PdfAs#reconstructXMLDSIG(ReconstructXMLDsigParameters) */ public ReconstructXMLDsigResult reconstructXMLDSIG( ReconstructXMLDsigParameters reconstructXMLDsigParameters) throws PdfAsException { AnalyzeParameters analyzeParameters = new AnalyzeParameters(); fillAnalyzeParametersWithReconstructXMLDsigParameters(analyzeParameters, reconstructXMLDsigParameters); AnalyzeResult ar = analyze(analyzeParameters); ReconstructXMLDsigAfterAnalysisParameters rxaap = new ReconstructXMLDsigAfterAnalysisParameters(); rxaap.setSignatureDevice(reconstructXMLDsigParameters.getSignatureDevice()); rxaap.setAnalyzeResult(ar); return reconstructXMLDSIG(rxaap); } /** * @see PdfAs#reconstructXMLDSIG(ReconstructXMLDsigAfterAnalysisParameters) */ public ReconstructXMLDsigResult reconstructXMLDSIG( ReconstructXMLDsigAfterAnalysisParameters reconstructXMLDsigParameters) throws PdfAsException { AnalyzeResult ar = reconstructXMLDsigParameters.getAnalyzeResult(); List extendedSignatureInfos = new Vector(); for (int i = 0; i < ar.getSignatures().size(); i++) { SignatureInformation si = (SignatureInformation)ar.getSignatures().get(i); XMLDsigData dsigData; try { dsigData = XMLDsigReconstructor.reconstruct(si, reconstructXMLDsigParameters.getSignatureDevice()); extendedSignatureInfos.add(new ExtendedSignatureInformation(si, dsigData)); } catch (ConnectorException e) { // don't care for connector exceptions because of mutli signs. they are handled during verify extendedSignatureInfos.add(new ExtendedSignatureInformation(si, null)); } } return new ReconstructXMLDsigResult(extendedSignatureInfos, reconstructXMLDsigParameters.getSignatureDevice()); } /** * @see PdfAs#verify(VerifyAfterReconstructXMLDsigParameters) */ public VerifyResults verify( VerifyAfterReconstructXMLDsigParameters verifyAfterReconstructXMLDsigParameters) throws PdfAsException { try { List extSignatures = verifyAfterReconstructXMLDsigParameters.getReconstructXMLDsigResult().getExtendedSignatures(); String signatureDevice = verifyAfterReconstructXMLDsigParameters.getSignatureDevice(); if (signatureDevice == null){ signatureDevice = verifyAfterReconstructXMLDsigParameters.getReconstructXMLDsigResult().getDevice(); } List results = PdfAS.verifyExtendedSignatureHolders(extSignatures, signatureDevice, verifyAfterReconstructXMLDsigParameters.isReturnHashInputData(), verifyAfterReconstructXMLDsigParameters.getVerificationTime(), verifyAfterReconstructXMLDsigParameters.getVerifySignatureIndex()); List vrs = new ArrayList(results.size()); int verifySignatureIndex = verifyAfterReconstructXMLDsigParameters.getVerifySignatureIndex(); if (verifySignatureIndex < 0) { for (int i = 0; i < extSignatures.size(); i++) { SignatureResponse response = (SignatureResponse) results.get(i); ExtendedSignatureInformation extSigInfo = (ExtendedSignatureInformation)extSignatures.get(i); SignatureHolder holder = (SignatureHolder) extSigInfo.getSignatureInformation().getInternalSignatureInformation(); VerifyResult vr = new VerifyResultAdapter(response, holder, verifyAfterReconstructXMLDsigParameters.getVerificationTime(), extSigInfo.getXmlDsigData()); vr.setNonTextualObjects( extSigInfo.getSignatureInformation().getNonTextualObjects()); vrs.add(vr); } }else{ SignatureResponse response = (SignatureResponse) results.get(0); ExtendedSignatureInformation extSigInfo = (ExtendedSignatureInformation)extSignatures.get(verifySignatureIndex); SignatureHolder holder = (SignatureHolder) extSigInfo.getSignatureInformation().getInternalSignatureInformation(); VerifyResult vr = new VerifyResultAdapter(response, holder, verifyAfterReconstructXMLDsigParameters.getVerificationTime(), extSigInfo.getXmlDsigData()); vr.setNonTextualObjects( extSigInfo.getSignatureInformation().getNonTextualObjects()); vrs.add(vr); } VerifyResultsImpl verifyResults = new VerifyResultsImpl(vrs); return verifyResults; } catch (java.lang.OutOfMemoryError e) { throw new OutOfMemoryException(ErrorCode.OUT_OF_MEMORY_ERROR, "Insufficient memory allocated to virtual machine. Start Java with parameters \"-Xms128m -Xmx786m -XX:MaxPermSize=256m\".", e); } } public DynamicSignatureProfile createDynamicSignatureProfile(String parentProfile, DynamicSignatureLifetimeEnum mode) { return DynamicSignatureProfileImpl.createFromParent(null, parentProfile, mode); } public DynamicSignatureProfile createEmptyDynamicSignatureProfile(DynamicSignatureLifetimeEnum mode) { return DynamicSignatureProfileImpl.createEmptyProfile(null, mode); } public DynamicSignatureProfile loadDynamicSignatureProfile(String name) { return DynamicSignatureProfileImpl.loadProfile(name); } public DynamicSignatureProfile createDynamicSignatureProfile(String myUniqueName, String parentProfile, DynamicSignatureLifetimeEnum mode) { return DynamicSignatureProfileImpl.createFromParent(myUniqueName, parentProfile, mode); } public DynamicSignatureProfile createEmptyDynamicSignatureProfile(String myUniqueName, DynamicSignatureLifetimeEnum mode) { return DynamicSignatureProfileImpl.createEmptyProfile(myUniqueName, mode); } /** * @see PdfAs#prepareSign(SignParameters) */ public SignatureDetailInformation prepareSign(SignParameters signParameters) throws PdfAsException { CheckHelper.checkSignParameters(signParameters, true); if (signParameters.getProfileOverrideProperties() != null) { OverridePropertyHolder.setOverrideProps(signParameters.getProfileOverrideProperties()); } signParameters.setDocument(PdfAS.applyStrictMode(signParameters.getDocument())); SettingsReader settings = SettingsReader.getInstance(); String defaultProfile = settings.getValueFromKey(SignatureTypes.DEFAULT_TYPE); SignaturePlaceholderData spd = getSignaturePlaceholder(signParameters, defaultProfile); if (spd != null){ if (spd.getProfile() != null) signParameters.setSignatureProfileId(spd.getProfile()); if (spd.getType() != null) signParameters.setSignatureType(spd.getType()); if (spd.getKey() != null) signParameters.setSignatureKeyIdentifier(spd.getKey()); // check again, we might have destroyed something CheckHelper.checkSignParameters(signParameters, true); } if (signParameters.getSignatureProfileId() == null) { signParameters.setSignatureProfileId(defaultProfile); } boolean fromPlaceholder = false; boolean fromSignParameters = false; boolean fromConfig = false; TablePos pos = null; if (spd != null && spd.getTablePos() != null){ // position and width is determined by placeholder image fromPlaceholder = true; pos = spd.getTablePos(); } else { // position and width is determined by api sign parameters pos = PosHelper.formTablePos(signParameters.getSignaturePositioning()); if (pos != null) { fromSignParameters = true; } } TablePos effectivePos = pos; if (effectivePos == null) { String pos_string = settings.getSetting(SignatureTypes.SIG_OBJ + signParameters.getSignatureProfileId() + ".pos", null); if (pos_string != null) { // position and width is determined by profile configuration effectivePos = PdfAS.parsePositionFromPosString(pos_string); fromConfig = true; } } if (effectivePos != null) { // check if width is lower than the smallest meaningful width String thresholdString = AdobeSignatureHelper.getDefaultableConfigProperty(signParameters.getSignatureProfileId(), SIGNATURE_BLOCK_WIDTH_THRESHOLD_FOR_WARNING_KEY, String.valueOf(DEFAULT_SIGNATURE_BLOCK_WIDTH_THRESHOLD)); float threshold = DEFAULT_SIGNATURE_BLOCK_WIDTH_THRESHOLD; try { threshold = Float.parseFloat(thresholdString); } catch (NumberFormatException e) { if (log.isDebugEnabled()) { log.debug("Unable to parse threshold value (\"" + thresholdString + "\") of configuration value \"" + SIGNATURE_BLOCK_WIDTH_THRESHOLD_FOR_WARNING_KEY + "\". Using default value: " + DEFAULT_SIGNATURE_BLOCK_WIDTH_THRESHOLD); } } if (!effectivePos.isWauto() && effectivePos.getWidth() < threshold) { String msg = "The {0} for the signature block is very small ({1}). The signature block might not get placed correcty."; String[] arguments = new String[]{ "given width", "" + effectivePos.getWidth()}; // very small, warn user if (fromPlaceholder) { arguments[0] = "width given by the placeholder image"; } else if (fromSignParameters) { arguments[0] = "width defined by the sign parameters"; } else if (fromConfig) { arguments[0] = "width defined by the profile " + signParameters.getSignatureProfileId(); } log.warn(MessageFormat.format(msg, arguments)); } } Signator signator = createSignator(signParameters.getSignatureType()); SignatorInformation signatorInfo = signator.prepareSign( new PdfDataSourceAdapter(signParameters.getDocument()), signParameters.getSignatureProfileId(), pos, signParameters.getTimeStamperImpl()); SignatureDetailInformationImpl ret = new SignatureDetailInformationImpl(); ret.setSignatorInformation(signatorInfo); return ret; } private SignaturePlaceholderData getSignaturePlaceholder(SignParameters signParameters, String defaultProfile) throws SettingsException, PDFDocumentException, PlaceholderExtractionException { SignaturePlaceholderData spd = null; SignaturePlaceholderContext.setSignaturePlaceholderData(null); SettingsReader settings = SettingsReader.getInstance(); // check sig_obj.PROFILEID.enable_placeholder_search String profile = signParameters.getSignatureProfileId(); if (profile == null) profile = defaultProfile; String key = SignatureTypes.SIG_OBJ + profile + "." + ENABLE_PLACEHOLDER_SEARCH_KEY; String configFileActivedString = settings.getValueFromKey(key); if (configFileActivedString == null){ // check global enable_placeholder_search configFileActivedString = settings.getValueFromKey(ENABLE_PLACEHOLDER_SEARCH_KEY); } Boolean configFileActived = null; if (configFileActivedString != null) configFileActived = Boolean.valueOf(configFileActivedString); Boolean signParamsActivated = signParameters.isCheckForPlaceholder(); boolean enableSearch; if (signParamsActivated != null) { enableSearch = signParamsActivated.booleanValue(); } else { if (configFileActived != null) enableSearch = configFileActived.booleanValue(); else enableSearch = false; } if (enableSearch) { spd = SignaturePlaceholderExtractor.extract( signParameters.getDocument().createInputStream(), signParameters.getPlaceholderId(), signParameters.getPlaceholderMatchMode()); } return spd; } private Signator createSignator(String signatureType) throws SignatorFactoryException { PdfASID signatorId = null; if (signatureType.equals(Constants.SIGNATURE_TYPE_BINARY)) { signatorId = SignatorFactory.MOST_RECENT_BINARY_SIGNATOR_ID; } if (signatureType.equals(Constants.SIGNATURE_TYPE_TEXTUAL)) { signatorId = SignatorFactory.MOST_RECENT_TEXTUAL_SIGNATOR_ID; } if (signatureType.equals(Constants.SIGNATURE_TYPE_DETACHEDTEXTUAL)) { signatorId = SignatorFactory.MOST_RECENT_DETACHEDTEXT_SIGNATOR_ID; } return at.gv.egiz.pdfas.framework.SignatorFactory.createSignator(signatorId); } public SignResult sign(SignParameters signParameters, SignatureDetailInformation signatorInfo) throws PdfAsException { CheckHelper.checkSignParametersForSignAfterPrepare(signParameters, false); if (signParameters.getProfileOverrideProperties() != null) { OverridePropertyHolder.setOverrideProps(signParameters.getProfileOverrideProperties()); } String connectorId = CommandlineConnectorChooser.chooseCommandlineConnectorForSign(signParameters.getSignatureDevice()); ConnectorParameters cp = new ConnectorParameters(); cp.setProfileId(signParameters.getSignatureProfileId()); cp.setSignatureKeyIdentifier(signParameters.getSignatureKeyIdentifier()); Connector c = at.gv.egiz.pdfas.framework.ConnectorFactory.createConnector(connectorId, cp); SignatureData sd = new SignatureDataImpl(new PdfDataSourceAdapter(signatorInfo.getSignatureData()), signatorInfo.getSignatureData().getMimeType()); SignSignatureObject sso = PdfAS.sign(sd, c, signParameters.getTimeStamperImpl()); ((SignatureDetailInformationImpl)signatorInfo).setSignSignatureObject(sso); return finishSign(signParameters, signatorInfo); } public SignResult finishSign(SignParameters signParameters, SignatureDetailInformation signatureDetailInformation) throws PdfAsException { try { CheckHelper.checkSignParametersForSignAfterPrepare(signParameters, true); CheckHelper.checkSignatureDetailInformation(signatureDetailInformation); if (signParameters.getProfileOverrideProperties() != null) { OverridePropertyHolder.setOverrideProps(signParameters.getProfileOverrideProperties()); } Signator signator = createSignator(signParameters.getSignatureType()); SignatorInformation signatorInfo = ((SignatureDetailInformationImpl)signatureDetailInformation).getSignatorInfo(); signator.finishSign(signatorInfo, new DataSinkAdapter(signParameters.getOutput())); return new SignResultImpl( signParameters.getOutput(), signatorInfo.getSignSignatureObject().getX509Certificate(), new ActualSignaturePositionAdapter(signatorInfo.getActualTablePos()), signatorInfo.getNonTextualObjects()); } finally { OverridePropertyHolder.removeProperties(); DynamicSignatureProfileImpl.disposeLocalProfile(); } } }