diff options
Diffstat (limited to 'bkucommon')
3 files changed, 118 insertions, 17 deletions
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(); |