From b9ccb62d35a755efb505d426ce924d5a8fbe937a Mon Sep 17 00:00:00 2001 From: "Bonato, Martin" Date: Thu, 8 Feb 2018 22:19:55 +0100 Subject: BulkSignature implementation --- .../gv/egiz/bku/slcommands/impl/cms/Signature.java | 187 ++++++++++++--------- 1 file changed, 105 insertions(+), 82 deletions(-) (limited to 'bkucommon/src/main/java/at/gv/egiz/bku/slcommands/impl/cms/Signature.java') 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)); + } } + + -- cgit v1.2.3