From 2b8b52bde3fefe29127473f5b71dba3239a0488f Mon Sep 17 00:00:00 2001 From: "Bonato, Martin" Date: Thu, 8 Feb 2018 14:35:24 +0100 Subject: Fix build --- BKUOnline/pom.xml | 1 + 1 file changed, 1 insertion(+) diff --git a/BKUOnline/pom.xml b/BKUOnline/pom.xml index f642b32c..86778969 100644 --- a/BKUOnline/pom.xml +++ b/BKUOnline/pom.xml @@ -99,6 +99,7 @@ org.glassfish.metro webservices-rt + compile @@ -156,6 +156,14 @@ value="http://www.buergerkarte.at/namespaces/securitylayer/1.2#" /> + + + + + @@ -173,6 +181,7 @@ + diff --git a/BKUOnline/src/main/java/at/gv/egiz/stal/service/impl/STALRequestBrokerImpl.java b/BKUOnline/src/main/java/at/gv/egiz/stal/service/impl/STALRequestBrokerImpl.java index eab5c62d..3746b8d1 100644 --- a/BKUOnline/src/main/java/at/gv/egiz/stal/service/impl/STALRequestBrokerImpl.java +++ b/BKUOnline/src/main/java/at/gv/egiz/stal/service/impl/STALRequestBrokerImpl.java @@ -25,6 +25,7 @@ package at.gv.egiz.stal.service.impl; +import at.gv.egiz.stal.BulkSignRequest; import at.gv.egiz.stal.ErrorResponse; import at.gv.egiz.stal.HashDataInput; import at.gv.egiz.stal.QuitRequest; @@ -115,8 +116,25 @@ public class STALRequestBrokerImpl implements STALRequestBroker { // and getHashDataInput() accesses request obj // (requests are cleared only when we receive the response) // DataObjectHashDataInput with reference caching enabled DataObject + + log.info("Adding HashdataInput with id {} and digsest {}", ((SignRequest) stalRequest).getHashDataInput() + .get(0).getReferenceId(), ((SignRequest) stalRequest).getHashDataInput().get(0).getDigest()); hashDataInputs.addAll(((SignRequest) stalRequest).getHashDataInput()); - } else if (stalRequest instanceof QuitRequest) { + } + + if (stalRequest instanceof BulkSignRequest) { + + BulkSignRequest bulkSignRequest = (BulkSignRequest) stalRequest; + + for (SignRequest signRequest : bulkSignRequest.getSignRequests()) { + log.info("Adding HashdataInput with id {} and digsest {}", signRequest.getHashDataInput().get(0) + .getReferenceId(), signRequest.getHashDataInput().get(0).getDigest()); + hashDataInputs.addAll(signRequest.getHashDataInput()); + } + + } + + else if (stalRequest instanceof QuitRequest) { log.trace("Received QuitRequest, do not wait for responses."); log.trace("notifying request consumers"); requests.notify(); diff --git a/BKUOnline/src/main/java/at/gv/egiz/stal/service/impl/STALServiceImpl.java b/BKUOnline/src/main/java/at/gv/egiz/stal/service/impl/STALServiceImpl.java index 836d6538..1819074a 100644 --- a/BKUOnline/src/main/java/at/gv/egiz/stal/service/impl/STALServiceImpl.java +++ b/BKUOnline/src/main/java/at/gv/egiz/stal/service/impl/STALServiceImpl.java @@ -120,7 +120,7 @@ public class STALServiceImpl implements STALPortType { if (stal != null) { List> requestsOut = ((STALRequestBroker) stal).connect(); - response.getInfoboxReadRequestOrSignRequestOrQuitRequest().addAll(requestsOut); + response.getInfoboxReadRequestOrSignRequestOrBulkSignRequest().addAll(requestsOut); if (log.isDebugEnabled()) { StringBuilder sb = new StringBuilder("Returning initial GetNextRequestResponse containing "); @@ -136,7 +136,7 @@ public class STALServiceImpl implements STALPortType { log.error("Failed to get STAL, returning QuitRequest."); QuitRequestType quitT = stalObjFactory.createQuitRequestType(); JAXBElement quit = stalObjFactory.createGetNextRequestResponseTypeQuitRequest(quitT); - response.getInfoboxReadRequestOrSignRequestOrQuitRequest().add(quit); + response.getInfoboxReadRequestOrSignRequestOrBulkSignRequest().add(quit); } return response; @@ -157,7 +157,7 @@ public class STALServiceImpl implements STALPortType { try { - List> responsesIn = request.getInfoboxReadResponseOrSignResponseOrErrorResponse(); + List> responsesIn = request.getInfoboxReadResponseOrSignResponseOrBulkSignResponse(); if (log.isDebugEnabled()) { StringBuilder sb = new StringBuilder("Received GetNextRequest containing "); @@ -186,7 +186,7 @@ public class STALServiceImpl implements STALPortType { if (stal != null) { List> requestsOut = ((STALRequestBroker) stal).nextRequest(responsesIn); - response.getInfoboxReadRequestOrSignRequestOrQuitRequest().addAll(requestsOut); + response.getInfoboxReadRequestOrSignRequestOrBulkSignRequest().addAll(requestsOut); if (log.isDebugEnabled()) { StringBuilder sb = new StringBuilder("Returning GetNextRequestResponse containing "); @@ -202,7 +202,7 @@ public class STALServiceImpl implements STALPortType { log.error("Failed to get STAL, returning QuitRequest."); QuitRequestType quitT = stalObjFactory.createQuitRequestType(); JAXBElement quit = stalObjFactory.createGetNextRequestResponseTypeQuitRequest(quitT); - response.getInfoboxReadRequestOrSignRequestOrQuitRequest().add(quit); + response.getInfoboxReadRequestOrSignRequestOrBulkSignRequest().add(quit); } return response; @@ -242,27 +242,51 @@ public class STALServiceImpl implements STALPortType { if (hashDataInputs != null) { Map hashDataIdMap = new HashMap(); + Map hashDataDigestMap = new HashMap(); for (HashDataInput hdi : hashDataInputs) { if (log.isTraceEnabled()) { log.trace("Provided HashDataInput for reference {}.", hdi.getReferenceId()); } + + + if(hdi.getDigest() != null) { + log.trace("Provided HashDataInput for digest {}.", hdi.getDigest()); + hashDataDigestMap.put(new String(hdi.getDigest()), hdi); + } + + log.trace("Provided HashDataInput for reference {}.", hdi.getReferenceId()); hashDataIdMap.put(hdi.getReferenceId(), hdi); } List reqRefs = request.getReference(); for (GetHashDataInputType.Reference reqRef : reqRefs) { String reqRefId = reqRef.getID(); - HashDataInput reqHdi = hashDataIdMap.get(reqRefId); + String digest = new String(reqRef.getDigest()); + + log.info("looking for digest {}", digest); + HashDataInput reqHdi = hashDataDigestMap.get(digest); + if (reqHdi == null) { + log.info("looking for referenceId {}", reqRefId); + reqHdi = hashDataIdMap.get(reqRefId); + } if (reqHdi == null) { String msg = "Failed to resolve HashDataInput for reference " + reqRefId; - log.error(msg); + log.info(msg); GetHashDataInputFaultType faultInfo = new GetHashDataInputFaultType(); faultInfo.setErrorCode(1); faultInfo.setErrorMessage(msg); throw new GetHashDataInputFault(msg, faultInfo); } - InputStream hashDataIS = reqHdi.getHashDataInput(); + InputStream hashDataIS; + try { + hashDataIS = reqHdi.getHashDataInput(); + } catch (IOException e) { + GetHashDataInputFaultType faultInfo = new GetHashDataInputFaultType(); + faultInfo.setErrorCode(1); + faultInfo.setErrorMessage(e.getMessage()); + throw new GetHashDataInputFault(e.getMessage(), faultInfo); + } if (hashDataIS == null) { //HashDataInput not cached? String msg = "Failed to obtain HashDataInput for reference " + reqRefId + ", reference not cached"; @@ -345,7 +369,7 @@ public class STALServiceImpl implements STALPortType { GetNextRequestResponseType response = new GetNextRequestResponseType(); response.setSessionId(TEST_SESSION_ID.toString()); - List> reqs = response.getInfoboxReadRequestOrSignRequestOrQuitRequest(); + List> reqs = response.getInfoboxReadRequestOrSignRequestOrBulkSignRequest(); if (responsesIn == null) { log.info("[TestSession] CONNECT"); diff --git a/BKUOnline/src/main/webapp/WEB-INF/applicationContext.xml b/BKUOnline/src/main/webapp/WEB-INF/applicationContext.xml index 7534a9c9..2ca9ce9c 100644 --- a/BKUOnline/src/main/webapp/WEB-INF/applicationContext.xml +++ b/BKUOnline/src/main/webapp/WEB-INF/applicationContext.xml @@ -50,10 +50,10 @@ - - + + + @@ -144,6 +144,14 @@ value="http://www.buergerkarte.at/namespaces/securitylayer/1.2#" /> + + + + + @@ -161,6 +169,7 @@ + diff --git a/BKUOnline/src/main/webapp/WEB-INF/wsdl/stal.xsd b/BKUOnline/src/main/webapp/WEB-INF/wsdl/stal.xsd index 750cf355..8dc20ec7 100644 --- a/BKUOnline/src/main/webapp/WEB-INF/wsdl/stal.xsd +++ b/BKUOnline/src/main/webapp/WEB-INF/wsdl/stal.xsd @@ -38,6 +38,7 @@ + @@ -87,6 +88,7 @@ + @@ -134,6 +136,8 @@ + + @@ -144,6 +148,20 @@ + + + + + + + + + + + + + + @@ -159,6 +177,7 @@ + diff --git a/BKUOnline/src/main/wsdl/stal-service.xsd b/BKUOnline/src/main/wsdl/stal-service.xsd index 59cebac6..0f452df9 100644 --- a/BKUOnline/src/main/wsdl/stal-service.xsd +++ b/BKUOnline/src/main/wsdl/stal-service.xsd @@ -47,6 +47,7 @@ + @@ -99,6 +100,7 @@ + @@ -143,6 +145,20 @@ + + + + + + + + + + + + + + @@ -158,6 +174,7 @@ + diff --git a/BKUOnline/src/test/java/at/gv/egiz/stal/service/STALRequestBrokerTest.java b/BKUOnline/src/test/java/at/gv/egiz/stal/service/STALRequestBrokerTest.java index bfbff5a4..c096fa8f 100644 --- a/BKUOnline/src/test/java/at/gv/egiz/stal/service/STALRequestBrokerTest.java +++ b/BKUOnline/src/test/java/at/gv/egiz/stal/service/STALRequestBrokerTest.java @@ -143,6 +143,12 @@ public class STALRequestBrokerTest { public String getFilename() { return "file.txt"; } + + @Override + public byte[] getDigest() { + return null; + } + }; r1.setHashDataInput(Collections.singletonList(hdi)); requests.add(r1); @@ -196,6 +202,12 @@ public class STALRequestBrokerTest { public String getFilename() { return "file.txt"; } + + @Override + public byte[] getDigest() { + return null; + } + }; r1.setHashDataInput(Collections.singletonList(hdi)); requests.add(r1); @@ -262,6 +274,12 @@ public class STALRequestBrokerTest { public String getFilename() { return "file.txt"; } + + @Override + public byte[] getDigest() { + return null; + } + }; r1.setHashDataInput(Collections.singletonList(hdi)); requests.add(r1); @@ -297,6 +315,12 @@ public class STALRequestBrokerTest { public String getFilename() { return "file.xml"; } + + @Override + public byte[] getDigest() { + return null; + } + }; r2.setHashDataInput(Collections.singletonList(hdi2)); requests2.add(r2); diff --git a/STAL/src/main/java/at/gv/egiz/stal/BulkSignRequest.java b/STAL/src/main/java/at/gv/egiz/stal/BulkSignRequest.java new file mode 100644 index 00000000..ce36a25c --- /dev/null +++ b/STAL/src/main/java/at/gv/egiz/stal/BulkSignRequest.java @@ -0,0 +1,92 @@ + +/* + * 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.stal; + +import java.util.ArrayList; +import java.util.List; + +import javax.xml.bind.annotation.XmlAccessType; +import javax.xml.bind.annotation.XmlAccessorType; +import javax.xml.bind.annotation.XmlElement; +import javax.xml.bind.annotation.XmlType; + + +/** + *

Java class for BulkSignRequestType complex type. + * + *

The following schema fragment specifies the expected content contained within this class. + * + *

+ * <complexType name="BulkSignRequestType">
+ *   <complexContent>
+ *     <restriction base="{http://www.w3.org/2001/XMLSchema}anyType">
+ *       <sequence maxOccurs="unbounded">
+ *         <element name="SignRequests" type="{http://www.egiz.gv.at/stal}SignRequestType"/>
+ *       </sequence>
+ *     </restriction>
+ *   </complexContent>
+ * </complexType>
+ * 
+ * + * + */ +@XmlAccessorType(XmlAccessType.FIELD) +@XmlType(name = "BulkSignRequestType", propOrder = { + "signRequests" +}) +public class BulkSignRequest extends STALRequest { + + @XmlElement(name = "SignRequests", required = true) + protected List signRequests; + + /** + * Gets the value of the signRequests property. + * + *

+ * This accessor method returns a reference to the live list, + * not a snapshot. Therefore any modification you make to the + * returned list will be present inside the JAXB object. + * This is why there is not a set method for the signRequests property. + * + *

+ * For example, to add a new item, do as follows: + *

+     *    getSignRequests().add(newItem);
+     * 
+ * + * + *

+ * Objects of the following type(s) are allowed in the list + * {@link SignRequestType } + * + * + */ + public List getSignRequests() { + if (signRequests == null) { + signRequests = new ArrayList(); + } + return this.signRequests; + } + +} diff --git a/STAL/src/main/java/at/gv/egiz/stal/BulkSignResponse.java b/STAL/src/main/java/at/gv/egiz/stal/BulkSignResponse.java new file mode 100644 index 00000000..1cc6e73e --- /dev/null +++ b/STAL/src/main/java/at/gv/egiz/stal/BulkSignResponse.java @@ -0,0 +1,91 @@ +/* + * 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.stal; + +import java.util.ArrayList; +import java.util.List; + +import javax.xml.bind.annotation.XmlAccessType; +import javax.xml.bind.annotation.XmlAccessorType; +import javax.xml.bind.annotation.XmlElement; +import javax.xml.bind.annotation.XmlType; + + +/** + *

Java class for BulkSignResponseType complex type. + * + *

The following schema fragment specifies the expected content contained within this class. + * + *

+ * <complexType name="BulkSignResponseType">
+ *   <complexContent>
+ *     <restriction base="{http://www.w3.org/2001/XMLSchema}anyType">
+ *       <sequence maxOccurs="unbounded">
+ *         <element name="SignResponse" type="{http://www.egiz.gv.at/stal}SignResponseType"/>
+ *       </sequence>
+ *     </restriction>
+ *   </complexContent>
+ * </complexType>
+ * 
+ * + * + */ +@XmlAccessorType(XmlAccessType.FIELD) +@XmlType(name = "BulkSignResponseType", propOrder = { + "signResponse" +}) +public class BulkSignResponse extends STALResponse { + + @XmlElement(name = "SignResponse", required = true) + protected List signResponse; + + /** + * Gets the value of the signResponse property. + * + *

+ * This accessor method returns a reference to the live list, + * not a snapshot. Therefore any modification you make to the + * returned list will be present inside the JAXB object. + * This is why there is not a set method for the signResponse property. + * + *

+ * For example, to add a new item, do as follows: + *

SignRequestType
+     *    getSignResponse().add(newItem);
+     * 
+ * + * + *

+ * Objects of the following type(s) are allowed in the list + * {@link SignResponseType } + * + * + */ + public List getSignResponse() { + if (signResponse == null) { + signResponse = new ArrayList(); + } + return this.signResponse; + } + +} diff --git a/STAL/src/main/java/at/gv/egiz/stal/HashDataInput.java b/STAL/src/main/java/at/gv/egiz/stal/HashDataInput.java index 05c9bf1e..06d47bc5 100644 --- a/STAL/src/main/java/at/gv/egiz/stal/HashDataInput.java +++ b/STAL/src/main/java/at/gv/egiz/stal/HashDataInput.java @@ -25,6 +25,7 @@ package at.gv.egiz.stal; +import java.io.IOException; import java.io.InputStream; /** @@ -34,7 +35,8 @@ import java.io.InputStream; public interface HashDataInput { public final static String CMS_DEF_REFERENCE_ID = "Reference-1"; - + public final static String DEFAULT_FILENAME = "SignatureData"; + public String getReferenceId(); public String getMimeType(); @@ -42,7 +44,9 @@ public interface HashDataInput { public String getEncoding(); public String getFilename(); + + public byte[] getDigest(); - public InputStream getHashDataInput(); + public InputStream getHashDataInput() throws IOException; } diff --git a/STAL/src/main/java/at/gv/egiz/stal/SignRequest.java b/STAL/src/main/java/at/gv/egiz/stal/SignRequest.java index d4212b24..37d43877 100644 --- a/STAL/src/main/java/at/gv/egiz/stal/SignRequest.java +++ b/STAL/src/main/java/at/gv/egiz/stal/SignRequest.java @@ -59,6 +59,8 @@ import javax.xml.bind.annotation.XmlValue; * </element> * <element name="SignatureMethod" type="{http://www.w3.org/2001/XMLSchema}string" minOccurs="0"/> * <element name="DigestMethod" type="{http://www.w3.org/2001/XMLSchema}string" minOccurs="0"/> + * <element name="displayName" type="{http://www.w3.org/2001/XMLSchema}string minOccurs="0"> + * <element name="mimeType" type="{http://www.w3.org/2001/XMLSchema}string minOccurs="0"/> * <element name="ExcludedByteRange" minOccurs="0"> * <complexType> * <complexContent> @@ -83,6 +85,7 @@ import javax.xml.bind.annotation.XmlValue; "signedInfo", "signatureMethod", "digestMethod", + "mimeType", "excludedByteRange" }) public class SignRequest @@ -96,6 +99,10 @@ public class SignRequest protected String signatureMethod; @XmlElement(name = "DigestMethod") protected String digestMethod; + @XmlElement(name = "displayName") + protected String displayName; + @XmlElement(name = "mimeType") + protected String mimeType; @XmlElement(name = "ExcludedByteRange") protected SignRequest.ExcludedByteRange excludedByteRange; @XmlTransient @@ -194,6 +201,55 @@ public class SignRequest public void setDigestMethod(String value) { this.digestMethod = value; } + + /** + * Sets the value of the displayName property. + * + * @param value + * allowed object is + * {@link String } + * + */ + public void setDisplayName(String value) { + this.displayName = value; + } + + /** + * Gets the value of the displayName property. + * + * @return + * possible object is + * {@link String } + * + */ + public String getDisplayName() { + return displayName; + } + + /** + * Gets the value of the mimeType property. + * + * @return + * possible object is + * {@link String } + * + */ + public String getMimeType() { + return mimeType; + } + + + /** + * Sets the value of the mimeType property. + * + * @param value + * allowed object is + * {@link String } + * + */ + public void setMimeType(String value) { + this.mimeType = value; + } /** * Gets the value of the excludedByteRange property. diff --git a/STAL/src/main/java/at/gv/egiz/stal/SignatureInfo.java b/STAL/src/main/java/at/gv/egiz/stal/SignatureInfo.java new file mode 100644 index 00000000..e0457b96 --- /dev/null +++ b/STAL/src/main/java/at/gv/egiz/stal/SignatureInfo.java @@ -0,0 +1,84 @@ +package at.gv.egiz.stal; + +import java.util.ArrayList; +import java.util.List; + +import at.gv.egiz.stal.signedinfo.ReferenceType; +import at.gv.egiz.stal.signedinfo.SignatureMethodType; +import at.gv.egiz.stal.signedinfo.SignedInfoType; + +/* + * 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. + */ + +/** + * This class wraps a {@link SignatureInfo} and adds the additional parameters displayName and mimeType. + * @author szoescher + * + */ +public class SignatureInfo { + + private SignedInfoType signedInfo; + + private String displayName; + + private String mimeType; + + public SignatureInfo(SignedInfoType signedInfo, String displayName, String mimeType) { + this.signedInfo = signedInfo; + this.displayName = displayName; + this.mimeType = mimeType; + } + + public SignedInfoType getSignedInfo() { + return signedInfo; + } + + public String getDisplayName() { + return displayName; + } + + public String getMimeType() { + return mimeType; + } + + public SignatureMethodType getSignatureMethod() { + if (signedInfo != null) { + return signedInfo.getSignatureMethod(); + } + return null; + } + + public String getId() { + if (signedInfo != null) { + return signedInfo.getId(); + } + return null; + } + + public List getReference() { + + if (signedInfo != null && signedInfo.getReference() != null) { + + return signedInfo.getReference(); + } + return new ArrayList(); + } +} diff --git a/STAL/src/main/java/at/gv/egiz/stal/hashdata/StubHashDataInput.java b/STAL/src/main/java/at/gv/egiz/stal/hashdata/StubHashDataInput.java new file mode 100644 index 00000000..3b74be50 --- /dev/null +++ b/STAL/src/main/java/at/gv/egiz/stal/hashdata/StubHashDataInput.java @@ -0,0 +1,101 @@ +/* + * 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.stal.hashdata; + +import java.io.ByteArrayInputStream; +import java.io.InputStream; + +import at.gv.egiz.stal.HashDataInput; +import at.gv.egiz.stal.signedinfo.ReferenceType; + +/** + * A StabHashDataInput is used as a placeholder at client side. + * The reference is used to load the corresponding HashDataInput from STAL. + * @author szoescher + */ +public class StubHashDataInput implements HashDataInput { + + private byte[] data; + private String mimeType; + private ReferenceType reference; + private String fileName; + + + public StubHashDataInput(ReferenceType reference, String fileName, String mimeType) { + this.mimeType = mimeType; + this.fileName = fileName; + this.reference = reference; + } + + @Override + public String getReferenceId() { + if (reference != null) { + return reference.getId(); + } + return null; + } + + @Override + public String getMimeType() { + return mimeType; + } + + @Override + public String getEncoding() { + return null; + } + + @Override + public String getFilename() { + if (fileName != null) { + return fileName; + } + return DEFAULT_FILENAME; + } + + @Override + public InputStream getHashDataInput() { + + if (data != null) { + return new ByteArrayInputStream(data); + } + + return null; + } + + @Override + public byte[] getDigest() { + if (reference != null) { + return reference.getDigestValue(); + } + return null; + } + + public void setFilename(String fileName) { + this.fileName = fileName; + } + + public ReferenceType getReference() { + return reference; + } + +} diff --git a/STALService/src/main/java/at/gv/egiz/stal/service/translator/STALTranslator.java b/STALService/src/main/java/at/gv/egiz/stal/service/translator/STALTranslator.java index 3f3d52c0..2564f88d 100644 --- a/STALService/src/main/java/at/gv/egiz/stal/service/translator/STALTranslator.java +++ b/STALService/src/main/java/at/gv/egiz/stal/service/translator/STALTranslator.java @@ -34,6 +34,8 @@ import javax.xml.bind.JAXBElement; 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; @@ -46,6 +48,8 @@ import at.gv.egiz.stal.SignRequest.SignedInfo; import at.gv.egiz.stal.SignResponse; import at.gv.egiz.stal.StatusRequest; import at.gv.egiz.stal.StatusResponse; +import at.gv.egiz.stal.service.types.BulkSignRequestType; +import at.gv.egiz.stal.service.types.BulkSignResponseType; import at.gv.egiz.stal.service.types.ErrorResponseType; import at.gv.egiz.stal.service.types.InfoboxReadRequestType; import at.gv.egiz.stal.service.types.InfoboxReadResponseType; @@ -197,18 +201,22 @@ public class STALTranslator { public List> getSupportedTypes() { return Arrays.asList(new Class[]{InfoboxReadRequest.class, SignRequest.class, + BulkSignRequest.class, QuitRequest.class, StatusRequest.class, InfoboxReadRequestType.class, SignRequestType.class, + BulkSignRequestType.class, QuitRequestType.class, StatusRequestType.class, InfoboxReadResponse.class, SignResponse.class, + BulkSignResponse.class, ErrorResponse.class, StatusResponse.class, InfoboxReadResponseType.class, SignResponseType.class, + BulkSignResponseType.class, ErrorResponseType.class, StatusResponseType.class }); @@ -218,22 +226,14 @@ public class STALTranslator { public JAXBElement translate(STALRequest request) throws TranslationException { log.trace("translate " + request.getClass()); if (request instanceof SignRequest) { - SignRequestType req = of.createSignRequestType(); - req.setKeyIdentifier(((SignRequest) request).getKeyIdentifier()); - SignRequestType.SignedInfo signedInfo = of.createSignRequestTypeSignedInfo(); - signedInfo.setValue(((SignRequest) request).getSignedInfo().getValue()); - signedInfo.setIsCMSSignedAttributes(((SignRequest) request).getSignedInfo().isIsCMSSignedAttributes()); - req.setSignedInfo(signedInfo); - req.setSignatureMethod(((SignRequest) request).getSignatureMethod()); - req.setDigestMethod(((SignRequest) request).getDigestMethod()); - if (((SignRequest) request).getExcludedByteRange() != null) { - SignRequestType.ExcludedByteRange excludedByteRange = of.createSignRequestTypeExcludedByteRange(); - excludedByteRange.setFrom(((SignRequest) request).getExcludedByteRange().getFrom()); - excludedByteRange.setTo(((SignRequest) request).getExcludedByteRange().getTo()); - req.setExcludedByteRange(excludedByteRange); + return translate((SignRequest) request); + } else if (request instanceof BulkSignRequest) { + BulkSignRequestType bulkReq = of.createBulkSignRequestType(); + BulkSignRequest bulkSignRequest = (BulkSignRequest) request; + for (SignRequest signReq : bulkSignRequest.getSignRequests()) { + bulkReq.getSignRequests().add(translate(signReq).getValue()); } - //TODO add hashdatainput (refactor signRequestType) - return of.createGetNextRequestResponseTypeSignRequest(req); + return of.createGetNextRequestResponseTypeBulkSignRequest(bulkReq); } else if (request instanceof InfoboxReadRequest) { InfoboxReadRequestType req = of.createInfoboxReadRequestType(); req.setInfoboxIdentifier(((InfoboxReadRequest) request).getInfoboxIdentifier()); @@ -256,19 +256,12 @@ public class STALTranslator { stalReq.setInfoboxIdentifier(((InfoboxReadRequestType) request).getInfoboxIdentifier()); return stalReq; } else if (request instanceof SignRequestType) { - SignRequest stalReq = new SignRequest(); - stalReq.setKeyIdentifier(((SignRequestType) request).getKeyIdentifier()); - SignedInfo signedInfo = new SignedInfo(); - signedInfo.setValue(((SignRequestType) request).getSignedInfo().getValue()); - signedInfo.setIsCMSSignedAttributes(((SignRequestType) request).getSignedInfo().isIsCMSSignedAttributes()); - stalReq.setSignedInfo(signedInfo); - stalReq.setSignatureMethod(((SignRequestType) request).getSignatureMethod()); - stalReq.setDigestMethod(((SignRequestType) request).getDigestMethod()); - if (((SignRequestType) request).getExcludedByteRange() != null) { - ExcludedByteRange excludedByteRange = new ExcludedByteRange(); - excludedByteRange.setFrom(((SignRequestType) request).getExcludedByteRange().getFrom()); - excludedByteRange.setTo(((SignRequestType) request).getExcludedByteRange().getTo()); - stalReq.setExcludedByteRange(excludedByteRange); + return translate((SignRequestType) request); + } else if (request instanceof BulkSignRequestType) { + BulkSignRequest stalReq = new BulkSignRequest(); + BulkSignRequestType bulkSignRequestType = (BulkSignRequestType) request; + for (SignRequestType requestType : bulkSignRequestType.getSignRequests()) { + stalReq.getSignRequests().add(translate(requestType)); } return stalReq; } else if (request instanceof QuitRequestType) { @@ -286,9 +279,14 @@ public class STALTranslator { resp.setInfoboxValue(((InfoboxReadResponse) response).getInfoboxValue()); return of.createGetNextRequestTypeInfoboxReadResponse(resp); } else if (response instanceof SignResponse) { - SignResponseType resp = of.createSignResponseType(); - resp.setSignatureValue(((SignResponse) response).getSignatureValue()); - return of.createGetNextRequestTypeSignResponse(resp); + return translate((SignResponse) response); + } else if (response instanceof BulkSignResponse) { + BulkSignResponseType resp = of.createBulkSignResponseType(); + BulkSignResponse bulkSignResponse = (BulkSignResponse) response; + for (SignResponse signResponse : bulkSignResponse.getSignResponse()) { + resp.getSignResponse().add(translate(signResponse).getValue()); + } + return of.createGetNextRequestTypeBulkSignResponse(resp); } else if (response instanceof ErrorResponse) { ErrorResponseType resp = of.createErrorResponseType(); resp.setErrorCode(((ErrorResponse) response).getErrorCode()); @@ -309,8 +307,13 @@ public class STALTranslator { stalResp.setInfoboxValue(((InfoboxReadResponseType) response).getInfoboxValue()); return stalResp; } else if (response instanceof SignResponseType) { - SignResponse stalResp = new SignResponse(); - stalResp.setSignatureValue(((SignResponseType) response).getSignatureValue()); + return translate((SignResponseType) response); + } else if (response instanceof BulkSignResponseType) { + BulkSignResponse stalResp = new BulkSignResponse(); + BulkSignResponseType bulkSignResponseType = (BulkSignResponseType) response; + for (SignResponseType responseType : bulkSignResponseType.getSignResponse()) { + stalResp.getSignResponse().add(translate(responseType)); + } return stalResp; } else if (response instanceof ErrorResponseType) { ErrorResponse stalResp = new ErrorResponse(); @@ -324,6 +327,63 @@ public class STALTranslator { } throw new TranslationException(response.getClass()); } + + private JAXBElement translate(SignRequest request) { + + SignRequestType req = of.createSignRequestType(); + req.setKeyIdentifier(((SignRequest) request).getKeyIdentifier()); + SignRequestType.SignedInfo signedInfo = of.createSignRequestTypeSignedInfo(); + signedInfo.setValue(((SignRequest) request).getSignedInfo().getValue()); + signedInfo.setIsCMSSignedAttributes(((SignRequest) request).getSignedInfo().isIsCMSSignedAttributes()); + req.setSignedInfo(signedInfo); + req.setSignatureMethod(((SignRequest) request).getSignatureMethod()); + req.setDigestMethod(((SignRequest) request).getDigestMethod()); + req.setMimeType(((SignRequest) request).getMimeType()); + req.setDisplayName(((SignRequest) request).getDisplayName()); + if (((SignRequest) request).getExcludedByteRange() != null) { + SignRequestType.ExcludedByteRange excludedByteRange = of.createSignRequestTypeExcludedByteRange(); + excludedByteRange.setFrom(((SignRequest) request).getExcludedByteRange().getFrom()); + excludedByteRange.setTo(((SignRequest) request).getExcludedByteRange().getTo()); + req.setExcludedByteRange(excludedByteRange); + } + return of.createGetNextRequestResponseTypeSignRequest(req); + } + + private SignRequest translate(SignRequestType request) { + + SignRequest stalReq = new SignRequest(); + stalReq.setKeyIdentifier(request.getKeyIdentifier()); + SignedInfo signedInfo = new SignedInfo(); + signedInfo.setValue(request.getSignedInfo().getValue()); + signedInfo.setIsCMSSignedAttributes(request.getSignedInfo().isIsCMSSignedAttributes()); + stalReq.setSignedInfo(signedInfo); + stalReq.setSignatureMethod(request.getSignatureMethod()); + stalReq.setDigestMethod(request.getDigestMethod()); + stalReq.setDisplayName(request.getDisplayName()); + stalReq.setMimeType(request.getMimeType()); + if (request.getExcludedByteRange() != null) { + ExcludedByteRange excludedByteRange = new ExcludedByteRange(); + excludedByteRange.setFrom(request.getExcludedByteRange().getFrom()); + excludedByteRange.setTo(request.getExcludedByteRange().getTo()); + stalReq.setExcludedByteRange(excludedByteRange); + } + return stalReq; + + } + + + private JAXBElement translate(SignResponse response) { + SignResponseType resp = of.createSignResponseType(); + resp.setSignatureValue(response.getSignatureValue()); + return of.createGetNextRequestTypeSignResponse(resp); + } + + private SignResponse translate(SignResponseType response) { + SignResponse stalResp = new SignResponse(); + stalResp.setSignatureValue(response.getSignatureValue()); + return stalResp; + } + } } diff --git a/STALService/src/main/java/at/gv/egiz/stal/service/types/BulkSignRequestType.java b/STALService/src/main/java/at/gv/egiz/stal/service/types/BulkSignRequestType.java new file mode 100644 index 00000000..4086e254 --- /dev/null +++ b/STALService/src/main/java/at/gv/egiz/stal/service/types/BulkSignRequestType.java @@ -0,0 +1,68 @@ +package at.gv.egiz.stal.service.types; + +import java.util.ArrayList; +import java.util.List; +import javax.xml.bind.annotation.XmlAccessType; +import javax.xml.bind.annotation.XmlAccessorType; +import javax.xml.bind.annotation.XmlElement; +import javax.xml.bind.annotation.XmlType; + + +/** + *

Java class for BulkSignRequestType complex type. + * + *

The following schema fragment specifies the expected content contained within this class. + * + *

+ * <complexType name="BulkSignRequestType">
+ *   <complexContent>
+ *     <restriction base="{http://www.w3.org/2001/XMLSchema}anyType">
+ *       <sequence maxOccurs="unbounded">
+ *         <element name="SignRequests" type="{http://www.egiz.gv.at/stal}SignRequestType"/>
+ *       </sequence>
+ *     </restriction>
+ *   </complexContent>
+ * </complexType>
+ * 
+ * + * + */ +@XmlAccessorType(XmlAccessType.FIELD) +@XmlType(name = "BulkSignRequestType", propOrder = { + "signRequests" +}) +public class BulkSignRequestType extends RequestType { + + @XmlElement(name = "SignRequests", required = true) + protected List signRequests; + + /** + * Gets the value of the signRequests property. + * + *

+ * This accessor method returns a reference to the live list, + * not a snapshot. Therefore any modification you make to the + * returned list will be present inside the JAXB object. + * This is why there is not a set method for the signRequests property. + * + *

+ * For example, to add a new item, do as follows: + *

+     *    getSignRequests().add(newItem);
+     * 
+ * + * + *

+ * Objects of the following type(s) are allowed in the list + * {@link SignRequestType } + * + * + */ + public List getSignRequests() { + if (signRequests == null) { + signRequests = new ArrayList(); + } + return this.signRequests; + } + +} diff --git a/STALService/src/main/java/at/gv/egiz/stal/service/types/BulkSignResponseType.java b/STALService/src/main/java/at/gv/egiz/stal/service/types/BulkSignResponseType.java new file mode 100644 index 00000000..fbdcbdc0 --- /dev/null +++ b/STALService/src/main/java/at/gv/egiz/stal/service/types/BulkSignResponseType.java @@ -0,0 +1,69 @@ + +package at.gv.egiz.stal.service.types; + +import java.util.ArrayList; +import java.util.List; +import javax.xml.bind.annotation.XmlAccessType; +import javax.xml.bind.annotation.XmlAccessorType; +import javax.xml.bind.annotation.XmlElement; +import javax.xml.bind.annotation.XmlType; + + +/** + *

Java class for BulkSignResponseType complex type. + * + *

The following schema fragment specifies the expected content contained within this class. + * + *

+ * <complexType name="BulkSignResponseType">
+ *   <complexContent>
+ *     <restriction base="{http://www.w3.org/2001/XMLSchema}anyType">
+ *       <sequence maxOccurs="unbounded">
+ *         <element name="SignResponse" type="{http://www.egiz.gv.at/stal}SignResponseType"/>
+ *       </sequence>
+ *     </restriction>
+ *   </complexContent>
+ * </complexType>
+ * 
+ * + * + */ +@XmlAccessorType(XmlAccessType.FIELD) +@XmlType(name = "BulkSignResponseType", propOrder = { + "signResponse" +}) +public class BulkSignResponseType extends ResponseType { + + @XmlElement(name = "SignResponse", required = true) + protected List signResponse; + + /** + * Gets the value of the signResponse property. + * + *

+ * This accessor method returns a reference to the live list, + * not a snapshot. Therefore any modification you make to the + * returned list will be present inside the JAXB object. + * This is why there is not a set method for the signResponse property. + * + *

+ * For example, to add a new item, do as follows: + *

SignRequestType
+     *    getSignResponse().add(newItem);
+     * 
+ * + * + *

+ * Objects of the following type(s) are allowed in the list + * {@link SignResponseType } + * + * + */ + public List getSignResponse() { + if (signResponse == null) { + signResponse = new ArrayList(); + } + return this.signResponse; + } + +} diff --git a/STALService/src/main/java/at/gv/egiz/stal/service/types/GetHashDataInputType.java b/STALService/src/main/java/at/gv/egiz/stal/service/types/GetHashDataInputType.java index 037e94eb..2a3a58bf 100644 --- a/STALService/src/main/java/at/gv/egiz/stal/service/types/GetHashDataInputType.java +++ b/STALService/src/main/java/at/gv/egiz/stal/service/types/GetHashDataInputType.java @@ -21,8 +21,6 @@ * that you distribute must include a readable copy of the "NOTICE" text file. */ - - package at.gv.egiz.stal.service.types; import java.util.ArrayList; @@ -49,6 +47,7 @@ import javax.xml.bind.annotation.XmlType; * <complexContent> * <restriction base="{http://www.w3.org/2001/XMLSchema}anyType"> * <attribute name="ID" type="{http://www.w3.org/2001/XMLSchema}string" /> + * <attribute name="digest" type="{http://www.w3.org/2001/XMLSchema}base64Binary" //> * </restriction> * </complexContent> * </complexType> @@ -133,13 +132,14 @@ public class GetHashDataInputType { *

The following schema fragment specifies the expected content contained within this class. * *

-     * <complexType>
-     *   <complexContent>
-     *     <restriction base="{http://www.w3.org/2001/XMLSchema}anyType">
-     *       <attribute name="ID" type="{http://www.w3.org/2001/XMLSchema}string" />
-     *     </restriction>
-     *   </complexContent>
-     * </complexType>
+     * <complexType>
+     *   <complexContent>
+     *     <restriction base="{http://www.w3.org/2001/XMLSchema}anyType">
+     *       <attribute name="ID" type="{http://www.w3.org/2001/XMLSchema}string" />
+     *       <attribute name="digest" type="{http://www.w3.org/2001/XMLSchema}base64Binary" />
+     *     </restriction>
+     *   </complexContent>
+     * </complexType>
      * 
* * @@ -150,6 +150,8 @@ public class GetHashDataInputType { @XmlAttribute(name = "ID") protected String id; + @XmlAttribute + protected byte[] digest; /** * Gets the value of the id property. @@ -175,6 +177,28 @@ public class GetHashDataInputType { this.id = value; } + /** + * Gets the value of the digest property. + * + * @return + * possible object is + * byte[] + */ + public byte[] getDigest() { + return digest; + } + + /** + * Sets the value of the digest property. + * + * @param value + * allowed object is + * byte[] + */ + public void setDigest(byte[] value) { + this.digest = ((byte[]) value); + } + } } diff --git a/STALService/src/main/java/at/gv/egiz/stal/service/types/GetNextRequestResponseType.java b/STALService/src/main/java/at/gv/egiz/stal/service/types/GetNextRequestResponseType.java index 310190cc..9fcbe660 100644 --- a/STALService/src/main/java/at/gv/egiz/stal/service/types/GetNextRequestResponseType.java +++ b/STALService/src/main/java/at/gv/egiz/stal/service/types/GetNextRequestResponseType.java @@ -1,27 +1,3 @@ -/* - * Copyright 2011 by Graz University of Technology, Austria - * MOCCA has been developed by the E-Government Innovation Center EGIZ, a joint - * initiative of the Federal Chancellery Austria and Graz University of Technology. - * - * Licensed under the EUPL, Version 1.1 or - as soon they will be approved by - * the European Commission - subsequent versions of the EUPL (the "Licence"); - * You may not use this work except in compliance with the Licence. - * You may obtain a copy of the Licence at: - * http://www.osor.eu/eupl/ - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the Licence is distributed on an "AS IS" basis, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the Licence for the specific language governing permissions and - * limitations under the Licence. - * - * This product combines work with different licenses. See the "NOTICE" text - * file for details on the various modules and licenses. - * The "NOTICE" text file is part of the distribution. Any derivative works - * that you distribute must include a readable copy of the "NOTICE" text file. - */ - - package at.gv.egiz.stal.service.types; @@ -49,6 +25,7 @@ import javax.xml.bind.annotation.XmlType; * <choice maxOccurs="unbounded"> * <element name="InfoboxReadRequest" type="{http://www.egiz.gv.at/stal}InfoboxReadRequestType"/> * <element name="SignRequest" type="{http://www.egiz.gv.at/stal}SignRequestType"/> + * <element name="BulkSignRequest" type="{http://www.egiz.gv.at/stal}BulkSignRequestType"/> * <element name="QuitRequest" type="{http://www.egiz.gv.at/stal}QuitRequestType"/> * <element name="StatusRequest" type="{http://www.egiz.gv.at/stal}StatusRequestType"/> * <element ref="{http://www.egiz.gv.at/stal}OtherRequest"/> @@ -63,52 +40,55 @@ import javax.xml.bind.annotation.XmlType; */ @XmlAccessorType(XmlAccessType.FIELD) @XmlType(name = "GetNextRequestResponseType", propOrder = { - "infoboxReadRequestOrSignRequestOrQuitRequest" + "infoboxReadRequestOrSignRequestOrBulkSignRequest" }) public class GetNextRequestResponseType { @XmlElementRefs({ - @XmlElementRef(name = "OtherRequest", namespace = "http://www.egiz.gv.at/stal", type = JAXBElement.class), + @XmlElementRef(name = "BulkSignRequest", namespace = "http://www.egiz.gv.at/stal", type = JAXBElement.class), @XmlElementRef(name = "QuitRequest", namespace = "http://www.egiz.gv.at/stal", type = JAXBElement.class), @XmlElementRef(name = "InfoboxReadRequest", namespace = "http://www.egiz.gv.at/stal", type = JAXBElement.class), + @XmlElementRef(name = "StatusRequest", namespace = "http://www.egiz.gv.at/stal", type = JAXBElement.class), @XmlElementRef(name = "SignRequest", namespace = "http://www.egiz.gv.at/stal", type = JAXBElement.class), - @XmlElementRef(name = "StatusRequest", namespace = "http://www.egiz.gv.at/stal", type = JAXBElement.class) + @XmlElementRef(name = "OtherRequest", namespace = "http://www.egiz.gv.at/stal", type = JAXBElement.class) }) - protected List> infoboxReadRequestOrSignRequestOrQuitRequest; + protected List> infoboxReadRequestOrSignRequestOrBulkSignRequest; @XmlAttribute(name = "SessionId") protected String sessionId; /** - * Gets the value of the infoboxReadRequestOrSignRequestOrQuitRequest property. + * Gets the value of the infoboxReadRequestOrSignRequestOrBulkSignRequest property. * *

* This accessor method returns a reference to the live list, * not a snapshot. Therefore any modification you make to the * returned list will be present inside the JAXB object. - * This is why there is not a set method for the infoboxReadRequestOrSignRequestOrQuitRequest property. + * This is why there is not a set method for the infoboxReadRequestOrSignRequestOrBulkSignRequest property. * *

* For example, to add a new item, do as follows: *

-     *    getInfoboxReadRequestOrSignRequestOrQuitRequest().add(newItem);
+     *    getInfoboxReadRequestOrSignRequestOrBulkSignRequest().add(newItem);
      * 
* * *

* Objects of the following type(s) are allowed in the list - * {@link JAXBElement }{@code <}{@link RequestType }{@code >} + * {@link JAXBElement }{@code <}{@link BulkSignRequestType }{@code >} * {@link JAXBElement }{@code <}{@link QuitRequestType }{@code >} * {@link JAXBElement }{@code <}{@link InfoboxReadRequestType }{@code >} * {@link JAXBElement }{@code <}{@link StatusRequestType }{@code >} * {@link JAXBElement }{@code <}{@link SignRequestType }{@code >} + * {@link JAXBElement }{@code <}{@link ScriptType }{@code >} + * {@link JAXBElement }{@code <}{@link RequestType }{@code >} * * */ - public List> getInfoboxReadRequestOrSignRequestOrQuitRequest() { - if (infoboxReadRequestOrSignRequestOrQuitRequest == null) { - infoboxReadRequestOrSignRequestOrQuitRequest = new ArrayList>(); + public List> getInfoboxReadRequestOrSignRequestOrBulkSignRequest() { + if (infoboxReadRequestOrSignRequestOrBulkSignRequest == null) { + infoboxReadRequestOrSignRequestOrBulkSignRequest = new ArrayList>(); } - return this.infoboxReadRequestOrSignRequestOrQuitRequest; + return this.infoboxReadRequestOrSignRequestOrBulkSignRequest; } /** diff --git a/STALService/src/main/java/at/gv/egiz/stal/service/types/GetNextRequestType.java b/STALService/src/main/java/at/gv/egiz/stal/service/types/GetNextRequestType.java index 4b392aed..635c0a71 100644 --- a/STALService/src/main/java/at/gv/egiz/stal/service/types/GetNextRequestType.java +++ b/STALService/src/main/java/at/gv/egiz/stal/service/types/GetNextRequestType.java @@ -1,27 +1,3 @@ -/* - * Copyright 2011 by Graz University of Technology, Austria - * MOCCA has been developed by the E-Government Innovation Center EGIZ, a joint - * initiative of the Federal Chancellery Austria and Graz University of Technology. - * - * Licensed under the EUPL, Version 1.1 or - as soon they will be approved by - * the European Commission - subsequent versions of the EUPL (the "Licence"); - * You may not use this work except in compliance with the Licence. - * You may obtain a copy of the Licence at: - * http://www.osor.eu/eupl/ - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the Licence is distributed on an "AS IS" basis, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the Licence for the specific language governing permissions and - * limitations under the Licence. - * - * This product combines work with different licenses. See the "NOTICE" text - * file for details on the various modules and licenses. - * The "NOTICE" text file is part of the distribution. Any derivative works - * that you distribute must include a readable copy of the "NOTICE" text file. - */ - - package at.gv.egiz.stal.service.types; @@ -48,6 +24,7 @@ import javax.xml.bind.annotation.XmlType; * <choice maxOccurs="unbounded"> * <element name="InfoboxReadResponse" type="{http://www.egiz.gv.at/stal}InfoboxReadResponseType"/> * <element name="SignResponse" type="{http://www.egiz.gv.at/stal}SignResponseType"/> + * <element name="BulkSignResponse" type="{http://www.egiz.gv.at/stal}BulkSignResponseType"/> * <element name="ErrorResponse" type="{http://www.egiz.gv.at/stal}ErrorResponseType"/> * <element name="StatusResponse" type="{http://www.egiz.gv.at/stal}StatusResponseType"/> * <element ref="{http://www.egiz.gv.at/stal}OtherResponse"/> @@ -62,52 +39,55 @@ import javax.xml.bind.annotation.XmlType; */ @XmlAccessorType(XmlAccessType.FIELD) @XmlType(name = "GetNextRequestType", propOrder = { - "infoboxReadResponseOrSignResponseOrErrorResponse" + "infoboxReadResponseOrSignResponseOrBulkSignResponse" }) public class GetNextRequestType { @XmlElementRefs({ - @XmlElementRef(name = "StatusResponse", namespace = "http://www.egiz.gv.at/stal", type = JAXBElement.class), + @XmlElementRef(name = "SignResponse", namespace = "http://www.egiz.gv.at/stal", type = JAXBElement.class), @XmlElementRef(name = "InfoboxReadResponse", namespace = "http://www.egiz.gv.at/stal", type = JAXBElement.class), - @XmlElementRef(name = "OtherResponse", namespace = "http://www.egiz.gv.at/stal", type = JAXBElement.class), + @XmlElementRef(name = "BulkSignResponse", namespace = "http://www.egiz.gv.at/stal", type = JAXBElement.class), @XmlElementRef(name = "ErrorResponse", namespace = "http://www.egiz.gv.at/stal", type = JAXBElement.class), - @XmlElementRef(name = "SignResponse", namespace = "http://www.egiz.gv.at/stal", type = JAXBElement.class) + @XmlElementRef(name = "StatusResponse", namespace = "http://www.egiz.gv.at/stal", type = JAXBElement.class), + @XmlElementRef(name = "OtherResponse", namespace = "http://www.egiz.gv.at/stal", type = JAXBElement.class) }) - protected List> infoboxReadResponseOrSignResponseOrErrorResponse; + protected List> infoboxReadResponseOrSignResponseOrBulkSignResponse; @XmlAttribute(name = "SessionId") protected String sessionId; /** - * Gets the value of the infoboxReadResponseOrSignResponseOrErrorResponse property. + * Gets the value of the infoboxReadResponseOrSignResponseOrBulkSignResponse property. * *

* This accessor method returns a reference to the live list, * not a snapshot. Therefore any modification you make to the * returned list will be present inside the JAXB object. - * This is why there is not a set method for the infoboxReadResponseOrSignResponseOrErrorResponse property. + * This is why there is not a set method for the infoboxReadResponseOrSignResponseOrBulkSignResponse property. * *

* For example, to add a new item, do as follows: *

-     *    getInfoboxReadResponseOrSignResponseOrErrorResponse().add(newItem);
+     *    getInfoboxReadResponseOrSignResponseOrBulkSignResponse().add(newItem);
      * 
* * *

* Objects of the following type(s) are allowed in the list - * {@link JAXBElement }{@code <}{@link StatusResponseType }{@code >} - * {@link JAXBElement }{@code <}{@link at.gv.egiz.stal.service.types.ResponseType }{@code >} - * {@link JAXBElement }{@code <}{@link ErrorResponseType }{@code >} * {@link JAXBElement }{@code <}{@link SignResponseType }{@code >} * {@link JAXBElement }{@code <}{@link InfoboxReadResponseType }{@code >} + * {@link JAXBElement }{@code <}{@link BulkSignResponseType }{@code >} + * {@link JAXBElement }{@code <}{@link ErrorResponseType }{@code >} + * {@link JAXBElement }{@code <}{@link StatusResponseType }{@code >} + * {@link JAXBElement }{@code <}{@link at.buergerkarte.namespaces.cardchannel.service.ResponseType }{@code >} + * {@link JAXBElement }{@code <}{@link at.gv.egiz.stal.service.types.ResponseType }{@code >} * * */ - public List> getInfoboxReadResponseOrSignResponseOrErrorResponse() { - if (infoboxReadResponseOrSignResponseOrErrorResponse == null) { - infoboxReadResponseOrSignResponseOrErrorResponse = new ArrayList>(); + public List> getInfoboxReadResponseOrSignResponseOrBulkSignResponse() { + if (infoboxReadResponseOrSignResponseOrBulkSignResponse == null) { + infoboxReadResponseOrSignResponseOrBulkSignResponse = new ArrayList>(); } - return this.infoboxReadResponseOrSignResponseOrErrorResponse; + return this.infoboxReadResponseOrSignResponseOrBulkSignResponse; } /** diff --git a/STALService/src/main/java/at/gv/egiz/stal/service/types/ObjectFactory.java b/STALService/src/main/java/at/gv/egiz/stal/service/types/ObjectFactory.java index ea7ca837..e9b5ac92 100644 --- a/STALService/src/main/java/at/gv/egiz/stal/service/types/ObjectFactory.java +++ b/STALService/src/main/java/at/gv/egiz/stal/service/types/ObjectFactory.java @@ -64,6 +64,8 @@ public class ObjectFactory { private final static QName _GetNextRequestTypeInfoboxReadResponse_QNAME = new QName("http://www.egiz.gv.at/stal", "InfoboxReadResponse"); private final static QName _GetNextRequestResponseTypeStatusRequest_QNAME = new QName("http://www.egiz.gv.at/stal", "StatusRequest"); private final static QName _GetNextRequestTypeStatusResponse_QNAME = new QName("http://www.egiz.gv.at/stal", "StatusResponse"); + private final static QName _GetNextRequestTypeBulkSignResponse_QNAME = new QName("http://www.egiz.gv.at/stal", "BulkSignResponse"); + private final static QName _GetNextRequestResponseTypeBulkSignRequest_QNAME = new QName("http://www.egiz.gv.at/stal", "BulkSignRequest"); /** * Create a new ObjectFactory that can be used to create new instances of schema derived classes for package: at.gv.egiz.stal.service.types @@ -72,6 +74,15 @@ public class ObjectFactory { public ObjectFactory() { } + + /** + * Create an instance of {@link BulkSignResponseType } + * + */ + public BulkSignResponseType createBulkSignResponseType() { + return new BulkSignResponseType(); + } + /** * Create an instance of {@link StatusResponseType } * @@ -168,6 +179,15 @@ public class ObjectFactory { return new InfoboxReadResponseType(); } + /** + * Create an instance of {@link BulkSignRequestType } + * + */ + public BulkSignRequestType createBulkSignRequestType() { + return new BulkSignRequestType(); + } + + /** * Create an instance of {@link InfoboxReadRequestType } * @@ -326,6 +346,15 @@ public class ObjectFactory { return new JAXBElement(_GetNextRequestResponseTypeSignRequest_QNAME, SignRequestType.class, GetNextRequestResponseType.class, value); } + /** + * Create an instance of {@link JAXBElement }{@code <}{@link BulkSignResponseType }{@code >}} + * + */ + @XmlElementDecl(namespace = "http://www.egiz.gv.at/stal", name = "BulkSignResponse", scope = GetNextRequestType.class) + public JAXBElement createGetNextRequestTypeBulkSignResponse(BulkSignResponseType value) { + return new JAXBElement(_GetNextRequestTypeBulkSignResponse_QNAME, BulkSignResponseType.class, GetNextRequestType.class, value); + } + /** * Create an instance of {@link JAXBElement }{@code <}{@link ErrorResponseType }{@code >}} * @@ -344,6 +373,17 @@ public class ObjectFactory { return new JAXBElement(_GetNextRequestTypeSignResponse_QNAME, SignResponseType.class, GetNextRequestType.class, value); } + + /** + * Create an instance of {@link JAXBElement }{@code <}{@link BulkSignRequestType }{@code >}} + * + */ + @XmlElementDecl(namespace = "http://www.egiz.gv.at/stal", name = "BulkSignRequest", scope = GetNextRequestResponseType.class) + public JAXBElement createGetNextRequestResponseTypeBulkSignRequest(BulkSignRequestType value) { + return new JAXBElement(_GetNextRequestResponseTypeBulkSignRequest_QNAME, BulkSignRequestType.class, GetNextRequestResponseType.class, value); + } + + /** * Create an instance of {@link JAXBElement }{@code <}{@link InfoboxReadResponseType }{@code >}} * diff --git a/STALService/src/main/java/at/gv/egiz/stal/service/types/RequestType.java b/STALService/src/main/java/at/gv/egiz/stal/service/types/RequestType.java index 2cf88988..fcefbd09 100644 --- a/STALService/src/main/java/at/gv/egiz/stal/service/types/RequestType.java +++ b/STALService/src/main/java/at/gv/egiz/stal/service/types/RequestType.java @@ -55,7 +55,8 @@ import javax.xml.bind.annotation.XmlType; SignRequestType.class, InfoboxReadRequestType.class, QuitRequestType.class, - StatusRequestType.class + StatusRequestType.class, + BulkSignRequestType.class }) public abstract class RequestType { diff --git a/STALService/src/main/java/at/gv/egiz/stal/service/types/ResponseType.java b/STALService/src/main/java/at/gv/egiz/stal/service/types/ResponseType.java index 02a91ef0..26c3de96 100644 --- a/STALService/src/main/java/at/gv/egiz/stal/service/types/ResponseType.java +++ b/STALService/src/main/java/at/gv/egiz/stal/service/types/ResponseType.java @@ -54,7 +54,8 @@ import javax.xml.bind.annotation.XmlType; ErrorResponseType.class, InfoboxReadResponseType.class, SignResponseType.class, - StatusResponseType.class + StatusResponseType.class, + BulkSignResponseType.class }) public abstract class ResponseType { diff --git a/STALService/src/main/java/at/gv/egiz/stal/service/types/SignRequestType.java b/STALService/src/main/java/at/gv/egiz/stal/service/types/SignRequestType.java index 6688d720..b5920d0a 100644 --- a/STALService/src/main/java/at/gv/egiz/stal/service/types/SignRequestType.java +++ b/STALService/src/main/java/at/gv/egiz/stal/service/types/SignRequestType.java @@ -65,6 +65,8 @@ import javax.xml.bind.annotation.XmlValue; * </element> * <element name="SignatureMethod" type="{http://www.w3.org/2001/XMLSchema}string" minOccurs="0"/> * <element name="DigestMethod" type="{http://www.w3.org/2001/XMLSchema}string" minOccurs="0"/> + * <element name="displayName" type="{http://www.w3.org/2001/XMLSchema}string minOccurs="0"/> + * <element name="mimeType" type="{http://www.w3.org/2001/XMLSchema}string minOccurs="0"/> * <element name="ExcludedByteRange" minOccurs="0"> * <complexType> * <complexContent> @@ -89,6 +91,8 @@ import javax.xml.bind.annotation.XmlValue; "signedInfo", "signatureMethod", "digestMethod", + "displayName", + "mimeType", "excludedByteRange" }) public class SignRequestType @@ -103,6 +107,10 @@ public class SignRequestType protected String signatureMethod; @XmlElement(name = "DigestMethod") protected String digestMethod; + @XmlElement(name = "displayName", required = true) + protected String displayName; + @XmlElement(name = "mimeType", required = true) + protected String mimeType; @XmlElement(name = "ExcludedByteRange") protected SignRequestType.ExcludedByteRange excludedByteRange; @@ -190,6 +198,55 @@ public class SignRequestType return digestMethod; } + /** + * Sets the value of the displayName property. + * + * @param value + * allowed object is + * {@link String } + * + */ + public void setDisplayName(String value) { + this.displayName = value; + } + + /** + * Gets the value of the displayName property. + * + * @return + * possible object is + * {@link String } + * + */ + public String getDisplayName() { + return displayName; + } + + /** + * Gets the value of the mimeType property. + * + * @return + * possible object is + * {@link String } + * + */ + public String getMimeType() { + return mimeType; + } + + + /** + * Sets the value of the mimeType property. + * + * @param value + * allowed object is + * {@link String } + * + */ + public void setMimeType(String value) { + this.mimeType = value; + } + /** * Sets the value of the digestMethod property. * @@ -233,14 +290,14 @@ public class SignRequestType *

The following schema fragment specifies the expected content contained within this class. * *

-     * <complexType>
-     *   <complexContent>
-     *     <restriction base="{http://www.w3.org/2001/XMLSchema}anyType">
-     *       <attribute name="from" use="required" type="{http://www.w3.org/2001/XMLSchema}unsignedLong" />
-     *       <attribute name="to" use="required" type="{http://www.w3.org/2001/XMLSchema}unsignedLong" />
-     *     </restriction>
-     *   </complexContent>
-     * </complexType>
+     * <complexType>
+     *   <complexContent>
+     *     <restriction base="{http://www.w3.org/2001/XMLSchema}anyType">
+     *       <attribute name="from" use="required" type="{http://www.w3.org/2001/XMLSchema}unsignedLong" />
+     *       <attribute name="to" use="required" type="{http://www.w3.org/2001/XMLSchema}unsignedLong" />
+     *     </restriction>
+     *   </complexContent>
+     * </complexType>
      * 
* * @@ -313,13 +370,13 @@ public class SignRequestType *

The following schema fragment specifies the expected content contained within this class. * *

-     * <complexType>
-     *   <simpleContent>
-     *     <extension base="<http://www.w3.org/2001/XMLSchema>base64Binary">
-     *       <attribute name="IsCMSSignedAttributes" type="{http://www.w3.org/2001/XMLSchema}boolean" default="false" />
-     *     </extension>
-     *   </simpleContent>
-     * </complexType>
+     * <complexType>
+     *   <simpleContent>
+     *     <extension base="<http://www.w3.org/2001/XMLSchema>base64Binary">
+     *       <attribute name="IsCMSSignedAttributes" type="{http://www.w3.org/2001/XMLSchema}boolean" default="false" />
+     *     </extension>
+     *   </simpleContent>
+     * </complexType>
      * 
* * diff --git a/STALXService/src/test/java/at/gv/egiz/stalx/service/STALServiceTest.java b/STALXService/src/test/java/at/gv/egiz/stalx/service/STALServiceTest.java index efe084d3..0bf7a0fc 100644 --- a/STALXService/src/test/java/at/gv/egiz/stalx/service/STALServiceTest.java +++ b/STALXService/src/test/java/at/gv/egiz/stalx/service/STALServiceTest.java @@ -91,7 +91,7 @@ public class STALServiceTest { System.out.println("connecting to STAL WS [TestSession] ..."); GetNextRequestResponseType wsResponse = port.connect("TestSession"); - List> stalRequests = wsResponse.getInfoboxReadRequestOrSignRequestOrQuitRequest(); + List> stalRequests = wsResponse.getInfoboxReadRequestOrSignRequestOrBulkSignRequest(); System.out.println("Received " + wsResponse.getClass() + " containing " + stalRequests.size() + " requests"); for (JAXBElement jAXBElement : stalRequests) { System.out.println(" STALRequest " + jAXBElement.getValue().getClass()); diff --git a/bkucommon/pom.xml b/bkucommon/pom.xml index 9e036ec6..9038a26c 100644 --- a/bkucommon/pom.xml +++ b/bkucommon/pom.xml @@ -82,6 +82,11 @@ compile + commons-io + commons-io + 2.5 + + xerces xercesImpl 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 BulkRequest. + * + * @author szoescher + */ +public class BulkCommandImpl extends SLCommandImpl 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 signatures = new LinkedList(); + + try { + + List signatureRequests = getRequestValue().getCreateSignatureRequest(); + + + List requestIds = new LinkedList(); + + 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 signBulkRequest(List bulkSignatureInfo, SLCommandContext commandContext, + List signatures) throws SLCommandException, SLRequestException { + + try { + + List signatureValues; + + BulkSignRequest signRequest = getSTALSignRequest(bulkSignatureInfo); + + // send BulkStalRequest + List 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(); + 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 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 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) { + 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 + * BulkRequest. + * + * @author szoescher + */ +public class BulkSignatureResultImpl extends SLResultImpl implements BulkSignatureResult { + + /** + * Logging facility. + */ + private final Logger log = LoggerFactory.getLogger(BulkSignatureResultImpl.class); + + /** + * The CMSSignatures data. + */ + protected List signatures; + + + protected List requestIds; + + + /** + * The BulkResponse. + */ + private Element content; + + /** + * Creates a new instance of this BulkSignatureResultImpl with the given + * signatures signatures. + */ + public BulkSignatureResultImpl(List signatures, List 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 BulkResponseType. + */ + 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 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 BulkSignatureInfo. + * @author szoescher + * + */ +public class BulkCollectionSecurityProvider extends IaikProvider { + + private final static Logger log = LoggerFactory.getLogger(BulkCollectionSecurityProvider.class); + + private String keyboxIdentifier; + private List hashDataInput; + private ExcludedByteRangeType excludedByteRange; + + private List bulkSignatureInfo; + + + public BulkCollectionSecurityProvider() { + bulkSignatureInfo = new LinkedList(); + } + + public BulkCollectionSecurityProvider(String keyboxIdentifier, HashDataInput hashDataInput, + ExcludedByteRangeType excludedByteRange) { + + bulkSignatureInfo = new LinkedList(); + updateBulkCollectionSecurityProvider(keyboxIdentifier, hashDataInput, excludedByteRange); + + } + + public void updateBulkCollectionSecurityProvider(String keyboxIdentifier, HashDataInput hashDataInput, + ExcludedByteRangeType excludedByteRange) { + + this.keyboxIdentifier = keyboxIdentifier; + this.hashDataInput = new ArrayList(); + 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 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 BulkSignatureRequest. + * + * @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 sign() 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; + + ExcludedByteRangeType excludedByteRange; + + PrivateKey privateKey; + + public BulkSignatureInfo(PrivateKey privateKey, AlgorithmID signatureAlgorithm, String keyboxIdentifier, + byte[] signedAttributes, String signatureMethod, String digestMethod, List 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 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(); @@ -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 responses = - stal.handleRequest(Collections.singletonList((STALRequest) signRequest)); + List 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, ExcludedByteRangeType excludedByteRange) { + private static SignRequest getSTALSignRequest(String keyboxIdentifier, byte[] signedAttributes, + String signatureMethod, String digestMethod, List 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; @@ -54,11 +55,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. */ @@ -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 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: <<>> + [<<>>] Whether to allow dereferencing of "file" URIs. + + Default: <<>> + [<<>>] 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 aliases = ks.aliases(); aliases - .hasMoreElements();) { + for (Enumeration 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 handleRequest(List requestList) { List responses = new ArrayList(); 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 @@ + + + + + SecureSignatureKeypair + + + text/plain + + + QW5kIG5vdyB0byBzb21ldGhpbmcgY29tcGxldGx5IGRpZmZlcmVudA== + + + + + + + + SecureSignatureKeypair + + + text/plain + + + Vm9uIGRlciBTaWduYXR1ciB1bXNjaGxvc3NlbmUgRGF0ZW4u + + + + + + \ 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 @@ + + + + + SecureSignatureKeypair + + + text/plain + + + + j6lwx3rvEPO0vKtMup4NbeVu8nk= + + + + + + + SecureSignatureKeypair + + + text/plainheis + + + + j6lwx3rvEPO0vKtMup4NbeVu8nk= + + + + + \ 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 @@ -118,6 +118,14 @@ +
+ + + + @@ -136,6 +144,7 @@ + diff --git a/pom.xml b/pom.xml index 06653e87..325493ca 100644 --- a/pom.xml +++ b/pom.xml @@ -481,12 +481,6 @@ 2.3.1 test - - javax.activation - activation - ${activation.version} - test - com.sun.xml.bind jaxb-impl @@ -499,12 +493,6 @@ ${jaxb.version} test - - javax.xml.bind - jaxb-api - ${jaxb.version} - test - diff --git a/smcc/src/main/java/at/gv/egiz/smcc/BulkSignException.java b/smcc/src/main/java/at/gv/egiz/smcc/BulkSignException.java new file mode 100644 index 00000000..6acfd6c9 --- /dev/null +++ b/smcc/src/main/java/at/gv/egiz/smcc/BulkSignException.java @@ -0,0 +1,47 @@ +/* + * 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. + */ + +/** + * @author szoescher szoescher + */ +package at.gv.egiz.smcc; + +public class BulkSignException extends SignatureCardException { + + private static final long serialVersionUID = 1L; + + public BulkSignException() { + super(); + } + + public BulkSignException(String message, Throwable cause) { + super(message, cause); + } + + public BulkSignException(String message) { + super(message); + } + + public BulkSignException(Throwable cause) { + super(cause); + } + +} diff --git a/smcc/src/main/java/at/gv/egiz/smcc/pin/gui/OverrulePinpadPINGUI.java b/smcc/src/main/java/at/gv/egiz/smcc/pin/gui/OverrulePinpadPINGUI.java new file mode 100644 index 00000000..3cfc7d98 --- /dev/null +++ b/smcc/src/main/java/at/gv/egiz/smcc/pin/gui/OverrulePinpadPINGUI.java @@ -0,0 +1,7 @@ +package at.gv.egiz.smcc.pin.gui; + +public interface OverrulePinpadPINGUI extends PINGUI { + + boolean allowOverrulePinpad() throws InterruptedException; + +} diff --git a/smcc/src/main/java/at/gv/egiz/smcc/pin/gui/PINProvider.java b/smcc/src/main/java/at/gv/egiz/smcc/pin/gui/PINProvider.java index b740c0ad..4e7d72f2 100644 --- a/smcc/src/main/java/at/gv/egiz/smcc/pin/gui/PINProvider.java +++ b/smcc/src/main/java/at/gv/egiz/smcc/pin/gui/PINProvider.java @@ -24,6 +24,7 @@ package at.gv.egiz.smcc.pin.gui; +import at.gv.egiz.smcc.BulkSignException; import at.gv.egiz.smcc.CancelledException; import at.gv.egiz.smcc.PinInfo; @@ -52,8 +53,9 @@ public interface PINProvider { * @return pin != null * @throws at.gv.egiz.smcc.CancelledException * @throws java.lang.InterruptedException + * @throws BulkSignException */ char[] providePIN(PinInfo pinSpec, int retries) - throws CancelledException, InterruptedException; + throws CancelledException, InterruptedException, BulkSignException; } diff --git a/smcc/src/main/java/at/gv/egiz/smcc/reader/PinpadCardReader.java b/smcc/src/main/java/at/gv/egiz/smcc/reader/PinpadCardReader.java index 48331278..45b70ca6 100644 --- a/smcc/src/main/java/at/gv/egiz/smcc/reader/PinpadCardReader.java +++ b/smcc/src/main/java/at/gv/egiz/smcc/reader/PinpadCardReader.java @@ -49,6 +49,7 @@ import at.gv.egiz.smcc.SignatureCardException; import at.gv.egiz.smcc.TimeoutException; import at.gv.egiz.smcc.VerifyAPDUSpec; import at.gv.egiz.smcc.pin.gui.ModifyPINGUI; +import at.gv.egiz.smcc.pin.gui.OverrulePinpadPINGUI; import at.gv.egiz.smcc.pin.gui.PINGUI; import at.gv.egiz.smcc.util.SMCCHelper; @@ -597,6 +598,15 @@ public class PinpadCardReader extends DefaultCardReader { byte[] s = createPINVerifyStructure(apduSpec, pinSpec); Card icc = channel.getCard(); + if (pinGUI instanceof OverrulePinpadPINGUI && (VERIFY || VERIFY_DIRECT)) { + if (((OverrulePinpadPINGUI) pinGUI).allowOverrulePinpad()) { + return super.verify(channel, apduSpec, pinGUI, pinSpec, retries); + } else { + log.debug("The User prohibited deactivation of the pinPad."); + throw new CancelledException(); + } + } + if (VERIFY) { boolean regain = dropExclusive(icc); try { diff --git a/smcc/src/test/java/at/gv/egiz/smcc/card/CreateSignature.java b/smcc/src/test/java/at/gv/egiz/smcc/card/CreateSignature.java index 5acc7e10..a2204bb7 100644 --- a/smcc/src/test/java/at/gv/egiz/smcc/card/CreateSignature.java +++ b/smcc/src/test/java/at/gv/egiz/smcc/card/CreateSignature.java @@ -35,6 +35,7 @@ import java.nio.charset.Charset; import java.util.Formatter; import java.util.Locale; +import at.gv.egiz.smcc.BulkSignException; import at.gv.egiz.smcc.CancelledException; import at.gv.egiz.smcc.PinInfo; import at.gv.egiz.smcc.SignatureCard; @@ -96,7 +97,7 @@ public class CreateSignature { @Override public char[] providePIN(PinInfo pinSpec, int retries) - throws CancelledException, InterruptedException { + throws CancelledException, InterruptedException, BulkSignException { System.out.print("Enter " + pinSpec.getLocalizedName() + ": "); BufferedReader in = new BufferedReader(new InputStreamReader(System.in)); String pin; diff --git a/smcc/src/test/java/at/gv/egiz/smcc/pin/gui/CancelPINProvider.java b/smcc/src/test/java/at/gv/egiz/smcc/pin/gui/CancelPINProvider.java index 281ef7b2..35dbafa8 100644 --- a/smcc/src/test/java/at/gv/egiz/smcc/pin/gui/CancelPINProvider.java +++ b/smcc/src/test/java/at/gv/egiz/smcc/pin/gui/CancelPINProvider.java @@ -24,6 +24,7 @@ package at.gv.egiz.smcc.pin.gui; +import at.gv.egiz.smcc.BulkSignException; import at.gv.egiz.smcc.CancelledException; import at.gv.egiz.smcc.PinInfo; @@ -31,7 +32,7 @@ public class CancelPINProvider extends DummyPINGUI implements PINGUI { @Override public char[] providePIN(PinInfo spec, int retries) - throws CancelledException, InterruptedException { + throws CancelledException, InterruptedException, BulkSignException { throw new CancelledException("cancelled by cancelPINProvider"); } } \ No newline at end of file diff --git a/smcc/src/test/java/at/gv/egiz/smcc/pin/gui/InterruptPINProvider.java b/smcc/src/test/java/at/gv/egiz/smcc/pin/gui/InterruptPINProvider.java index 184cabc5..9eaa2945 100644 --- a/smcc/src/test/java/at/gv/egiz/smcc/pin/gui/InterruptPINProvider.java +++ b/smcc/src/test/java/at/gv/egiz/smcc/pin/gui/InterruptPINProvider.java @@ -24,6 +24,7 @@ package at.gv.egiz.smcc.pin.gui; +import at.gv.egiz.smcc.BulkSignException; import at.gv.egiz.smcc.CancelledException; import at.gv.egiz.smcc.PinInfo; @@ -34,7 +35,7 @@ public class InterruptPINProvider extends DummyPINGUI implements PINGUI { @Override public char[] providePIN(PinInfo spec, int retries) - throws CancelledException, InterruptedException { + throws CancelledException, InterruptedException, BulkSignException { throw new InterruptedException("interrupted by cancelPINProvider"); } diff --git a/smcc/src/test/java/at/gv/egiz/smcc/pin/gui/InvalidPINProvider.java b/smcc/src/test/java/at/gv/egiz/smcc/pin/gui/InvalidPINProvider.java index 22f155de..ab2f646b 100644 --- a/smcc/src/test/java/at/gv/egiz/smcc/pin/gui/InvalidPINProvider.java +++ b/smcc/src/test/java/at/gv/egiz/smcc/pin/gui/InvalidPINProvider.java @@ -24,6 +24,7 @@ package at.gv.egiz.smcc.pin.gui; +import at.gv.egiz.smcc.BulkSignException; import at.gv.egiz.smcc.CancelledException; import at.gv.egiz.smcc.PinInfo; @@ -41,7 +42,7 @@ public class InvalidPINProvider extends DummyPINGUI implements PINGUI { @Override public char[] providePIN(PinInfo spec, int retries) - throws CancelledException, InterruptedException { + throws CancelledException, InterruptedException, BulkSignException { if (provided >= numWrongTries) { throw new CancelledException("Number of wrong tries reached: " + provided); } else { diff --git a/smcc/src/test/java/at/gv/egiz/smcc/pin/gui/SMCCTestPINProvider.java b/smcc/src/test/java/at/gv/egiz/smcc/pin/gui/SMCCTestPINProvider.java index 05bbc9df..05e18d90 100644 --- a/smcc/src/test/java/at/gv/egiz/smcc/pin/gui/SMCCTestPINProvider.java +++ b/smcc/src/test/java/at/gv/egiz/smcc/pin/gui/SMCCTestPINProvider.java @@ -24,6 +24,7 @@ package at.gv.egiz.smcc.pin.gui; +import at.gv.egiz.smcc.BulkSignException; import at.gv.egiz.smcc.CancelledException; import at.gv.egiz.smcc.PinInfo; @@ -38,7 +39,7 @@ public class SMCCTestPINProvider extends DummyPINGUI implements PINGUI { @Override public char[] providePIN(PinInfo spec, int retries) - throws CancelledException, InterruptedException { + throws CancelledException, InterruptedException, BulkSignException { provided++; return pin; } diff --git a/smcc/src/test/java/at/gv/egiz/smcc/test/AbstractCardTest.java b/smcc/src/test/java/at/gv/egiz/smcc/test/AbstractCardTest.java index f6faafe6..5012f34d 100644 --- a/smcc/src/test/java/at/gv/egiz/smcc/test/AbstractCardTest.java +++ b/smcc/src/test/java/at/gv/egiz/smcc/test/AbstractCardTest.java @@ -36,6 +36,7 @@ import java.security.NoSuchAlgorithmException; import org.junit.Test; +import at.gv.egiz.smcc.BulkSignException; import at.gv.egiz.smcc.CancelledException; import at.gv.egiz.smcc.CardNotSupportedException; import at.gv.egiz.smcc.LockedException; @@ -176,7 +177,7 @@ public abstract class AbstractCardTest extends AbstractCardTestBase { PINGUI pinProvider = new DummyPINGUI() { @Override public char[] providePIN(PinInfo spec, int retries) - throws CancelledException, InterruptedException { + throws CancelledException, InterruptedException, BulkSignException { try { signatureCard.getCertificate(KeyboxName.SECURE_SIGNATURE_KEYPAIR, null); @@ -201,7 +202,7 @@ public abstract class AbstractCardTest extends AbstractCardTestBase { PINGUI pinProvider = new DummyPINGUI() { @Override public char[] providePIN(PinInfo spec, int retries) - throws CancelledException, InterruptedException { + throws CancelledException, InterruptedException, BulkSignException { try { signatureCard.getCertificate(KeyboxName.CERTIFIED_KEYPAIR, null); diff --git a/smcc/src/test/java/at/gv/egiz/smcc/test/ecard/ECardG3InfoboxContainerTest.java b/smcc/src/test/java/at/gv/egiz/smcc/test/ecard/ECardG3InfoboxContainerTest.java index 9351fa21..a625168e 100644 --- a/smcc/src/test/java/at/gv/egiz/smcc/test/ecard/ECardG3InfoboxContainerTest.java +++ b/smcc/src/test/java/at/gv/egiz/smcc/test/ecard/ECardG3InfoboxContainerTest.java @@ -29,6 +29,7 @@ import static org.junit.Assert.*; import org.junit.Test; +import at.gv.egiz.smcc.BulkSignException; import at.gv.egiz.smcc.CancelledException; import at.gv.egiz.smcc.PinInfo; import at.gv.egiz.smcc.SignatureCardException; @@ -44,7 +45,7 @@ public class ECardG3InfoboxContainerTest extends AbstractCardTestBase { PINGUI pinProvider = new DummyPINGUI() { @Override public char[] providePIN(PinInfo pinSpec, int retries) - throws CancelledException, InterruptedException { + throws CancelledException, InterruptedException, BulkSignException { // must not require a PIN! fail(); return null; diff --git a/smccSTAL/src/main/java/at/gv/egiz/bku/pin/gui/BulkSignPINGUI.java b/smccSTAL/src/main/java/at/gv/egiz/bku/pin/gui/BulkSignPINGUI.java new file mode 100644 index 00000000..b792fed2 --- /dev/null +++ b/smccSTAL/src/main/java/at/gv/egiz/bku/pin/gui/BulkSignPINGUI.java @@ -0,0 +1,172 @@ +/* + * 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.pin.gui; + +import at.gv.egiz.bku.gui.BKUGUIFacade; +import at.gv.egiz.bku.gui.viewer.SecureViewer; +import at.gv.egiz.smcc.BulkSignException; +import at.gv.egiz.smcc.CancelledException; +import at.gv.egiz.smcc.PinInfo; +import at.gv.egiz.smcc.pin.gui.OverrulePinpadPINGUI; +import at.gv.egiz.stal.SignatureInfo; + +import java.security.DigestException; +import java.util.List; + +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +/** + * This PinProvider is used for BulkSignatureRequests. + * The pin input field is called once and the pin is stored for further sign requests. + * + * + * @author szoescher + */ +public class BulkSignPINGUI extends SignPINGUI implements OverrulePinpadPINGUI { + + private final Logger log = LoggerFactory.getLogger(BulkSignPINGUI.class); + + private boolean retry = false; + + private char[] pin; + + private boolean showSignaturePINDialog; + + private int maxSignatures; + + private int signatureCount; + + List signedInfo; + + + + public BulkSignPINGUI(BKUGUIFacade gui, SecureViewer viewer, List signedInfo, int maxSignatures) { + super(gui, viewer, null); + + this.signedInfo = signedInfo; + this.maxSignatures = maxSignatures; + + showSignaturePINDialog = true; + signatureCount = 0; + } + + public int getSignatureCount() { + return signatureCount; + } + + public boolean isShowSignaturePINDialog() { + return showSignaturePINDialog; + } + + public void setShowSignaturePINDialog(boolean showSignaturePINDialog) { + this.showSignaturePINDialog = showSignaturePINDialog; + } + + + + @Override + public char[] providePIN(PinInfo spec, int retries) throws CancelledException, InterruptedException, BulkSignException { + + if (showSignaturePINDialog) { + + signatureCount = 1; + gui.showSignaturePINDialog(spec, (retry) ? retries : -1, maxSignatures, this, "sign", this, "cancel", this, "secureViewer"); + + do { + log.trace("[{}] wait for action.", Thread.currentThread().getName()); + waitForAction(); + log.trace("[{}] received action {}.", Thread.currentThread().getName(), action); + + if ("secureViewer".equals(action)) { + try { + + viewer.displayDataToBeSigned(signedInfo, this, "pinEntry"); + + } catch (DigestException ex) { + log.error("Bad digest value: {}", ex.getMessage()); + gui.showErrorDialog(BKUGUIFacade.ERR_INVALID_HASH, new Object[] { ex.getMessage() }, this, "error"); + } catch (Exception ex) { + log.error("Could not display hashdata inputs: {}", ex.getMessage()); + gui.showErrorDialog(BKUGUIFacade.ERR_DISPLAY_HASHDATA, new Object[] { ex.getMessage() }, this, "error"); + } + } else if ("sign".equals(action)) { + gui.showMessageDialog(BKUGUIFacade.TITLE_BULKSIGNATURE, BKUGUIFacade.MESSAGE_BULKSIGN, new Object[]{signatureCount,maxSignatures}, BKUGUIFacade.BUTTON_CANCEL, this, "cancel"); + retry = true; + pin = gui.getPin(); + return pin; + } else if ("pinEntry".equals(action)) { + gui.showSignaturePINDialog(spec, (retry) ? retries : -1, this, "sign", this, "cancel", this, "secureViewer"); + } else if ("cancel".equals(action) || "error".equals(action)) { + gui.showMessageDialog(BKUGUIFacade.TITLE_WAIT, BKUGUIFacade.MESSAGE_WAIT); + throw new CancelledException(spec.getLocalizedName() + " entry cancelled"); + } else { + log.error("Unknown action command {}.", action); + } + } while (true); + } else { + + signatureCount ++; + + if(signatureCount > maxSignatures) { + throw new BulkSignException("Limit of "+ signatureCount + "Signatures exceeded."); + } + + gui.updateMessageDialog(BKUGUIFacade.TITLE_BULKSIGNATURE, BKUGUIFacade.MESSAGE_BULKSIGN, new Object[]{signatureCount,maxSignatures}, BKUGUIFacade.BUTTON_CANCEL, this, "cancel"); + + if ("cancel".equals(action) || "error".equals(action)) { + gui.showMessageDialog(BKUGUIFacade.TITLE_WAIT, BKUGUIFacade.MESSAGE_WAIT); + throw new CancelledException(spec.getLocalizedName() + " entry cancelled"); + } + + return pin; + } + } + + @Override + public boolean allowOverrulePinpad() throws InterruptedException { + + if (showSignaturePINDialog) { + gui.showPinPadDeactivationDialog(this, "cancel", this, "ok"); + + do { + log.trace("[{}] wait for action.", Thread.currentThread().getName()); + waitForAction(); + log.trace("[{}] received action {}.", Thread.currentThread().getName(), action); + + if ("cancel".equals(action)) { + + return false; + + } else if ("ok".equals(action)) { + + return true; + + } else { + log.error("Unknown action command {}.", action); + } + } while (true); + } + + return true; + } +} diff --git a/smccSTAL/src/main/java/at/gv/egiz/bku/pin/gui/SignPINGUI.java b/smccSTAL/src/main/java/at/gv/egiz/bku/pin/gui/SignPINGUI.java index bc49b85e..da6c39b0 100644 --- a/smccSTAL/src/main/java/at/gv/egiz/bku/pin/gui/SignPINGUI.java +++ b/smccSTAL/src/main/java/at/gv/egiz/bku/pin/gui/SignPINGUI.java @@ -25,12 +25,14 @@ package at.gv.egiz.bku.pin.gui; import at.gv.egiz.bku.gui.BKUGUIFacade; -import at.gv.egiz.bku.smccstal.SecureViewer; +import at.gv.egiz.bku.gui.viewer.SecureViewer; import at.gv.egiz.smcc.CancelledException; import at.gv.egiz.smcc.PinInfo; import at.gv.egiz.smcc.pin.gui.PINGUI; -import at.gv.egiz.stal.signedinfo.SignedInfoType; +import at.gv.egiz.stal.SignatureInfo; + import java.security.DigestException; + import org.slf4j.Logger; import org.slf4j.LoggerFactory; @@ -51,7 +53,7 @@ public class SignPINGUI extends SignPINProvider implements PINGUI { private boolean retry = false; - public SignPINGUI(BKUGUIFacade gui, SecureViewer viewer, SignedInfoType signedInfo) { + public SignPINGUI(BKUGUIFacade gui, SecureViewer viewer, SignatureInfo signedInfo) { super(gui, viewer, signedInfo); } diff --git a/smccSTAL/src/main/java/at/gv/egiz/bku/pin/gui/SignPINProvider.java b/smccSTAL/src/main/java/at/gv/egiz/bku/pin/gui/SignPINProvider.java index f9dfe068..efda713c 100644 --- a/smccSTAL/src/main/java/at/gv/egiz/bku/pin/gui/SignPINProvider.java +++ b/smccSTAL/src/main/java/at/gv/egiz/bku/pin/gui/SignPINProvider.java @@ -25,12 +25,15 @@ package at.gv.egiz.bku.pin.gui; import at.gv.egiz.bku.gui.BKUGUIFacade; -import at.gv.egiz.bku.smccstal.SecureViewer; +import at.gv.egiz.bku.gui.viewer.SecureViewer; +import at.gv.egiz.smcc.BulkSignException; import at.gv.egiz.smcc.CancelledException; import at.gv.egiz.smcc.PinInfo; import at.gv.egiz.smcc.pin.gui.PINProvider; -import at.gv.egiz.stal.signedinfo.SignedInfoType; +import at.gv.egiz.stal.SignatureInfo; + import java.security.DigestException; + import org.slf4j.Logger; import org.slf4j.LoggerFactory; @@ -51,10 +54,10 @@ public class SignPINProvider extends AbstractPINProvider implements PINProvider protected BKUGUIFacade gui; protected SecureViewer viewer; - protected SignedInfoType signedInfo; + protected SignatureInfo signedInfo; private boolean retry = false; - public SignPINProvider(BKUGUIFacade gui, SecureViewer viewer, SignedInfoType signedInfo) { + public SignPINProvider(BKUGUIFacade gui, SecureViewer viewer, SignatureInfo signedInfo) { this.gui = gui; this.viewer = viewer; this.signedInfo = signedInfo; @@ -62,7 +65,7 @@ public class SignPINProvider extends AbstractPINProvider implements PINProvider @Override public char[] providePIN(PinInfo spec, int retries) - throws CancelledException, InterruptedException { + throws CancelledException, InterruptedException, BulkSignException { gui.showSignaturePINDialog(spec, (retry) ? retries : -1, this, "sign", diff --git a/smccSTAL/src/main/java/at/gv/egiz/bku/pin/gui/VerifyPINProvider.java b/smccSTAL/src/main/java/at/gv/egiz/bku/pin/gui/VerifyPINProvider.java index 59ee0593..77528ecb 100644 --- a/smccSTAL/src/main/java/at/gv/egiz/bku/pin/gui/VerifyPINProvider.java +++ b/smccSTAL/src/main/java/at/gv/egiz/bku/pin/gui/VerifyPINProvider.java @@ -25,9 +25,11 @@ package at.gv.egiz.bku.pin.gui; import at.gv.egiz.bku.gui.BKUGUIFacade; +import at.gv.egiz.smcc.BulkSignException; import at.gv.egiz.smcc.CancelledException; import at.gv.egiz.smcc.PinInfo; import at.gv.egiz.smcc.pin.gui.PINProvider; + import org.slf4j.Logger; import org.slf4j.LoggerFactory; @@ -55,7 +57,7 @@ public class VerifyPINProvider extends AbstractPINProvider implements PINProvide @Override public char[] providePIN(PinInfo spec, int retries) - throws CancelledException, InterruptedException { + throws CancelledException, InterruptedException, BulkSignException { gui.showVerifyPINDialog(spec, (retry) ? retries : -1, this, "verify", diff --git a/smccSTAL/src/main/java/at/gv/egiz/bku/smccstal/BulkSignRequestHandler.java b/smccSTAL/src/main/java/at/gv/egiz/bku/smccstal/BulkSignRequestHandler.java new file mode 100644 index 00000000..6d0403f7 --- /dev/null +++ b/smccSTAL/src/main/java/at/gv/egiz/bku/smccstal/BulkSignRequestHandler.java @@ -0,0 +1,273 @@ +/* + * 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.smccstal; + +import iaik.me.asn1.ASN1; + +import java.io.ByteArrayInputStream; +import java.io.IOException; +import java.io.InputStream; +import java.security.SignatureException; +import java.util.LinkedList; +import java.util.List; + +import javax.xml.bind.JAXBContext; +import javax.xml.bind.JAXBElement; +import javax.xml.bind.JAXBException; +import javax.xml.bind.Unmarshaller; + +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +import at.gv.egiz.bku.gui.BKUGUIFacade; +import at.gv.egiz.bku.gui.viewer.SecureViewer; +import at.gv.egiz.bku.pin.gui.BulkSignPINGUI; +import at.gv.egiz.smcc.BulkSignException; +import at.gv.egiz.smcc.CancelledException; +import at.gv.egiz.smcc.LockedException; +import at.gv.egiz.smcc.NotActivatedException; +import at.gv.egiz.smcc.SignatureCard; +import at.gv.egiz.smcc.SignatureCard.KeyboxName; +import at.gv.egiz.smcc.SignatureCardException; +import at.gv.egiz.smcc.TimeoutException; +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.STALRequest; +import at.gv.egiz.stal.STALResponse; +import at.gv.egiz.stal.SignRequest; +import at.gv.egiz.stal.SignResponse; +import at.gv.egiz.stal.SignatureInfo; +import at.gv.egiz.stal.signedinfo.CanonicalizationMethodType; +import at.gv.egiz.stal.signedinfo.DigestMethodType; +import at.gv.egiz.stal.signedinfo.ObjectFactory; +import at.gv.egiz.stal.signedinfo.ReferenceType; +import at.gv.egiz.stal.signedinfo.SignatureMethodType; +import at.gv.egiz.stal.signedinfo.SignedInfoType; + +/** + * @author szoescher + */ +public class BulkSignRequestHandler extends AbstractRequestHandler { + + private final static Logger log = LoggerFactory.getLogger(BulkSignRequestHandler.class); + + private final static String CMS_DEF_SIGNEDINFO_ID = "SignedInfo-1"; + private final static String OID_MESSAGEDIGEST = "1.2.840.113549.1.9.4"; + + private static JAXBContext jaxbContext; + + static { + try { + jaxbContext = JAXBContext.newInstance(ObjectFactory.class.getPackage().getName()); + } catch (JAXBException e) { + Logger log = LoggerFactory.getLogger(BulkSignRequestHandler.class); + log.error("Cannot init jaxbContext", e); + } + } + + protected SecureViewer secureViewer; + + public BulkSignRequestHandler(SecureViewer secureViewer) { + this.secureViewer = secureViewer; + } + + private static ErrorResponse errorResponse(int errorCode, String errorMessage, Exception e) { + log.error(errorMessage, e); + ErrorResponse err = new ErrorResponse(errorCode); + err.setErrorMessage(errorMessage + (e == null ? "" : " " + e)); + return err; + } + + @Override + public STALResponse handleRequest(STALRequest request) throws InterruptedException { + if (request instanceof BulkSignRequest) { + BulkSignRequest bulkSignRequest = (BulkSignRequest) request; + BulkSignResponse stalResp = new BulkSignResponse(); + + + LinkedList signatureInfoList = new LinkedList(); + try { + + for(SignRequest signRequest : bulkSignRequest.getSignRequests()){ + + byte[] signedInfoData = signRequest.getSignedInfo().getValue(); + + SignatureInfo signatureInfo; + if (signRequest.getSignedInfo().isIsCMSSignedAttributes()) { + signatureInfo = createCMSSignedInfo(signRequest); + } else { + + Unmarshaller unmarshaller = jaxbContext.createUnmarshaller(); + InputStream is = new ByteArrayInputStream(signedInfoData); + @SuppressWarnings("unchecked") + JAXBElement si = (JAXBElement) unmarshaller.unmarshal(is); + + signatureInfo = new SignatureInfo(si.getValue(), signRequest.getDisplayName(), signRequest.getMimeType()); + } + signatureInfoList.add(signatureInfo); + } + + BulkSignPINGUI pinGUI = new BulkSignPINGUI(gui, secureViewer, signatureInfoList, bulkSignRequest.getSignRequests().size()); + + + for (int i = 0; i < bulkSignRequest.getSignRequests().size(); i++) { + SignRequest signRequest = bulkSignRequest.getSignRequests().get(i); + STALResponse response = handleSignRequest(signRequest, pinGUI, signatureInfoList.get(i)); + pinGUI.setShowSignaturePINDialog(false); + + if (response instanceof SignResponse) { + stalResp.getSignResponse().add((SignResponse) response); + } + + if (response instanceof ErrorResponse) { + return response; + } + + } + } catch (SignatureException e) { + return errorResponse(4000, "Error while parsing CMS signature.", e); + } catch (JAXBException e) { + return errorResponse(1000, "Cannot unmarshal signed info.", e); + } + + return stalResp; + } else { + return errorResponse(1000, "Got unexpected STAL request: " + request + ".", null); + } + } + + @Override + public boolean requireCard() { + return true; + } + + private STALResponse handleSignRequest(SignRequest request, BulkSignPINGUI pinGUI, SignatureInfo signatureInfo) throws InterruptedException { + if (request instanceof SignRequest) { + + SignRequest signReq = (SignRequest) request; + byte[] signedInfoData = signReq.getSignedInfo().getValue(); + try { + + String signatureMethod = signatureInfo.getSignatureMethod().getAlgorithm(); + log.debug("Found signature method: {}.", signatureMethod); + KeyboxName kb = SignatureCard.KeyboxName.getKeyboxName(signReq.getKeyIdentifier()); + + byte[] resp = card.createSignature(new ByteArrayInputStream(signedInfoData), kb, pinGUI, signatureMethod); + + if (resp == null) { + return errorResponse(6001, "Response is null", null); + } + + SignResponse stalResp = new SignResponse(); + stalResp.setSignatureValue(resp); + return stalResp; + } catch (NotActivatedException e) { + gui.showErrorDialog(BKUGUIFacade.ERR_CARD_NOTACTIVATED, null, this, null); + waitForAction(); + gui.showMessageDialog(BKUGUIFacade.TITLE_WAIT, BKUGUIFacade.MESSAGE_WAIT); + return errorResponse(6001, "Citizen card not activated.", e); + } catch (LockedException e) { + gui.showErrorDialog(BKUGUIFacade.ERR_CARD_LOCKED, null, this, null); + waitForAction(); + gui.showMessageDialog(BKUGUIFacade.TITLE_WAIT, BKUGUIFacade.MESSAGE_WAIT); + return errorResponse(6001, "Citizen card locked.", e); + } catch (CancelledException cx) { + return errorResponse(6001, "User cancelled request.", null); + }catch (BulkSignException cx) { + return errorResponse(6001, "Limit of Signatures exceeded.", null); + } catch (TimeoutException ex) { + gui.showMessageDialog(BKUGUIFacade.TITLE_ENTRY_TIMEOUT, BKUGUIFacade.ERR_PIN_TIMEOUT, null, + BKUGUIFacade.BUTTON_CANCEL, this, null); + waitForAction(); + gui.showMessageDialog(BKUGUIFacade.TITLE_WAIT, BKUGUIFacade.MESSAGE_WAIT); + return errorResponse(6001, "Timeout during pin entry.", null); + } catch (SignatureCardException e) { + return errorResponse(4000, "Error while creating signature.", e); + } catch (IOException e) { + return errorResponse(4000, "Error while creating signature.", e); + } + } else { + return errorResponse(1000, "Got unexpected STAL request: " + request + ".", null); + } + } + + private static SignatureInfo createCMSSignedInfo(SignRequest signReq) throws SignatureException { + SignedInfoType signedInfo = new SignedInfoType(); + + log.trace("createCMSSignedInfo from SignRequest"); + byte[] signedInfoData = signReq.getSignedInfo().getValue(); + + CanonicalizationMethodType canonicalizationMethod = new CanonicalizationMethodType(); + canonicalizationMethod.setAlgorithm(""); + signedInfo.setCanonicalizationMethod(canonicalizationMethod); + + SignatureMethodType signatureMethod = new SignatureMethodType(); + signatureMethod.setAlgorithm(signReq.getSignatureMethod()); + signedInfo.setSignatureMethod(signatureMethod); + + signedInfo.setId(CMS_DEF_SIGNEDINFO_ID); + + List references = signedInfo.getReference(); + ReferenceType reference = new ReferenceType(); + reference.setId(HashDataInput.CMS_DEF_REFERENCE_ID); + DigestMethodType digestMethod = new DigestMethodType(); + digestMethod.setAlgorithm(signReq.getDigestMethod()); + reference.setDigestMethod(digestMethod); + byte[] messageDigest = null; + try { + ASN1 signedAttributes = new ASN1(signedInfoData); + if (!signedAttributes.isConstructed()) + throw new SignatureException("Error while parsing CMS signature"); + for (int i = 0; i < signedAttributes.getSize(); ++i) { + ASN1 signedAttribute = signedAttributes.getElementAt(i); + if (!signedAttribute.isConstructed()) + throw new SignatureException("Error while parsing CMS signature"); + ASN1 oid = signedAttribute.getElementAt(0); + if (oid.gvObjectId().equals(OID_MESSAGEDIGEST)) { + ASN1 value = signedAttribute.getElementAt(1); + if (!value.isConstructed()) + throw new SignatureException("Error while parsing CMS signature"); + messageDigest = value.getElementAt(0).gvByteArray(); + break; + } + } + } catch (IOException e) { + throw new SignatureException(e); + } + reference.setDigestValue(messageDigest); + if (signReq.getExcludedByteRange() != null) { + // Abuse URI to store ExcludedByteRange + String range = "CMSExcludedByteRange:" + signReq.getExcludedByteRange().getFrom() + "-" + + signReq.getExcludedByteRange().getTo(); + reference.setURI(range); + } + + references.add(reference); + + log.trace("Added SignatureInfo {} with name {} of type{}", new Object[] { signedInfo.getId(), signReq.getDisplayName(), signReq.getMimeType() }); + return new SignatureInfo(signedInfo, signReq.getDisplayName(), signReq.getMimeType()); + } + +} diff --git a/smccSTAL/src/main/java/at/gv/egiz/bku/smccstal/SecureViewer.java b/smccSTAL/src/main/java/at/gv/egiz/bku/smccstal/SecureViewer.java deleted file mode 100644 index ea279f40..00000000 --- a/smccSTAL/src/main/java/at/gv/egiz/bku/smccstal/SecureViewer.java +++ /dev/null @@ -1,53 +0,0 @@ -/* - * Copyright 2011 by Graz University of Technology, Austria - * MOCCA has been developed by the E-Government Innovation Center EGIZ, a joint - * initiative of the Federal Chancellery Austria and Graz University of Technology. - * - * Licensed under the EUPL, Version 1.1 or - as soon they will be approved by - * the European Commission - subsequent versions of the EUPL (the "Licence"); - * You may not use this work except in compliance with the Licence. - * You may obtain a copy of the Licence at: - * http://www.osor.eu/eupl/ - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the Licence is distributed on an "AS IS" basis, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the Licence for the specific language governing permissions and - * limitations under the Licence. - * - * This product combines work with different licenses. See the "NOTICE" text - * file for details on the various modules and licenses. - * The "NOTICE" text file is part of the distribution. Any derivative works - * that you distribute must include a readable copy of the "NOTICE" text file. - */ - - -package at.gv.egiz.bku.smccstal; - -import at.gv.egiz.stal.signedinfo.SignedInfoType; -import java.awt.event.ActionListener; -import java.security.DigestException; - -/** - * - * @author Clemens Orthacker <clemens.orthacker@iaik.tugraz.at> - */ -public interface SecureViewer { - - /** - * Displays the hashdata inputs for all provided dsig:SignedReferences. - * Implementations may verify the digest value if necessary. - * (LocalSignRequestHandler operates on DataObjectHashDataInput, - * other SignRequestHandlers should cache the HashDataInputs obtained by webservice calls, - * or simply forward to a HashDataInputServlet.) - * @param signedInfo The caller may select a subset of the references in SignedInfo to be displayed. - * @param okListener - * @param okCommand - * @throws java.security.DigestException if digest values are verified and do not correspond - * (or any other digest computation error occurs) - * @throws java.lang.Exception - */ - void displayDataToBeSigned(SignedInfoType signedInfo, - ActionListener okListener, String okCommand) - throws DigestException, Exception; -} diff --git a/smccSTAL/src/main/java/at/gv/egiz/bku/smccstal/SignRequestHandler.java b/smccSTAL/src/main/java/at/gv/egiz/bku/smccstal/SignRequestHandler.java index 3026d27a..31c63379 100644 --- a/smccSTAL/src/main/java/at/gv/egiz/bku/smccstal/SignRequestHandler.java +++ b/smccSTAL/src/main/java/at/gv/egiz/bku/smccstal/SignRequestHandler.java @@ -41,6 +41,7 @@ import org.slf4j.Logger; import org.slf4j.LoggerFactory; import at.gv.egiz.bku.gui.BKUGUIFacade; +import at.gv.egiz.bku.gui.viewer.SecureViewer; import at.gv.egiz.bku.pin.gui.SignPINGUI; import at.gv.egiz.smcc.CancelledException; import at.gv.egiz.smcc.LockedException; @@ -55,6 +56,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 at.gv.egiz.stal.SignatureInfo; import at.gv.egiz.stal.signedinfo.CanonicalizationMethodType; import at.gv.egiz.stal.signedinfo.DigestMethodType; import at.gv.egiz.stal.signedinfo.ObjectFactory; @@ -97,10 +99,12 @@ public class SignRequestHandler extends AbstractRequestHandler { @Override public STALResponse handleRequest(STALRequest request) throws InterruptedException { if (request instanceof SignRequest) { + SignRequest signReq = (SignRequest) request; + byte[] signedInfoData = signReq.getSignedInfo().getValue(); try { - SignedInfoType signedInfo; + SignatureInfo signedInfo; if (signReq.getSignedInfo().isIsCMSSignedAttributes()) { signedInfo = createCMSSignedInfo(signReq); } else { @@ -109,7 +113,8 @@ public class SignRequestHandler extends AbstractRequestHandler { @SuppressWarnings("unchecked") JAXBElement si = (JAXBElement) unmarshaller.unmarshal(is); - signedInfo = si.getValue(); + + signedInfo = new SignatureInfo(si.getValue(), signReq.getDisplayName(), signReq.getMimeType()); } String signatureMethod = signedInfo.getSignatureMethod().getAlgorithm(); log.debug("Found signature method: {}.", signatureMethod); @@ -159,7 +164,7 @@ public class SignRequestHandler extends AbstractRequestHandler { } } - private static SignedInfoType createCMSSignedInfo(SignRequest signReq) throws SignatureException { + private static SignatureInfo createCMSSignedInfo(SignRequest signReq) throws SignatureException { SignedInfoType signedInfo = new SignedInfoType(); byte[] signedInfoData = signReq.getSignedInfo().getValue(); @@ -210,7 +215,7 @@ public class SignRequestHandler extends AbstractRequestHandler { reference.setURI(range); } references.add(reference); - return signedInfo; + return new SignatureInfo(signedInfo, signReq.getDisplayName(), signReq.getMimeType()); } @Override diff --git a/utils/src/main/java/at/buergerkarte/namespaces/securitylayer/_1_2_3/CMSDataObjectOptionalMetaType.java b/utils/src/main/java/at/buergerkarte/namespaces/securitylayer/_1_2_3/CMSDataObjectOptionalMetaType.java index 325d8dbf..8e00e85d 100644 --- a/utils/src/main/java/at/buergerkarte/namespaces/securitylayer/_1_2_3/CMSDataObjectOptionalMetaType.java +++ b/utils/src/main/java/at/buergerkarte/namespaces/securitylayer/_1_2_3/CMSDataObjectOptionalMetaType.java @@ -26,7 +26,10 @@ import javax.xml.bind.annotation.XmlType; * <restriction base="{http://www.w3.org/2001/XMLSchema}anyType"> * <sequence> * <element name="MetaInfo" type="{http://www.buergerkarte.at/namespaces/securitylayer/1.2#}MetaInfoType" minOccurs="0"/> - * <element name="Content" type="{http://www.buergerkarte.at/namespaces/securitylayer/1.2#}Base64OptRefContentType"/> + * <choice> + * <element name="Content" type="{http://www.buergerkarte.at/namespaces/securitylayer/1.2#}Base64OptRefContentType"/> + * <element name="DigestAndRef" type="{http://www.buergerkarte.at/namespaces/securitylayer/1.2#}DigestAndRefType"/> + * </choice> * <element name="ExcludedByteRange" type="{http://www.buergerkarte.at/namespaces/securitylayer/1.2#}ExcludedByteRangeType" minOccurs="0"/> * </sequence> * </restriction> @@ -40,10 +43,12 @@ import javax.xml.bind.annotation.XmlType; @XmlType(name = "CMSDataObjectOptionalMetaType", propOrder = { "metaInfo", "content", + "digestAndRef", "excludedByteRange" }) @XmlSeeAlso({ - CMSDataObjectRequiredMetaType.class + CMSReferenceObject.class, + CMSDataObjectRequiredMetaType.class }) public class CMSDataObjectOptionalMetaType { @@ -51,6 +56,8 @@ public class CMSDataObjectOptionalMetaType { protected MetaInfoType metaInfo; @XmlElement(name = "Content", required = true) protected Base64OptRefContentType content; + @XmlElement(name = "DigestAndRef") + protected DigestAndRefType digestAndRef; @XmlElement(name = "ExcludedByteRange") protected ExcludedByteRangeType excludedByteRange; @@ -101,6 +108,30 @@ public class CMSDataObjectOptionalMetaType { public void setContent(Base64OptRefContentType value) { this.content = value; } + + /** + * Ruft den Wert der digestAndRef-Eigenschaft ab. + * + * @return + * possible object is + * {@link DigestAndRefType } + * + */ + public DigestAndRefType getDigestAndRef() { + return digestAndRef; + } + + /** + * Legt den Wert der digestAndRef-Eigenschaft fest. + * + * @param value + * allowed object is + * {@link DigestAndRefType } + * + */ + public void setDigestAndRef(DigestAndRefType value) { + this.digestAndRef = value; + } /** * Gets the value of the excludedByteRange property. diff --git a/utils/src/main/java/at/buergerkarte/namespaces/securitylayer/_1_2_3/CMSReferenceObject.java b/utils/src/main/java/at/buergerkarte/namespaces/securitylayer/_1_2_3/CMSReferenceObject.java new file mode 100644 index 00000000..b7c18e6b --- /dev/null +++ b/utils/src/main/java/at/buergerkarte/namespaces/securitylayer/_1_2_3/CMSReferenceObject.java @@ -0,0 +1,46 @@ +// +// Diese Datei wurde mit der JavaTM Architecture for XML Binding(JAXB) Reference Implementation, v2.2.5 generiert +// Siehe http://java.sun.com/xml/jaxb +// Änderungen an dieser Datei gehen bei einer Neukompilierung des Quellschemas verloren. +// Generiert: 2015.09.28 um 04:08:24 PM CEST +// + +package at.buergerkarte.namespaces.securitylayer._1_2_3; + +import javax.xml.bind.annotation.XmlAccessType; +import javax.xml.bind.annotation.XmlAccessorType; +import javax.xml.bind.annotation.XmlType; + + +/** + *

Java-Klasse für CMSReferenceObject complex type. + * + *

Das folgende Schemafragment gibt den erwarteten Content an, der in dieser Klasse enthalten ist. + * + *

+ * <complexType name="CMSReferenceObject">
+ *   <complexContent>
+ *     <restriction base="{http://www.buergerkarte.at/namespaces/securitylayer/1.2#}CMSDataObjectOptionalMetaType">
+ *       <sequence>
+ *         <element name="MetaInfo" type="{http://www.buergerkarte.at/namespaces/securitylayer/1.2#}MetaInfoType"/>
+ *         <choice>
+ *           <element name="Content" type="{http://www.buergerkarte.at/namespaces/securitylayer/1.2#}Base64OptRefContentType"/>
+ *           <element name="DigestAndRef" type="{http://www.buergerkarte.at/namespaces/securitylayer/1.2#}DigestAndRefType"/>
+ *         </choice>
+ *         <element name="ExcludedByteRange" type="{http://www.buergerkarte.at/namespaces/securitylayer/1.2#}ExcludedByteRangeType" minOccurs="0"/>
+ *       </sequence>
+ *     </restriction>
+ *   </complexContent>
+ * </complexType>
+ * 
+ * + * + */ +@XmlAccessorType(XmlAccessType.FIELD) +@XmlType(name = "CMSReferenceObject") +public class CMSReferenceObject + extends CMSDataObjectOptionalMetaType +{ + + +} diff --git a/utils/src/main/java/at/buergerkarte/namespaces/securitylayer/_1_2_3/CreateCMSSignatureRequestType.java b/utils/src/main/java/at/buergerkarte/namespaces/securitylayer/_1_2_3/CreateCMSSignatureRequestType.java index 5c0d0a4b..9f1befe0 100644 --- a/utils/src/main/java/at/buergerkarte/namespaces/securitylayer/_1_2_3/CreateCMSSignatureRequestType.java +++ b/utils/src/main/java/at/buergerkarte/namespaces/securitylayer/_1_2_3/CreateCMSSignatureRequestType.java @@ -28,7 +28,10 @@ import javax.xml.bind.annotation.adapters.XmlJavaTypeAdapter; * <restriction base="{http://www.w3.org/2001/XMLSchema}anyType"> * <sequence> * <element name="KeyboxIdentifier" type="{http://www.buergerkarte.at/namespaces/securitylayer/1.2#}BoxIdentifierType"/> - * <element name="DataObject" type="{http://www.buergerkarte.at/namespaces/securitylayer/1.2#}CMSDataObjectRequiredMetaType"/> + * <choice> + * <element name="DataObject" type="{http://www.buergerkarte.at/namespaces/securitylayer/1.2#}CMSDataObjectRequiredMetaType"/> + * <element name="ReferenceObject" type="{http://www.buergerkarte.at/namespaces/securitylayer/1.2#}CMSReferenceObject"/> + * </choice> * </sequence> * <attribute name="Structure" use="required"> * <simpleType> @@ -49,15 +52,18 @@ import javax.xml.bind.annotation.adapters.XmlJavaTypeAdapter; @XmlAccessorType(XmlAccessType.FIELD) @XmlType(name = "CreateCMSSignatureRequestType", propOrder = { "keyboxIdentifier", - "dataObject" + "dataObject", + "referenceObject" }) public class CreateCMSSignatureRequestType { @XmlElement(name = "KeyboxIdentifier", required = true) @XmlJavaTypeAdapter(CollapsedStringAdapter.class) protected String keyboxIdentifier; - @XmlElement(name = "DataObject", required = true) + @XmlElement(name = "DataObject") protected CMSDataObjectRequiredMetaType dataObject; + @XmlElement(name = "ReferenceObject") + protected CMSReferenceObject referenceObject; @XmlAttribute(name = "Structure", required = true) protected String structure; @XmlAttribute(name = "PAdESCompatibility") @@ -110,6 +116,30 @@ public class CreateCMSSignatureRequestType { public void setDataObject(CMSDataObjectRequiredMetaType value) { this.dataObject = value; } + + /** + * Ruft den Wert der referenceObject-Eigenschaft ab. + * + * @return + * possible object is + * {@link CMSReferenceObject } + * + */ + public CMSReferenceObject getReferenceObject() { + return referenceObject; + } + + /** + * Legt den Wert der referenceObject-Eigenschaft fest. + * + * @param value + * allowed object is + * {@link CMSReferenceObject } + * + */ + public void setReferenceObject(CMSReferenceObject value) { + this.referenceObject = value; + } /** * Gets the value of the structure property. diff --git a/utils/src/main/java/at/buergerkarte/namespaces/securitylayer/_1_2_3/DigestAndRefType.java b/utils/src/main/java/at/buergerkarte/namespaces/securitylayer/_1_2_3/DigestAndRefType.java new file mode 100644 index 00000000..477925ca --- /dev/null +++ b/utils/src/main/java/at/buergerkarte/namespaces/securitylayer/_1_2_3/DigestAndRefType.java @@ -0,0 +1,128 @@ +// +// Diese Datei wurde mit der JavaTM Architecture for XML Binding(JAXB) Reference Implementation, v2.2.5 generiert +// Siehe http://java.sun.com/xml/jaxb +// Änderungen an dieser Datei gehen bei einer Neukompilierung des Quellschemas verloren. +// Generiert: 2015.09.29 um 11:17:38 AM CEST +// + + +package at.buergerkarte.namespaces.securitylayer._1_2_3; + + +import javax.xml.bind.annotation.XmlAccessType; +import javax.xml.bind.annotation.XmlAccessorType; +import javax.xml.bind.annotation.XmlAttribute; +import javax.xml.bind.annotation.XmlElement; +import javax.xml.bind.annotation.XmlSchemaType; +import javax.xml.bind.annotation.XmlType; + +import org.w3._2000._09.xmldsig_.DigestMethodType; + + +/** + *

Java-Klasse für DigestAndRefType complex type. + * + *

Das folgende Schemafragment gibt den erwarteten Content an, der in dieser Klasse enthalten ist. + * + *

+ * <complexType name="DigestAndRefType">
+ *   <complexContent>
+ *     <restriction base="{http://www.w3.org/2001/XMLSchema}anyType">
+ *       <sequence>
+ *         <element ref="{http://www.w3.org/2000/09/xmldsig#}DigestMethod"/>
+ *         <element ref="{http://www.w3.org/2000/09/xmldsig#}DigestValue"/>
+ *       </sequence>
+ *       <attribute name="Reference" type="{http://www.w3.org/2001/XMLSchema}anyURI" />
+ *     </restriction>
+ *   </complexContent>
+ * </complexType>
+ * 
+ * + * + */ +@XmlAccessorType(XmlAccessType.FIELD) +@XmlType(name = "DigestAndRefType", propOrder = { + "digestMethod", + "digestValue" +}) +public class DigestAndRefType { + + @XmlElement(name = "DigestMethod", namespace = "http://www.w3.org/2000/09/xmldsig#", required = true) + protected DigestMethodType digestMethod; + @XmlElement(name = "DigestValue", namespace = "http://www.w3.org/2000/09/xmldsig#", required = true) + protected byte[] digestValue; + @XmlAttribute(name = "Reference") + @XmlSchemaType(name = "anyURI") + protected String reference; + + /** + * Ruft den Wert der digestMethod-Eigenschaft ab. + * + * @return + * possible object is + * {@link DigestMethodType } + * + */ + public DigestMethodType getDigestMethod() { + return digestMethod; + } + + /** + * Legt den Wert der digestMethod-Eigenschaft fest. + * + * @param value + * allowed object is + * {@link DigestMethodType } + * + */ + public void setDigestMethod(DigestMethodType value) { + this.digestMethod = value; + } + + /** + * Ruft den Wert der digestValue-Eigenschaft ab. + * + * @return + * possible object is + * byte[] + */ + public byte[] getDigestValue() { + return digestValue; + } + + /** + * Legt den Wert der digestValue-Eigenschaft fest. + * + * @param value + * allowed object is + * byte[] + */ + public void setDigestValue(byte[] value) { + this.digestValue = value; + } + + /** + * Ruft den Wert der reference-Eigenschaft ab. + * + * @return + * possible object is + * {@link String } + * + */ + public String getReference() { + return reference; + } + + /** + * Legt den Wert der reference-Eigenschaft fest. + * + * @param value + * allowed object is + * {@link String } + * + */ + public void setReference(String value) { + this.reference = value; + } + +} diff --git a/utils/src/main/java/at/buergerkarte/namespaces/securitylayer/_1_2_3/ObjectFactory.java b/utils/src/main/java/at/buergerkarte/namespaces/securitylayer/_1_2_3/ObjectFactory.java index 20d5b15d..b3be3b76 100644 --- a/utils/src/main/java/at/buergerkarte/namespaces/securitylayer/_1_2_3/ObjectFactory.java +++ b/utils/src/main/java/at/buergerkarte/namespaces/securitylayer/_1_2_3/ObjectFactory.java @@ -660,6 +660,14 @@ public class ObjectFactory { public CMSDataObjectRequiredMetaType createCMSDataObjectRequiredMetaType() { return new CMSDataObjectRequiredMetaType(); } + + /** + * Create an instance of {@link CMSReferenceObject } + * + */ + public CMSReferenceObject createCMSReferenceObject() { + return new CMSReferenceObject(); + } /** * Create an instance of {@link at.buergerkarte.namespaces.securitylayer._1_2_3.XMLContentType } diff --git a/utils/src/main/java/at/gv/egiz/bku/utils/urldereferencer/FileURLProtocolHandlerImpl.java b/utils/src/main/java/at/gv/egiz/bku/utils/urldereferencer/FileURLProtocolHandlerImpl.java new file mode 100644 index 00000000..1580eb48 --- /dev/null +++ b/utils/src/main/java/at/gv/egiz/bku/utils/urldereferencer/FileURLProtocolHandlerImpl.java @@ -0,0 +1,63 @@ +/* + * 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.utils.urldereferencer; + +import java.io.IOException; +import java.net.URL; +import java.net.URLConnection; + +import javax.net.ssl.HostnameVerifier; +import javax.net.ssl.SSLSocketFactory; + +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +public class FileURLProtocolHandlerImpl implements URLProtocolHandler { + + private final Logger log = LoggerFactory.getLogger(FileURLProtocolHandlerImpl.class); + + public final static String FILE = "file"; + + + @Override + public StreamData dereference(String url) + throws IOException { + + URL u = new URL(url); + URLConnection connection = u.openConnection(); + + log.trace("Successfully opened connection."); + return new StreamData(url.toString(), connection.getContentType(), connection.getInputStream()); + + } + + @Override + public void setHostnameVerifier(HostnameVerifier hostnameVerifier) { + log.warn("not implemented for {}", this.getClass().getName()); + } + + @Override + public void setSSLSocketFactory(SSLSocketFactory socketFactory) { + log.warn("not implemented for {}", this.getClass().getName()); + } + +} diff --git a/utils/src/main/resources/at/gv/egiz/bku/slschema/Core-1.2.xsd b/utils/src/main/resources/at/gv/egiz/bku/slschema/Core-1.2.xsd index a97a98a5..75b999c7 100644 --- a/utils/src/main/resources/at/gv/egiz/bku/slschema/Core-1.2.xsd +++ b/utils/src/main/resources/at/gv/egiz/bku/slschema/Core-1.2.xsd @@ -1,1120 +1,1147 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + -- cgit v1.2.3