From 0165e2dd986389f7c04b48cd0452f73c3d01c10a Mon Sep 17 00:00:00 2001 From: tkellner Date: Thu, 12 Dec 2013 18:44:48 +0000 Subject: Display CMS data in Secure Viewer git-svn-id: https://joinup.ec.europa.eu/svn/mocca/trunk@1251 8a26b1a7-26f0-462f-b9ef-d0e30c41f5a4 --- .../src/main/java/at/gv/egiz/stal/SignRequest.java | 10 ++-- .../bku/slcommands/impl/cms/CMSHashDataInput.java | 67 ++++++++++++++++++++++ .../slcommands/impl/cms/STALSecurityProvider.java | 39 +++++++++---- .../gv/egiz/bku/slcommands/impl/cms/Signature.java | 29 ++++++++-- .../gv/egiz/bku/smccstal/SignRequestHandler.java | 30 +++++++--- 5 files changed, 144 insertions(+), 31 deletions(-) create mode 100644 bkucommon/src/main/java/at/gv/egiz/bku/slcommands/impl/cms/CMSHashDataInput.java 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 a649d3ba..7319efcb 100644 --- a/STAL/src/main/java/at/gv/egiz/stal/SignRequest.java +++ b/STAL/src/main/java/at/gv/egiz/stal/SignRequest.java @@ -66,7 +66,7 @@ public class SignRequest @XmlTransient protected List hashData; @XmlTransient - protected boolean signedInfoIsRawData = false; + protected boolean signedInfoIsCMSSignedAttributes = false; @XmlTransient protected String signatureMethod; @@ -124,12 +124,12 @@ public class SignRequest this.hashData = hashData; } - public boolean getSignedInfoIsRawData() { - return signedInfoIsRawData; + public boolean getSignedInfoIsCMSSignedAttributes() { + return signedInfoIsCMSSignedAttributes; } - public void setSignedInfoIsRawData(boolean signedInfoIsRawData) { - this.signedInfoIsRawData = signedInfoIsRawData; + public void setSignedInfoIsCMSSignedAttributes(boolean signedInfoIsCMSSignedAttributes) { + this.signedInfoIsCMSSignedAttributes = signedInfoIsCMSSignedAttributes; } public String getSignatureMethod() { 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 new file mode 100644 index 00000000..6aa37e15 --- /dev/null +++ b/bkucommon/src/main/java/at/gv/egiz/bku/slcommands/impl/cms/CMSHashDataInput.java @@ -0,0 +1,67 @@ +package at.gv.egiz.bku.slcommands.impl.cms; + +import java.io.ByteArrayInputStream; +import java.io.InputStream; + +import at.gv.egiz.stal.HashDataInput; + +public class CMSHashDataInput implements HashDataInput { + + private final static String DEFAULT_FILENAME = "SignatureData"; + private final static String CMS_DEF_REFERENCE_ID = "Reference-1"; + + private byte[] data; + private String mimeType; + + public CMSHashDataInput(byte[] data, String mimeType) { + this.data = data; + this.mimeType = mimeType; + } + + @Override + public String getReferenceId() { + return CMS_DEF_REFERENCE_ID; + } + + @Override + public String getMimeType() { + return mimeType; + } + + @Override + public String getEncoding() { + return null; + } + + @Override + public String getFilename() { + String fileName = DEFAULT_FILENAME; + String extension = getExtensionForMimeType(mimeType); + if (extension != null) + fileName += extension; + return fileName; + } + + @Override + public InputStream getHashDataInput() { + return new ByteArrayInputStream(data); + } + private static String getExtensionForMimeType(String mimeType) { + if (mimeType.equalsIgnoreCase("application/pdf")) { + return ".pdf"; + } + else if (mimeType.equalsIgnoreCase("text/plain")) { + return ".txt"; + } + else if (mimeType.equalsIgnoreCase("application/xml")) { + return ".xml"; + } + else if (mimeType.equalsIgnoreCase("application/zip")) { + return ".zip"; + } + else if (mimeType.equalsIgnoreCase("application/gzip")) { + return ".gz"; + } + return null; + } +} 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 cb7d9a7a..cdd8f111 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 @@ -12,6 +12,7 @@ import java.security.InvalidKeyException; import java.security.NoSuchAlgorithmException; import java.security.PrivateKey; import java.security.SignatureException; +import java.util.ArrayList; import java.util.Arrays; import java.util.Collections; import java.util.List; @@ -21,6 +22,7 @@ import org.slf4j.LoggerFactory; import at.gv.egiz.bku.slcommands.impl.xsect.STALSignatureException; import at.gv.egiz.stal.ErrorResponse; +import at.gv.egiz.stal.HashDataInput; import at.gv.egiz.stal.STAL; import at.gv.egiz.stal.STALRequest; import at.gv.egiz.stal.STALResponse; @@ -29,15 +31,22 @@ import at.gv.egiz.stal.SignResponse; public class STALSecurityProvider extends IaikProvider { - private final Logger log = LoggerFactory.getLogger(STALSecurityProvider.class); + private final static Logger log = LoggerFactory.getLogger(STALSecurityProvider.class); - private String keyboxIdentifier; + private final static String ID_ECSIGTYPE = "1.2.840.10045.4"; + @SuppressWarnings("unused") + private final static String ECDSA_PLAIN_SIGNATURES = "0.4.0.127.0.7.1.1.4.1"; + private String keyboxIdentifier; private STAL stal; + private List hashDataInput; - public STALSecurityProvider(STAL stal, String keyboxIdentifier) { + public STALSecurityProvider(STAL stal, String keyboxIdentifier, + HashDataInput hashDataInput) { this.keyboxIdentifier = keyboxIdentifier; this.stal = stal; + this.hashDataInput = new ArrayList(); + this.hashDataInput.add(hashDataInput); } /* (non-Javadoc) @@ -50,12 +59,8 @@ public class STALSecurityProvider extends IaikProvider { throws SignatureException, InvalidKeyException, NoSuchAlgorithmException { log.debug("calculateSignatureFromSignedAttributes: " + signatureAlgorithm + ", " + digestAlgorithm); - SignRequest signRequest = new SignRequest(); - signRequest.setKeyIdentifier(keyboxIdentifier); - log.debug("SignedAttributes: " + Util.toBase64String(signedAttributes)); - signRequest.setSignedInfo(signedAttributes); - signRequest.setSignedInfoIsRawData(true); - signRequest.setSignatureMethod(privateKey.getAlgorithm()); + SignRequest signRequest = getSTALSignRequest(keyboxIdentifier, signedAttributes, + privateKey.getAlgorithm(), hashDataInput); log.debug("Sending STAL request ({})", privateKey.getAlgorithm()); List responses = @@ -79,11 +84,21 @@ public class STALSecurityProvider extends IaikProvider { } } + private static SignRequest getSTALSignRequest(String keyboxIdentifier, + byte[] signedAttributes, String signatureMethod, List hashDataInput) { + SignRequest signRequest = new SignRequest(); + signRequest.setKeyIdentifier(keyboxIdentifier); + log.debug("SignedAttributes: " + Util.toBase64String(signedAttributes)); + signRequest.setSignedInfo(signedAttributes); + signRequest.setSignedInfoIsCMSSignedAttributes(true); + signRequest.setSignatureMethod(signatureMethod); + signRequest.setHashDataInput(hashDataInput); + return signRequest; + } + private static byte[] wrapSignatureValue(byte[] sig, AlgorithmID sigAlgorithmID) { String id = sigAlgorithmID.getAlgorithm().getID(); - // 0.4.0.127.0.7.1.1.4.1...: ecdsa-plain-signatures - // 1.2.840.10045.4...: id-ecSigType - if (id.startsWith("1.2.840.10045.4")) //X9.62 Format ECDSA signatures + 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); 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 26de1052..307f0bfc 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 @@ -70,6 +70,7 @@ import at.gv.egiz.bku.slcommands.impl.xsect.AlgorithmMethodFactory; import at.gv.egiz.bku.slcommands.impl.xsect.AlgorithmMethodFactoryImpl; import at.gv.egiz.bku.slcommands.impl.xsect.STALSignatureException; import at.gv.egiz.bku.slexceptions.SLCommandException; +import at.gv.egiz.stal.HashDataInput; import at.gv.egiz.stal.STAL; /** @@ -79,6 +80,9 @@ import at.gv.egiz.stal.STAL; * @author tkellner */ public class Signature { + + public final static String ID_AA_ETS_MIMETYPE = "0.4.0.1733.2.1"; + /** * Logging facility. */ @@ -86,6 +90,8 @@ public class Signature { private SignedData signedData; private SignerInfo signerInfo; + private byte[] signedDocument; + private String mimeType; private AlgorithmID signatureAlgorithm; private AlgorithmID digestAlgorithm; private String signatureAlgorithmURI; @@ -95,13 +101,14 @@ public class Signature { public Signature(CMSDataObjectRequiredMetaType dataObject, String structure, X509Certificate signingCertificate, Date signingTime, boolean useStrongHash) throws NoSuchAlgorithmException, CertificateEncodingException, CertificateException, X509ExtensionException, InvalidParameterException, CodingException { - byte[] data = getContent(dataObject); + byte[] dataToBeSigned = getContent(dataObject); int mode = structure.equalsIgnoreCase("enveloping") ? SignedData.IMPLICIT : SignedData.EXPLICIT; - this.signedData = new SignedData(data, mode); + this.signedData = new SignedData(dataToBeSigned, mode); setAlgorithmIDs(signingCertificate, useStrongHash); createSignerInfo(signingCertificate); setSignerCertificate(signingCertificate); - setAttributes(dataObject.getMetaInfo().getMimeType(), signingCertificate, signingTime); + this.mimeType = dataObject.getMetaInfo().getMimeType(); + setAttributes(this.mimeType, signingCertificate, signingTime); } private void createSignerInfo(X509Certificate signingCertificate) throws CertificateEncodingException, CertificateException { @@ -130,7 +137,7 @@ public class Signature { } private void setMimeTypeAttrib(List attributes, String mimeType) { - String oidStr = "0.4.0.1733.2.1"; + String oidStr = ID_AA_ETS_MIMETYPE; String name = "mime-type"; ObjectID mimeTypeOID = new ObjectID(oidStr, name); @@ -167,6 +174,8 @@ public class Signature { private byte[] getContent(CMSDataObjectRequiredMetaType dataObject) throws InvalidParameterException { byte[] data = dataObject.getContent().getBase64Content(); + this.signedDocument = data.clone(); + ExcludedByteRangeType ebr = dataObject.getExcludedByteRange(); if (ebr == null) return data; @@ -176,6 +185,11 @@ public class Signature { if (from > data.length || to > data.length || from > to) throw new InvalidParameterException("ExcludeByteRange contains invalid data: [" + from + "-" + to + "], Content length: " + data.length); + + // Fill ExcludeByteRange with 0s for document to display in viewer + Arrays.fill(this.signedDocument, from, to+1, (byte)0); + + // Remove ExcludeByteRange from data to be signed byte[] first = null; byte[] second = null; if (from > 0) @@ -264,8 +278,13 @@ public class Signature { } } + private HashDataInput getHashDataInput() { + return new CMSHashDataInput(signedDocument, mimeType); + } + public byte[] sign(STAL stal, String keyboxIdentifier) throws CMSException, CMSSignatureException, SLCommandException { - signedData.setSecurityProvider(new STALSecurityProvider(stal, keyboxIdentifier)); + signedData.setSecurityProvider( + new STALSecurityProvider(stal, keyboxIdentifier, getHashDataInput())); setSignerInfo(); ContentInfo contentInfo = new ContentInfo(signedData); return contentInfo.getEncoded(); 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 10b2e191..8ba18010 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 @@ -24,11 +24,10 @@ package at.gv.egiz.bku.smccstal; -import at.gv.egiz.bku.gui.BKUGUIFacade; -import at.gv.egiz.bku.pin.gui.SignPINGUI; import java.io.ByteArrayInputStream; import java.io.IOException; import java.io.InputStream; +import java.util.List; import javax.xml.bind.JAXBContext; import javax.xml.bind.JAXBElement; @@ -38,12 +37,14 @@ 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.pin.gui.SignPINGUI; 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.SignatureCardException; import at.gv.egiz.smcc.SignatureCard.KeyboxName; +import at.gv.egiz.smcc.SignatureCardException; import at.gv.egiz.smcc.TimeoutException; import at.gv.egiz.stal.ErrorResponse; import at.gv.egiz.stal.STALRequest; @@ -52,12 +53,18 @@ import at.gv.egiz.stal.SignRequest; import at.gv.egiz.stal.SignResponse; import at.gv.egiz.stal.signedinfo.CanonicalizationMethodType; 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; public class SignRequestHandler extends AbstractRequestHandler { private final static Logger log = LoggerFactory.getLogger(SignRequestHandler.class); + + private final static String CMS_DEF_SIGNEDINFO_ID = "SignedInfo-1"; + private final static String CMS_DEF_OBJECT_ID = "SignatureData-1"; + private final static String CMS_DEF_REFERENCE_ID = "Reference-1"; + private static JAXBContext jaxbContext; static { @@ -88,12 +95,10 @@ public class SignRequestHandler extends AbstractRequestHandler { public STALResponse handleRequest(STALRequest request) throws InterruptedException { if (request instanceof SignRequest) { SignRequest signReq = (SignRequest) request; + byte[] signedInfoData = signReq.getSignedInfo(); try { - Unmarshaller unmarshaller = jaxbContext.createUnmarshaller(); - InputStream is = new ByteArrayInputStream(signReq.getSignedInfo()); - SignedInfoType signedInfo; - if (signReq.getSignedInfoIsRawData()) { + if (signReq.getSignedInfoIsCMSSignedAttributes()) { signedInfo = new SignedInfoType(); CanonicalizationMethodType canonicalizationMethod = new CanonicalizationMethodType(); @@ -102,8 +107,15 @@ public class SignRequestHandler extends AbstractRequestHandler { signatureMethod.setAlgorithm(signReq.getSignatureMethod()); signedInfo.setCanonicalizationMethod(canonicalizationMethod); signedInfo.setSignatureMethod(signatureMethod); - signedInfo.setId(""); + signedInfo.setId(CMS_DEF_SIGNEDINFO_ID); + List references = signedInfo.getReference(); + ReferenceType reference = new ReferenceType(); + reference.setId(CMS_DEF_REFERENCE_ID); + reference.setURI(CMS_DEF_OBJECT_ID); + references.add(reference); } else { + Unmarshaller unmarshaller = jaxbContext.createUnmarshaller(); + InputStream is = new ByteArrayInputStream(signedInfoData); JAXBElement si = (JAXBElement) unmarshaller.unmarshal(is); signedInfo = si.getValue(); @@ -112,7 +124,7 @@ public class SignRequestHandler extends AbstractRequestHandler { log.debug("Found signature method: {}.", signatureMethod); KeyboxName kb = SignatureCard.KeyboxName.getKeyboxName(signReq.getKeyIdentifier()); - byte[] resp = card.createSignature(new ByteArrayInputStream(signReq.getSignedInfo()), kb, + byte[] resp = card.createSignature(new ByteArrayInputStream(signedInfoData), kb, new SignPINGUI(gui, secureViewer, signedInfo), signatureMethod); if (resp == null) { return errorResponse(6001, "Response is null", null); -- cgit v1.2.3