summaryrefslogtreecommitdiff
path: root/bkucommon/src
diff options
context:
space:
mode:
authorBonato, Martin <martin.bonato@prime-sign.com>2018-02-08 22:19:55 +0100
committerBonato, Martin <martin.bonato@prime-sign.com>2018-02-08 22:19:55 +0100
commitb9ccb62d35a755efb505d426ce924d5a8fbe937a (patch)
tree00d17aa7dc660eb0e90ae753e36a623d672fc0e0 /bkucommon/src
parent84794c877062fe0424f357be0e83bdd045d75d52 (diff)
downloadmocca-b9ccb62d35a755efb505d426ce924d5a8fbe937a.tar.gz
mocca-b9ccb62d35a755efb505d426ce924d5a8fbe937a.tar.bz2
mocca-b9ccb62d35a755efb505d426ce924d5a8fbe937a.zip
BulkSignature implementationfb-bulksignature
Diffstat (limited to 'bkucommon/src')
-rw-r--r--bkucommon/src/main/java/at/gv/egiz/bku/slcommands/BulkCommand.java27
-rw-r--r--bkucommon/src/main/java/at/gv/egiz/bku/slcommands/BulkSignatureResult.java31
-rw-r--r--bkucommon/src/main/java/at/gv/egiz/bku/slcommands/impl/BulkCommandFactory.java40
-rw-r--r--bkucommon/src/main/java/at/gv/egiz/bku/slcommands/impl/BulkCommandImpl.java439
-rw-r--r--bkucommon/src/main/java/at/gv/egiz/bku/slcommands/impl/BulkSignatureResultImpl.java138
-rw-r--r--bkucommon/src/main/java/at/gv/egiz/bku/slcommands/impl/CreateCMSSignatureCommandImpl.java5
-rw-r--r--bkucommon/src/main/java/at/gv/egiz/bku/slcommands/impl/DataObjectHashDataInput.java4
-rw-r--r--bkucommon/src/main/java/at/gv/egiz/bku/slcommands/impl/cms/BulkCollectionSecurityProvider.java114
-rw-r--r--bkucommon/src/main/java/at/gv/egiz/bku/slcommands/impl/cms/BulkSignature.java116
-rw-r--r--bkucommon/src/main/java/at/gv/egiz/bku/slcommands/impl/cms/BulkSignatureInfo.java104
-rw-r--r--bkucommon/src/main/java/at/gv/egiz/bku/slcommands/impl/cms/CMSHashDataInput.java49
-rw-r--r--bkucommon/src/main/java/at/gv/egiz/bku/slcommands/impl/cms/ReferencedHashDataInput.java81
-rw-r--r--bkucommon/src/main/java/at/gv/egiz/bku/slcommands/impl/cms/STALSecurityProvider.java37
-rw-r--r--bkucommon/src/main/java/at/gv/egiz/bku/slcommands/impl/cms/Signature.java187
-rw-r--r--bkucommon/src/main/java/at/gv/egiz/bku/slcommands/impl/xsect/AlgorithmMethodFactory.java6
-rw-r--r--bkucommon/src/main/java/at/gv/egiz/bku/slcommands/impl/xsect/AlgorithmMethodFactoryImpl.java35
-rw-r--r--bkucommon/src/main/java/at/gv/egiz/bku/spring/URLDereferencerFactoryBean.java75
-rw-r--r--bkucommon/src/main/resources/at/gv/egiz/bku/slexceptions/SLExceptionMessages.properties3
-rw-r--r--bkucommon/src/main/resources/at/gv/egiz/bku/slexceptions/SLExceptionMessages_en.properties2
-rw-r--r--bkucommon/src/site/apt/configuration.apt4
-rw-r--r--bkucommon/src/test/java/at/gv/egiz/bku/slcommands/impl/BulkCommandImplTest.java130
-rw-r--r--bkucommon/src/test/java/at/gv/egiz/bku/slcommands/impl/CreateCMSSignatureCommandImplTest.java33
-rw-r--r--bkucommon/src/test/java/at/gv/egiz/bku/slcommands/impl/cms/SignatureTest.java130
-rw-r--r--bkucommon/src/test/java/at/gv/egiz/bku/slcommands/impl/xsect/SignatureTest.java12
-rw-r--r--bkucommon/src/test/java/at/gv/egiz/stal/dummy/DummySTAL.java65
-rw-r--r--bkucommon/src/test/resources/at/gv/egiz/bku/slcommands/bulksignaturerequest/BulkSignatureRequest.xml34
-rw-r--r--bkucommon/src/test/resources/at/gv/egiz/bku/slcommands/bulksignaturerequest/BulkSignatureRequestWithReference.xml37
-rw-r--r--bkucommon/src/test/resources/at/gv/egiz/bku/slcommands/testApplicationContext.xml9
28 files changed, 1826 insertions, 121 deletions
diff --git a/bkucommon/src/main/java/at/gv/egiz/bku/slcommands/BulkCommand.java b/bkucommon/src/main/java/at/gv/egiz/bku/slcommands/BulkCommand.java
new file mode 100644
index 00000000..7deb8e22
--- /dev/null
+++ b/bkucommon/src/main/java/at/gv/egiz/bku/slcommands/BulkCommand.java
@@ -0,0 +1,27 @@
+/*
+ * Copyright 2015 Datentechnik Innovation and Prime Sign GmbH, Austria
+ *
+ * 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.bku.slcommands;
+
+
+public interface BulkCommand extends SLCommand {
+
+}
diff --git a/bkucommon/src/main/java/at/gv/egiz/bku/slcommands/BulkSignatureResult.java b/bkucommon/src/main/java/at/gv/egiz/bku/slcommands/BulkSignatureResult.java
new file mode 100644
index 00000000..8670d635
--- /dev/null
+++ b/bkucommon/src/main/java/at/gv/egiz/bku/slcommands/BulkSignatureResult.java
@@ -0,0 +1,31 @@
+/*
+ * Copyright 2015 Datentechnik Innovation and Prime Sign GmbH, Austria
+ *
+ * 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.bku.slcommands;
+
+import org.w3c.dom.Element;
+
+public interface BulkSignatureResult extends SLResult {
+
+ public Element getContent();
+
+}
diff --git a/bkucommon/src/main/java/at/gv/egiz/bku/slcommands/impl/BulkCommandFactory.java b/bkucommon/src/main/java/at/gv/egiz/bku/slcommands/impl/BulkCommandFactory.java
new file mode 100644
index 00000000..7f7d7f1e
--- /dev/null
+++ b/bkucommon/src/main/java/at/gv/egiz/bku/slcommands/impl/BulkCommandFactory.java
@@ -0,0 +1,40 @@
+/*
+ * Copyright 2015 Datentechnik Innovation and Prime Sign GmbH, Austria
+ *
+ * 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.bku.slcommands.impl;
+
+import javax.xml.bind.JAXBElement;
+
+import at.gv.egiz.bku.slcommands.AbstractSLCommandFactory;
+import at.gv.egiz.bku.slcommands.SLCommand;
+import at.gv.egiz.bku.slexceptions.SLCommandException;
+
+public class BulkCommandFactory extends AbstractSLCommandFactory {
+
+ @Override
+ public SLCommand createSLCommand(JAXBElement<?> element) throws SLCommandException {
+ BulkCommandImpl command = new BulkCommandImpl();
+ command.init(element);
+ command.setConfiguration(configuration);
+ return command;
+ }
+}
diff --git a/bkucommon/src/main/java/at/gv/egiz/bku/slcommands/impl/BulkCommandImpl.java b/bkucommon/src/main/java/at/gv/egiz/bku/slcommands/impl/BulkCommandImpl.java
new file mode 100644
index 00000000..7094e284
--- /dev/null
+++ b/bkucommon/src/main/java/at/gv/egiz/bku/slcommands/impl/BulkCommandImpl.java
@@ -0,0 +1,439 @@
+/*
+ * Copyright 2015 Datentechnik Innovation GmbH and Prime Sign GmbH, Austria
+ *
+ * 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.bku.slcommands.impl;
+
+import iaik.asn1.DerCoder;
+import iaik.asn1.INTEGER;
+import iaik.asn1.SEQUENCE;
+import iaik.asn1.structures.AlgorithmID;
+import iaik.cms.CMSException;
+import iaik.cms.CMSSignatureException;
+import iaik.utils.Util;
+
+import java.math.BigInteger;
+import java.security.InvalidParameterException;
+import java.security.SignatureException;
+import java.security.cert.X509Certificate;
+import java.util.Arrays;
+import java.util.Collections;
+import java.util.Date;
+import java.util.LinkedList;
+import java.util.List;
+
+import org.apache.commons.configuration.Configuration;
+import org.apache.commons.io.FilenameUtils;
+import org.apache.commons.lang.StringUtils;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+import at.buergerkarte.namespaces.securitylayer._1_2_3.BulkRequestType;
+import at.buergerkarte.namespaces.securitylayer._1_2_3.BulkRequestType.CreateSignatureRequest;
+import at.buergerkarte.namespaces.securitylayer._1_2_3.CreateCMSSignatureRequestType;
+import at.buergerkarte.namespaces.securitylayer._1_2_3.ExcludedByteRangeType;
+import at.gv.egiz.bku.conf.MoccaConfigurationFacade;
+import at.gv.egiz.bku.slcommands.BulkCommand;
+import at.gv.egiz.bku.slcommands.SLCommandContext;
+import at.gv.egiz.bku.slcommands.SLResult;
+import at.gv.egiz.bku.slcommands.impl.cms.BulkCollectionSecurityProvider;
+import at.gv.egiz.bku.slcommands.impl.cms.BulkSignature;
+import at.gv.egiz.bku.slcommands.impl.cms.BulkSignatureInfo;
+import at.gv.egiz.bku.slcommands.impl.cms.CMSHashDataInput;
+import at.gv.egiz.bku.slcommands.impl.xsect.STALSignatureException;
+import at.gv.egiz.bku.slexceptions.SLCommandException;
+import at.gv.egiz.bku.slexceptions.SLException;
+import at.gv.egiz.bku.slexceptions.SLRequestException;
+import at.gv.egiz.bku.slexceptions.SLViewerException;
+import at.gv.egiz.stal.BulkSignRequest;
+import at.gv.egiz.stal.BulkSignResponse;
+import at.gv.egiz.stal.ErrorResponse;
+import at.gv.egiz.stal.HashDataInput;
+import at.gv.egiz.stal.InfoboxReadRequest;
+import at.gv.egiz.stal.STALRequest;
+import at.gv.egiz.stal.STALResponse;
+import at.gv.egiz.stal.SignRequest;
+import at.gv.egiz.stal.SignRequest.SignedInfo;
+
+/**
+ * This class implements the security layer command <code>BulkRequest</code>.
+ *
+ * @author szoescher
+ */
+public class BulkCommandImpl extends SLCommandImpl<BulkRequestType> implements BulkCommand {
+
+ private final static String ID_ECSIGTYPE = "1.2.840.10045.4";
+
+ /**
+ * Logging facility.
+ */
+ private final static Logger log = LoggerFactory.getLogger(BulkCommandImpl.class);
+
+ /**
+ * The signing certificate.
+ */
+ protected X509Certificate signingCertificate;
+
+ /**
+ * The keybox identifier of the key used for signing.
+ */
+ protected String keyboxIdentifier;
+
+ /**
+ * The configuration facade used to access the MOCCA configuration.
+ */
+ private ConfigurationFacade configurationFacade = new ConfigurationFacade();
+
+ private class ConfigurationFacade implements MoccaConfigurationFacade {
+ private Configuration configuration;
+
+ public static final String USE_STRONG_HASH = "UseStrongHash";
+
+ public void setConfiguration(Configuration configuration) {
+ this.configuration = configuration;
+ }
+
+ public boolean getUseStrongHash() {
+ return configuration.getBoolean(USE_STRONG_HASH, true);
+ }
+ }
+
+ @Override
+ public String getName() {
+ return "BulkRequest";
+ }
+
+ public void setConfiguration(Configuration configuration) {
+ configurationFacade.setConfiguration(configuration);
+ }
+
+ @Override
+ public SLResult execute(SLCommandContext commandContext) {
+
+ List<BulkSignature> signatures = new LinkedList<BulkSignature>();
+
+ try {
+
+ List<CreateSignatureRequest> signatureRequests = getRequestValue().getCreateSignatureRequest();
+
+
+ List<String> requestIds = new LinkedList<String>();
+
+ if (signatureRequests != null && signatureRequests.size() != 0) {
+
+ BulkCollectionSecurityProvider securityProvider = new BulkCollectionSecurityProvider();
+
+ log.debug("get keyboxIdentifier from BulkSingatureRequest");
+ keyboxIdentifier = setKeyboxIdentifier(signatureRequests);
+
+ log.info("Requesting signing certificate.");
+ signingCertificate = requestSigningCertificate(keyboxIdentifier, commandContext);
+ log.debug("Got signing certificate. {}", signingCertificate);
+
+
+ for (int i=0; i<signatureRequests.size(); i++) {
+
+ CreateSignatureRequest request = signatureRequests.get(i);
+ if (request.getCreateCMSSignatureRequest() != null) {
+ log.info("execute CMSSignature request.");
+
+ requestIds.add(request.getId());
+
+ BulkSignature signature = prepareCMSSignatureRequests(securityProvider, request.getCreateCMSSignatureRequest(),
+ commandContext);
+
+ signatures.add(signature);
+
+ for(HashDataInput hashDataInput : securityProvider.getBulkSignatureInfo().get(i).getHashDataInput()){
+
+ if(hashDataInput instanceof CMSHashDataInput) {
+ CMSHashDataInput cmsHashDataInput = (CMSHashDataInput) hashDataInput;
+ log.debug("setting fileName {}", getFileName(request, i+1));
+ cmsHashDataInput.setFilename(getFileName(request, i+1));
+ cmsHashDataInput.setDigest(signature.getSignerInfo().getDigest());
+ }
+
+
+ }
+ } else {
+ if (request.getCreateXMLSignatureRequest() != null) {
+ log.error("XML signature requests are currently not supported in bulk signature requests.");
+ throw new SLCommandException(4124);
+ }
+ }
+ }
+
+
+ return new BulkSignatureResultImpl(signBulkRequest(securityProvider.getBulkSignatureInfo(), commandContext,
+ signatures), requestIds);
+
+
+
+ }
+
+ } catch (SLException e) {
+ return new ErrorResultImpl(e, commandContext.getLocale());
+
+ } catch (CMSException e) {
+ log.error("Error reading message digest.",e);
+ }
+ return null;
+ }
+
+ private String getFileName(CreateSignatureRequest request, int requestCounter) {
+
+ String referenceURL = null;
+
+ if (request.getCreateCMSSignatureRequest().getDataObject() != null
+ && request.getCreateCMSSignatureRequest().getDataObject().getContent() != null) {
+ referenceURL = request.getCreateCMSSignatureRequest().getDataObject().getContent().getReference();
+ }
+
+ if (StringUtils.isNotEmpty(referenceURL)) {
+ return FilenameUtils.getBaseName(referenceURL);
+ } else {
+
+ StringBuilder fileNameBuilder = new StringBuilder();
+
+ if (StringUtils.isNotEmpty(request.getDisplayName())) {
+ fileNameBuilder.append(request.getDisplayName());
+ } else {
+ fileNameBuilder.append(HashDataInput.DEFAULT_FILENAME);
+ fileNameBuilder.append("_");
+ fileNameBuilder.append(requestCounter);
+ }
+
+ return fileNameBuilder.toString();
+ }
+ }
+
+ private List<byte[]> signBulkRequest(List<BulkSignatureInfo> bulkSignatureInfo, SLCommandContext commandContext,
+ List<BulkSignature> signatures) throws SLCommandException, SLRequestException {
+
+ try {
+
+ List<byte[]> signatureValues;
+
+ BulkSignRequest signRequest = getSTALSignRequest(bulkSignatureInfo);
+
+ // send BulkStalRequest
+ List<STALResponse> responses = commandContext.getSTAL().handleRequest(
+ Collections.singletonList((STALRequest) signRequest));
+
+ if (responses == null || responses.size() != 1) {
+ throw new SignatureException("Failed to access STAL.");
+ }
+
+ STALResponse response = responses.get(0);
+
+ // setSignatureValues from STALResponse
+ if (response instanceof BulkSignResponse) {
+ BulkSignResponse bulkSignatureResponse = ((BulkSignResponse) response);
+
+ signatureValues = new LinkedList<byte[]>();
+ for (int i = 0; i < bulkSignatureResponse.getSignResponse().size(); i++) {
+ byte[] sig = ((BulkSignResponse) response).getSignResponse().get(i).getSignatureValue();
+ log.debug("Got signature response: " + Util.toBase64String(sig));
+ signatures.get(i).getSignerInfo()
+ .setSignatureValue(wrapSignatureValue(sig, bulkSignatureInfo.get(i).getSignatureAlgorithm()));
+ signatureValues.add(signatures.get(i).getEncoded());
+ }
+
+ return signatureValues;
+
+ } else if (response instanceof ErrorResponse) {
+
+ ErrorResponse err = (ErrorResponse) response;
+ log.debug("Error signing bulk request. Error response code: " + err.getErrorCode() + " (" + err.getErrorMessage() + ").");
+ throw new SLCommandException(err.getErrorCode());
+ }
+
+ } catch (SignatureException e) {
+ log.error("Error creating CMSSignature", e);
+ throw new SLCommandException(4000);
+ } catch (CMSException e) {
+ log.error("Error creating CMSSignature", e);
+ }
+ return null;
+ }
+
+ private String setKeyboxIdentifier(List<CreateSignatureRequest> signatureRequests) throws SLCommandException {
+
+ String keyboxIdentifier = null;
+
+ for (CreateSignatureRequest request : signatureRequests) {
+ if (request.getCreateCMSSignatureRequest() != null) {
+
+ if (keyboxIdentifier == null) {
+ keyboxIdentifier = request.getCreateCMSSignatureRequest().getKeyboxIdentifier();
+ } else {
+ if (request.getCreateCMSSignatureRequest().getKeyboxIdentifier() == null) {
+ log.error("No keyboxIdentifier has been specified for this signature request.");
+ throw new SLCommandException(3003);
+
+ } else if (!request.getCreateCMSSignatureRequest().getKeyboxIdentifier().equals(keyboxIdentifier)) {
+
+ log.error("Error creating bulk signature. The bulkSignature value has to be the same fo all signature requests.");
+ throw new SLCommandException(3003);
+ }
+ }
+ }
+ }
+
+
+ return keyboxIdentifier;
+ }
+
+ private BulkSignature prepareCMSSignatureRequests(BulkCollectionSecurityProvider securityProvieder,
+ CreateCMSSignatureRequestType request, SLCommandContext commandContext) throws SLCommandException,
+ SLRequestException, SLViewerException {
+
+ BulkSignature signature;
+
+ // prepare the CMSSignature for signing
+ log.debug("Preparing CMS signature.");
+ signature = prepareCMSSignature(request, commandContext);
+
+ try {
+
+ // update securityProvieder with parameters of the given signature
+ securityProvieder.updateBulkCollectionSecurityProvider(keyboxIdentifier, signature.getHashDataInput(),
+ signature.getExcludedByteRange());
+
+ // prepare the CMSSignatures of the Bulk Request
+ log.debug("Signing CMS signature.");
+
+
+
+ return prepareStalRequest(securityProvieder, signature, commandContext);
+
+ } catch (Exception e) {
+ log.error("Error creating CMS Signature.", e);
+ throw new SLCommandException(4000);
+ }
+
+ }
+
+ private BulkSignature prepareCMSSignature(CreateCMSSignatureRequestType request, SLCommandContext commandContext)
+ throws SLCommandException, SLRequestException {
+
+ // DataObject, SigningCertificate, SigningTime
+ Date signingTime = new Date();
+ try {
+ return new BulkSignature(
+ request.getDataObject() != null ? request.getDataObject() : request.getReferenceObject(),
+ request.getStructure(), signingCertificate, signingTime, commandContext.getURLDereferencer(),
+ configurationFacade.getUseStrongHash());
+ } catch (SLCommandException e) {
+ log.error("Error creating CMS Signature.", e);
+ throw e;
+ } catch (InvalidParameterException e) {
+ log.error("Error creating CMS Signature.", e);
+ throw new SLCommandException(3004);
+ } catch (Exception e) {
+ log.error("Error creating CMS Signature.", e);
+ throw new SLCommandException(4000);
+ }
+ }
+
+ private BulkSignature prepareStalRequest(BulkCollectionSecurityProvider securityProvieder, BulkSignature signature,
+ SLCommandContext commandContext) throws SLCommandException, SLViewerException {
+
+ try {
+
+ signature.sign(securityProvieder, commandContext.getSTAL(), keyboxIdentifier);
+ return signature;
+ } catch (CMSException e) {
+ log.error("Error creating CMSSignature", e);
+ throw new SLCommandException(4000);
+ } catch (CMSSignatureException e) {
+ log.error("Error creating CMSSignature", e);
+ throw new SLCommandException(4000);
+ }
+ }
+
+ private X509Certificate requestSigningCertificate(String keyboxIdentifier, SLCommandContext commandContext)
+ throws SLCommandException {
+
+ InfoboxReadRequest stalRequest = new InfoboxReadRequest();
+ stalRequest.setInfoboxIdentifier(keyboxIdentifier);
+
+ STALHelper stalHelper = new STALHelper(commandContext.getSTAL());
+
+ stalHelper.transmitSTALRequest(Collections.singletonList((STALRequest) stalRequest));
+ List<X509Certificate> certificates = stalHelper.getCertificatesFromResponses();
+ if (certificates == null || certificates.size() != 1) {
+ log.info("Got an unexpected number of certificates from STAL.");
+ throw new SLCommandException(4000);
+ }
+ return signingCertificate = certificates.get(0);
+
+ }
+
+ private static BulkSignRequest getSTALSignRequest(List<BulkSignatureInfo> bulkSignatureInfo) {
+ BulkSignRequest bulkSignRequest = new BulkSignRequest();
+
+ for (int i = 0; i< bulkSignatureInfo.size(); i++) {
+
+ BulkSignatureInfo signatureInfo = bulkSignatureInfo.get(i);
+ SignRequest signRequest = new SignRequest();
+ signRequest.setKeyIdentifier(signatureInfo.getKeyboxIdentifier());
+ log.debug("SignedAttributes: " + Util.toBase64String(signatureInfo.getSignedAttributes()));
+ SignedInfo signedInfo = new SignedInfo();
+ signedInfo.setValue(signatureInfo.getSignedAttributes());
+ signedInfo.setIsCMSSignedAttributes(true);
+ signRequest.setSignedInfo(signedInfo);
+ log.info("set displayName for Request {}", signatureInfo.getHashDataInput().get(0).getFilename());
+ signRequest.setDisplayName(signatureInfo.getHashDataInput().get(0).getFilename());
+ signRequest.setMimeType(signatureInfo.getHashDataInput().get(0).getMimeType());
+
+ signRequest.setSignatureMethod(signatureInfo.getSignatureMethod());
+ signRequest.setDigestMethod(signatureInfo.getDigestMethod());
+ signRequest.setHashDataInput(signatureInfo.getHashDataInput());
+
+ ExcludedByteRangeType excludedByteRange = signatureInfo.getExcludedByteRange();
+ if (excludedByteRange != null) {
+ SignRequest.ExcludedByteRange ebr = new SignRequest.ExcludedByteRange();
+ ebr.setFrom(excludedByteRange.getFrom());
+ ebr.setTo(excludedByteRange.getTo());
+ signRequest.setExcludedByteRange(ebr);
+ }
+
+ bulkSignRequest.getSignRequests().add(signRequest);
+ }
+ return bulkSignRequest;
+ }
+
+ private static byte[] wrapSignatureValue(byte[] sig, AlgorithmID sigAlgorithmID) {
+ String id = sigAlgorithmID.getAlgorithm().getID();
+ if (id.startsWith(ID_ECSIGTYPE)) // X9.62 Format ECDSA signatures
+ {
+ // Wrap r and s in ASN.1 SEQUENCE
+ byte[] r = Arrays.copyOfRange(sig, 0, sig.length / 2);
+ byte[] s = Arrays.copyOfRange(sig, sig.length / 2, sig.length);
+ SEQUENCE sigS = new SEQUENCE();
+ sigS.addComponent(new INTEGER(new BigInteger(1, r)));
+ sigS.addComponent(new INTEGER(new BigInteger(1, s)));
+ return DerCoder.encode(sigS);
+ } else
+ return sig;
+ }
+
+} \ No newline at end of file
diff --git a/bkucommon/src/main/java/at/gv/egiz/bku/slcommands/impl/BulkSignatureResultImpl.java b/bkucommon/src/main/java/at/gv/egiz/bku/slcommands/impl/BulkSignatureResultImpl.java
new file mode 100644
index 00000000..2a88b6be
--- /dev/null
+++ b/bkucommon/src/main/java/at/gv/egiz/bku/slcommands/impl/BulkSignatureResultImpl.java
@@ -0,0 +1,138 @@
+/*
+ * Copyright 2015 Datentechnik Innovation and Prime Sign GmbH, Austria
+ *
+ * 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.bku.slcommands.impl;
+
+import java.util.List;
+
+import javax.xml.bind.JAXBElement;
+import javax.xml.bind.JAXBException;
+import javax.xml.bind.Marshaller;
+import javax.xml.transform.Result;
+import javax.xml.transform.Templates;
+import javax.xml.transform.dom.DOMResult;
+
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+import org.w3c.dom.Document;
+import org.w3c.dom.Element;
+
+import at.buergerkarte.namespaces.securitylayer._1_2_3.BulkResponseType;
+import at.buergerkarte.namespaces.securitylayer._1_2_3.BulkResponseType.CreateSignatureResponse;
+import at.buergerkarte.namespaces.securitylayer._1_2_3.CreateCMSSignatureResponseType;
+import at.buergerkarte.namespaces.securitylayer._1_2_3.ObjectFactory;
+import at.gv.egiz.bku.slcommands.BulkSignatureResult;
+import at.gv.egiz.bku.slcommands.SLMarshallerFactory;
+import at.gv.egiz.bku.slexceptions.SLRuntimeException;
+
+/**
+ * This implements the result of the security layer command
+ * <code>BulkRequest</code>.
+ *
+ * @author szoescher
+ */
+public class BulkSignatureResultImpl extends SLResultImpl implements BulkSignatureResult {
+
+ /**
+ * Logging facility.
+ */
+ private final Logger log = LoggerFactory.getLogger(BulkSignatureResultImpl.class);
+
+ /**
+ * The CMSSignatures data.
+ */
+ protected List<byte[]> signatures;
+
+
+ protected List<String> requestIds;
+
+
+ /**
+ * The BulkResponse.
+ */
+ private Element content;
+
+ /**
+ * Creates a new instance of this BulkSignatureResultImpl with the given
+ * signatures <code>signatures</code>.
+ */
+ public BulkSignatureResultImpl(List<byte[]> signatures, List<String> requestIds) {
+ super();
+
+ if (signatures == null || signatures.size() == 0)
+ throw new NullPointerException("Argument 'signature' must not be null.");
+ this.signatures = signatures;
+
+ this.requestIds = requestIds;
+
+ marshallBulkSignatureResponse();
+ }
+
+ /**
+ * Marshalls the <code>BulkResponseType</code>.
+ */
+ private void marshallBulkSignatureResponse() {
+
+ ObjectFactory factory = new ObjectFactory();
+
+ BulkResponseType bulkResponseType = factory.createBulkResponseType();
+
+ for (int i=0; i< signatures.size(); i++) {
+
+ byte[] signature = signatures.get(i);
+ CreateSignatureResponse createSignatureResponse = factory.createBulkResponseTypeCreateSignatureResponse();
+
+ if (requestIds.get(i) != null) {
+ createSignatureResponse.setId(requestIds.get(i));
+ }
+ CreateCMSSignatureResponseType createCreateCMSSignatureResponseType = factory
+ .createCreateCMSSignatureResponseType();
+ createCreateCMSSignatureResponseType.setCMSSignature(signature);
+ createSignatureResponse.setCreateCMSSignatureResponse(createCreateCMSSignatureResponseType);
+ bulkResponseType.getCreateSignatureResponse().add(createSignatureResponse);
+
+
+ }
+
+ JAXBElement<BulkResponseType> createBulkResponse = factory.createBulkResponse(bulkResponseType);
+ DOMResult res = new DOMResult();
+
+ Marshaller marshaller = SLMarshallerFactory.getInstance().createMarshaller(false);
+
+ try {
+ marshaller.marshal(createBulkResponse, res);
+ } catch (JAXBException e) {
+ log.error("Failed to marshall 'createBulkResponse'.", e);
+ throw new SLRuntimeException(e);
+ }
+ content = ((Document) res.getNode()).getDocumentElement();
+ }
+
+ @Override
+ public void writeTo(Result result, Templates templates, boolean fragment) {
+ writeTo(content, result, templates, fragment);
+ }
+
+ @Override
+ public Element getContent() {
+ return content;
+ }
+}
diff --git a/bkucommon/src/main/java/at/gv/egiz/bku/slcommands/impl/CreateCMSSignatureCommandImpl.java b/bkucommon/src/main/java/at/gv/egiz/bku/slcommands/impl/CreateCMSSignatureCommandImpl.java
index eaf3e70a..93e0eee8 100644
--- a/bkucommon/src/main/java/at/gv/egiz/bku/slcommands/impl/CreateCMSSignatureCommandImpl.java
+++ b/bkucommon/src/main/java/at/gv/egiz/bku/slcommands/impl/CreateCMSSignatureCommandImpl.java
@@ -123,8 +123,9 @@ public class CreateCMSSignatureCommandImpl extends
// DataObject, SigningCertificate, SigningTime
Date signingTime = request.isPAdESCompatibility() ? null : new Date();
- signature = new Signature(request.getDataObject(), request.getStructure(),
- signingCertificate, signingTime, commandContext.getURLDereferencer(),
+ signature = new Signature(request.getDataObject() != null ? request.getDataObject()
+ : request.getReferenceObject(), request.getStructure(), signingCertificate, signingTime,
+ commandContext.getURLDereferencer(),
configurationFacade.getUseStrongHash());
}
} catch (SLCommandException e) {
diff --git a/bkucommon/src/main/java/at/gv/egiz/bku/slcommands/impl/DataObjectHashDataInput.java b/bkucommon/src/main/java/at/gv/egiz/bku/slcommands/impl/DataObjectHashDataInput.java
index d0451138..74a0b4da 100644
--- a/bkucommon/src/main/java/at/gv/egiz/bku/slcommands/impl/DataObjectHashDataInput.java
+++ b/bkucommon/src/main/java/at/gv/egiz/bku/slcommands/impl/DataObjectHashDataInput.java
@@ -76,4 +76,8 @@ public class DataObjectHashDataInput implements HashDataInput {
return dataObject.getFilename();
}
+ @Override
+ public byte[] getDigest() {
+ return dataObject.getReference().getDigestValue();
+ }
}
diff --git a/bkucommon/src/main/java/at/gv/egiz/bku/slcommands/impl/cms/BulkCollectionSecurityProvider.java b/bkucommon/src/main/java/at/gv/egiz/bku/slcommands/impl/cms/BulkCollectionSecurityProvider.java
new file mode 100644
index 00000000..6bbdc682
--- /dev/null
+++ b/bkucommon/src/main/java/at/gv/egiz/bku/slcommands/impl/cms/BulkCollectionSecurityProvider.java
@@ -0,0 +1,114 @@
+/*
+ * Copyright 2015 Datentechnik Innovation GmbH and Prime Sign GmbH, Austria
+ *
+ * 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.bku.slcommands.impl.cms;
+
+import iaik.asn1.structures.AlgorithmID;
+import iaik.cms.IaikProvider;
+
+import java.security.InvalidKeyException;
+import java.security.NoSuchAlgorithmException;
+import java.security.PrivateKey;
+import java.security.SignatureException;
+import java.util.ArrayList;
+import java.util.LinkedList;
+import java.util.List;
+
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+import at.buergerkarte.namespaces.securitylayer._1_2_3.ExcludedByteRangeType;
+import at.gv.egiz.stal.HashDataInput;
+
+
+/**
+ * This security Provider is used to collect multiple sign Requests to create one Stal BulkRequest.
+ * The related signature parameters are stored as a List of <code>BulkSignatureInfo</code>.
+ * @author szoescher
+ *
+ */
+public class BulkCollectionSecurityProvider extends IaikProvider {
+
+ private final static Logger log = LoggerFactory.getLogger(BulkCollectionSecurityProvider.class);
+
+ private String keyboxIdentifier;
+ private List<HashDataInput> hashDataInput;
+ private ExcludedByteRangeType excludedByteRange;
+
+ private List<BulkSignatureInfo> bulkSignatureInfo;
+
+
+ public BulkCollectionSecurityProvider() {
+ bulkSignatureInfo = new LinkedList<BulkSignatureInfo>();
+ }
+
+ public BulkCollectionSecurityProvider(String keyboxIdentifier, HashDataInput hashDataInput,
+ ExcludedByteRangeType excludedByteRange) {
+
+ bulkSignatureInfo = new LinkedList<BulkSignatureInfo>();
+ updateBulkCollectionSecurityProvider(keyboxIdentifier, hashDataInput, excludedByteRange);
+
+ }
+
+ public void updateBulkCollectionSecurityProvider(String keyboxIdentifier, HashDataInput hashDataInput,
+ ExcludedByteRangeType excludedByteRange) {
+
+ this.keyboxIdentifier = keyboxIdentifier;
+ this.hashDataInput = new ArrayList<HashDataInput>();
+ this.hashDataInput.add(hashDataInput);
+ this.excludedByteRange = excludedByteRange;
+
+ }
+
+ /* (non-Javadoc)
+ * @see iaik.cms.IaikProvider#calculateSignatureFromSignedAttributes(iaik.asn1.structures.AlgorithmID, iaik.asn1.structures.AlgorithmID, java.security.PrivateKey, byte[])
+ */
+ @Override
+ public byte[] calculateSignatureFromSignedAttributes(AlgorithmID signatureAlgorithm,
+ AlgorithmID digestAlgorithm, PrivateKey privateKey,
+ byte[] signedAttributes)
+ throws SignatureException, InvalidKeyException, NoSuchAlgorithmException {
+ log.debug("calculateSignatureFromSignedAttributes: " + signatureAlgorithm + ", " + digestAlgorithm);
+
+
+ STALPrivateKey spk = (STALPrivateKey) privateKey;
+
+ //Store signature information that is required to create a StalBulkSignatureRequest.
+ bulkSignatureInfo.add(new BulkSignatureInfo(privateKey, signatureAlgorithm, keyboxIdentifier, signedAttributes,
+ spk.getAlgorithm(), spk.getDigestAlgorithm(), hashDataInput, excludedByteRange));
+
+ //Size of placeholder doesn't matter
+ byte[] signaturePlaceholder = new byte[1];
+ return signaturePlaceholder;
+ }
+
+public List<BulkSignatureInfo> getBulkSignatureInfo() {
+ return bulkSignatureInfo;
+}
+
+
+
+
+
+
+}
diff --git a/bkucommon/src/main/java/at/gv/egiz/bku/slcommands/impl/cms/BulkSignature.java b/bkucommon/src/main/java/at/gv/egiz/bku/slcommands/impl/cms/BulkSignature.java
new file mode 100644
index 00000000..bf220034
--- /dev/null
+++ b/bkucommon/src/main/java/at/gv/egiz/bku/slcommands/impl/cms/BulkSignature.java
@@ -0,0 +1,116 @@
+/*
+ * Copyright 2015 Datentechnik Innovation GmbH and Prime Sign GmbH, Austria
+ *
+ * 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.bku.slcommands.impl.cms;
+
+import iaik.asn1.CodingException;
+import iaik.cms.CMSException;
+import iaik.cms.CMSSignatureException;
+import iaik.cms.ContentInfo;
+import iaik.cms.SecurityProvider;
+import iaik.cms.SignedData;
+import iaik.cms.SignerInfo;
+import iaik.x509.X509ExtensionException;
+
+import java.io.IOException;
+import java.security.InvalidParameterException;
+import java.security.NoSuchAlgorithmException;
+import java.security.cert.CertificateEncodingException;
+import java.security.cert.CertificateException;
+import java.security.cert.X509Certificate;
+import java.util.Date;
+
+import at.buergerkarte.namespaces.securitylayer._1_2_3.CMSDataObjectOptionalMetaType;
+import at.buergerkarte.namespaces.securitylayer._1_2_3.ExcludedByteRangeType;
+import at.gv.egiz.bku.slexceptions.SLCommandException;
+import at.gv.egiz.bku.utils.urldereferencer.URLDereferencer;
+import at.gv.egiz.stal.STAL;
+
+/**
+ * This class represents a CMS-Signature as to be created by the
+ * security layer command <code>BulkSignatureRequest</code>.
+ *
+ * @author szoescher
+ */
+public class BulkSignature extends Signature {
+
+ public final static String ID_AA_ETS_MIMETYPE = "0.4.0.1733.2.1";
+
+ public BulkSignature(CMSDataObjectOptionalMetaType dataObject, String structure,
+ X509Certificate signingCertificate, Date signingTime, URLDereferencer urlDereferencer,
+ boolean useStrongHash)
+ throws NoSuchAlgorithmException, CertificateEncodingException,
+ CertificateException, X509ExtensionException, InvalidParameterException,
+ CodingException, SLCommandException, IOException, CMSException {
+ super(dataObject, structure, signingCertificate, signingTime, urlDereferencer, useStrongHash);
+ }
+
+ /**
+ * Additionally to the <code>sign()<code> method from the supertype,
+ * contains a additional parameter to set a custom securityProvider.
+ * @param securityProvider The Security Provider that handles the sign request.
+ */
+ public byte[] sign(SecurityProvider securityProvider, STAL stal, String keyboxIdentifier) throws CMSException, CMSSignatureException, SLCommandException {
+ signedData.setSecurityProvider(securityProvider);
+ try {
+ signedData.addSignerInfo(signerInfo);
+ } catch (NoSuchAlgorithmException e) {
+ throw new CMSSignatureException(e);
+ }
+ if (digestValue != null) {
+ try {
+ signedData.setMessageDigest(digestAlgorithm, digestValue);
+ } catch (NoSuchAlgorithmException e) {
+ throw new CMSSignatureException(e);
+ }
+ }
+ ContentInfo contentInfo = new ContentInfo(signedData);
+ return contentInfo.getEncoded();
+ }
+
+
+ public ExcludedByteRangeType getExcludedByteRange() {
+ return excludedByteRange;
+ }
+
+ public SignerInfo getSignerInfo() {
+ return signerInfo;
+ }
+
+ public void setSignerInfo(SignerInfo signerInfo) {
+ this.signerInfo = signerInfo;
+ }
+
+
+ public SignedData getSignedData() {
+ return signedData;
+ }
+
+ public byte[] getEncoded() throws CMSException{
+ ContentInfo contentInfo = new ContentInfo(signedData);
+ return contentInfo.getEncoded();
+ }
+
+
+}
+
diff --git a/bkucommon/src/main/java/at/gv/egiz/bku/slcommands/impl/cms/BulkSignatureInfo.java b/bkucommon/src/main/java/at/gv/egiz/bku/slcommands/impl/cms/BulkSignatureInfo.java
new file mode 100644
index 00000000..1d918f9f
--- /dev/null
+++ b/bkucommon/src/main/java/at/gv/egiz/bku/slcommands/impl/cms/BulkSignatureInfo.java
@@ -0,0 +1,104 @@
+/*
+ * Copyright 2015 Datentechnik Innovation GmbH and Prime Sign GmbH, Austria
+ *
+ * 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.bku.slcommands.impl.cms;
+
+import iaik.asn1.structures.AlgorithmID;
+
+import java.security.PrivateKey;
+import java.util.List;
+
+import at.buergerkarte.namespaces.securitylayer._1_2_3.ExcludedByteRangeType;
+import at.gv.egiz.stal.HashDataInput;
+
+
+/**
+ *
+ * @author szoescher
+ *
+ */
+public class BulkSignatureInfo {
+
+ AlgorithmID signatureAlgorithm;
+
+ String keyboxIdentifier;
+
+ byte[] signedAttributes;
+
+ String signatureMethod;
+
+ String digestMethod;
+
+ List<HashDataInput> hashDataInput;
+
+ ExcludedByteRangeType excludedByteRange;
+
+ PrivateKey privateKey;
+
+ public BulkSignatureInfo(PrivateKey privateKey, AlgorithmID signatureAlgorithm, String keyboxIdentifier,
+ byte[] signedAttributes, String signatureMethod, String digestMethod, List<HashDataInput> hashDataInput,
+ ExcludedByteRangeType excludedByteRange) {
+ this.privateKey = privateKey;
+ this.signatureAlgorithm = signatureAlgorithm;
+ this.keyboxIdentifier = keyboxIdentifier;
+ this.signedAttributes = signedAttributes;
+ this.signatureMethod = signatureMethod;
+ this.digestMethod = digestMethod;
+ this.hashDataInput = hashDataInput;
+ this.excludedByteRange = excludedByteRange;
+ }
+
+ public String getKeyboxIdentifier() {
+ return keyboxIdentifier;
+ }
+
+ public byte[] getSignedAttributes() {
+ return signedAttributes;
+ }
+
+ public String getSignatureMethod() {
+ return signatureMethod;
+ }
+
+ public String getDigestMethod() {
+ return digestMethod;
+ }
+
+ public List<HashDataInput> getHashDataInput() {
+ return hashDataInput;
+ }
+
+ public ExcludedByteRangeType getExcludedByteRange() {
+ return excludedByteRange;
+ }
+
+ public AlgorithmID getSignatureAlgorithm() {
+ return signatureAlgorithm;
+ }
+
+ public PrivateKey getPrivateKey() {
+ return privateKey;
+ }
+
+
+
+
+}
diff --git a/bkucommon/src/main/java/at/gv/egiz/bku/slcommands/impl/cms/CMSHashDataInput.java b/bkucommon/src/main/java/at/gv/egiz/bku/slcommands/impl/cms/CMSHashDataInput.java
index e51c5823..25162dc4 100644
--- a/bkucommon/src/main/java/at/gv/egiz/bku/slcommands/impl/cms/CMSHashDataInput.java
+++ b/bkucommon/src/main/java/at/gv/egiz/bku/slcommands/impl/cms/CMSHashDataInput.java
@@ -25,6 +25,7 @@
package at.gv.egiz.bku.slcommands.impl.cms;
import java.io.ByteArrayInputStream;
+import java.io.IOException;
import java.io.InputStream;
import at.gv.egiz.bku.gui.viewer.MimeTypes;
@@ -32,18 +33,33 @@ import at.gv.egiz.stal.HashDataInput;
public class CMSHashDataInput implements HashDataInput {
- private final static String DEFAULT_FILENAME = "SignatureData";
+ public final static String DEFAULT_FILENAME = "SignatureData";
private byte[] data;
- private String mimeType;
+ private byte[] digest;
+ protected String mimeType;
+ private String referenceId;
+ private String fileName;
public CMSHashDataInput(byte[] data, String mimeType) {
this.data = data;
this.mimeType = mimeType;
}
+ public CMSHashDataInput(byte[] data, String mimeType, byte[] digest) {
+ this.data = data;
+ this.mimeType = mimeType;
+ }
+
+ public CMSHashDataInput() {
+ }
+
@Override
public String getReferenceId() {
+
+ if (referenceId != null) {
+ return referenceId;
+ }
return CMS_DEF_REFERENCE_ID;
}
@@ -59,11 +75,38 @@ public class CMSHashDataInput implements HashDataInput {
@Override
public String getFilename() {
+ if (fileName != null) {
+ return fileName;
+ }
+
+ if (mimeType != null) {
return DEFAULT_FILENAME + MimeTypes.getExtension(mimeType);
}
+ return DEFAULT_FILENAME;
+ }
+
@Override
- public InputStream getHashDataInput() {
+ public InputStream getHashDataInput() throws IOException {
return new ByteArrayInputStream(data);
}
+
+ @Override
+ public byte[] getDigest() {
+ return digest;
+ }
+
+
+ public void setFilename(String fileName) {
+ this.fileName = fileName;
+ }
+
+ public void setDigest(byte[] digest) {
+ this.digest = digest;
+ }
+
+ public void setReferenceId(String referenceId) {
+ this.referenceId = referenceId;
+ }
+
}
diff --git a/bkucommon/src/main/java/at/gv/egiz/bku/slcommands/impl/cms/ReferencedHashDataInput.java b/bkucommon/src/main/java/at/gv/egiz/bku/slcommands/impl/cms/ReferencedHashDataInput.java
new file mode 100644
index 00000000..96e0e7de
--- /dev/null
+++ b/bkucommon/src/main/java/at/gv/egiz/bku/slcommands/impl/cms/ReferencedHashDataInput.java
@@ -0,0 +1,81 @@
+/*
+ * Copyright 2015 Datentechnik Innovation GmbH and Prime Sign GmbH, Austria
+ *
+ * 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.bku.slcommands.impl.cms;
+
+import java.io.ByteArrayInputStream;
+import java.io.IOException;
+import java.io.InputStream;
+
+import org.apache.commons.io.IOUtils;
+import org.apache.commons.lang.ArrayUtils;
+
+import at.buergerkarte.namespaces.securitylayer._1_2_3.ExcludedByteRangeType;
+import at.gv.egiz.bku.utils.urldereferencer.URLDereferencer;
+
+public class ReferencedHashDataInput extends CMSHashDataInput {
+
+ private String urlReference;
+ private URLDereferencer urlDereferencer;
+ private ExcludedByteRangeType excludedByteRange;
+
+ public ReferencedHashDataInput(String mimeType, URLDereferencer urlDereferencer, String urlReference, ExcludedByteRangeType excludedByteRange) {
+ super(null, mimeType);
+ this.urlDereferencer = urlDereferencer;
+ this.urlReference = urlReference;
+ this.excludedByteRange = excludedByteRange;
+ }
+
+
+ public URLDereferencer getUrlDereferencer() {
+ return urlDereferencer;
+ }
+
+
+ public void setUrlDereferencer(URLDereferencer urlDereferencer) {
+ this.urlDereferencer = urlDereferencer;
+ }
+
+ public InputStream getHashDataInput() throws IOException {
+
+ InputStream hashDataInputStream = urlDereferencer.dereference(urlReference).getStream();
+
+ try {
+ byte[] content = IOUtils.toByteArray(hashDataInputStream);
+
+ if (excludedByteRange != null) {
+
+ int from = excludedByteRange.getFrom().intValue();
+ int to = excludedByteRange.getTo().intValue();
+
+ byte[] signedContent = ArrayUtils.addAll(ArrayUtils.subarray(content, 0, from), ArrayUtils.subarray(content, to, content.length));
+
+ return new ByteArrayInputStream(signedContent);
+
+ } else {
+ return new ByteArrayInputStream(content);
+ }
+
+ } finally {
+ hashDataInputStream.close();
+ }
+ }
+}
diff --git a/bkucommon/src/main/java/at/gv/egiz/bku/slcommands/impl/cms/STALSecurityProvider.java b/bkucommon/src/main/java/at/gv/egiz/bku/slcommands/impl/cms/STALSecurityProvider.java
index 87c00644..1dd6cc9e 100644
--- a/bkucommon/src/main/java/at/gv/egiz/bku/slcommands/impl/cms/STALSecurityProvider.java
+++ b/bkucommon/src/main/java/at/gv/egiz/bku/slcommands/impl/cms/STALSecurityProvider.java
@@ -69,8 +69,8 @@ public class STALSecurityProvider extends IaikProvider {
private ExcludedByteRangeType excludedByteRange;
private STALSignatureException stalSignatureException;
- public STALSecurityProvider(STAL stal, String keyboxIdentifier,
- HashDataInput hashDataInput, ExcludedByteRangeType excludedByteRange) {
+ public STALSecurityProvider(STAL stal, String keyboxIdentifier, HashDataInput hashDataInput,
+ ExcludedByteRangeType excludedByteRange) {
this.keyboxIdentifier = keyboxIdentifier;
this.stal = stal;
this.hashDataInput = new ArrayList<HashDataInput>();
@@ -78,23 +78,27 @@ public class STALSecurityProvider extends IaikProvider {
this.excludedByteRange = excludedByteRange;
}
- /* (non-Javadoc)
- * @see iaik.cms.IaikProvider#calculateSignatureFromSignedAttributes(iaik.asn1.structures.AlgorithmID, iaik.asn1.structures.AlgorithmID, java.security.PrivateKey, byte[])
+ /*
+ * (non-Javadoc)
+ *
+ * @see
+ * iaik.cms.IaikProvider#calculateSignatureFromSignedAttributes(iaik.asn1.
+ * structures.AlgorithmID, iaik.asn1.structures.AlgorithmID,
+ * java.security.PrivateKey, byte[])
*/
@Override
- public byte[] calculateSignatureFromSignedAttributes(AlgorithmID signatureAlgorithm,
- AlgorithmID digestAlgorithm, PrivateKey privateKey,
- byte[] signedAttributes)
- throws SignatureException, InvalidKeyException, NoSuchAlgorithmException {
+ public byte[] calculateSignatureFromSignedAttributes(AlgorithmID signatureAlgorithm, AlgorithmID digestAlgorithm,
+ PrivateKey privateKey, byte[] signedAttributes) throws SignatureException, InvalidKeyException,
+ NoSuchAlgorithmException {
+ stalSignatureException = null;
log.debug("calculateSignatureFromSignedAttributes: " + signatureAlgorithm + ", " + digestAlgorithm);
STALPrivateKey spk = (STALPrivateKey) privateKey;
- SignRequest signRequest = getSTALSignRequest(keyboxIdentifier, signedAttributes,
- spk.getAlgorithm(), spk.getDigestAlgorithm(), hashDataInput, excludedByteRange);
+ SignRequest signRequest = getSTALSignRequest(keyboxIdentifier, signedAttributes, spk.getAlgorithm(),
+ spk.getDigestAlgorithm(), hashDataInput, excludedByteRange);
log.debug("Sending STAL request ({})", privateKey.getAlgorithm());
- List<STALResponse> responses =
- stal.handleRequest(Collections.singletonList((STALRequest) signRequest));
+ List<STALResponse> responses = stal.handleRequest(Collections.singletonList((STALRequest) signRequest));
if (responses == null || responses.size() != 1) {
throw new SignatureException("Failed to access STAL.");
@@ -114,9 +118,9 @@ public class STALSecurityProvider extends IaikProvider {
}
}
- private static SignRequest getSTALSignRequest(String keyboxIdentifier,
- byte[] signedAttributes, String signatureMethod, String digestMethod,
- List<HashDataInput> hashDataInput, ExcludedByteRangeType excludedByteRange) {
+ private static SignRequest getSTALSignRequest(String keyboxIdentifier, byte[] signedAttributes,
+ String signatureMethod, String digestMethod, List<HashDataInput> hashDataInput,
+ ExcludedByteRangeType excludedByteRange) {
SignRequest signRequest = new SignRequest();
signRequest.setKeyIdentifier(keyboxIdentifier);
log.debug("SignedAttributes: " + Util.toBase64String(signedAttributes));
@@ -147,8 +151,7 @@ public class STALSecurityProvider extends IaikProvider {
sigS.addComponent(new INTEGER(new BigInteger(1, r)));
sigS.addComponent(new INTEGER(new BigInteger(1, s)));
return DerCoder.encode(sigS);
- }
- else
+ } else
return sig;
}
diff --git a/bkucommon/src/main/java/at/gv/egiz/bku/slcommands/impl/cms/Signature.java b/bkucommon/src/main/java/at/gv/egiz/bku/slcommands/impl/cms/Signature.java
index 7be546de..4a94ca7f 100644
--- a/bkucommon/src/main/java/at/gv/egiz/bku/slcommands/impl/cms/Signature.java
+++ b/bkucommon/src/main/java/at/gv/egiz/bku/slcommands/impl/cms/Signature.java
@@ -24,48 +24,32 @@
package at.gv.egiz.bku.slcommands.impl.cms;
-import iaik.asn1.ASN1Object;
-import iaik.asn1.CodingException;
-import iaik.asn1.ObjectID;
-import iaik.asn1.SEQUENCE;
-import iaik.asn1.UTF8String;
-import iaik.asn1.structures.AlgorithmID;
-import iaik.asn1.structures.Attribute;
-import iaik.asn1.structures.ChoiceOfTime;
-import iaik.cms.CMSException;
-import iaik.cms.CMSSignatureException;
-import iaik.cms.CertificateIdentifier;
-import iaik.cms.ContentInfo;
-import iaik.cms.IssuerAndSerialNumber;
-import iaik.cms.SignedData;
-import iaik.cms.SignerInfo;
-import iaik.smime.ess.ESSCertID;
-import iaik.smime.ess.ESSCertIDv2;
-import iaik.x509.X509ExtensionException;
-
import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.io.InputStream;
+import java.net.URI;
+import java.net.URISyntaxException;
import java.security.InvalidParameterException;
import java.security.NoSuchAlgorithmException;
import java.security.PrivateKey;
-import java.security.PublicKey;
import java.security.cert.CertificateEncodingException;
import java.security.cert.CertificateException;
import java.security.cert.X509Certificate;
-import java.security.interfaces.ECPublicKey;
-import java.security.interfaces.RSAPublicKey;
-import java.security.spec.ECParameterSpec;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Date;
import java.util.List;
+import javax.xml.crypto.dsig.DigestMethod;
+
import org.apache.commons.lang.ArrayUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
+import org.w3._2000._09.xmldsig_.DigestMethodType;
+import at.buergerkarte.namespaces.securitylayer._1_2_3.CMSDataObjectOptionalMetaType;
import at.buergerkarte.namespaces.securitylayer._1_2_3.CMSDataObjectRequiredMetaType;
+import at.buergerkarte.namespaces.securitylayer._1_2_3.DigestAndRefType;
import at.buergerkarte.namespaces.securitylayer._1_2_3.ExcludedByteRangeType;
import at.gv.egiz.bku.slcommands.impl.xsect.AlgorithmMethodFactory;
import at.gv.egiz.bku.slcommands.impl.xsect.AlgorithmMethodFactoryImpl;
@@ -74,6 +58,24 @@ import at.gv.egiz.bku.slexceptions.SLCommandException;
import at.gv.egiz.bku.utils.urldereferencer.URLDereferencer;
import at.gv.egiz.stal.HashDataInput;
import at.gv.egiz.stal.STAL;
+import iaik.asn1.ASN1Object;
+import iaik.asn1.CodingException;
+import iaik.asn1.ObjectID;
+import iaik.asn1.SEQUENCE;
+import iaik.asn1.UTF8String;
+import iaik.asn1.structures.AlgorithmID;
+import iaik.asn1.structures.Attribute;
+import iaik.asn1.structures.ChoiceOfTime;
+import iaik.cms.CMSException;
+import iaik.cms.CMSSignatureException;
+import iaik.cms.CertificateIdentifier;
+import iaik.cms.ContentInfo;
+import iaik.cms.IssuerAndSerialNumber;
+import iaik.cms.SignedData;
+import iaik.cms.SignerInfo;
+import iaik.smime.ess.ESSCertID;
+import iaik.smime.ess.ESSCertIDv2;
+import iaik.x509.X509ExtensionException;
/**
* This class represents a CMS-Signature as to be created by the
@@ -90,25 +92,51 @@ public class Signature {
*/
private final Logger log = LoggerFactory.getLogger(Signature.class);
- private SignedData signedData;
- private SignerInfo signerInfo;
- private byte[] signedDocument;
- private String mimeType;
- private AlgorithmID signatureAlgorithm;
- private AlgorithmID digestAlgorithm;
- private String signatureAlgorithmURI;
- private String digestAlgorithmURI;
- private ExcludedByteRangeType excludedByteRange;
+ protected SignedData signedData;
+ protected SignerInfo signerInfo;
+ protected byte[] signedDocument;
+ protected String mimeType;
+ protected AlgorithmID signatureAlgorithm;
+ protected AlgorithmID digestAlgorithm;
+ protected byte[] digestValue;
+ protected String signatureAlgorithmURI;
+ protected String digestAlgorithmURI;
+ protected ExcludedByteRangeType excludedByteRange;
+ private HashDataInput hashDataInput;
+
- public Signature(CMSDataObjectRequiredMetaType dataObject, String structure,
+public Signature(CMSDataObjectOptionalMetaType dataObject, String structure,
X509Certificate signingCertificate, Date signingTime, URLDereferencer urlDereferencer,
boolean useStrongHash)
throws NoSuchAlgorithmException, CertificateEncodingException,
CertificateException, X509ExtensionException, InvalidParameterException,
- CodingException, SLCommandException, IOException {
- byte[] dataToBeSigned = getContent(dataObject, urlDereferencer);
+ CodingException, SLCommandException, IOException, CMSException {
int mode = structure.equalsIgnoreCase("enveloping") ? SignedData.IMPLICIT : SignedData.EXPLICIT;
+ if (dataObject.getContent() != null) {
+ byte[] dataToBeSigned = getContent(dataObject, urlDereferencer);
this.signedData = new SignedData(dataToBeSigned, mode);
+ if (dataObject.getMetaInfo() != null) {
+ this.mimeType = dataObject.getMetaInfo().getMimeType();
+ }
+
+ hashDataInput = new CMSHashDataInput(signedDocument, mimeType);
+
+ } else {
+ DigestAndRefType digestAndRef = dataObject.getDigestAndRef();
+ DigestMethodType digestMethod = digestAndRef.getDigestMethod();
+
+ hashDataInput = new ReferencedHashDataInput(dataObject.getMetaInfo().getMimeType(), urlDereferencer,
+ digestAndRef.getReference(), dataObject.getExcludedByteRange());
+
+ try {
+ digestAlgorithm = getAlgorithmID(digestMethod.getAlgorithm());
+ } catch (URISyntaxException e) {
+ //TODO: choose proper execption
+ throw new NoSuchAlgorithmException(e);
+ }
+ digestValue = digestAndRef.getDigestValue();
+ this.signedData = new SignedData(ObjectID.pkcs7_data);
+ }
setAlgorithmIDs(signingCertificate, useStrongHash);
createSignerInfo(signingCertificate);
setSignerCertificate(signingCertificate);
@@ -208,7 +236,7 @@ public class Signature {
attributes.add(signingTime);
}
- private byte[] getContent(CMSDataObjectRequiredMetaType dataObject, URLDereferencer urlDereferencer)
+ private byte[] getContent(CMSDataObjectOptionalMetaType dataObject, URLDereferencer urlDereferencer)
throws InvalidParameterException, SLCommandException, IOException {
byte[] data = dataObject.getContent().getBase64Content();
if (data == null) {
@@ -252,63 +280,36 @@ public class Signature {
}
private void setAlgorithmIDs(X509Certificate signingCertificate, boolean useStrongHash) throws NoSuchAlgorithmException {
- PublicKey publicKey = signingCertificate.getPublicKey();
- String algorithm = publicKey.getAlgorithm();
AlgorithmMethodFactory amf = new AlgorithmMethodFactoryImpl(signingCertificate, useStrongHash);
signatureAlgorithmURI = amf.getSignatureAlgorithmURI();
+ signatureAlgorithm = amf.getSignatureAlgorithmID();
+ if (digestAlgorithm != null) {
+ if (AlgorithmID.sha1.equals(digestAlgorithm)) {
+ digestAlgorithmURI = DigestMethod.SHA1;
+ } else if (AlgorithmID.sha256.equals(digestAlgorithm)) {
+ digestAlgorithmURI = DigestMethod.SHA256;
+ } else if (AlgorithmID.sha512.equals(digestAlgorithm)) {
+ digestAlgorithmURI = DigestMethod.SHA512;
+ } else if (AlgorithmID.ripeMd160.equals(digestAlgorithm)) {
+ digestAlgorithmURI = DigestMethod.RIPEMD160;
+ } else {
+ throw new NoSuchAlgorithmException("Algorithm '" + digestAlgorithm + "' not supported.");
+ }
+ } else {
digestAlgorithmURI = amf.getDigestAlgorithmURI();
-
- if ("DSA".equals(algorithm)) {
- signatureAlgorithm = AlgorithmID.dsaWithSHA1;
- } else if ("RSA".equals(algorithm)) {
-
- int keyLength = 0;
- if (publicKey instanceof RSAPublicKey) {
- keyLength = ((RSAPublicKey) publicKey).getModulus().bitLength();
+ digestAlgorithm = amf.getDigestAlgorithmID();
}
-
- if (useStrongHash && keyLength >= 2048) {
- signatureAlgorithm = AlgorithmID.sha256WithRSAEncryption;
- digestAlgorithm = AlgorithmID.sha256;
-// } else if (useStrongHash) { // Cannot be used if not enabled in AlgorithmMethodFactoryImpl
-// signatureAlgorithm = AlgorithmID.rsaSignatureWithRipemd160;
-// digestAlgorithm = AlgorithmID.ripeMd160;
- } else {
- signatureAlgorithm = AlgorithmID.sha1WithRSAEncryption;
- digestAlgorithm = AlgorithmID.sha1;
}
- } else if (("EC".equals(algorithm)) || ("ECDSA".equals(algorithm))) {
- int fieldSize = 0;
- if (publicKey instanceof ECPublicKey) {
- ECParameterSpec params = ((ECPublicKey) publicKey).getParams();
- fieldSize = params.getCurve().getField().getFieldSize();
- } else {
- throw new NoSuchAlgorithmException("Public key type not supported.");
- }
+ public HashDataInput getHashDataInput() {
- if (useStrongHash && fieldSize >= 512) {
- signatureAlgorithm = AlgorithmID.ecdsa_With_SHA512;
- digestAlgorithm = AlgorithmID.sha512;
- } else if (useStrongHash && fieldSize >= 256) {
- signatureAlgorithm = AlgorithmID.ecdsa_With_SHA256;
- digestAlgorithm = AlgorithmID.sha256;
- } else if (useStrongHash) {
- signatureAlgorithm = AlgorithmID.ecdsa_plain_With_RIPEMD160;
- digestAlgorithm = AlgorithmID.ripeMd160;
+ if (hashDataInput != null) {
+ return hashDataInput;
} else {
- signatureAlgorithm = AlgorithmID.ecdsa_With_SHA1;
- digestAlgorithm = AlgorithmID.sha1;
- }
- } else {
- throw new NoSuchAlgorithmException("Public key algorithm '" + algorithm
- + "' not supported.");
+ return new CMSHashDataInput(signedDocument, mimeType);
}
}
- private HashDataInput getHashDataInput() {
- return new CMSHashDataInput(signedDocument, mimeType);
- }
public byte[] sign(STAL stal, String keyboxIdentifier) throws CMSException, CMSSignatureException, SLCommandException {
STALSecurityProvider securityProvider = new STALSecurityProvider(stal, keyboxIdentifier, getHashDataInput(), this.excludedByteRange);
@@ -322,7 +323,29 @@ public class Signature {
}
throw new CMSSignatureException(e);
}
+ if (digestValue != null) {
+ try {
+ signedData.setMessageDigest(digestAlgorithm, digestValue);
+ } catch (NoSuchAlgorithmException e) {
+ throw new CMSSignatureException(e);
+ }
+ }
ContentInfo contentInfo = new ContentInfo(signedData);
return contentInfo.getEncoded();
}
+
+ protected AlgorithmID getAlgorithmID(String uri) throws URISyntaxException {
+ String oid = null;
+ URI urn = new URI(uri);
+ String scheme = urn.getScheme();
+ if ("URN".equalsIgnoreCase(scheme)) {
+ String schemeSpecificPart = urn.getSchemeSpecificPart().toLowerCase();
+ if (schemeSpecificPart.startsWith("oid:")) {
+ oid = schemeSpecificPart.substring(4, schemeSpecificPart.length());
+}
+ }
+ return new AlgorithmID(new ObjectID(oid));
+ }
}
+
+
diff --git a/bkucommon/src/main/java/at/gv/egiz/bku/slcommands/impl/xsect/AlgorithmMethodFactory.java b/bkucommon/src/main/java/at/gv/egiz/bku/slcommands/impl/xsect/AlgorithmMethodFactory.java
index d2484b56..1b801ec5 100644
--- a/bkucommon/src/main/java/at/gv/egiz/bku/slcommands/impl/xsect/AlgorithmMethodFactory.java
+++ b/bkucommon/src/main/java/at/gv/egiz/bku/slcommands/impl/xsect/AlgorithmMethodFactory.java
@@ -32,6 +32,8 @@ import javax.xml.crypto.dsig.CanonicalizationMethod;
import javax.xml.crypto.dsig.DigestMethod;
import javax.xml.crypto.dsig.SignatureMethod;
+import iaik.asn1.structures.AlgorithmID;
+
/**
* A factory for creating {@link AlgorithmMethod}s.
*
@@ -87,4 +89,8 @@ public interface AlgorithmMethodFactory {
public String getSignatureAlgorithmURI();
public String getDigestAlgorithmURI();
+
+ AlgorithmID getSignatureAlgorithmID();
+
+ AlgorithmID getDigestAlgorithmID();
}
diff --git a/bkucommon/src/main/java/at/gv/egiz/bku/slcommands/impl/xsect/AlgorithmMethodFactoryImpl.java b/bkucommon/src/main/java/at/gv/egiz/bku/slcommands/impl/xsect/AlgorithmMethodFactoryImpl.java
index 896552d8..c3fcd146 100644
--- a/bkucommon/src/main/java/at/gv/egiz/bku/slcommands/impl/xsect/AlgorithmMethodFactoryImpl.java
+++ b/bkucommon/src/main/java/at/gv/egiz/bku/slcommands/impl/xsect/AlgorithmMethodFactoryImpl.java
@@ -24,6 +24,7 @@
package at.gv.egiz.bku.slcommands.impl.xsect;
+import iaik.asn1.structures.AlgorithmID;
import iaik.xml.crypto.XmldsigMore;
import java.security.InvalidAlgorithmParameterException;
@@ -55,11 +56,21 @@ public class AlgorithmMethodFactoryImpl implements AlgorithmMethodFactory {
private String signatureAlgorithmURI;
/**
+ * The signature algorithm ID.
+ */
+ private AlgorithmID signatureAlgorithmID;
+
+ /**
* the digest algorithm URI.
*/
private String digestAlgorithmURI = DigestMethod.SHA1;
/**
+ * The digest algorithm ID.
+ */
+ private AlgorithmID digestAlgorithmID = AlgorithmID.sha1;
+
+ /**
* The algorithm parameters for the signature algorithm.
*/
private SignatureMethodParameterSpec signatureMethodParameterSpec;
@@ -82,6 +93,7 @@ public class AlgorithmMethodFactoryImpl implements AlgorithmMethodFactory {
if ("DSA".equals(algorithm)) {
signatureAlgorithmURI = SignatureMethod.DSA_SHA1;
+ signatureAlgorithmID = AlgorithmID.dsaWithSHA1;
} else if ("RSA".equals(algorithm)) {
int keyLength = 0;
@@ -91,12 +103,12 @@ public class AlgorithmMethodFactoryImpl implements AlgorithmMethodFactory {
if (useStrongHash && keyLength >= 2048) {
signatureAlgorithmURI = XmldsigMore.SIGNATURE_RSA_SHA256;
+ signatureAlgorithmID = AlgorithmID.sha256WithRSAEncryption;
digestAlgorithmURI = DigestMethod.SHA256;
-// } else if (useStrongHash) {
-// signatureAlgorithmURI = XmldsigMore.SIGNATURE_RSA_RIPEMD160_ERRATA;
-// digestAlgorithmURI = DigestMethod.RIPEMD160;
+ digestAlgorithmID = AlgorithmID.sha256;
} else {
signatureAlgorithmURI = SignatureMethod.RSA_SHA1;
+ signatureAlgorithmID = AlgorithmID.sha1WithRSAEncryption;
}
} else if (("EC".equals(algorithm)) || ("ECDSA".equals(algorithm))) {
@@ -111,15 +123,22 @@ public class AlgorithmMethodFactoryImpl implements AlgorithmMethodFactory {
if (useStrongHash && fieldSize >= 512) {
signatureAlgorithmURI = XmldsigMore.SIGNATURE_ECDSA_SHA512;
+ signatureAlgorithmID = AlgorithmID.ecdsa_With_SHA512;
digestAlgorithmURI = DigestMethod.SHA512;
+ digestAlgorithmID = AlgorithmID.sha512;
} else if (useStrongHash && fieldSize >= 256) {
signatureAlgorithmURI = XmldsigMore.SIGNATURE_ECDSA_SHA256;
+ signatureAlgorithmID = AlgorithmID.ecdsa_With_SHA256;
digestAlgorithmURI = DigestMethod.SHA256;
+ digestAlgorithmID = AlgorithmID.sha256;
} else if (useStrongHash) {
signatureAlgorithmURI = XmldsigMore.SIGNATURE_ECDSA_RIPEMD160;
+ signatureAlgorithmID = AlgorithmID.ecdsa_plain_With_RIPEMD160;
digestAlgorithmURI = DigestMethod.RIPEMD160;
+ digestAlgorithmID = AlgorithmID.ripeMd160;
} else {
signatureAlgorithmURI = XmldsigMore.SIGNATURE_ECDSA_SHA1;
+ signatureAlgorithmID = AlgorithmID.ecdsa_With_SHA1;
}
} else {
@@ -185,4 +204,14 @@ public class AlgorithmMethodFactoryImpl implements AlgorithmMethodFactory {
return digestAlgorithmURI;
}
+ @Override
+ public AlgorithmID getSignatureAlgorithmID() {
+ return signatureAlgorithmID;
+ }
+
+ @Override
+ public AlgorithmID getDigestAlgorithmID() {
+ return digestAlgorithmID;
+ }
+
}
diff --git a/bkucommon/src/main/java/at/gv/egiz/bku/spring/URLDereferencerFactoryBean.java b/bkucommon/src/main/java/at/gv/egiz/bku/spring/URLDereferencerFactoryBean.java
new file mode 100644
index 00000000..1a95a146
--- /dev/null
+++ b/bkucommon/src/main/java/at/gv/egiz/bku/spring/URLDereferencerFactoryBean.java
@@ -0,0 +1,75 @@
+package at.gv.egiz.bku.spring;
+
+import javax.net.ssl.HostnameVerifier;
+import javax.net.ssl.SSLSocketFactory;
+
+import org.apache.commons.configuration.Configuration;
+import org.springframework.beans.factory.FactoryBean;
+
+import at.gv.egiz.bku.conf.MoccaConfigurationFacade;
+import at.gv.egiz.bku.utils.urldereferencer.FileURLProtocolHandlerImpl;
+import at.gv.egiz.bku.utils.urldereferencer.URLDereferencerImpl;
+
+public class URLDereferencerFactoryBean implements FactoryBean {
+
+ private HostnameVerifier hostnameVerifier;
+ private SSLSocketFactory sslSocketFactory;
+
+ protected final ConfigurationFacade configurationFacade = new ConfigurationFacade();
+
+ public class ConfigurationFacade implements MoccaConfigurationFacade {
+
+ private Configuration configuration;
+ public static final String ENABLE_FILEURIS = "enableFileURIs";
+
+ public boolean isEnableFileURIs() {
+ return configuration.getBoolean(ENABLE_FILEURIS, false);
+ }
+
+ }
+
+ public void setConfiguration(Configuration configuration) {
+ configurationFacade.configuration = configuration;
+ }
+
+ @Override
+ public Object getObject() throws Exception {
+
+ URLDereferencerImpl urlDereferencer = URLDereferencerImpl.getInstance();
+ urlDereferencer.setHostnameVerifier(hostnameVerifier);
+ urlDereferencer.setSSLSocketFactory(sslSocketFactory);
+
+ if(!configurationFacade.isEnableFileURIs()) {
+ urlDereferencer.registerHandler(FileURLProtocolHandlerImpl.FILE, new FileURLProtocolHandlerImpl());
+ }
+
+ return urlDereferencer;
+ }
+
+ @Override
+ public Class<URLDereferencerImpl> getObjectType() {
+ return URLDereferencerImpl.class;
+ }
+
+ @Override
+ public boolean isSingleton() {
+ return true;
+ }
+
+ public HostnameVerifier getHostnameVerifier() {
+ return hostnameVerifier;
+ }
+
+ public void setHostnameVerifier(HostnameVerifier hostnameVerifier) {
+ this.hostnameVerifier = hostnameVerifier;
+ }
+
+ public SSLSocketFactory getSslSocketFactory() {
+ return sslSocketFactory;
+ }
+
+ public void setSslSocketFactory(SSLSocketFactory sslSocketFactory) {
+ this.sslSocketFactory = sslSocketFactory;
+ }
+
+}
diff --git a/bkucommon/src/main/resources/at/gv/egiz/bku/slexceptions/SLExceptionMessages.properties b/bkucommon/src/main/resources/at/gv/egiz/bku/slexceptions/SLExceptionMessages.properties
index de54e9b2..92955fc9 100644
--- a/bkucommon/src/main/resources/at/gv/egiz/bku/slexceptions/SLExceptionMessages.properties
+++ b/bkucommon/src/main/resources/at/gv/egiz/bku/slexceptions/SLExceptionMessages.properties
@@ -108,3 +108,6 @@ ec4011.notimplemented=Befehl {0} ist nicht implementiert.
lec2901.notimplemented=Die in der Anfrage verwendete Version des Security-Layer Protokolls ({0}) wird nicht mehr unterstützt.
+# custom error messages for bulk signature
+ec4124= XML Signatur Requests werden aktuell in der Stapelsignatur nicht unterstützt.
+
diff --git a/bkucommon/src/main/resources/at/gv/egiz/bku/slexceptions/SLExceptionMessages_en.properties b/bkucommon/src/main/resources/at/gv/egiz/bku/slexceptions/SLExceptionMessages_en.properties
index 471f4a13..4d90f71c 100644
--- a/bkucommon/src/main/resources/at/gv/egiz/bku/slexceptions/SLExceptionMessages_en.properties
+++ b/bkucommon/src/main/resources/at/gv/egiz/bku/slexceptions/SLExceptionMessages_en.properties
@@ -106,3 +106,5 @@ ec4011.notimplemented=Command {0} not implemented.
# Legacy error codes
#
lec2901.notimplemented=The version ({0}) of the security-layer protocol used in the request is not supported.
+# custom error messages for bulk signature
+ec4124= XML signature requests are currently not supported in bulk signature requests.
diff --git a/bkucommon/src/site/apt/configuration.apt b/bkucommon/src/site/apt/configuration.apt
index ec6b7cd0..2aca5dc7 100644
--- a/bkucommon/src/site/apt/configuration.apt
+++ b/bkucommon/src/site/apt/configuration.apt
@@ -54,6 +54,10 @@ MOCCA Configuration
Default: <<<true>>>
+ [<<<enableFileURIs>>>] Whether to allow dereferencing of "file" URIs.
+
+ Default: <<<false>>>
+
[<<<SSL>>>]
The following two configuration elements must provide an URL which resolves to a directory in the file system. It may either be an absolute URL or a relative URL, which is resolved using the URL of the configuration file.
diff --git a/bkucommon/src/test/java/at/gv/egiz/bku/slcommands/impl/BulkCommandImplTest.java b/bkucommon/src/test/java/at/gv/egiz/bku/slcommands/impl/BulkCommandImplTest.java
new file mode 100644
index 00000000..b91bec98
--- /dev/null
+++ b/bkucommon/src/test/java/at/gv/egiz/bku/slcommands/impl/BulkCommandImplTest.java
@@ -0,0 +1,130 @@
+/*
+ * Copyright 2015 Datentechnik Innovation and Prime Sign GmbH, Austria
+ *
+ * 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.bku.slcommands.impl;
+
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertNotNull;
+import static org.junit.Assert.assertTrue;
+import iaik.asn1.ObjectID;
+import iaik.cms.SignedData;
+import iaik.xml.crypto.XSecProvider;
+
+import java.io.ByteArrayInputStream;
+import java.io.InputStream;
+import java.io.InputStreamReader;
+
+import javax.xml.bind.JAXBException;
+import javax.xml.bind.Unmarshaller;
+import javax.xml.transform.stream.StreamResult;
+import javax.xml.transform.stream.StreamSource;
+
+import org.junit.Before;
+import org.junit.BeforeClass;
+import org.junit.Test;
+import org.springframework.context.ApplicationContext;
+import org.springframework.context.support.ClassPathXmlApplicationContext;
+
+import at.buergerkarte.namespaces.securitylayer._1_2_3.BulkResponseType;
+import at.gv.egiz.bku.slcommands.BulkCommand;
+import at.gv.egiz.bku.slcommands.BulkSignatureResult;
+import at.gv.egiz.bku.slcommands.SLCommand;
+import at.gv.egiz.bku.slcommands.SLCommandContext;
+import at.gv.egiz.bku.slcommands.SLCommandFactory;
+import at.gv.egiz.bku.slcommands.SLResult;
+import at.gv.egiz.bku.utils.urldereferencer.URLDereferencer;
+import at.gv.egiz.stal.STAL;
+import at.gv.egiz.stal.STALFactory;
+
+public class BulkCommandImplTest {
+
+ protected static ApplicationContext appCtx;
+ private SLCommandFactory factory;
+
+ private STAL stal;
+
+ private URLDereferencer urlDereferencer;
+
+ @BeforeClass
+ public static void setUpClass() {
+ appCtx = new ClassPathXmlApplicationContext("at/gv/egiz/bku/slcommands/testApplicationContext.xml");
+ XSecProvider.addAsProvider(true);
+ }
+
+ @Before
+ public void setUp() throws JAXBException {
+
+ Object bean = appCtx.getBean("slCommandFactory");
+ assertTrue(bean instanceof SLCommandFactory);
+
+ factory = (SLCommandFactory) bean;
+
+ bean = appCtx.getBean("stalFactory");
+ assertTrue(bean instanceof STALFactory);
+
+ stal = ((STALFactory) bean).createSTAL();
+
+ bean = appCtx.getBean("urlDereferencer");
+ assertTrue(bean instanceof URLDereferencer);
+
+ urlDereferencer = (URLDereferencer) bean;
+
+ }
+
+ @Test
+ public void testCreateCMSSignatureRequest() throws Exception {
+ InputStream inputStream = getClass().getClassLoader().getResourceAsStream(
+ "at/gv/egiz/bku/slcommands/bulksignaturerequest/BulkSignatureRequest.xml");
+ assertNotNull(inputStream);
+
+ SLCommand command = factory.createSLCommand(new StreamSource(new InputStreamReader(inputStream)));
+ assertTrue(command instanceof BulkCommand);
+
+ SLCommandContext context = new SLCommandContext(stal, urlDereferencer, null);
+ SLResult result = command.execute(context);
+
+ assertTrue(result instanceof BulkSignatureResult);
+
+ BulkSignatureResult bulkResult = (BulkSignatureResult) result;
+ System.out.println(bulkResult.getContent());
+
+ bulkResult.getContent();
+
+ // unmarshall response
+ Unmarshaller unmarshaller = factory.getJaxbContext().createUnmarshaller();
+
+ BulkResponseType response = unmarshaller.unmarshal(bulkResult.getContent(), BulkResponseType.class).getValue();
+
+ // verify ContentType of singature
+ byte[] cmsSignature = response.getCreateSignatureResponse().get(0).getCreateCMSSignatureResponse()
+ .getCMSSignature();
+ SignedData signedData = new SignedData(new ByteArrayInputStream(cmsSignature));
+
+ assertNotNull(signedData);
+ assertEquals(ObjectID.pkcs7_signedData, signedData.getContentType());
+ assertNotNull(response.getCreateSignatureResponse());
+ assertEquals(2, response.getCreateSignatureResponse().size());
+
+ result.writeTo(new StreamResult(System.out), false);
+
+ }
+
+}
diff --git a/bkucommon/src/test/java/at/gv/egiz/bku/slcommands/impl/CreateCMSSignatureCommandImplTest.java b/bkucommon/src/test/java/at/gv/egiz/bku/slcommands/impl/CreateCMSSignatureCommandImplTest.java
index b1ec7777..09b70f09 100644
--- a/bkucommon/src/test/java/at/gv/egiz/bku/slcommands/impl/CreateCMSSignatureCommandImplTest.java
+++ b/bkucommon/src/test/java/at/gv/egiz/bku/slcommands/impl/CreateCMSSignatureCommandImplTest.java
@@ -24,13 +24,21 @@
package at.gv.egiz.bku.slcommands.impl;
+import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertNotNull;
import static org.junit.Assert.assertTrue;
+import iaik.asn1.ObjectID;
+import iaik.cms.CMSParsingException;
+import iaik.cms.SignedData;
import iaik.xml.crypto.XSecProvider;
+import java.io.ByteArrayInputStream;
+import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
+import javax.xml.bind.JAXBException;
+import javax.xml.bind.Unmarshaller;
import javax.xml.transform.stream.StreamResult;
import javax.xml.transform.stream.StreamSource;
@@ -40,7 +48,9 @@ import org.junit.Test;
import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;
+import at.buergerkarte.namespaces.securitylayer._1_2_3.CreateCMSSignatureResponseType;
import at.gv.egiz.bku.slcommands.CreateCMSSignatureCommand;
+import at.gv.egiz.bku.slcommands.CreateCMSSignatureResult;
import at.gv.egiz.bku.slcommands.SLCommand;
import at.gv.egiz.bku.slcommands.SLCommandContext;
import at.gv.egiz.bku.slcommands.SLCommandFactory;
@@ -89,8 +99,11 @@ public class CreateCMSSignatureCommandImplTest {
}
@Test
- public void testCreateCMSSignatureRequest() throws SLCommandException, SLRuntimeException, SLRequestException, SLVersionException {
- InputStream inputStream = getClass().getClassLoader().getResourceAsStream("at/gv/egiz/bku/slcommands/createcmssignaturerequest/CreateCMSSignatureRequest.xml");
+ public void testCreateCMSSignatureRequest() throws SLCommandException, SLRuntimeException, SLRequestException,
+ SLVersionException, JAXBException, CMSParsingException, IOException {
+
+ InputStream inputStream = getClass().getClassLoader().getResourceAsStream(
+ "at/gv/egiz/bku/slcommands/createcmssignaturerequest/CreateCMSSignatureRequest.xml");
assertNotNull(inputStream);
SLCommand command = factory.createSLCommand(new StreamSource(new InputStreamReader(inputStream)));
@@ -98,6 +111,22 @@ public class CreateCMSSignatureCommandImplTest {
SLCommandContext context = new SLCommandContext(stal, urlDereferencer, null);
SLResult result = command.execute(context);
+
+ assertTrue(result instanceof CreateCMSSignatureResult);
+ CreateCMSSignatureResult sigResult = (CreateCMSSignatureResult) result;
+
+ //unmarshall response
+ Unmarshaller unmarshaller = factory.getJaxbContext().createUnmarshaller();
+
+ CreateCMSSignatureResponseType response = unmarshaller.unmarshal(sigResult.getContent(), CreateCMSSignatureResponseType.class).getValue();
+
+ //verify ContentType of singature
+ byte[] cmsSignature = response.getCMSSignature();
+ SignedData signedData = new SignedData(new ByteArrayInputStream(cmsSignature));
+
+ assertNotNull(signedData);
+ assertEquals(ObjectID.pkcs7_signedData, signedData.getContentType());
+
result.writeTo(new StreamResult(System.out), false);
}
}
diff --git a/bkucommon/src/test/java/at/gv/egiz/bku/slcommands/impl/cms/SignatureTest.java b/bkucommon/src/test/java/at/gv/egiz/bku/slcommands/impl/cms/SignatureTest.java
new file mode 100644
index 00000000..56229b83
--- /dev/null
+++ b/bkucommon/src/test/java/at/gv/egiz/bku/slcommands/impl/cms/SignatureTest.java
@@ -0,0 +1,130 @@
+package at.gv.egiz.bku.slcommands.impl.cms;
+
+import static org.junit.Assert.*;
+
+import java.io.ByteArrayInputStream;
+import java.net.URI;
+import java.net.URISyntaxException;
+import java.nio.charset.Charset;
+import java.security.MessageDigest;
+import java.util.Date;
+
+import org.junit.BeforeClass;
+import org.junit.Test;
+import org.w3._2000._09.xmldsig_.DigestMethodType;
+
+import at.buergerkarte.namespaces.securitylayer._1_2_3.Base64OptRefContentType;
+import at.buergerkarte.namespaces.securitylayer._1_2_3.CMSDataObjectRequiredMetaType;
+import at.buergerkarte.namespaces.securitylayer._1_2_3.DigestAndRefType;
+import at.buergerkarte.namespaces.securitylayer._1_2_3.MetaInfoType;
+import at.gv.egiz.stal.dummy.DummySTAL;
+import iaik.asn1.ObjectID;
+import iaik.asn1.structures.AlgorithmID;
+import iaik.cms.InvalidSignatureValueException;
+import iaik.cms.SignedData;
+import iaik.cms.SignerInfo;
+import iaik.security.ecc.provider.ECCProvider;
+import iaik.security.provider.IAIK;
+import iaik.x509.X509Certificate;
+
+public class SignatureTest {
+
+ private DummySTAL stal = new DummySTAL();
+
+ @BeforeClass
+ public static void setUpClass() {
+ IAIK.addAsProvider();
+ ECCProvider.addAsProvider();
+ }
+
+ @Test
+ public void testSignCMSDataObject() throws Exception {
+
+ byte[] plaintext = "Plaintext".getBytes(Charset.forName("UTF-8"));
+
+ CMSDataObjectRequiredMetaType dataObject = new CMSDataObjectRequiredMetaType();
+ Base64OptRefContentType base64OptRefContentType = new Base64OptRefContentType();
+ base64OptRefContentType.setBase64Content(plaintext);
+ dataObject.setContent(base64OptRefContentType);
+ MetaInfoType metaInfoType = new MetaInfoType();
+ metaInfoType.setMimeType("text/plain");
+ dataObject.setMetaInfo(metaInfoType);
+
+ Signature signature = new Signature(dataObject, "detached", stal.getCert(), new Date(), null, true);
+ byte[] cmsSignature = signature.sign(stal, "SecureSignatureKeypair");
+
+ SignedData signedData = new SignedData(new ByteArrayInputStream(cmsSignature));
+ signedData.setContent(plaintext);
+ assertEquals(ObjectID.pkcs7_data, signedData.getEncapsulatedContentType());
+ SignerInfo[] signerInfos = signedData.getSignerInfos();
+ assertEquals(1, signerInfos.length);
+ SignerInfo signerInfo = signerInfos[0];
+ signedData.verify((X509Certificate) stal.getCert());
+ assertEquals(AlgorithmID.sha1, signerInfo.getDigestAlgorithm());
+ assertEquals(AlgorithmID.sha1WithRSAEncryption, signerInfo.getSignatureAlgorithm());
+
+ System.out.println(AlgorithmID.sha1);
+
+ }
+
+ @Test
+ public void testSignCMSReferenceSha1() throws Exception {
+ testSignCMSReference(AlgorithmID.sha1);
+ }
+
+ //TODO Why doesn't it work this way??
+ @Test(expected = InvalidSignatureValueException.class)
+ public void testSignCMSReferenceSha256() throws Exception {
+ testSignCMSReference(AlgorithmID.sha256);
+ }
+
+ private void testSignCMSReference(AlgorithmID digestAlgorithmID) throws Exception {
+
+ byte[] plaintext = "Plaintext".getBytes(Charset.forName("UTF-8"));
+
+ MessageDigest messageDigest = MessageDigest.getInstance(digestAlgorithmID.getImplementationName());
+ byte[] digestValue = messageDigest.digest(plaintext);
+
+ CMSDataObjectRequiredMetaType dataObject = new CMSDataObjectRequiredMetaType();
+ DigestAndRefType digestAndRefType = new DigestAndRefType();
+ DigestMethodType digestMethodType = new DigestMethodType();
+ digestMethodType.setAlgorithm("URN:OID:" + digestAlgorithmID.getAlgorithm().getID());
+ digestAndRefType.setDigestMethod(digestMethodType);
+ digestAndRefType.setDigestValue(digestValue);
+ dataObject.setDigestAndRef(digestAndRefType);
+ MetaInfoType metaInfoType = new MetaInfoType();
+ metaInfoType.setMimeType("text/plain");
+ dataObject.setMetaInfo(metaInfoType);
+
+ Signature signature = new Signature(dataObject, "detached", stal.getCert(), new Date(), null, true);
+ byte[] cmsSignature = signature.sign(stal, "SecureSignatureKeypair");
+
+ SignedData signedData = new SignedData(new ByteArrayInputStream(cmsSignature));
+ signedData.setContent(plaintext);
+ assertEquals(ObjectID.pkcs7_data, signedData.getEncapsulatedContentType());
+ SignerInfo[] signerInfos = signedData.getSignerInfos();
+ assertEquals(1, signerInfos.length);
+ SignerInfo signerInfo = signerInfos[0];
+ signedData.verify((X509Certificate) stal.getCert());
+ assertEquals(digestAlgorithmID, signerInfo.getDigestAlgorithm());
+ assertEquals(AlgorithmID.sha1WithRSAEncryption, signerInfo.getSignatureAlgorithm());
+
+ }
+
+ @Test
+ public void test() throws URISyntaxException {
+
+ String oid = null;
+ URI uri = new URI("URN:OID:1.3.14.3.2.26");
+ String scheme = uri.getScheme();
+ if ("URN".equalsIgnoreCase(scheme)) {
+ String schemeSpecificPart = uri.getSchemeSpecificPart().toLowerCase();
+ if (schemeSpecificPart.startsWith("oid:")) {
+ oid = schemeSpecificPart.substring(4, schemeSpecificPart.length());
+ }
+ }
+ assertEquals("1.3.14.3.2.26", oid);
+
+ }
+
+}
diff --git a/bkucommon/src/test/java/at/gv/egiz/bku/slcommands/impl/xsect/SignatureTest.java b/bkucommon/src/test/java/at/gv/egiz/bku/slcommands/impl/xsect/SignatureTest.java
index 6e5612f6..04cf3552 100644
--- a/bkucommon/src/test/java/at/gv/egiz/bku/slcommands/impl/xsect/SignatureTest.java
+++ b/bkucommon/src/test/java/at/gv/egiz/bku/slcommands/impl/xsect/SignatureTest.java
@@ -27,7 +27,7 @@ package at.gv.egiz.bku.slcommands.impl.xsect;
import static org.junit.Assert.assertNotNull;
import static org.junit.Assert.assertNull;
import static org.junit.Assert.assertTrue;
-
+import iaik.asn1.structures.AlgorithmID;
import iaik.xml.crypto.XSecProvider;
import java.io.IOException;
@@ -140,6 +140,16 @@ public class SignatureTest {
return DigestMethod.SHA1;
}
+ @Override
+ public AlgorithmID getSignatureAlgorithmID() {
+ return null;
+ }
+
+ @Override
+ public AlgorithmID getDigestAlgorithmID() {
+ return null;
+ }
+
}
private static final String RESOURCE_PREFIX = "at/gv/egiz/bku/slcommands/impl/";
diff --git a/bkucommon/src/test/java/at/gv/egiz/stal/dummy/DummySTAL.java b/bkucommon/src/test/java/at/gv/egiz/stal/dummy/DummySTAL.java
index 61d0d480..0f054cf0 100644
--- a/bkucommon/src/test/java/at/gv/egiz/stal/dummy/DummySTAL.java
+++ b/bkucommon/src/test/java/at/gv/egiz/stal/dummy/DummySTAL.java
@@ -36,9 +36,13 @@ import java.util.ArrayList;
import java.util.Enumeration;
import java.util.List;
+import javax.xml.crypto.dsig.SignatureMethod;
+
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
+import at.gv.egiz.stal.BulkSignRequest;
+import at.gv.egiz.stal.BulkSignResponse;
import at.gv.egiz.stal.ErrorResponse;
import at.gv.egiz.stal.InfoboxReadRequest;
import at.gv.egiz.stal.InfoboxReadResponse;
@@ -47,6 +51,7 @@ import at.gv.egiz.stal.STALRequest;
import at.gv.egiz.stal.STALResponse;
import at.gv.egiz.stal.SignRequest;
import at.gv.egiz.stal.SignResponse;
+import iaik.xml.crypto.XmldsigMore;
public class DummySTAL implements STAL {
@@ -58,11 +63,9 @@ public class DummySTAL implements STAL {
public DummySTAL() {
try {
KeyStore ks = KeyStore.getInstance("pkcs12");
- InputStream ksStream = getClass().getClassLoader().getResourceAsStream(
- "at/gv/egiz/bku/slcommands/impl/Cert.p12");
+ InputStream ksStream = getClass().getClassLoader().getResourceAsStream("at/gv/egiz/bku/slcommands/impl/Cert.p12");
ks.load(ksStream, "1622".toCharArray());
- for (Enumeration<String> aliases = ks.aliases(); aliases
- .hasMoreElements();) {
+ for (Enumeration<String> aliases = ks.aliases(); aliases.hasMoreElements();) {
String alias = aliases.nextElement();
log.debug("Found alias " + alias + " in keystore");
if (ks.isKeyEntry(alias)) {
@@ -78,25 +81,28 @@ public class DummySTAL implements STAL {
}
+ public X509Certificate getCert() {
+ return cert;
+ }
+
@Override
public List<STALResponse> handleRequest(List<? extends STALRequest> requestList) {
List<STALResponse> responses = new ArrayList<STALResponse>();
for (STALRequest request : requestList) {
- log.debug("Got STALRequest " + request + ".");
+ log.info("Got STALRequest " + request + ".");
if (request instanceof InfoboxReadRequest) {
- String infoboxIdentifier = ((InfoboxReadRequest) request)
- .getInfoboxIdentifier();
+ String infoboxIdentifier = ((InfoboxReadRequest) request).getInfoboxIdentifier();
InputStream stream = getClass().getClassLoader().getResourceAsStream(
"at/gv/egiz/stal/dummy/infoboxes4/" + infoboxIdentifier + ".bin");
STALResponse response;
if (stream != null) {
- log.debug("Infobox " + infoboxIdentifier + " found.");
+ log.info("Infobox " + infoboxIdentifier + " found.");
byte[] infobox;
try {
@@ -114,7 +120,8 @@ public class DummySTAL implements STAL {
infoboxReadResponse.setInfoboxValue(infobox);
response = infoboxReadResponse;
- } else if ((infoboxIdentifier.equals("SecureSignatureKeypair")) ||(infoboxIdentifier.equals("CertifiedKeypair"))) {
+ } else if ((infoboxIdentifier.equals("SecureSignatureKeypair"))
+ || (infoboxIdentifier.equals("CertifiedKeypair"))) {
try {
InfoboxReadResponse infoboxReadResponse = new InfoboxReadResponse();
infoboxReadResponse.setInfoboxValue(cert.getEncoded());
@@ -135,7 +142,13 @@ public class DummySTAL implements STAL {
try {
SignRequest signReq = (SignRequest) request;
- Signature s = Signature.getInstance("SHA1withRSA");
+ String signatureMethod = ((SignRequest) request).getSignatureMethod();
+ Signature s = null;
+ if (SignatureMethod.RSA_SHA1.equals(signatureMethod)) {
+ s = Signature.getInstance("SHA1withRSA");
+ } else if (XmldsigMore.SIGNATURE_RSA_SHA256.equals(signatureMethod)) {
+ s = Signature.getInstance("SHA256withRSA");
+ }
s.initSign(privateKey);
s.update(signReq.getSignedInfo().getValue());
byte[] sigVal = s.sign();
@@ -147,7 +160,37 @@ public class DummySTAL implements STAL {
responses.add(new ErrorResponse());
}
- } else {
+ }
+
+ //dummy handler for BulkSignRequest
+ else if (request instanceof BulkSignRequest) {
+
+ try {
+ BulkSignRequest bulkSignReq = (BulkSignRequest) request;
+
+ BulkSignResponse bulkSignResp = new BulkSignResponse();
+
+ for (int i = 0; i < bulkSignReq.getSignRequests().size(); i++) {
+
+ Signature s = Signature.getInstance("SHA1withRSA");
+ s.initSign(privateKey);
+ s.update(bulkSignReq.getSignRequests().get(i).getSignedInfo().getValue());
+ byte[] sigVal = s.sign();
+ SignResponse resp = new SignResponse();
+ resp.setSignatureValue(sigVal);
+ bulkSignResp.getSignResponse().add(resp);
+ }
+
+ responses.add(bulkSignResp);
+
+ } catch (Exception e) {
+ log.error("Failed to create signature.", e);
+ responses.add(new ErrorResponse());
+ }
+
+ }
+
+ else {
log.debug("Request not implemented.");
diff --git a/bkucommon/src/test/resources/at/gv/egiz/bku/slcommands/bulksignaturerequest/BulkSignatureRequest.xml b/bkucommon/src/test/resources/at/gv/egiz/bku/slcommands/bulksignaturerequest/BulkSignatureRequest.xml
new file mode 100644
index 00000000..7fa39f57
--- /dev/null
+++ b/bkucommon/src/test/resources/at/gv/egiz/bku/slcommands/bulksignaturerequest/BulkSignatureRequest.xml
@@ -0,0 +1,34 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<sl:BulkRequest
+ xmlns:sl="http://www.buergerkarte.at/namespaces/securitylayer/1.2#" >
+ <sl:CreateSignatureRequest displayName="Urlaubsantrag &quot;Rössler&quot;">
+ <sl:CreateCMSSignatureRequest Structure="detached">
+ <sl:KeyboxIdentifier>SecureSignatureKeypair</sl:KeyboxIdentifier>
+ <sl:DataObject>
+ <sl:MetaInfo>
+ <sl:MimeType>text/plain</sl:MimeType>
+ </sl:MetaInfo>
+ <sl:Content Reference="">
+ <sl:Base64Content>QW5kIG5vdyB0byBzb21ldGhpbmcgY29tcGxldGx5IGRpZmZlcmVudA==
+ </sl:Base64Content>
+ </sl:Content>
+ </sl:DataObject>
+ </sl:CreateCMSSignatureRequest>
+ </sl:CreateSignatureRequest>
+ <sl:CreateSignatureRequest displayName="Krankmeldung &quot;Meyer&quot;">
+ <sl:CreateCMSSignatureRequest
+ xmlns:sl="http://www.buergerkarte.at/namespaces/securitylayer/1.2#"
+ Structure="detached">
+ <sl:KeyboxIdentifier>SecureSignatureKeypair</sl:KeyboxIdentifier>
+ <sl:DataObject>
+ <sl:MetaInfo>
+ <sl:MimeType>text/plain</sl:MimeType>
+ </sl:MetaInfo>
+ <sl:Content Reference="">
+ <sl:Base64Content>Vm9uIGRlciBTaWduYXR1ciB1bXNjaGxvc3NlbmUgRGF0ZW4u
+ </sl:Base64Content>
+ </sl:Content>
+ </sl:DataObject>
+ </sl:CreateCMSSignatureRequest>
+ </sl:CreateSignatureRequest>
+</sl:BulkRequest> \ No newline at end of file
diff --git a/bkucommon/src/test/resources/at/gv/egiz/bku/slcommands/bulksignaturerequest/BulkSignatureRequestWithReference.xml b/bkucommon/src/test/resources/at/gv/egiz/bku/slcommands/bulksignaturerequest/BulkSignatureRequestWithReference.xml
new file mode 100644
index 00000000..a506d50c
--- /dev/null
+++ b/bkucommon/src/test/resources/at/gv/egiz/bku/slcommands/bulksignaturerequest/BulkSignatureRequestWithReference.xml
@@ -0,0 +1,37 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<sl:BulkRequest
+ xmlns:sl="http://www.buergerkarte.at/namespaces/securitylayer/1.2#"
+ xmlns:dsig="http://www.w3.org/2000/09/xmldsig#" >
+ <sl:CreateSignatureRequest displayName="Urlaubsantrag &quot;Rössler&quot;">
+ <sl:CreateCMSSignatureRequest
+ xmlns:sl="http://www.buergerkarte.at/namespaces/securitylayer/1.2#"
+ Structure="detached">
+ <sl:KeyboxIdentifier>SecureSignatureKeypair</sl:KeyboxIdentifier>
+ <sl:ReferenceObject>
+ <sl:MetaInfo>
+ <sl:MimeType>text/plain</sl:MimeType>
+ </sl:MetaInfo>
+ <sl:DigestAndRef>
+ <dsig:DigestMethod Algorithm="urn:oid:1.3.14.3.2.26"/>
+ <dsig:DigestValue>j6lwx3rvEPO0vKtMup4NbeVu8nk=</dsig:DigestValue>
+ </sl:DigestAndRef>
+ </sl:ReferenceObject>
+ </sl:CreateCMSSignatureRequest>
+ </sl:CreateSignatureRequest>
+ <sl:CreateSignatureRequest displayName="Krankmeldung &quot;Meyer&quot;">
+ <sl:CreateCMSSignatureRequest
+ xmlns:sl="http://www.buergerkarte.at/namespaces/securitylayer/1.2#"
+ Structure="detached">
+ <sl:KeyboxIdentifier>SecureSignatureKeypair</sl:KeyboxIdentifier>
+ <sl:ReferenceObject>
+ <sl:MetaInfo>
+ <sl:MimeType>text/plain</sl:MimeType>heis
+ </sl:MetaInfo>
+ <sl:DigestAndRef>
+ <dsig:DigestMethod Algorithm="urn:oid:1.3.14.3.2.26"/>
+ <dsig:DigestValue>j6lwx3rvEPO0vKtMup4NbeVu8nk=</dsig:DigestValue>
+ </sl:DigestAndRef>
+ </sl:ReferenceObject>
+ </sl:CreateCMSSignatureRequest>
+ </sl:CreateSignatureRequest>
+</sl:BulkRequest> \ No newline at end of file
diff --git a/bkucommon/src/test/resources/at/gv/egiz/bku/slcommands/testApplicationContext.xml b/bkucommon/src/test/resources/at/gv/egiz/bku/slcommands/testApplicationContext.xml
index fffabb47..9a76291c 100644
--- a/bkucommon/src/test/resources/at/gv/egiz/bku/slcommands/testApplicationContext.xml
+++ b/bkucommon/src/test/resources/at/gv/egiz/bku/slcommands/testApplicationContext.xml
@@ -119,6 +119,14 @@
value="http://www.buergerkarte.at/namespaces/securitylayer/1.2#" />
<constructor-arg value="CreateCMSSignatureRequest" />
</bean>
+ <bean id="bulkCommandFactory"
+ class="at.gv.egiz.bku.slcommands.impl.BulkCommandFactory"
+ parent="abstractCommandFactory" />
+ <bean id="bulkRequest" class="javax.xml.namespace.QName">
+ <constructor-arg
+ value="http://www.buergerkarte.at/namespaces/securitylayer/1.2#" />
+ <constructor-arg value="BulkRequest"/>
+ </bean>
<bean id="getStatusCommandFactory" class="at.gv.egiz.bku.slcommands.impl.GetStatusCommandFactory"
parent="abstractCommandFactory" />
<bean id="getStatusRequest" class="javax.xml.namespace.QName">
@@ -136,6 +144,7 @@
<entry key-ref="infoboxUpdateRequest" value-ref="infoboxUpdateCommandFactory" />
<entry key-ref="createXMLSignatureRequest" value-ref="createXMLSignatureCommandFactory" />
<entry key-ref="createCMSSignatureRequest" value-ref="createCMSSignatureCommandFactory" />
+ <entry key-ref="bulkRequest" value-ref="bulkCommandFactory" />
<entry key-ref="getStatusRequest" value-ref="getStatusCommandFactory" />
</map>
</property>