From 535a04fa05f739ec16dd81666e3b0f82dfbd442d Mon Sep 17 00:00:00 2001 From: tknall Date: Wed, 9 Jan 2013 15:41:29 +0000 Subject: pdf-as-lib maven project files moved to pdf-as-lib git-svn-id: https://joinup.ec.europa.eu/svn/pdf-as/pdf-as/trunk@926 7b5415b0-85f9-ee4d-85bd-d5d0c3b42d1c --- .../mocca/LocRefDetachedMOCCAConnector.java | 623 +++++++++++++++++++++ 1 file changed, 623 insertions(+) create mode 100644 pdf-as-lib/src/main/java/at/knowcenter/wag/egov/egiz/sig/connectors/mocca/LocRefDetachedMOCCAConnector.java (limited to 'pdf-as-lib/src/main/java/at/knowcenter/wag/egov/egiz/sig/connectors/mocca/LocRefDetachedMOCCAConnector.java') diff --git a/pdf-as-lib/src/main/java/at/knowcenter/wag/egov/egiz/sig/connectors/mocca/LocRefDetachedMOCCAConnector.java b/pdf-as-lib/src/main/java/at/knowcenter/wag/egov/egiz/sig/connectors/mocca/LocRefDetachedMOCCAConnector.java new file mode 100644 index 0000000..12fc709 --- /dev/null +++ b/pdf-as-lib/src/main/java/at/knowcenter/wag/egov/egiz/sig/connectors/mocca/LocRefDetachedMOCCAConnector.java @@ -0,0 +1,623 @@ +/** + * 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.knowcenter.wag.egov.egiz.sig.connectors.mocca; + +import java.security.cert.X509Certificate; +import java.util.Properties; +import java.util.regex.Matcher; +import java.util.regex.Pattern; + +import org.apache.commons.logging.Log; +import org.apache.commons.logging.LogFactory; + +import at.gv.egiz.pdfas.algorithmSuite.AlgorithmSuiteObject; +import at.gv.egiz.pdfas.algorithmSuite.AlgorithmSuiteUtil; +import at.gv.egiz.pdfas.api.xmldsig.XMLDsigData; +import at.gv.egiz.pdfas.exceptions.ErrorCode; +import at.gv.egiz.pdfas.framework.ConnectorParameters; +import at.knowcenter.wag.egov.egiz.cfg.SettingsReader; +import at.knowcenter.wag.egov.egiz.exceptions.ConnectorException; +import at.knowcenter.wag.egov.egiz.exceptions.SettingsException; +import at.knowcenter.wag.egov.egiz.sig.SignatureData; +import at.knowcenter.wag.egov.egiz.sig.SignatureResponse; +import at.knowcenter.wag.egov.egiz.sig.connectors.Connector; +import at.knowcenter.wag.egov.egiz.sig.connectors.ConnectorEnvironment; +import at.knowcenter.wag.egov.egiz.sig.connectors.LocalConnector; +import at.knowcenter.wag.egov.egiz.sig.connectors.TemplateReplaces; +import at.knowcenter.wag.egov.egiz.sig.connectors.bku.BKUHelper; +import at.knowcenter.wag.egov.egiz.sig.connectors.bku.BKUPostConnection; +import at.knowcenter.wag.egov.egiz.sig.connectors.bku.SignSignatureObject; +import at.knowcenter.wag.egov.egiz.sig.signaturelayout.SignatureLayoutHandler; +import at.knowcenter.wag.egov.egiz.sig.signaturelayout.SignatureLayoutHandlerFactory; +import at.knowcenter.wag.egov.egiz.tools.CodingHelper; + +/** + * Connector for MOCCA. + * @author tknall + */ +public class LocRefDetachedMOCCAConnector implements Connector, LocalConnector { + //23.11.2010 changed by exthex - added reconstructXMLDsig method and moved xmldsig creation to chooseAndCreateXMLDsig method + + private static Log log = LogFactory.getLog(LocRefDetachedMOCCAConnector.class); + + /** + * The connector parameters. + */ + protected ConnectorParameters params = null; + + /** + * The environment of this connector containing templates. + */ + protected Environment environment = null; + + /** + * Constructor that builds the configuration environment for this connector according to the + * given profile. + * @param connectorParameters The connectot parameters. + * @throws ConnectorException Thrown in case of error. + */ + public LocRefDetachedMOCCAConnector(ConnectorParameters connectorParameters, String loc_ref_content) throws ConnectorException { + this(connectorParameters, loc_ref_content, null); + } + + /** + * Constructor that builds the configuration environment for this connector according to the + * given profile. + * @param connectorParameters The connectot parameters. + * @param algorithmId The algorithm idenifier. + * @throws ConnectorException Thrown in case of error. + */ + public LocRefDetachedMOCCAConnector(ConnectorParameters connectorParameters, String loc_ref_content, String algorithmId) throws ConnectorException { + this.params = connectorParameters; + this.environment = new Environment(this.params.getProfileId(), loc_ref_content, algorithmId); + } + + /** + * Sends the request to the given URL. This method handles communication exceptions. + * The actual send work is done by doPostRequestMultipart. + * @see BKUPostConnection#doPostRequestMultipart(String, String, SignatureData) + * @param url The URL to send the request to. + * @param request_string The request XML. + * @param data The data. + * @return Returns the response properties containing among others the response XML. + * @throws ConnectorException Thrown in case of an error. + */ + protected Properties sendRequest(String url, String request_string, SignatureData data) throws ConnectorException { + try { + Properties response_properties = BKUPostConnection.doPostRequestMultipart(url, request_string, data); + return response_properties; + } catch (Exception e) { + ConnectorException se = new ConnectorException(320, e); + throw se; + } + } + + /** + * Starts a signature process. + * @param data The data to be signed. + * @return Returns the signature object containing the signed data. + * @throws ConnectorException Thrown in case of an error. + */ + public SignSignatureObject doSign(SignatureData data) throws ConnectorException { + log.debug("doSign:"); + + String sign_request_xml = prepareSignRequest(data); + log.debug("sign_request_xml = " + sign_request_xml); + + String url = this.environment.getSignURL(); + Properties response_properties = sendRequest(url, sign_request_xml, data); + + SignSignatureObject sso = analyzeSignResponse(response_properties); + + sso.response_properties = response_properties; + + log.debug("doSign finished."); + return sso; + } + + /** + * Verification is not supported by MOCCA. Therefore this method always throws a + * {@link ConnectorException} with error code {@link ErrorCode#SIGNATURE_VERIFICATION_NOT_SUPPORTED}. + */ + public SignatureResponse doVerify(SignatureData data, SignSignatureObject so, XMLDsigData dsig) throws ConnectorException { + throw new ConnectorException(ErrorCode.SIGNATURE_VERIFICATION_NOT_SUPPORTED, "Signature Verification is not supported by MOCCA."); + } + + /** + * This method analyzes a signature response of the signature device. + * @param response_properties The response elements of the signature device. + * @return The parsed signed signature object. + * @throws ConnectorException Thrown in case of an error. + */ + public SignSignatureObject analyzeSignResponse(Properties response_properties) throws ConnectorException { + log.debug("analyzeSignResponse:"); + String response_string = response_properties.getProperty(BKUPostConnection.RESPONSE_STRING_KEY); + + String bkuIdentifier = BKUHelper.getBKUIdentifier(response_properties); + log.debug("BKU identifier: \"" + bkuIdentifier + "\""); + SignatureLayoutHandler sigLayout; + try { + sigLayout = SignatureLayoutHandlerFactory.getSignatureLayoutHandlerInstance(bkuIdentifier); + } catch (SettingsException e) { + throw new ConnectorException(e.getErrorCode(), e.getMessage()); + } + + BKUHelper.checkResponseForError(response_string); + +// SignSignatureObject so = MOCCAHelper.parseCreateXMLResponse(response_string, new DetachedMOCIdFormatter()); + SignSignatureObject so = sigLayout.parseCreateXMLSignatureResponse(response_string, this.environment); + so.response_properties = response_properties; + log.debug("analyzeSignResponse finished."); + return so; + } + + /** + * Verification is not supported by MOCCA. Therefore this method always throws a + * {@link ConnectorException} with error code {@link ErrorCode#SIGNATURE_VERIFICATION_NOT_SUPPORTED}. + */ + public SignatureResponse analyzeVerifyResponse(Properties response_properties) throws ConnectorException { + throw new ConnectorException(ErrorCode.SIGNATURE_VERIFICATION_NOT_SUPPORTED, "Signature Verification is not supported by MOCCA."); + } + + /** + * Prepares the signature request xml to be sent using the sign request template. + * @param data The signature data. + * @return Returns the sign request xml to be sent. + * @throws ConnectorException Thrown in case of an error. + */ + public String prepareSignRequest(SignatureData data) throws ConnectorException { + log.debug("prepareSignRequestDetached:"); + + String sign_request_template = this.environment.getSignRequestTemplate(); + + String sign_keybox_identifier = this.environment.getSignKeyboxIdentifier(); + String mime_type = data.getMimeType(); + String loc_ref_content = this.environment.getLocRefContent(); + + if (log.isDebugEnabled()) { + log.debug("sign keybox identifier = " + sign_keybox_identifier); + log.debug("mime type = " + mime_type); + log.debug("loc_ref_content = " + loc_ref_content); + } + + String sign_request_xml = sign_request_template.replaceFirst(TemplateReplaces.KEYBOX_IDENTIFIER_REPLACE, sign_keybox_identifier); + sign_request_xml = sign_request_xml.replaceFirst(TemplateReplaces.MIME_TYPE_REPLACE, mime_type); + sign_request_xml = sign_request_xml.replaceFirst(TemplateReplaces.LOC_REF_CONTENT_REPLACE, loc_ref_content); + + log.debug("sign_request_xml = " + sign_request_xml); + log.debug("prepareSignRequestDetached finished."); + return sign_request_xml; + } + + /** + * Verification is not supported by MOCCA. Therefore this method always throws a + * {@link ConnectorException} with error code {@link ErrorCode#SIGNATURE_VERIFICATION_NOT_SUPPORTED}. + */ + public String prepareVerifyRequest(SignatureData data, SignSignatureObject so, XMLDsigData dsigData) throws ConnectorException { + throw new ConnectorException(ErrorCode.SIGNATURE_VERIFICATION_NOT_SUPPORTED, "Signature Verification is not supported by MOCCA."); + } + + /** + * Prepares the xml content of a signature creation request including the link to the signature data. + * @param data The signature data. + * @param so The signature object containing the signature information. + * @return Returns the xml content. + * @throws ConnectorException Thrown in case of an error. + */ + public String prepareXMLContent(SignatureData data, SignSignatureObject so) throws ConnectorException { + log.debug("prepareXMLContent:"); + try { + + String ids_string = so.getSigID(); + String sigId = this.parseSigId(ids_string); + + X509Certificate cert = so.getX509Certificate(); + + + // dferbas + AlgorithmSuiteObject algSuite = new AlgorithmSuiteObject(); + String verify_xml = AlgorithmSuiteUtil.evaluateReplaceAlgs(algSuite, this.environment, so); + + // data digest replace + byte[] data_value_hash = CodingHelper.buildDigest(data.getDataSource(), algSuite.getDataDigestMethod()); + String object_data_hash = CodingHelper.encodeBase64(data_value_hash); + + // template replacements + + verify_xml = verify_xml.replaceFirst(TemplateReplaces.DIGEST_VALUE_SIGNED_DATA_REPLACE, object_data_hash); + verify_xml = verify_xml.replaceFirst(TemplateReplaces.SIGNATURE_VALUE_REPLACE, so.getSignatureValue()); + + // X.509 Certificate replace + byte[] der = cert.getEncoded(); + byte[] cert_hash = CodingHelper.buildDigest(der, algSuite.getCertDigestMethod()); + String certDigest = CodingHelper.encodeBase64(cert_hash); + String x509_cert_string = CodingHelper.encodeBase64(der); + verify_xml = verify_xml.replaceFirst(TemplateReplaces.X509_CERTIFICATE_REPLACE, x509_cert_string); + + // Qualified Properties replaces + verify_xml = verify_xml.replaceAll(TemplateReplaces.SIG_ID_REPLACE, sigId); + verify_xml = verify_xml.replaceFirst(TemplateReplaces.SIGNING_TIME_REPLACE, so.getDate()); + verify_xml = verify_xml.replaceFirst(TemplateReplaces.DIGEST_VALUE_CERTIFICATE_REPLACE, certDigest); + verify_xml = verify_xml.replaceFirst(TemplateReplaces.X509_ISSUER_NAME_REPLACE, so.getIssuer()); + verify_xml = verify_xml.replaceFirst(TemplateReplaces.X509_SERIAL_NUMBER_REPLACE, so.getSerialNumber()); + // SigDataRefReplace already done above + verify_xml = verify_xml.replaceFirst(TemplateReplaces.MIME_TYPE_REPLACE, data.getMimeType()); + + // Signed Properties hash + Pattern spPattern = Pattern.compile("(<(\\w+:)?SignedProperties.*>.*)"); + Matcher matcher = spPattern.matcher(verify_xml); + if (matcher.find()) { + log.debug("SignedProperties found."); + String string_to_be_hashed = matcher.group(1); + log.debug("SignedProperties string to be hashed: " + string_to_be_hashed); + final byte[] bytes_to_be_hashed = string_to_be_hashed.getBytes("UTF-8"); + byte[] sig_prop_code = CodingHelper.buildDigest(bytes_to_be_hashed, algSuite.getPropertiesDigestMethod()); + String sig_prop_hash = CodingHelper.encodeBase64(sig_prop_code); + + verify_xml = verify_xml.replaceFirst(TemplateReplaces.DIGEST_VALUE_SIGNED_PROPERTIES_REPLACE, sig_prop_hash); + } + + log.debug("prepareXMLContent finished."); + return verify_xml; + } catch (Exception e) { + log.debug(e); + throw new ConnectorException(310, e); + } + } + + /** + * Holds environment configuration information like templates. + * @author wprinz + */ + public static class Environment extends ConnectorEnvironment { + + /** + * The configuration key of the sign keybox identifier. + */ + protected static final String SIGN_KEYBOX_IDENTIFIER_KEY = "moc.sign.KeyboxIdentifier"; + + /** + * The configuration key of the sign request template. + */ + protected static final String SIGN_REQUEST_TEMPLATE_KEY = "moc.sign.request.detached"; + + /** + * The configuration key of the sign URL. + */ + protected static final String SIGN_URL_KEY = "moc.sign.url"; + + /** + * BKU template file prefix + */ + protected static final String TEMPLATE_FILE_PREFIX = "/templates/moc."; + + /** + * signing file template suffix + */ + protected static final String SIGN_TEMPLATE_FILE_SUFFIX = ".sign.request.xml"; + + /** + * verifing template file suffix + */ + /* signature verification is not supported by mocca + protected static final String VERIFY_REQUEST_TEMPLATE_FILE_SUFIX = ".verify.request.xml"; + */ + + /** + * verifing file template key suffix + */ + protected static final String VERIFY_TEMPLATE_SUFFIX = ".verify.template.xml"; + + /** + * The configuration key of the verify request template. + */ + /* signature verification is not supported by mocca + protected static final String VERIFY_REQUEST_TEMPLATE_KEY = "moc.verify.request.detached"; + */ + + /** + * The configuration key of the verify template. + */ + protected static final String VERIFY_TEMPLATE_KEY = "moc.verify.template.detached"; + + /** + * The configuration key of the verify URL. + */ + /* signature verification is not supported by mocca + protected static final String xxxVERIFY_URL_KEY = "moc.verify.url"; + */ + + /** + * The configuration key for the ECDSA cert alg property. + */ + protected static final String ECDSA_CERT_ALG_KEY = "cert.alg.ecdsa"; + + /** + * The configuration key for the RSA cert alg property. + */ + protected static final String RSA_CERT_ALG_KEY = "cert.alg.rsa"; + + protected String profile = null; + + protected String loc_ref_content = null; + + protected String sign_keybox_identifier = null; + + protected String sign_request_template = null; + + protected String sign_url = null; + + /* signature verification is not supported by mocca + protected String verify_request_template = null; + */ + + protected String verify_template = null; + + /* signature verification is not supported by mocca + protected String verify_url = null; + */ + + protected String cert_alg_ecdsa = null; + + protected String cert_alg_rsa = null; + + protected String algorithmId = null; + + /** + * Initializes the environment with a given profile. + * @param profile The configuration profile. + * @param algorithmId The algorithm identifer. + * @throws ConnectorException Thrown in case of an error. + */ + public Environment(String profile, String loc_ref_content, String algorithmId) throws ConnectorException { + this.profile = profile; + + this.loc_ref_content = loc_ref_content; + + SettingsReader settings = null; + try { + settings = SettingsReader.getInstance(); + } catch (SettingsException e) { + throw new ConnectorException(300, e); + } + + this.sign_keybox_identifier = getConnectorValueFromProfile(settings, profile, SIGN_KEYBOX_IDENTIFIER_KEY); + + if (algorithmId == null) { + this.algorithmId = settings.getValueFromKey("default.moc.algorithm.id"); + } else { + this.algorithmId = algorithmId; + } + + // SIGN REQUEST + + // try specific file + String sign_request_filename = TEMPLATE_FILE_PREFIX + this.algorithmId + SIGN_TEMPLATE_FILE_SUFFIX; + log.debug("Trying to load specific sign request file " + sign_request_filename); + //this.sign_request_template = FileHelper.readFromFile(SettingsReader.relocateFile(sign_request_filename)); + this.sign_request_template = settings.readInternalResourceAsString(sign_request_filename); + + // try default request file + if (this.sign_request_template == null) { + sign_request_filename = getConnectorValueFromProfile(settings, profile, SIGN_REQUEST_TEMPLATE_KEY); + log.debug("Specific file not found. Trying default sign request file " + sign_request_filename); + //this.sign_request_template = FileHelper.readFromFile(SettingsReader.relocateFile(sign_request_filename)); + this.sign_request_template = settings.readInternalResourceAsString(sign_request_filename); + } + + // request file is needed !!! + if (this.sign_request_template == null) { + throw new ConnectorException(300, "Can not read the create xml request template"); + } + + this.sign_url = getConnectorValueFromProfile(settings, profile, SIGN_URL_KEY); + + + // VERIFY REQUEST + /* signature verification is not supported by mocca + + // try specific file + String verify_request_filename = TEMPLATE_FILE_PREFIX + settings.getValueFromKey("default.moc.algorithm.id") + VERIFY_REQUEST_TEMPLATE_FILE_SUFIX; + log.debug("Trying to load specific verify request file " + verify_request_filename); + this.verify_request_template = FileHelper.readFromFile(SettingsReader.relocateFile(verify_request_filename)); + + // try default request file + if (this.verify_request_template == null) { + verify_request_filename = getConnectorValueFromProfile(settings, profile, VERIFY_REQUEST_TEMPLATE_KEY); + log.debug("Specific file not found. Trying default verify request file " + verify_request_filename); + this.verify_request_template = FileHelper.readFromFile(SettingsReader.relocateFile(verify_request_filename)); + } + + // request file is needed !!! + if (this.verify_request_template == null) { + throw new ConnectorException(ErrorCode.SETTING_NOT_FOUND, "Can not read the verify xml request template"); + } + + */ + + // load template file + // try specific file + String verify_filename = TEMPLATE_FILE_PREFIX + this.algorithmId + VERIFY_TEMPLATE_SUFFIX; + log.debug("Trying to load specific signature template file " + verify_filename); + //this.verify_template = FileHelper.readFromFile(SettingsReader.relocateFile(verify_filename)); + this.verify_template = settings.readInternalResourceAsString(verify_filename); + + // try default signature template file + if (this.verify_template == null) { + verify_filename = getConnectorValueFromProfile(settings, profile, VERIFY_TEMPLATE_KEY); + log.debug("Specific signature template file not found. Trying default signature template file " + verify_filename); + //this.verify_template = FileHelper.readFromFile(SettingsReader.relocateFile(verify_filename)); + this.verify_template = settings.readInternalResourceAsString(verify_filename); + } + + // signature template is needed !!! + if (this.verify_template == null) { + throw new ConnectorException(ErrorCode.SETTING_NOT_FOUND, "Can not read the verify template"); + } + + /* signature verification is not supported by mocca + this.verify_url = getConnectorValueFromProfile(settings, profile, VERIFY_URL_KEY); + */ + + this.cert_alg_ecdsa = settings.getValueFromKey(ECDSA_CERT_ALG_KEY); + + this.cert_alg_rsa = settings.getValueFromKey(RSA_CERT_ALG_KEY); + + } + + /** + * Returns the profile name. + * @return The profile name. + */ + public String getProfile() { + return this.profile; + } + + /** + * Returns the LocRef content. + * + * @return Returns the LocRef content. + */ + public String getLocRefContent() { + return this.loc_ref_content; + } + + /** + * Returns the sign keybox identifier. + * + * @return Returns the sign keybox identifier. + */ + public String getSignKeyboxIdentifier() { + return this.sign_keybox_identifier; + } + + /** + * Returns the sign request template. + * + * @return Returns the sign request template. + */ + public String getSignRequestTemplate() { + return this.sign_request_template; + } + + /** + * Returns the sign URL. + * + * @return Returns the sign URL. + */ + public String getSignURL() { + return this.sign_url; + } + + /** + * Returns the verify request template. + * + * @return Returns the verify request template. + */ + /* signature verification is not supported by mocca + public String getVerifyRequestTemplate() { + return this.verify_request_template; + } + */ + + /** + * Returns the verify template. + * + * @return Returns the verify template. + */ + public String getVerifyTemplate() { + return this.verify_template; + } + + /** + * Returns the verify URL. + * + * @return Returns the verify URL. + */ + /* signature verification is not supported by mocca + public String getVerifyURL() { + return this.verify_url; + } + */ + + /** + * Returns the ecdsa cert alg property. + * + * @return Returns the ecdsa cert alg property. + */ + public String getCertAlgEcdsa() { + return this.cert_alg_ecdsa; + } + + /** + * Returns the rsa cert alg property. + * + * @return Returns the rsa cert alg property. + */ + public String getCertAlgRsa() { + return this.cert_alg_rsa; + } + + /** + * Reads the configuration entry given by the key, first from the given + * profile, if not found from the defaults. + * + * @param settings + * The settings. + * @param profile + * The profile. + * @param key + * The configuration key. + * @return Returns the configuration entry. + */ + public static String getConnectorValueFromProfile(SettingsReader settings, String profile, String key) { + String value = settings.getValueFromKey("sig_obj." + profile + "." + key); //$NON-NLS-2$ + if (value == null) { + value = settings.getValueFromKey(key); + } + return value; + } + } + + /** + * Parses the common part for all id attributes from a given signature parameter string. + * @param sigIdString The given signature parameter string. + * @return The common part of all id attributes. + */ + protected String parseSigId(String sigIdString) { + String[] parts = sigIdString.split("@"); + String result = null; + if (parts != null && parts.length > 1) { + result = parts[1].trim(); + } + return result; + } + + public XMLDsigData reconstructXMLDsig(SignatureData data, SignSignatureObject so) + throws ConnectorException { + String xmldsig = prepareXMLContent(data, so); + return new XMLDsigData(xmldsig, true); + } + +} -- cgit v1.2.3