From b9ccb62d35a755efb505d426ce924d5a8fbe937a Mon Sep 17 00:00:00 2001 From: "Bonato, Martin" Date: Thu, 8 Feb 2018 22:19:55 +0100 Subject: BulkSignature implementation --- .../bku/slcommands/impl/BulkCommandImplTest.java | 130 +++++++++++++++++++++ .../impl/CreateCMSSignatureCommandImplTest.java | 33 +++++- .../bku/slcommands/impl/cms/SignatureTest.java | 130 +++++++++++++++++++++ .../bku/slcommands/impl/xsect/SignatureTest.java | 12 +- .../test/java/at/gv/egiz/stal/dummy/DummySTAL.java | 65 +++++++++-- 5 files changed, 356 insertions(+), 14 deletions(-) create mode 100644 bkucommon/src/test/java/at/gv/egiz/bku/slcommands/impl/BulkCommandImplTest.java create mode 100644 bkucommon/src/test/java/at/gv/egiz/bku/slcommands/impl/cms/SignatureTest.java (limited to 'bkucommon/src/test/java/at/gv') diff --git a/bkucommon/src/test/java/at/gv/egiz/bku/slcommands/impl/BulkCommandImplTest.java b/bkucommon/src/test/java/at/gv/egiz/bku/slcommands/impl/BulkCommandImplTest.java new file mode 100644 index 00000000..b91bec98 --- /dev/null +++ b/bkucommon/src/test/java/at/gv/egiz/bku/slcommands/impl/BulkCommandImplTest.java @@ -0,0 +1,130 @@ +/* + * Copyright 2015 Datentechnik Innovation 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; + +import static org.junit.Assert.assertEquals; +import static org.junit.Assert.assertNotNull; +import static org.junit.Assert.assertTrue; +import iaik.asn1.ObjectID; +import iaik.cms.SignedData; +import iaik.xml.crypto.XSecProvider; + +import java.io.ByteArrayInputStream; +import java.io.InputStream; +import java.io.InputStreamReader; + +import javax.xml.bind.JAXBException; +import javax.xml.bind.Unmarshaller; +import javax.xml.transform.stream.StreamResult; +import javax.xml.transform.stream.StreamSource; + +import org.junit.Before; +import org.junit.BeforeClass; +import org.junit.Test; +import org.springframework.context.ApplicationContext; +import org.springframework.context.support.ClassPathXmlApplicationContext; + +import at.buergerkarte.namespaces.securitylayer._1_2_3.BulkResponseType; +import at.gv.egiz.bku.slcommands.BulkCommand; +import at.gv.egiz.bku.slcommands.BulkSignatureResult; +import at.gv.egiz.bku.slcommands.SLCommand; +import at.gv.egiz.bku.slcommands.SLCommandContext; +import at.gv.egiz.bku.slcommands.SLCommandFactory; +import at.gv.egiz.bku.slcommands.SLResult; +import at.gv.egiz.bku.utils.urldereferencer.URLDereferencer; +import at.gv.egiz.stal.STAL; +import at.gv.egiz.stal.STALFactory; + +public class BulkCommandImplTest { + + protected static ApplicationContext appCtx; + private SLCommandFactory factory; + + private STAL stal; + + private URLDereferencer urlDereferencer; + + @BeforeClass + public static void setUpClass() { + appCtx = new ClassPathXmlApplicationContext("at/gv/egiz/bku/slcommands/testApplicationContext.xml"); + XSecProvider.addAsProvider(true); + } + + @Before + public void setUp() throws JAXBException { + + Object bean = appCtx.getBean("slCommandFactory"); + assertTrue(bean instanceof SLCommandFactory); + + factory = (SLCommandFactory) bean; + + bean = appCtx.getBean("stalFactory"); + assertTrue(bean instanceof STALFactory); + + stal = ((STALFactory) bean).createSTAL(); + + bean = appCtx.getBean("urlDereferencer"); + assertTrue(bean instanceof URLDereferencer); + + urlDereferencer = (URLDereferencer) bean; + + } + + @Test + public void testCreateCMSSignatureRequest() throws Exception { + InputStream inputStream = getClass().getClassLoader().getResourceAsStream( + "at/gv/egiz/bku/slcommands/bulksignaturerequest/BulkSignatureRequest.xml"); + assertNotNull(inputStream); + + SLCommand command = factory.createSLCommand(new StreamSource(new InputStreamReader(inputStream))); + assertTrue(command instanceof BulkCommand); + + SLCommandContext context = new SLCommandContext(stal, urlDereferencer, null); + SLResult result = command.execute(context); + + assertTrue(result instanceof BulkSignatureResult); + + BulkSignatureResult bulkResult = (BulkSignatureResult) result; + System.out.println(bulkResult.getContent()); + + bulkResult.getContent(); + + // unmarshall response + Unmarshaller unmarshaller = factory.getJaxbContext().createUnmarshaller(); + + BulkResponseType response = unmarshaller.unmarshal(bulkResult.getContent(), BulkResponseType.class).getValue(); + + // verify ContentType of singature + byte[] cmsSignature = response.getCreateSignatureResponse().get(0).getCreateCMSSignatureResponse() + .getCMSSignature(); + SignedData signedData = new SignedData(new ByteArrayInputStream(cmsSignature)); + + assertNotNull(signedData); + assertEquals(ObjectID.pkcs7_signedData, signedData.getContentType()); + assertNotNull(response.getCreateSignatureResponse()); + assertEquals(2, response.getCreateSignatureResponse().size()); + + result.writeTo(new StreamResult(System.out), false); + + } + +} diff --git a/bkucommon/src/test/java/at/gv/egiz/bku/slcommands/impl/CreateCMSSignatureCommandImplTest.java b/bkucommon/src/test/java/at/gv/egiz/bku/slcommands/impl/CreateCMSSignatureCommandImplTest.java index b1ec7777..09b70f09 100644 --- a/bkucommon/src/test/java/at/gv/egiz/bku/slcommands/impl/CreateCMSSignatureCommandImplTest.java +++ b/bkucommon/src/test/java/at/gv/egiz/bku/slcommands/impl/CreateCMSSignatureCommandImplTest.java @@ -24,13 +24,21 @@ package at.gv.egiz.bku.slcommands.impl; +import static org.junit.Assert.assertEquals; import static org.junit.Assert.assertNotNull; import static org.junit.Assert.assertTrue; +import iaik.asn1.ObjectID; +import iaik.cms.CMSParsingException; +import iaik.cms.SignedData; import iaik.xml.crypto.XSecProvider; +import java.io.ByteArrayInputStream; +import java.io.IOException; import java.io.InputStream; import java.io.InputStreamReader; +import javax.xml.bind.JAXBException; +import javax.xml.bind.Unmarshaller; import javax.xml.transform.stream.StreamResult; import javax.xml.transform.stream.StreamSource; @@ -40,7 +48,9 @@ import org.junit.Test; import org.springframework.context.ApplicationContext; import org.springframework.context.support.ClassPathXmlApplicationContext; +import at.buergerkarte.namespaces.securitylayer._1_2_3.CreateCMSSignatureResponseType; import at.gv.egiz.bku.slcommands.CreateCMSSignatureCommand; +import at.gv.egiz.bku.slcommands.CreateCMSSignatureResult; import at.gv.egiz.bku.slcommands.SLCommand; import at.gv.egiz.bku.slcommands.SLCommandContext; import at.gv.egiz.bku.slcommands.SLCommandFactory; @@ -89,8 +99,11 @@ public class CreateCMSSignatureCommandImplTest { } @Test - public void testCreateCMSSignatureRequest() throws SLCommandException, SLRuntimeException, SLRequestException, SLVersionException { - InputStream inputStream = getClass().getClassLoader().getResourceAsStream("at/gv/egiz/bku/slcommands/createcmssignaturerequest/CreateCMSSignatureRequest.xml"); + public void testCreateCMSSignatureRequest() throws SLCommandException, SLRuntimeException, SLRequestException, + SLVersionException, JAXBException, CMSParsingException, IOException { + + InputStream inputStream = getClass().getClassLoader().getResourceAsStream( + "at/gv/egiz/bku/slcommands/createcmssignaturerequest/CreateCMSSignatureRequest.xml"); assertNotNull(inputStream); SLCommand command = factory.createSLCommand(new StreamSource(new InputStreamReader(inputStream))); @@ -98,6 +111,22 @@ public class CreateCMSSignatureCommandImplTest { SLCommandContext context = new SLCommandContext(stal, urlDereferencer, null); SLResult result = command.execute(context); + + assertTrue(result instanceof CreateCMSSignatureResult); + CreateCMSSignatureResult sigResult = (CreateCMSSignatureResult) result; + + //unmarshall response + Unmarshaller unmarshaller = factory.getJaxbContext().createUnmarshaller(); + + CreateCMSSignatureResponseType response = unmarshaller.unmarshal(sigResult.getContent(), CreateCMSSignatureResponseType.class).getValue(); + + //verify ContentType of singature + byte[] cmsSignature = response.getCMSSignature(); + SignedData signedData = new SignedData(new ByteArrayInputStream(cmsSignature)); + + assertNotNull(signedData); + assertEquals(ObjectID.pkcs7_signedData, signedData.getContentType()); + result.writeTo(new StreamResult(System.out), false); } } diff --git a/bkucommon/src/test/java/at/gv/egiz/bku/slcommands/impl/cms/SignatureTest.java b/bkucommon/src/test/java/at/gv/egiz/bku/slcommands/impl/cms/SignatureTest.java new file mode 100644 index 00000000..56229b83 --- /dev/null +++ b/bkucommon/src/test/java/at/gv/egiz/bku/slcommands/impl/cms/SignatureTest.java @@ -0,0 +1,130 @@ +package at.gv.egiz.bku.slcommands.impl.cms; + +import static org.junit.Assert.*; + +import java.io.ByteArrayInputStream; +import java.net.URI; +import java.net.URISyntaxException; +import java.nio.charset.Charset; +import java.security.MessageDigest; +import java.util.Date; + +import org.junit.BeforeClass; +import org.junit.Test; +import org.w3._2000._09.xmldsig_.DigestMethodType; + +import at.buergerkarte.namespaces.securitylayer._1_2_3.Base64OptRefContentType; +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.MetaInfoType; +import at.gv.egiz.stal.dummy.DummySTAL; +import iaik.asn1.ObjectID; +import iaik.asn1.structures.AlgorithmID; +import iaik.cms.InvalidSignatureValueException; +import iaik.cms.SignedData; +import iaik.cms.SignerInfo; +import iaik.security.ecc.provider.ECCProvider; +import iaik.security.provider.IAIK; +import iaik.x509.X509Certificate; + +public class SignatureTest { + + private DummySTAL stal = new DummySTAL(); + + @BeforeClass + public static void setUpClass() { + IAIK.addAsProvider(); + ECCProvider.addAsProvider(); + } + + @Test + public void testSignCMSDataObject() throws Exception { + + byte[] plaintext = "Plaintext".getBytes(Charset.forName("UTF-8")); + + CMSDataObjectRequiredMetaType dataObject = new CMSDataObjectRequiredMetaType(); + Base64OptRefContentType base64OptRefContentType = new Base64OptRefContentType(); + base64OptRefContentType.setBase64Content(plaintext); + dataObject.setContent(base64OptRefContentType); + MetaInfoType metaInfoType = new MetaInfoType(); + metaInfoType.setMimeType("text/plain"); + dataObject.setMetaInfo(metaInfoType); + + Signature signature = new Signature(dataObject, "detached", stal.getCert(), new Date(), null, true); + byte[] cmsSignature = signature.sign(stal, "SecureSignatureKeypair"); + + SignedData signedData = new SignedData(new ByteArrayInputStream(cmsSignature)); + signedData.setContent(plaintext); + assertEquals(ObjectID.pkcs7_data, signedData.getEncapsulatedContentType()); + SignerInfo[] signerInfos = signedData.getSignerInfos(); + assertEquals(1, signerInfos.length); + SignerInfo signerInfo = signerInfos[0]; + signedData.verify((X509Certificate) stal.getCert()); + assertEquals(AlgorithmID.sha1, signerInfo.getDigestAlgorithm()); + assertEquals(AlgorithmID.sha1WithRSAEncryption, signerInfo.getSignatureAlgorithm()); + + System.out.println(AlgorithmID.sha1); + + } + + @Test + public void testSignCMSReferenceSha1() throws Exception { + testSignCMSReference(AlgorithmID.sha1); + } + + //TODO Why doesn't it work this way?? + @Test(expected = InvalidSignatureValueException.class) + public void testSignCMSReferenceSha256() throws Exception { + testSignCMSReference(AlgorithmID.sha256); + } + + private void testSignCMSReference(AlgorithmID digestAlgorithmID) throws Exception { + + byte[] plaintext = "Plaintext".getBytes(Charset.forName("UTF-8")); + + MessageDigest messageDigest = MessageDigest.getInstance(digestAlgorithmID.getImplementationName()); + byte[] digestValue = messageDigest.digest(plaintext); + + CMSDataObjectRequiredMetaType dataObject = new CMSDataObjectRequiredMetaType(); + DigestAndRefType digestAndRefType = new DigestAndRefType(); + DigestMethodType digestMethodType = new DigestMethodType(); + digestMethodType.setAlgorithm("URN:OID:" + digestAlgorithmID.getAlgorithm().getID()); + digestAndRefType.setDigestMethod(digestMethodType); + digestAndRefType.setDigestValue(digestValue); + dataObject.setDigestAndRef(digestAndRefType); + MetaInfoType metaInfoType = new MetaInfoType(); + metaInfoType.setMimeType("text/plain"); + dataObject.setMetaInfo(metaInfoType); + + Signature signature = new Signature(dataObject, "detached", stal.getCert(), new Date(), null, true); + byte[] cmsSignature = signature.sign(stal, "SecureSignatureKeypair"); + + SignedData signedData = new SignedData(new ByteArrayInputStream(cmsSignature)); + signedData.setContent(plaintext); + assertEquals(ObjectID.pkcs7_data, signedData.getEncapsulatedContentType()); + SignerInfo[] signerInfos = signedData.getSignerInfos(); + assertEquals(1, signerInfos.length); + SignerInfo signerInfo = signerInfos[0]; + signedData.verify((X509Certificate) stal.getCert()); + assertEquals(digestAlgorithmID, signerInfo.getDigestAlgorithm()); + assertEquals(AlgorithmID.sha1WithRSAEncryption, signerInfo.getSignatureAlgorithm()); + + } + + @Test + public void test() throws URISyntaxException { + + String oid = null; + URI uri = new URI("URN:OID:1.3.14.3.2.26"); + String scheme = uri.getScheme(); + if ("URN".equalsIgnoreCase(scheme)) { + String schemeSpecificPart = uri.getSchemeSpecificPart().toLowerCase(); + if (schemeSpecificPart.startsWith("oid:")) { + oid = schemeSpecificPart.substring(4, schemeSpecificPart.length()); + } + } + assertEquals("1.3.14.3.2.26", oid); + + } + +} diff --git a/bkucommon/src/test/java/at/gv/egiz/bku/slcommands/impl/xsect/SignatureTest.java b/bkucommon/src/test/java/at/gv/egiz/bku/slcommands/impl/xsect/SignatureTest.java index 6e5612f6..04cf3552 100644 --- a/bkucommon/src/test/java/at/gv/egiz/bku/slcommands/impl/xsect/SignatureTest.java +++ b/bkucommon/src/test/java/at/gv/egiz/bku/slcommands/impl/xsect/SignatureTest.java @@ -27,7 +27,7 @@ package at.gv.egiz.bku.slcommands.impl.xsect; import static org.junit.Assert.assertNotNull; import static org.junit.Assert.assertNull; import static org.junit.Assert.assertTrue; - +import iaik.asn1.structures.AlgorithmID; import iaik.xml.crypto.XSecProvider; import java.io.IOException; @@ -140,6 +140,16 @@ public class SignatureTest { return DigestMethod.SHA1; } + @Override + public AlgorithmID getSignatureAlgorithmID() { + return null; + } + + @Override + public AlgorithmID getDigestAlgorithmID() { + return null; + } + } private static final String RESOURCE_PREFIX = "at/gv/egiz/bku/slcommands/impl/"; diff --git a/bkucommon/src/test/java/at/gv/egiz/stal/dummy/DummySTAL.java b/bkucommon/src/test/java/at/gv/egiz/stal/dummy/DummySTAL.java index 61d0d480..0f054cf0 100644 --- a/bkucommon/src/test/java/at/gv/egiz/stal/dummy/DummySTAL.java +++ b/bkucommon/src/test/java/at/gv/egiz/stal/dummy/DummySTAL.java @@ -36,9 +36,13 @@ import java.util.ArrayList; import java.util.Enumeration; import java.util.List; +import javax.xml.crypto.dsig.SignatureMethod; + import org.slf4j.Logger; import org.slf4j.LoggerFactory; +import at.gv.egiz.stal.BulkSignRequest; +import at.gv.egiz.stal.BulkSignResponse; import at.gv.egiz.stal.ErrorResponse; import at.gv.egiz.stal.InfoboxReadRequest; import at.gv.egiz.stal.InfoboxReadResponse; @@ -47,6 +51,7 @@ import at.gv.egiz.stal.STALRequest; import at.gv.egiz.stal.STALResponse; import at.gv.egiz.stal.SignRequest; import at.gv.egiz.stal.SignResponse; +import iaik.xml.crypto.XmldsigMore; public class DummySTAL implements STAL { @@ -58,11 +63,9 @@ public class DummySTAL implements STAL { public DummySTAL() { try { KeyStore ks = KeyStore.getInstance("pkcs12"); - InputStream ksStream = getClass().getClassLoader().getResourceAsStream( - "at/gv/egiz/bku/slcommands/impl/Cert.p12"); + InputStream ksStream = getClass().getClassLoader().getResourceAsStream("at/gv/egiz/bku/slcommands/impl/Cert.p12"); ks.load(ksStream, "1622".toCharArray()); - for (Enumeration aliases = ks.aliases(); aliases - .hasMoreElements();) { + for (Enumeration aliases = ks.aliases(); aliases.hasMoreElements();) { String alias = aliases.nextElement(); log.debug("Found alias " + alias + " in keystore"); if (ks.isKeyEntry(alias)) { @@ -78,25 +81,28 @@ public class DummySTAL implements STAL { } + public X509Certificate getCert() { + return cert; + } + @Override public List handleRequest(List requestList) { List responses = new ArrayList(); for (STALRequest request : requestList) { - log.debug("Got STALRequest " + request + "."); + log.info("Got STALRequest " + request + "."); if (request instanceof InfoboxReadRequest) { - String infoboxIdentifier = ((InfoboxReadRequest) request) - .getInfoboxIdentifier(); + String infoboxIdentifier = ((InfoboxReadRequest) request).getInfoboxIdentifier(); InputStream stream = getClass().getClassLoader().getResourceAsStream( "at/gv/egiz/stal/dummy/infoboxes4/" + infoboxIdentifier + ".bin"); STALResponse response; if (stream != null) { - log.debug("Infobox " + infoboxIdentifier + " found."); + log.info("Infobox " + infoboxIdentifier + " found."); byte[] infobox; try { @@ -114,7 +120,8 @@ public class DummySTAL implements STAL { infoboxReadResponse.setInfoboxValue(infobox); response = infoboxReadResponse; - } else if ((infoboxIdentifier.equals("SecureSignatureKeypair")) ||(infoboxIdentifier.equals("CertifiedKeypair"))) { + } else if ((infoboxIdentifier.equals("SecureSignatureKeypair")) + || (infoboxIdentifier.equals("CertifiedKeypair"))) { try { InfoboxReadResponse infoboxReadResponse = new InfoboxReadResponse(); infoboxReadResponse.setInfoboxValue(cert.getEncoded()); @@ -135,7 +142,13 @@ public class DummySTAL implements STAL { try { SignRequest signReq = (SignRequest) request; - Signature s = Signature.getInstance("SHA1withRSA"); + String signatureMethod = ((SignRequest) request).getSignatureMethod(); + Signature s = null; + if (SignatureMethod.RSA_SHA1.equals(signatureMethod)) { + s = Signature.getInstance("SHA1withRSA"); + } else if (XmldsigMore.SIGNATURE_RSA_SHA256.equals(signatureMethod)) { + s = Signature.getInstance("SHA256withRSA"); + } s.initSign(privateKey); s.update(signReq.getSignedInfo().getValue()); byte[] sigVal = s.sign(); @@ -147,7 +160,37 @@ public class DummySTAL implements STAL { responses.add(new ErrorResponse()); } - } else { + } + + //dummy handler for BulkSignRequest + else if (request instanceof BulkSignRequest) { + + try { + BulkSignRequest bulkSignReq = (BulkSignRequest) request; + + BulkSignResponse bulkSignResp = new BulkSignResponse(); + + for (int i = 0; i < bulkSignReq.getSignRequests().size(); i++) { + + Signature s = Signature.getInstance("SHA1withRSA"); + s.initSign(privateKey); + s.update(bulkSignReq.getSignRequests().get(i).getSignedInfo().getValue()); + byte[] sigVal = s.sign(); + SignResponse resp = new SignResponse(); + resp.setSignatureValue(sigVal); + bulkSignResp.getSignResponse().add(resp); + } + + responses.add(bulkSignResp); + + } catch (Exception e) { + log.error("Failed to create signature.", e); + responses.add(new ErrorResponse()); + } + + } + + else { log.debug("Request not implemented."); -- cgit v1.2.3