summaryrefslogtreecommitdiff
path: root/bkucommon/src/main/java/at/gv/egiz/bku/slcommands/impl/cms
diff options
context:
space:
mode:
Diffstat (limited to 'bkucommon/src/main/java/at/gv/egiz/bku/slcommands/impl/cms')
-rw-r--r--bkucommon/src/main/java/at/gv/egiz/bku/slcommands/impl/cms/BulkCollectionSecurityProvider.java114
-rw-r--r--bkucommon/src/main/java/at/gv/egiz/bku/slcommands/impl/cms/BulkSignature.java116
-rw-r--r--bkucommon/src/main/java/at/gv/egiz/bku/slcommands/impl/cms/BulkSignatureInfo.java104
-rw-r--r--bkucommon/src/main/java/at/gv/egiz/bku/slcommands/impl/cms/CMSHashDataInput.java49
-rw-r--r--bkucommon/src/main/java/at/gv/egiz/bku/slcommands/impl/cms/ReferencedHashDataInput.java81
-rw-r--r--bkucommon/src/main/java/at/gv/egiz/bku/slcommands/impl/cms/STALSecurityProvider.java37
-rw-r--r--bkucommon/src/main/java/at/gv/egiz/bku/slcommands/impl/cms/Signature.java187
7 files changed, 586 insertions, 102 deletions
diff --git a/bkucommon/src/main/java/at/gv/egiz/bku/slcommands/impl/cms/BulkCollectionSecurityProvider.java b/bkucommon/src/main/java/at/gv/egiz/bku/slcommands/impl/cms/BulkCollectionSecurityProvider.java
new file mode 100644
index 00000000..6bbdc682
--- /dev/null
+++ b/bkucommon/src/main/java/at/gv/egiz/bku/slcommands/impl/cms/BulkCollectionSecurityProvider.java
@@ -0,0 +1,114 @@
+/*
+ * Copyright 2015 Datentechnik Innovation GmbH and Prime Sign GmbH, Austria
+ *
+ * Licensed under the EUPL, Version 1.1 or - as soon they will be approved by
+ * the European Commission - subsequent versions of the EUPL (the "Licence");
+ * You may not use this work except in compliance with the Licence.
+ * You may obtain a copy of the Licence at:
+ * http://www.osor.eu/eupl/
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the Licence is distributed on an "AS IS" basis,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the Licence for the specific language governing permissions and
+ * limitations under the Licence.
+ *
+ * This product combines work with different licenses. See the "NOTICE" text
+ * file for details on the various modules and licenses.
+ * The "NOTICE" text file is part of the distribution. Any derivative works
+ * that you distribute must include a readable copy of the "NOTICE" text file.
+ */
+
+
+
+package at.gv.egiz.bku.slcommands.impl.cms;
+
+import iaik.asn1.structures.AlgorithmID;
+import iaik.cms.IaikProvider;
+
+import java.security.InvalidKeyException;
+import java.security.NoSuchAlgorithmException;
+import java.security.PrivateKey;
+import java.security.SignatureException;
+import java.util.ArrayList;
+import java.util.LinkedList;
+import java.util.List;
+
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+import at.buergerkarte.namespaces.securitylayer._1_2_3.ExcludedByteRangeType;
+import at.gv.egiz.stal.HashDataInput;
+
+
+/**
+ * This security Provider is used to collect multiple sign Requests to create one Stal BulkRequest.
+ * The related signature parameters are stored as a List of <code>BulkSignatureInfo</code>.
+ * @author szoescher
+ *
+ */
+public class BulkCollectionSecurityProvider extends IaikProvider {
+
+ private final static Logger log = LoggerFactory.getLogger(BulkCollectionSecurityProvider.class);
+
+ private String keyboxIdentifier;
+ private List<HashDataInput> hashDataInput;
+ private ExcludedByteRangeType excludedByteRange;
+
+ private List<BulkSignatureInfo> bulkSignatureInfo;
+
+
+ public BulkCollectionSecurityProvider() {
+ bulkSignatureInfo = new LinkedList<BulkSignatureInfo>();
+ }
+
+ public BulkCollectionSecurityProvider(String keyboxIdentifier, HashDataInput hashDataInput,
+ ExcludedByteRangeType excludedByteRange) {
+
+ bulkSignatureInfo = new LinkedList<BulkSignatureInfo>();
+ updateBulkCollectionSecurityProvider(keyboxIdentifier, hashDataInput, excludedByteRange);
+
+ }
+
+ public void updateBulkCollectionSecurityProvider(String keyboxIdentifier, HashDataInput hashDataInput,
+ ExcludedByteRangeType excludedByteRange) {
+
+ this.keyboxIdentifier = keyboxIdentifier;
+ this.hashDataInput = new ArrayList<HashDataInput>();
+ this.hashDataInput.add(hashDataInput);
+ this.excludedByteRange = excludedByteRange;
+
+ }
+
+ /* (non-Javadoc)
+ * @see iaik.cms.IaikProvider#calculateSignatureFromSignedAttributes(iaik.asn1.structures.AlgorithmID, iaik.asn1.structures.AlgorithmID, java.security.PrivateKey, byte[])
+ */
+ @Override
+ public byte[] calculateSignatureFromSignedAttributes(AlgorithmID signatureAlgorithm,
+ AlgorithmID digestAlgorithm, PrivateKey privateKey,
+ byte[] signedAttributes)
+ throws SignatureException, InvalidKeyException, NoSuchAlgorithmException {
+ log.debug("calculateSignatureFromSignedAttributes: " + signatureAlgorithm + ", " + digestAlgorithm);
+
+
+ STALPrivateKey spk = (STALPrivateKey) privateKey;
+
+ //Store signature information that is required to create a StalBulkSignatureRequest.
+ bulkSignatureInfo.add(new BulkSignatureInfo(privateKey, signatureAlgorithm, keyboxIdentifier, signedAttributes,
+ spk.getAlgorithm(), spk.getDigestAlgorithm(), hashDataInput, excludedByteRange));
+
+ //Size of placeholder doesn't matter
+ byte[] signaturePlaceholder = new byte[1];
+ return signaturePlaceholder;
+ }
+
+public List<BulkSignatureInfo> getBulkSignatureInfo() {
+ return bulkSignatureInfo;
+}
+
+
+
+
+
+
+}
diff --git a/bkucommon/src/main/java/at/gv/egiz/bku/slcommands/impl/cms/BulkSignature.java b/bkucommon/src/main/java/at/gv/egiz/bku/slcommands/impl/cms/BulkSignature.java
new file mode 100644
index 00000000..bf220034
--- /dev/null
+++ b/bkucommon/src/main/java/at/gv/egiz/bku/slcommands/impl/cms/BulkSignature.java
@@ -0,0 +1,116 @@
+/*
+ * Copyright 2015 Datentechnik Innovation GmbH and Prime Sign GmbH, Austria
+ *
+ * Licensed under the EUPL, Version 1.1 or - as soon they will be approved by
+ * the European Commission - subsequent versions of the EUPL (the "Licence");
+ * You may not use this work except in compliance with the Licence.
+ * You may obtain a copy of the Licence at:
+ * http://www.osor.eu/eupl/
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the Licence is distributed on an "AS IS" basis,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the Licence for the specific language governing permissions and
+ * limitations under the Licence.
+ *
+ * This product combines work with different licenses. See the "NOTICE" text
+ * file for details on the various modules and licenses.
+ * The "NOTICE" text file is part of the distribution. Any derivative works
+ * that you distribute must include a readable copy of the "NOTICE" text file.
+ */
+
+
+
+package at.gv.egiz.bku.slcommands.impl.cms;
+
+import iaik.asn1.CodingException;
+import iaik.cms.CMSException;
+import iaik.cms.CMSSignatureException;
+import iaik.cms.ContentInfo;
+import iaik.cms.SecurityProvider;
+import iaik.cms.SignedData;
+import iaik.cms.SignerInfo;
+import iaik.x509.X509ExtensionException;
+
+import java.io.IOException;
+import java.security.InvalidParameterException;
+import java.security.NoSuchAlgorithmException;
+import java.security.cert.CertificateEncodingException;
+import java.security.cert.CertificateException;
+import java.security.cert.X509Certificate;
+import java.util.Date;
+
+import at.buergerkarte.namespaces.securitylayer._1_2_3.CMSDataObjectOptionalMetaType;
+import at.buergerkarte.namespaces.securitylayer._1_2_3.ExcludedByteRangeType;
+import at.gv.egiz.bku.slexceptions.SLCommandException;
+import at.gv.egiz.bku.utils.urldereferencer.URLDereferencer;
+import at.gv.egiz.stal.STAL;
+
+/**
+ * This class represents a CMS-Signature as to be created by the
+ * security layer command <code>BulkSignatureRequest</code>.
+ *
+ * @author szoescher
+ */
+public class BulkSignature extends Signature {
+
+ public final static String ID_AA_ETS_MIMETYPE = "0.4.0.1733.2.1";
+
+ public BulkSignature(CMSDataObjectOptionalMetaType dataObject, String structure,
+ X509Certificate signingCertificate, Date signingTime, URLDereferencer urlDereferencer,
+ boolean useStrongHash)
+ throws NoSuchAlgorithmException, CertificateEncodingException,
+ CertificateException, X509ExtensionException, InvalidParameterException,
+ CodingException, SLCommandException, IOException, CMSException {
+ super(dataObject, structure, signingCertificate, signingTime, urlDereferencer, useStrongHash);
+ }
+
+ /**
+ * Additionally to the <code>sign()<code> method from the supertype,
+ * contains a additional parameter to set a custom securityProvider.
+ * @param securityProvider The Security Provider that handles the sign request.
+ */
+ public byte[] sign(SecurityProvider securityProvider, STAL stal, String keyboxIdentifier) throws CMSException, CMSSignatureException, SLCommandException {
+ signedData.setSecurityProvider(securityProvider);
+ try {
+ signedData.addSignerInfo(signerInfo);
+ } catch (NoSuchAlgorithmException e) {
+ throw new CMSSignatureException(e);
+ }
+ if (digestValue != null) {
+ try {
+ signedData.setMessageDigest(digestAlgorithm, digestValue);
+ } catch (NoSuchAlgorithmException e) {
+ throw new CMSSignatureException(e);
+ }
+ }
+ ContentInfo contentInfo = new ContentInfo(signedData);
+ return contentInfo.getEncoded();
+ }
+
+
+ public ExcludedByteRangeType getExcludedByteRange() {
+ return excludedByteRange;
+ }
+
+ public SignerInfo getSignerInfo() {
+ return signerInfo;
+ }
+
+ public void setSignerInfo(SignerInfo signerInfo) {
+ this.signerInfo = signerInfo;
+ }
+
+
+ public SignedData getSignedData() {
+ return signedData;
+ }
+
+ public byte[] getEncoded() throws CMSException{
+ ContentInfo contentInfo = new ContentInfo(signedData);
+ return contentInfo.getEncoded();
+ }
+
+
+}
+
diff --git a/bkucommon/src/main/java/at/gv/egiz/bku/slcommands/impl/cms/BulkSignatureInfo.java b/bkucommon/src/main/java/at/gv/egiz/bku/slcommands/impl/cms/BulkSignatureInfo.java
new file mode 100644
index 00000000..1d918f9f
--- /dev/null
+++ b/bkucommon/src/main/java/at/gv/egiz/bku/slcommands/impl/cms/BulkSignatureInfo.java
@@ -0,0 +1,104 @@
+/*
+ * Copyright 2015 Datentechnik Innovation GmbH and Prime Sign GmbH, Austria
+ *
+ * Licensed under the EUPL, Version 1.1 or - as soon they will be approved by
+ * the European Commission - subsequent versions of the EUPL (the "Licence");
+ * You may not use this work except in compliance with the Licence.
+ * You may obtain a copy of the Licence at:
+ * http://www.osor.eu/eupl/
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the Licence is distributed on an "AS IS" basis,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the Licence for the specific language governing permissions and
+ * limitations under the Licence.
+ *
+ * This product combines work with different licenses. See the "NOTICE" text
+ * file for details on the various modules and licenses.
+ * The "NOTICE" text file is part of the distribution. Any derivative works
+ * that you distribute must include a readable copy of the "NOTICE" text file.
+ */
+
+package at.gv.egiz.bku.slcommands.impl.cms;
+
+import iaik.asn1.structures.AlgorithmID;
+
+import java.security.PrivateKey;
+import java.util.List;
+
+import at.buergerkarte.namespaces.securitylayer._1_2_3.ExcludedByteRangeType;
+import at.gv.egiz.stal.HashDataInput;
+
+
+/**
+ *
+ * @author szoescher
+ *
+ */
+public class BulkSignatureInfo {
+
+ AlgorithmID signatureAlgorithm;
+
+ String keyboxIdentifier;
+
+ byte[] signedAttributes;
+
+ String signatureMethod;
+
+ String digestMethod;
+
+ List<HashDataInput> hashDataInput;
+
+ ExcludedByteRangeType excludedByteRange;
+
+ PrivateKey privateKey;
+
+ public BulkSignatureInfo(PrivateKey privateKey, AlgorithmID signatureAlgorithm, String keyboxIdentifier,
+ byte[] signedAttributes, String signatureMethod, String digestMethod, List<HashDataInput> hashDataInput,
+ ExcludedByteRangeType excludedByteRange) {
+ this.privateKey = privateKey;
+ this.signatureAlgorithm = signatureAlgorithm;
+ this.keyboxIdentifier = keyboxIdentifier;
+ this.signedAttributes = signedAttributes;
+ this.signatureMethod = signatureMethod;
+ this.digestMethod = digestMethod;
+ this.hashDataInput = hashDataInput;
+ this.excludedByteRange = excludedByteRange;
+ }
+
+ public String getKeyboxIdentifier() {
+ return keyboxIdentifier;
+ }
+
+ public byte[] getSignedAttributes() {
+ return signedAttributes;
+ }
+
+ public String getSignatureMethod() {
+ return signatureMethod;
+ }
+
+ public String getDigestMethod() {
+ return digestMethod;
+ }
+
+ public List<HashDataInput> getHashDataInput() {
+ return hashDataInput;
+ }
+
+ public ExcludedByteRangeType getExcludedByteRange() {
+ return excludedByteRange;
+ }
+
+ public AlgorithmID getSignatureAlgorithm() {
+ return signatureAlgorithm;
+ }
+
+ public PrivateKey getPrivateKey() {
+ return privateKey;
+ }
+
+
+
+
+}
diff --git a/bkucommon/src/main/java/at/gv/egiz/bku/slcommands/impl/cms/CMSHashDataInput.java b/bkucommon/src/main/java/at/gv/egiz/bku/slcommands/impl/cms/CMSHashDataInput.java
index e51c5823..25162dc4 100644
--- a/bkucommon/src/main/java/at/gv/egiz/bku/slcommands/impl/cms/CMSHashDataInput.java
+++ b/bkucommon/src/main/java/at/gv/egiz/bku/slcommands/impl/cms/CMSHashDataInput.java
@@ -25,6 +25,7 @@
package at.gv.egiz.bku.slcommands.impl.cms;
import java.io.ByteArrayInputStream;
+import java.io.IOException;
import java.io.InputStream;
import at.gv.egiz.bku.gui.viewer.MimeTypes;
@@ -32,18 +33,33 @@ import at.gv.egiz.stal.HashDataInput;
public class CMSHashDataInput implements HashDataInput {
- private final static String DEFAULT_FILENAME = "SignatureData";
+ public final static String DEFAULT_FILENAME = "SignatureData";
private byte[] data;
- private String mimeType;
+ private byte[] digest;
+ protected String mimeType;
+ private String referenceId;
+ private String fileName;
public CMSHashDataInput(byte[] data, String mimeType) {
this.data = data;
this.mimeType = mimeType;
}
+ public CMSHashDataInput(byte[] data, String mimeType, byte[] digest) {
+ this.data = data;
+ this.mimeType = mimeType;
+ }
+
+ public CMSHashDataInput() {
+ }
+
@Override
public String getReferenceId() {
+
+ if (referenceId != null) {
+ return referenceId;
+ }
return CMS_DEF_REFERENCE_ID;
}
@@ -59,11 +75,38 @@ public class CMSHashDataInput implements HashDataInput {
@Override
public String getFilename() {
+ if (fileName != null) {
+ return fileName;
+ }
+
+ if (mimeType != null) {
return DEFAULT_FILENAME + MimeTypes.getExtension(mimeType);
}
+ return DEFAULT_FILENAME;
+ }
+
@Override
- public InputStream getHashDataInput() {
+ public InputStream getHashDataInput() throws IOException {
return new ByteArrayInputStream(data);
}
+
+ @Override
+ public byte[] getDigest() {
+ return digest;
+ }
+
+
+ public void setFilename(String fileName) {
+ this.fileName = fileName;
+ }
+
+ public void setDigest(byte[] digest) {
+ this.digest = digest;
+ }
+
+ public void setReferenceId(String referenceId) {
+ this.referenceId = referenceId;
+ }
+
}
diff --git a/bkucommon/src/main/java/at/gv/egiz/bku/slcommands/impl/cms/ReferencedHashDataInput.java b/bkucommon/src/main/java/at/gv/egiz/bku/slcommands/impl/cms/ReferencedHashDataInput.java
new file mode 100644
index 00000000..96e0e7de
--- /dev/null
+++ b/bkucommon/src/main/java/at/gv/egiz/bku/slcommands/impl/cms/ReferencedHashDataInput.java
@@ -0,0 +1,81 @@
+/*
+ * Copyright 2015 Datentechnik Innovation GmbH and Prime Sign GmbH, Austria
+ *
+ * Licensed under the EUPL, Version 1.1 or - as soon they will be approved by
+ * the European Commission - subsequent versions of the EUPL (the "Licence");
+ * You may not use this work except in compliance with the Licence.
+ * You may obtain a copy of the Licence at:
+ * http://www.osor.eu/eupl/
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the Licence is distributed on an "AS IS" basis,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the Licence for the specific language governing permissions and
+ * limitations under the Licence.
+ *
+ * This product combines work with different licenses. See the "NOTICE" text
+ * file for details on the various modules and licenses.
+ * The "NOTICE" text file is part of the distribution. Any derivative works
+ * that you distribute must include a readable copy of the "NOTICE" text file.
+ */
+
+package at.gv.egiz.bku.slcommands.impl.cms;
+
+import java.io.ByteArrayInputStream;
+import java.io.IOException;
+import java.io.InputStream;
+
+import org.apache.commons.io.IOUtils;
+import org.apache.commons.lang.ArrayUtils;
+
+import at.buergerkarte.namespaces.securitylayer._1_2_3.ExcludedByteRangeType;
+import at.gv.egiz.bku.utils.urldereferencer.URLDereferencer;
+
+public class ReferencedHashDataInput extends CMSHashDataInput {
+
+ private String urlReference;
+ private URLDereferencer urlDereferencer;
+ private ExcludedByteRangeType excludedByteRange;
+
+ public ReferencedHashDataInput(String mimeType, URLDereferencer urlDereferencer, String urlReference, ExcludedByteRangeType excludedByteRange) {
+ super(null, mimeType);
+ this.urlDereferencer = urlDereferencer;
+ this.urlReference = urlReference;
+ this.excludedByteRange = excludedByteRange;
+ }
+
+
+ public URLDereferencer getUrlDereferencer() {
+ return urlDereferencer;
+ }
+
+
+ public void setUrlDereferencer(URLDereferencer urlDereferencer) {
+ this.urlDereferencer = urlDereferencer;
+ }
+
+ public InputStream getHashDataInput() throws IOException {
+
+ InputStream hashDataInputStream = urlDereferencer.dereference(urlReference).getStream();
+
+ try {
+ byte[] content = IOUtils.toByteArray(hashDataInputStream);
+
+ if (excludedByteRange != null) {
+
+ int from = excludedByteRange.getFrom().intValue();
+ int to = excludedByteRange.getTo().intValue();
+
+ byte[] signedContent = ArrayUtils.addAll(ArrayUtils.subarray(content, 0, from), ArrayUtils.subarray(content, to, content.length));
+
+ return new ByteArrayInputStream(signedContent);
+
+ } else {
+ return new ByteArrayInputStream(content);
+ }
+
+ } finally {
+ hashDataInputStream.close();
+ }
+ }
+}
diff --git a/bkucommon/src/main/java/at/gv/egiz/bku/slcommands/impl/cms/STALSecurityProvider.java b/bkucommon/src/main/java/at/gv/egiz/bku/slcommands/impl/cms/STALSecurityProvider.java
index 87c00644..1dd6cc9e 100644
--- a/bkucommon/src/main/java/at/gv/egiz/bku/slcommands/impl/cms/STALSecurityProvider.java
+++ b/bkucommon/src/main/java/at/gv/egiz/bku/slcommands/impl/cms/STALSecurityProvider.java
@@ -69,8 +69,8 @@ public class STALSecurityProvider extends IaikProvider {
private ExcludedByteRangeType excludedByteRange;
private STALSignatureException stalSignatureException;
- public STALSecurityProvider(STAL stal, String keyboxIdentifier,
- HashDataInput hashDataInput, ExcludedByteRangeType excludedByteRange) {
+ public STALSecurityProvider(STAL stal, String keyboxIdentifier, HashDataInput hashDataInput,
+ ExcludedByteRangeType excludedByteRange) {
this.keyboxIdentifier = keyboxIdentifier;
this.stal = stal;
this.hashDataInput = new ArrayList<HashDataInput>();
@@ -78,23 +78,27 @@ public class STALSecurityProvider extends IaikProvider {
this.excludedByteRange = excludedByteRange;
}
- /* (non-Javadoc)
- * @see iaik.cms.IaikProvider#calculateSignatureFromSignedAttributes(iaik.asn1.structures.AlgorithmID, iaik.asn1.structures.AlgorithmID, java.security.PrivateKey, byte[])
+ /*
+ * (non-Javadoc)
+ *
+ * @see
+ * iaik.cms.IaikProvider#calculateSignatureFromSignedAttributes(iaik.asn1.
+ * structures.AlgorithmID, iaik.asn1.structures.AlgorithmID,
+ * java.security.PrivateKey, byte[])
*/
@Override
- public byte[] calculateSignatureFromSignedAttributes(AlgorithmID signatureAlgorithm,
- AlgorithmID digestAlgorithm, PrivateKey privateKey,
- byte[] signedAttributes)
- throws SignatureException, InvalidKeyException, NoSuchAlgorithmException {
+ public byte[] calculateSignatureFromSignedAttributes(AlgorithmID signatureAlgorithm, AlgorithmID digestAlgorithm,
+ PrivateKey privateKey, byte[] signedAttributes) throws SignatureException, InvalidKeyException,
+ NoSuchAlgorithmException {
+ stalSignatureException = null;
log.debug("calculateSignatureFromSignedAttributes: " + signatureAlgorithm + ", " + digestAlgorithm);
STALPrivateKey spk = (STALPrivateKey) privateKey;
- SignRequest signRequest = getSTALSignRequest(keyboxIdentifier, signedAttributes,
- spk.getAlgorithm(), spk.getDigestAlgorithm(), hashDataInput, excludedByteRange);
+ SignRequest signRequest = getSTALSignRequest(keyboxIdentifier, signedAttributes, spk.getAlgorithm(),
+ spk.getDigestAlgorithm(), hashDataInput, excludedByteRange);
log.debug("Sending STAL request ({})", privateKey.getAlgorithm());
- List<STALResponse> responses =
- stal.handleRequest(Collections.singletonList((STALRequest) signRequest));
+ List<STALResponse> responses = stal.handleRequest(Collections.singletonList((STALRequest) signRequest));
if (responses == null || responses.size() != 1) {
throw new SignatureException("Failed to access STAL.");
@@ -114,9 +118,9 @@ public class STALSecurityProvider extends IaikProvider {
}
}
- private static SignRequest getSTALSignRequest(String keyboxIdentifier,
- byte[] signedAttributes, String signatureMethod, String digestMethod,
- List<HashDataInput> hashDataInput, ExcludedByteRangeType excludedByteRange) {
+ private static SignRequest getSTALSignRequest(String keyboxIdentifier, byte[] signedAttributes,
+ String signatureMethod, String digestMethod, List<HashDataInput> hashDataInput,
+ ExcludedByteRangeType excludedByteRange) {
SignRequest signRequest = new SignRequest();
signRequest.setKeyIdentifier(keyboxIdentifier);
log.debug("SignedAttributes: " + Util.toBase64String(signedAttributes));
@@ -147,8 +151,7 @@ public class STALSecurityProvider extends IaikProvider {
sigS.addComponent(new INTEGER(new BigInteger(1, r)));
sigS.addComponent(new INTEGER(new BigInteger(1, s)));
return DerCoder.encode(sigS);
- }
- else
+ } else
return sig;
}
diff --git a/bkucommon/src/main/java/at/gv/egiz/bku/slcommands/impl/cms/Signature.java b/bkucommon/src/main/java/at/gv/egiz/bku/slcommands/impl/cms/Signature.java
index 7be546de..4a94ca7f 100644
--- a/bkucommon/src/main/java/at/gv/egiz/bku/slcommands/impl/cms/Signature.java
+++ b/bkucommon/src/main/java/at/gv/egiz/bku/slcommands/impl/cms/Signature.java
@@ -24,48 +24,32 @@
package at.gv.egiz.bku.slcommands.impl.cms;
-import iaik.asn1.ASN1Object;
-import iaik.asn1.CodingException;
-import iaik.asn1.ObjectID;
-import iaik.asn1.SEQUENCE;
-import iaik.asn1.UTF8String;
-import iaik.asn1.structures.AlgorithmID;
-import iaik.asn1.structures.Attribute;
-import iaik.asn1.structures.ChoiceOfTime;
-import iaik.cms.CMSException;
-import iaik.cms.CMSSignatureException;
-import iaik.cms.CertificateIdentifier;
-import iaik.cms.ContentInfo;
-import iaik.cms.IssuerAndSerialNumber;
-import iaik.cms.SignedData;
-import iaik.cms.SignerInfo;
-import iaik.smime.ess.ESSCertID;
-import iaik.smime.ess.ESSCertIDv2;
-import iaik.x509.X509ExtensionException;
-
import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.io.InputStream;
+import java.net.URI;
+import java.net.URISyntaxException;
import java.security.InvalidParameterException;
import java.security.NoSuchAlgorithmException;
import java.security.PrivateKey;
-import java.security.PublicKey;
import java.security.cert.CertificateEncodingException;
import java.security.cert.CertificateException;
import java.security.cert.X509Certificate;
-import java.security.interfaces.ECPublicKey;
-import java.security.interfaces.RSAPublicKey;
-import java.security.spec.ECParameterSpec;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Date;
import java.util.List;
+import javax.xml.crypto.dsig.DigestMethod;
+
import org.apache.commons.lang.ArrayUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
+import org.w3._2000._09.xmldsig_.DigestMethodType;
+import at.buergerkarte.namespaces.securitylayer._1_2_3.CMSDataObjectOptionalMetaType;
import at.buergerkarte.namespaces.securitylayer._1_2_3.CMSDataObjectRequiredMetaType;
+import at.buergerkarte.namespaces.securitylayer._1_2_3.DigestAndRefType;
import at.buergerkarte.namespaces.securitylayer._1_2_3.ExcludedByteRangeType;
import at.gv.egiz.bku.slcommands.impl.xsect.AlgorithmMethodFactory;
import at.gv.egiz.bku.slcommands.impl.xsect.AlgorithmMethodFactoryImpl;
@@ -74,6 +58,24 @@ import at.gv.egiz.bku.slexceptions.SLCommandException;
import at.gv.egiz.bku.utils.urldereferencer.URLDereferencer;
import at.gv.egiz.stal.HashDataInput;
import at.gv.egiz.stal.STAL;
+import iaik.asn1.ASN1Object;
+import iaik.asn1.CodingException;
+import iaik.asn1.ObjectID;
+import iaik.asn1.SEQUENCE;
+import iaik.asn1.UTF8String;
+import iaik.asn1.structures.AlgorithmID;
+import iaik.asn1.structures.Attribute;
+import iaik.asn1.structures.ChoiceOfTime;
+import iaik.cms.CMSException;
+import iaik.cms.CMSSignatureException;
+import iaik.cms.CertificateIdentifier;
+import iaik.cms.ContentInfo;
+import iaik.cms.IssuerAndSerialNumber;
+import iaik.cms.SignedData;
+import iaik.cms.SignerInfo;
+import iaik.smime.ess.ESSCertID;
+import iaik.smime.ess.ESSCertIDv2;
+import iaik.x509.X509ExtensionException;
/**
* This class represents a CMS-Signature as to be created by the
@@ -90,25 +92,51 @@ public class Signature {
*/
private final Logger log = LoggerFactory.getLogger(Signature.class);
- private SignedData signedData;
- private SignerInfo signerInfo;
- private byte[] signedDocument;
- private String mimeType;
- private AlgorithmID signatureAlgorithm;
- private AlgorithmID digestAlgorithm;
- private String signatureAlgorithmURI;
- private String digestAlgorithmURI;
- private ExcludedByteRangeType excludedByteRange;
+ protected SignedData signedData;
+ protected SignerInfo signerInfo;
+ protected byte[] signedDocument;
+ protected String mimeType;
+ protected AlgorithmID signatureAlgorithm;
+ protected AlgorithmID digestAlgorithm;
+ protected byte[] digestValue;
+ protected String signatureAlgorithmURI;
+ protected String digestAlgorithmURI;
+ protected ExcludedByteRangeType excludedByteRange;
+ private HashDataInput hashDataInput;
+
- public Signature(CMSDataObjectRequiredMetaType dataObject, String structure,
+public Signature(CMSDataObjectOptionalMetaType dataObject, String structure,
X509Certificate signingCertificate, Date signingTime, URLDereferencer urlDereferencer,
boolean useStrongHash)
throws NoSuchAlgorithmException, CertificateEncodingException,
CertificateException, X509ExtensionException, InvalidParameterException,
- CodingException, SLCommandException, IOException {
- byte[] dataToBeSigned = getContent(dataObject, urlDereferencer);
+ CodingException, SLCommandException, IOException, CMSException {
int mode = structure.equalsIgnoreCase("enveloping") ? SignedData.IMPLICIT : SignedData.EXPLICIT;
+ if (dataObject.getContent() != null) {
+ byte[] dataToBeSigned = getContent(dataObject, urlDereferencer);
this.signedData = new SignedData(dataToBeSigned, mode);
+ if (dataObject.getMetaInfo() != null) {
+ this.mimeType = dataObject.getMetaInfo().getMimeType();
+ }
+
+ hashDataInput = new CMSHashDataInput(signedDocument, mimeType);
+
+ } else {
+ DigestAndRefType digestAndRef = dataObject.getDigestAndRef();
+ DigestMethodType digestMethod = digestAndRef.getDigestMethod();
+
+ hashDataInput = new ReferencedHashDataInput(dataObject.getMetaInfo().getMimeType(), urlDereferencer,
+ digestAndRef.getReference(), dataObject.getExcludedByteRange());
+
+ try {
+ digestAlgorithm = getAlgorithmID(digestMethod.getAlgorithm());
+ } catch (URISyntaxException e) {
+ //TODO: choose proper execption
+ throw new NoSuchAlgorithmException(e);
+ }
+ digestValue = digestAndRef.getDigestValue();
+ this.signedData = new SignedData(ObjectID.pkcs7_data);
+ }
setAlgorithmIDs(signingCertificate, useStrongHash);
createSignerInfo(signingCertificate);
setSignerCertificate(signingCertificate);
@@ -208,7 +236,7 @@ public class Signature {
attributes.add(signingTime);
}
- private byte[] getContent(CMSDataObjectRequiredMetaType dataObject, URLDereferencer urlDereferencer)
+ private byte[] getContent(CMSDataObjectOptionalMetaType dataObject, URLDereferencer urlDereferencer)
throws InvalidParameterException, SLCommandException, IOException {
byte[] data = dataObject.getContent().getBase64Content();
if (data == null) {
@@ -252,63 +280,36 @@ public class Signature {
}
private void setAlgorithmIDs(X509Certificate signingCertificate, boolean useStrongHash) throws NoSuchAlgorithmException {
- PublicKey publicKey = signingCertificate.getPublicKey();
- String algorithm = publicKey.getAlgorithm();
AlgorithmMethodFactory amf = new AlgorithmMethodFactoryImpl(signingCertificate, useStrongHash);
signatureAlgorithmURI = amf.getSignatureAlgorithmURI();
+ signatureAlgorithm = amf.getSignatureAlgorithmID();
+ if (digestAlgorithm != null) {
+ if (AlgorithmID.sha1.equals(digestAlgorithm)) {
+ digestAlgorithmURI = DigestMethod.SHA1;
+ } else if (AlgorithmID.sha256.equals(digestAlgorithm)) {
+ digestAlgorithmURI = DigestMethod.SHA256;
+ } else if (AlgorithmID.sha512.equals(digestAlgorithm)) {
+ digestAlgorithmURI = DigestMethod.SHA512;
+ } else if (AlgorithmID.ripeMd160.equals(digestAlgorithm)) {
+ digestAlgorithmURI = DigestMethod.RIPEMD160;
+ } else {
+ throw new NoSuchAlgorithmException("Algorithm '" + digestAlgorithm + "' not supported.");
+ }
+ } else {
digestAlgorithmURI = amf.getDigestAlgorithmURI();
-
- if ("DSA".equals(algorithm)) {
- signatureAlgorithm = AlgorithmID.dsaWithSHA1;
- } else if ("RSA".equals(algorithm)) {
-
- int keyLength = 0;
- if (publicKey instanceof RSAPublicKey) {
- keyLength = ((RSAPublicKey) publicKey).getModulus().bitLength();
+ digestAlgorithm = amf.getDigestAlgorithmID();
}
-
- if (useStrongHash && keyLength >= 2048) {
- signatureAlgorithm = AlgorithmID.sha256WithRSAEncryption;
- digestAlgorithm = AlgorithmID.sha256;
-// } else if (useStrongHash) { // Cannot be used if not enabled in AlgorithmMethodFactoryImpl
-// signatureAlgorithm = AlgorithmID.rsaSignatureWithRipemd160;
-// digestAlgorithm = AlgorithmID.ripeMd160;
- } else {
- signatureAlgorithm = AlgorithmID.sha1WithRSAEncryption;
- digestAlgorithm = AlgorithmID.sha1;
}
- } else if (("EC".equals(algorithm)) || ("ECDSA".equals(algorithm))) {
- int fieldSize = 0;
- if (publicKey instanceof ECPublicKey) {
- ECParameterSpec params = ((ECPublicKey) publicKey).getParams();
- fieldSize = params.getCurve().getField().getFieldSize();
- } else {
- throw new NoSuchAlgorithmException("Public key type not supported.");
- }
+ public HashDataInput getHashDataInput() {
- if (useStrongHash && fieldSize >= 512) {
- signatureAlgorithm = AlgorithmID.ecdsa_With_SHA512;
- digestAlgorithm = AlgorithmID.sha512;
- } else if (useStrongHash && fieldSize >= 256) {
- signatureAlgorithm = AlgorithmID.ecdsa_With_SHA256;
- digestAlgorithm = AlgorithmID.sha256;
- } else if (useStrongHash) {
- signatureAlgorithm = AlgorithmID.ecdsa_plain_With_RIPEMD160;
- digestAlgorithm = AlgorithmID.ripeMd160;
+ if (hashDataInput != null) {
+ return hashDataInput;
} else {
- signatureAlgorithm = AlgorithmID.ecdsa_With_SHA1;
- digestAlgorithm = AlgorithmID.sha1;
- }
- } else {
- throw new NoSuchAlgorithmException("Public key algorithm '" + algorithm
- + "' not supported.");
+ return new CMSHashDataInput(signedDocument, mimeType);
}
}
- private HashDataInput getHashDataInput() {
- return new CMSHashDataInput(signedDocument, mimeType);
- }
public byte[] sign(STAL stal, String keyboxIdentifier) throws CMSException, CMSSignatureException, SLCommandException {
STALSecurityProvider securityProvider = new STALSecurityProvider(stal, keyboxIdentifier, getHashDataInput(), this.excludedByteRange);
@@ -322,7 +323,29 @@ public class Signature {
}
throw new CMSSignatureException(e);
}
+ if (digestValue != null) {
+ try {
+ signedData.setMessageDigest(digestAlgorithm, digestValue);
+ } catch (NoSuchAlgorithmException e) {
+ throw new CMSSignatureException(e);
+ }
+ }
ContentInfo contentInfo = new ContentInfo(signedData);
return contentInfo.getEncoded();
}
+
+ protected AlgorithmID getAlgorithmID(String uri) throws URISyntaxException {
+ String oid = null;
+ URI urn = new URI(uri);
+ String scheme = urn.getScheme();
+ if ("URN".equalsIgnoreCase(scheme)) {
+ String schemeSpecificPart = urn.getSchemeSpecificPart().toLowerCase();
+ if (schemeSpecificPart.startsWith("oid:")) {
+ oid = schemeSpecificPart.substring(4, schemeSpecificPart.length());
+}
+ }
+ return new AlgorithmID(new ObjectID(oid));
+ }
}
+
+