| package org.bouncycastle.tsp.test; |
| |
| import java.io.ByteArrayInputStream; |
| import java.io.ByteArrayOutputStream; |
| import java.io.InputStream; |
| import java.math.BigInteger; |
| import java.security.KeyPair; |
| import java.security.PrivateKey; |
| import java.security.Security; |
| import java.security.cert.X509Certificate; |
| import java.util.ArrayList; |
| import java.util.Date; |
| import java.util.List; |
| |
| import junit.framework.TestCase; |
| import org.bouncycastle.asn1.ASN1ObjectIdentifier; |
| import org.bouncycastle.asn1.nist.NISTObjectIdentifiers; |
| import org.bouncycastle.asn1.x509.AlgorithmIdentifier; |
| import org.bouncycastle.cert.jcajce.JcaCertStore; |
| import org.bouncycastle.cms.jcajce.JcaSimpleSignerInfoGeneratorBuilder; |
| import org.bouncycastle.jce.provider.BouncyCastleProvider; |
| import org.bouncycastle.operator.DigestCalculator; |
| import org.bouncycastle.operator.DigestCalculatorProvider; |
| import org.bouncycastle.operator.bc.BcDigestCalculatorProvider; |
| import org.bouncycastle.tsp.TSPAlgorithms; |
| import org.bouncycastle.tsp.TimeStampRequest; |
| import org.bouncycastle.tsp.TimeStampRequestGenerator; |
| import org.bouncycastle.tsp.TimeStampResponse; |
| import org.bouncycastle.tsp.TimeStampResponseGenerator; |
| import org.bouncycastle.tsp.TimeStampToken; |
| import org.bouncycastle.tsp.TimeStampTokenGenerator; |
| import org.bouncycastle.tsp.cms.CMSTimeStampedData; |
| import org.bouncycastle.tsp.cms.CMSTimeStampedDataGenerator; |
| import org.bouncycastle.tsp.cms.CMSTimeStampedDataParser; |
| import org.bouncycastle.util.Arrays; |
| import org.bouncycastle.util.Store; |
| import org.bouncycastle.util.io.Streams; |
| |
| public class CMSTimeStampedDataGeneratorTest |
| extends TestCase |
| { |
| |
| BouncyCastleProvider bouncyCastleProvider; |
| CMSTimeStampedDataGenerator cmsTimeStampedDataGenerator = null; |
| String fileInput = "FileDaFirmare.data"; |
| byte[] baseData; |
| |
| protected void setUp() |
| throws Exception |
| { |
| bouncyCastleProvider = new BouncyCastleProvider(); |
| if (Security.getProvider(bouncyCastleProvider.getName()) == null) |
| { |
| Security.addProvider(bouncyCastleProvider); |
| } |
| |
| cmsTimeStampedDataGenerator = new CMSTimeStampedDataGenerator(); |
| ByteArrayOutputStream origStream = new ByteArrayOutputStream(); |
| InputStream in = this.getClass().getResourceAsStream(fileInput); |
| int ch; |
| |
| while ((ch = in.read()) >= 0) |
| { |
| origStream.write(ch); |
| } |
| |
| origStream.close(); |
| |
| this.baseData = origStream.toByteArray(); |
| |
| } |
| |
| protected void tearDown() |
| throws Exception |
| { |
| cmsTimeStampedDataGenerator = null; |
| Security.removeProvider(bouncyCastleProvider.getName()); |
| } |
| |
| public void testGenerate() |
| throws Exception |
| { |
| BcDigestCalculatorProvider calculatorProvider = new BcDigestCalculatorProvider(); |
| ASN1ObjectIdentifier algOID = new ASN1ObjectIdentifier("2.16.840.1.101.3.4.2.1"); // SHA-256 |
| DigestCalculator hashCalculator = calculatorProvider.get(new AlgorithmIdentifier(algOID)); |
| |
| cmsTimeStampedDataGenerator.initialiseMessageImprintDigestCalculator(hashCalculator); |
| |
| hashCalculator.getOutputStream().write(baseData); |
| hashCalculator.getOutputStream().close(); |
| |
| TimeStampToken timeStampToken = createTimeStampToken(hashCalculator.getDigest(), NISTObjectIdentifiers.id_sha256); |
| CMSTimeStampedData cmsTimeStampedData = cmsTimeStampedDataGenerator.generate(timeStampToken, baseData); |
| |
| for (int i = 0; i < 3; i++) |
| { |
| byte[] newRequestData = cmsTimeStampedData.calculateNextHash(hashCalculator); |
| TimeStampToken newTimeStampToken = createTimeStampToken(newRequestData, NISTObjectIdentifiers.id_sha256); |
| cmsTimeStampedData = cmsTimeStampedData.addTimeStamp(newTimeStampToken); |
| } |
| byte[] timeStampedData = cmsTimeStampedData.getEncoded(); |
| |
| // verify |
| DigestCalculatorProvider newCalculatorProvider = new BcDigestCalculatorProvider(); |
| DigestCalculator imprintCalculator = cmsTimeStampedData.getMessageImprintDigestCalculator(newCalculatorProvider); |
| CMSTimeStampedData newCMSTimeStampedData = new CMSTimeStampedData(timeStampedData); |
| byte[] newContent = newCMSTimeStampedData.getContent(); |
| assertEquals("Content expected and verified are different", true, Arrays.areEqual(newContent, baseData)); |
| |
| imprintCalculator.getOutputStream().write(newContent); |
| |
| byte[] digest = imprintCalculator.getDigest(); |
| |
| TimeStampToken[] tokens = cmsTimeStampedData.getTimeStampTokens(); |
| assertEquals("TimeStampToken expected and verified are different", 4, tokens.length); |
| for (int i = 0; i < tokens.length; i++) |
| { |
| cmsTimeStampedData.validate(newCalculatorProvider, digest, tokens[i]); |
| } |
| } |
| |
| public void testGenerateWithMetadata() |
| throws Exception |
| { |
| cmsTimeStampedDataGenerator.setMetaData(true, fileInput, "TXT"); |
| |
| BcDigestCalculatorProvider calculatorProvider = new BcDigestCalculatorProvider(); |
| ASN1ObjectIdentifier algOID = new ASN1ObjectIdentifier("2.16.840.1.101.3.4.2.1"); // SHA-256 |
| DigestCalculator hashCalculator = calculatorProvider.get(new AlgorithmIdentifier(algOID)); |
| |
| cmsTimeStampedDataGenerator.initialiseMessageImprintDigestCalculator(hashCalculator); |
| |
| hashCalculator.getOutputStream().write(baseData); |
| hashCalculator.getOutputStream().close(); |
| |
| TimeStampToken timeStampToken = createTimeStampToken(hashCalculator.getDigest(), NISTObjectIdentifiers.id_sha256); |
| CMSTimeStampedData cmsTimeStampedData = cmsTimeStampedDataGenerator.generate(timeStampToken, baseData); |
| |
| for (int i = 0; i <= 3; i++) |
| { |
| byte[] newRequestData = cmsTimeStampedData.calculateNextHash(hashCalculator); |
| TimeStampToken newTimeStampToken = createTimeStampToken(newRequestData, NISTObjectIdentifiers.id_sha256); |
| cmsTimeStampedData = cmsTimeStampedData.addTimeStamp(newTimeStampToken); |
| } |
| byte[] timeStampedData = cmsTimeStampedData.getEncoded(); |
| |
| metadataCheck(timeStampedData); |
| metadataParserCheck(timeStampedData); |
| } |
| |
| public void testGenerateWithMetadataAndDifferentAlgorithmIdentifier() |
| throws Exception |
| { |
| cmsTimeStampedDataGenerator.setMetaData(true, fileInput, "TXT"); |
| |
| BcDigestCalculatorProvider calculatorProvider = new BcDigestCalculatorProvider(); |
| |
| ASN1ObjectIdentifier algIdentifier = NISTObjectIdentifiers.id_sha224; |
| |
| DigestCalculator hashCalculator = calculatorProvider.get(new AlgorithmIdentifier(algIdentifier)); |
| cmsTimeStampedDataGenerator.initialiseMessageImprintDigestCalculator(hashCalculator); |
| hashCalculator.getOutputStream().write(baseData); |
| hashCalculator.getOutputStream().close(); |
| |
| byte[] requestData = hashCalculator.getDigest(); |
| TimeStampToken timeStampToken = createTimeStampToken(requestData, algIdentifier); |
| |
| CMSTimeStampedData cmsTimeStampedData = cmsTimeStampedDataGenerator.generate(timeStampToken, baseData); |
| |
| for (int i = 0; i <= 3; i++) { |
| switch (i) { |
| case 0: |
| algIdentifier = NISTObjectIdentifiers.id_sha224; |
| break; |
| case 1: |
| algIdentifier = NISTObjectIdentifiers.id_sha256; |
| break; |
| case 2: |
| algIdentifier = NISTObjectIdentifiers.id_sha384; |
| break; |
| case 3: |
| algIdentifier = NISTObjectIdentifiers.id_sha512; |
| break; |
| } |
| hashCalculator = calculatorProvider.get(new AlgorithmIdentifier(algIdentifier)); |
| byte[] newRequestData = cmsTimeStampedData.calculateNextHash(hashCalculator); |
| TimeStampToken newTimeStampToken = createTimeStampToken(newRequestData, algIdentifier); |
| cmsTimeStampedData = cmsTimeStampedData.addTimeStamp(newTimeStampToken); |
| } |
| byte[] timeStampedData = cmsTimeStampedData.getEncoded(); |
| |
| metadataCheck(timeStampedData); |
| metadataParserCheck(timeStampedData); |
| |
| } |
| |
| |
| private void metadataCheck(byte[] timeStampedData) |
| throws Exception |
| { |
| CMSTimeStampedData cmsTspData = new CMSTimeStampedData(timeStampedData); |
| DigestCalculatorProvider newCalculatorProvider = new BcDigestCalculatorProvider(); |
| DigestCalculator imprintCalculator = cmsTspData.getMessageImprintDigestCalculator(newCalculatorProvider); |
| |
| byte[] newContent = cmsTspData.getContent(); |
| assertEquals("Content expected and verified are different", true, Arrays.areEqual(newContent, baseData)); |
| |
| imprintCalculator.getOutputStream().write(newContent); |
| |
| assertEquals(fileInput, cmsTspData.getFileName()); |
| assertEquals("TXT", cmsTspData.getMediaType()); |
| |
| byte[] digest = imprintCalculator.getDigest(); |
| |
| TimeStampToken[] tokens = cmsTspData.getTimeStampTokens(); |
| assertEquals("TimeStampToken expected and verified are different", 5, tokens.length); |
| for (int i = 0; i < tokens.length; i++) |
| { |
| cmsTspData.validate(newCalculatorProvider, digest, tokens[i]); |
| } |
| } |
| |
| private void metadataParserCheck(byte[] timeStampedData) |
| throws Exception |
| { |
| CMSTimeStampedDataParser cmsTspData = new CMSTimeStampedDataParser(timeStampedData); |
| DigestCalculatorProvider newCalculatorProvider = new BcDigestCalculatorProvider(); |
| |
| InputStream input = cmsTspData.getContent(); |
| ByteArrayOutputStream bOut = new ByteArrayOutputStream(); |
| |
| Streams.pipeAll(input, bOut); |
| |
| assertEquals("Content expected and verified are different", true, Arrays.areEqual(bOut.toByteArray(), baseData)); |
| |
| DigestCalculator imprintCalculator = cmsTspData.getMessageImprintDigestCalculator(newCalculatorProvider); |
| |
| Streams.pipeAll(new ByteArrayInputStream(bOut.toByteArray()), imprintCalculator.getOutputStream()); |
| |
| assertEquals(fileInput, cmsTspData.getFileName()); |
| assertEquals("TXT", cmsTspData.getMediaType()); |
| |
| byte[] digest = imprintCalculator.getDigest(); |
| |
| TimeStampToken[] tokens = cmsTspData.getTimeStampTokens(); |
| assertEquals("TimeStampToken expected and verified are different", 5, tokens.length); |
| for (int i = 0; i < tokens.length; i++) |
| { |
| cmsTspData.validate(newCalculatorProvider, digest, tokens[i]); |
| } |
| } |
| |
| private TimeStampToken createTimeStampToken(byte[] hash, ASN1ObjectIdentifier hashAlg) |
| throws Exception |
| { |
| String algorithmName = null; |
| if (hashAlg.equals(NISTObjectIdentifiers.id_sha224)) |
| { |
| algorithmName = "SHA224withRSA"; |
| } |
| else if (hashAlg.equals(NISTObjectIdentifiers.id_sha256)) |
| { |
| algorithmName = "SHA256withRSA"; |
| } |
| else if (hashAlg.equals(NISTObjectIdentifiers.id_sha384)) |
| { |
| algorithmName = "SHA384withRSA"; |
| } |
| else if (hashAlg.equals(NISTObjectIdentifiers.id_sha512)) |
| { |
| algorithmName = "SHA512withRSA"; |
| } |
| |
| String signDN = "O=Bouncy Castle, C=AU"; |
| KeyPair signKP = TSPTestUtil.makeKeyPair(); |
| X509Certificate signCert = TSPTestUtil.makeCACertificate(signKP, |
| signDN, signKP, signDN); |
| |
| String origDN = "CN=Eric H. Echidna, E=eric@bouncycastle.org, O=Bouncy Castle, C=AU"; |
| KeyPair origKP = TSPTestUtil.makeKeyPair(); |
| X509Certificate cert = TSPTestUtil.makeCertificate(origKP, |
| origDN, signKP, signDN); |
| |
| PrivateKey privateKey = origKP.getPrivate(); |
| |
| List certList = new ArrayList(); |
| certList.add(cert); |
| certList.add(signCert); |
| |
| Store certs = new JcaCertStore(certList); |
| |
| |
| TimeStampTokenGenerator tsTokenGen = new TimeStampTokenGenerator( |
| new JcaSimpleSignerInfoGeneratorBuilder().build(algorithmName, privateKey, cert), new SHA1DigestCalculator(), new ASN1ObjectIdentifier("1.2")); |
| |
| tsTokenGen.addCertificates(certs); |
| |
| TimeStampRequestGenerator reqGen = new TimeStampRequestGenerator(); |
| TimeStampRequest request = reqGen.generate(hashAlg, hash); |
| |
| TimeStampResponseGenerator tsRespGen = new TimeStampResponseGenerator(tsTokenGen, TSPAlgorithms.ALLOWED); |
| |
| TimeStampResponse tsResp = tsRespGen.generate(request, new BigInteger("23"), new Date()); |
| |
| tsResp = new TimeStampResponse(tsResp.getEncoded()); |
| |
| return tsResp.getTimeStampToken(); |
| } |
| } |