From 0165e2dd986389f7c04b48cd0452f73c3d01c10a Mon Sep 17 00:00:00 2001
From: tkellner <tkellner@8a26b1a7-26f0-462f-b9ef-d0e30c41f5a4>
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
---
 .../bku/slcommands/impl/cms/CMSHashDataInput.java  | 67 ++++++++++++++++++++++
 .../slcommands/impl/cms/STALSecurityProvider.java  | 39 +++++++++----
 .../gv/egiz/bku/slcommands/impl/cms/Signature.java | 29 ++++++++--
 3 files changed, 118 insertions(+), 17 deletions(-)
 create mode 100644 bkucommon/src/main/java/at/gv/egiz/bku/slcommands/impl/cms/CMSHashDataInput.java

(limited to 'bkucommon/src/main/java')

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> 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<HashDataInput>();
+    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<STALResponse> responses =
@@ -79,11 +84,21 @@ public class STALSecurityProvider extends IaikProvider {
     }
   }
 
+  private static SignRequest getSTALSignRequest(String keyboxIdentifier,
+      byte[] signedAttributes, String signatureMethod, List<HashDataInput> 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<Attribute> 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();
-- 
cgit v1.2.3