package org.bouncycastle.tsp.test; import java.math.BigInteger; import java.security.KeyPair; import java.security.PrivateKey; import java.security.cert.CertStore; import java.security.cert.CollectionCertStoreParameters; import java.security.cert.X509Certificate; import java.util.ArrayList; import java.util.Collection; import java.util.Date; import java.util.HashSet; import java.util.List; import junit.framework.TestCase; import org.bouncycastle.asn1.cmp.PKIFailureInfo; import org.bouncycastle.asn1.cms.AttributeTable; import org.bouncycastle.asn1.pkcs.PKCSObjectIdentifiers; import org.bouncycastle.tsp.GenTimeAccuracy; import org.bouncycastle.tsp.TSPAlgorithms; import org.bouncycastle.tsp.TSPValidationException; 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.TimeStampTokenInfo; import org.bouncycastle.util.Arrays; public class TSPTest extends TestCase { public void testGeneral() throws Exception { 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 origCert = TSPTestUtil.makeCertificate(origKP, origDN, signKP, signDN); List certList = new ArrayList(); certList.add(origCert); certList.add(signCert); CertStore certs = CertStore.getInstance("Collection", new CollectionCertStoreParameters(certList), "BC"); basicTest(origKP.getPrivate(), origCert, certs); responseValidationTest(origKP.getPrivate(), origCert, certs); incorrectHashTest(origKP.getPrivate(), origCert, certs); badAlgorithmTest(origKP.getPrivate(), origCert, certs); timeNotAvailableTest(origKP.getPrivate(), origCert, certs); badPolicyTest(origKP.getPrivate(), origCert, certs); tokenEncodingTest(origKP.getPrivate(), origCert, certs); certReqTest(origKP.getPrivate(), origCert, certs); testAccuracyZeroCerts(origKP.getPrivate(), origCert, certs); testAccuracyWithCertsAndOrdering(origKP.getPrivate(), origCert, certs); testNoNonse(origKP.getPrivate(), origCert, certs); } private void basicTest( PrivateKey privateKey, X509Certificate cert, CertStore certs) throws Exception { TimeStampTokenGenerator tsTokenGen = new TimeStampTokenGenerator( privateKey, cert, TSPAlgorithms.SHA1, "1.2"); tsTokenGen.setCertificatesAndCRLs(certs); TimeStampRequestGenerator reqGen = new TimeStampRequestGenerator(); TimeStampRequest request = reqGen.generate(TSPAlgorithms.SHA1, new byte[20], BigInteger.valueOf(100)); TimeStampResponseGenerator tsRespGen = new TimeStampResponseGenerator(tsTokenGen, TSPAlgorithms.ALLOWED); TimeStampResponse tsResp = tsRespGen.generate(request, new BigInteger("23"), new Date(), "BC"); tsResp = new TimeStampResponse(tsResp.getEncoded()); TimeStampToken tsToken = tsResp.getTimeStampToken(); tsToken.validate(cert, "BC"); AttributeTable table = tsToken.getSignedAttributes(); assertNotNull("no signingCertificate attribute found", table.get(PKCSObjectIdentifiers.id_aa_signingCertificate)); } private void responseValidationTest( PrivateKey privateKey, X509Certificate cert, CertStore certs) throws Exception { TimeStampTokenGenerator tsTokenGen = new TimeStampTokenGenerator( privateKey, cert, TSPAlgorithms.MD5, "1.2"); tsTokenGen.setCertificatesAndCRLs(certs); TimeStampRequestGenerator reqGen = new TimeStampRequestGenerator(); TimeStampRequest request = reqGen.generate(TSPAlgorithms.SHA1, new byte[20], BigInteger.valueOf(100)); TimeStampResponseGenerator tsRespGen = new TimeStampResponseGenerator(tsTokenGen, TSPAlgorithms.ALLOWED); TimeStampResponse tsResp = tsRespGen.generate(request, new BigInteger("23"), new Date(), "BC"); tsResp = new TimeStampResponse(tsResp.getEncoded()); TimeStampToken tsToken = tsResp.getTimeStampToken(); tsToken.validate(cert, "BC"); // // check validation // tsResp.validate(request); try { request = reqGen.generate(TSPAlgorithms.SHA1, new byte[20], BigInteger.valueOf(101)); tsResp.validate(request); fail("response validation failed on invalid nonce."); } catch (TSPValidationException e) { // ignore } try { request = reqGen.generate(TSPAlgorithms.SHA1, new byte[22], BigInteger.valueOf(100)); tsResp.validate(request); fail("response validation failed on wrong digest."); } catch (TSPValidationException e) { // ignore } try { request = reqGen.generate(TSPAlgorithms.MD5, new byte[20], BigInteger.valueOf(100)); tsResp.validate(request); fail("response validation failed on wrong digest."); } catch (TSPValidationException e) { // ignore } } private void incorrectHashTest( PrivateKey privateKey, X509Certificate cert, CertStore certs) throws Exception { TimeStampTokenGenerator tsTokenGen = new TimeStampTokenGenerator( privateKey, cert, TSPAlgorithms.SHA1, "1.2"); tsTokenGen.setCertificatesAndCRLs(certs); TimeStampRequestGenerator reqGen = new TimeStampRequestGenerator(); TimeStampRequest request = reqGen.generate(TSPAlgorithms.SHA1, new byte[16]); TimeStampResponseGenerator tsRespGen = new TimeStampResponseGenerator(tsTokenGen, TSPAlgorithms.ALLOWED); TimeStampResponse tsResp = tsRespGen.generate(request, new BigInteger("23"), new Date(), "BC"); tsResp = new TimeStampResponse(tsResp.getEncoded()); TimeStampToken tsToken = tsResp.getTimeStampToken(); if (tsToken != null) { fail("incorrectHash - token not null."); } PKIFailureInfo failInfo = tsResp.getFailInfo(); if (failInfo == null) { fail("incorrectHash - failInfo set to null."); } if (failInfo.intValue() != PKIFailureInfo.badDataFormat) { fail("incorrectHash - wrong failure info returned."); } } private void badAlgorithmTest( PrivateKey privateKey, X509Certificate cert, CertStore certs) throws Exception { TimeStampTokenGenerator tsTokenGen = new TimeStampTokenGenerator( privateKey, cert, TSPAlgorithms.SHA1, "1.2"); tsTokenGen.setCertificatesAndCRLs(certs); TimeStampRequestGenerator reqGen = new TimeStampRequestGenerator(); TimeStampRequest request = reqGen.generate("1.2.3.4.5", new byte[20]); TimeStampResponseGenerator tsRespGen = new TimeStampResponseGenerator(tsTokenGen, TSPAlgorithms.ALLOWED); TimeStampResponse tsResp = tsRespGen.generate(request, new BigInteger("23"), new Date(), "BC"); tsResp = new TimeStampResponse(tsResp.getEncoded()); TimeStampToken tsToken = tsResp.getTimeStampToken(); if (tsToken != null) { fail("badAlgorithm - token not null."); } PKIFailureInfo failInfo = tsResp.getFailInfo(); if (failInfo == null) { fail("badAlgorithm - failInfo set to null."); } if (failInfo.intValue() != PKIFailureInfo.badAlg) { fail("badAlgorithm - wrong failure info returned."); } } private void timeNotAvailableTest( PrivateKey privateKey, X509Certificate cert, CertStore certs) throws Exception { TimeStampTokenGenerator tsTokenGen = new TimeStampTokenGenerator( privateKey, cert, TSPAlgorithms.SHA1, "1.2"); tsTokenGen.setCertificatesAndCRLs(certs); TimeStampRequestGenerator reqGen = new TimeStampRequestGenerator(); TimeStampRequest request = reqGen.generate("1.2.3.4.5", new byte[20]); TimeStampResponseGenerator tsRespGen = new TimeStampResponseGenerator(tsTokenGen, TSPAlgorithms.ALLOWED); TimeStampResponse tsResp = tsRespGen.generate(request, new BigInteger("23"), null, "BC"); tsResp = new TimeStampResponse(tsResp.getEncoded()); TimeStampToken tsToken = tsResp.getTimeStampToken(); if (tsToken != null) { fail("timeNotAvailable - token not null."); } PKIFailureInfo failInfo = tsResp.getFailInfo(); if (failInfo == null) { fail("timeNotAvailable - failInfo set to null."); } if (failInfo.intValue() != PKIFailureInfo.timeNotAvailable) { fail("timeNotAvailable - wrong failure info returned."); } } private void badPolicyTest( PrivateKey privateKey, X509Certificate cert, CertStore certs) throws Exception { TimeStampTokenGenerator tsTokenGen = new TimeStampTokenGenerator( privateKey, cert, TSPAlgorithms.SHA1, "1.2"); tsTokenGen.setCertificatesAndCRLs(certs); TimeStampRequestGenerator reqGen = new TimeStampRequestGenerator(); reqGen.setReqPolicy("1.1"); TimeStampRequest request = reqGen.generate(TSPAlgorithms.SHA1, new byte[20]); TimeStampResponseGenerator tsRespGen = new TimeStampResponseGenerator(tsTokenGen, TSPAlgorithms.ALLOWED, new HashSet()); TimeStampResponse tsResp = tsRespGen.generate(request, new BigInteger("23"), new Date(), "BC"); tsResp = new TimeStampResponse(tsResp.getEncoded()); TimeStampToken tsToken = tsResp.getTimeStampToken(); if (tsToken != null) { fail("badPolicy - token not null."); } PKIFailureInfo failInfo = tsResp.getFailInfo(); if (failInfo == null) { fail("badPolicy - failInfo set to null."); } if (failInfo.intValue() != PKIFailureInfo.unacceptedPolicy) { fail("badPolicy - wrong failure info returned."); } } private void certReqTest( PrivateKey privateKey, X509Certificate cert, CertStore certs) throws Exception { TimeStampTokenGenerator tsTokenGen = new TimeStampTokenGenerator( privateKey, cert, TSPAlgorithms.MD5, "1.2"); tsTokenGen.setCertificatesAndCRLs(certs); TimeStampRequestGenerator reqGen = new TimeStampRequestGenerator(); // // request with certReq false // reqGen.setCertReq(false); TimeStampRequest request = reqGen.generate(TSPAlgorithms.SHA1, new byte[20], BigInteger.valueOf(100)); TimeStampResponseGenerator tsRespGen = new TimeStampResponseGenerator(tsTokenGen, TSPAlgorithms.ALLOWED); TimeStampResponse tsResp = tsRespGen.generate(request, new BigInteger("23"), new Date(), "BC"); tsResp = new TimeStampResponse(tsResp.getEncoded()); TimeStampToken tsToken = tsResp.getTimeStampToken(); assertNull(tsToken.getTimeStampInfo().getGenTimeAccuracy()); // check for abscence of accuracy assertEquals("1.2", tsToken.getTimeStampInfo().getPolicy()); try { tsToken.validate(cert, "BC"); } catch (TSPValidationException e) { fail("certReq(false) verification of token failed."); } CertStore respCerts = tsToken.getCertificatesAndCRLs("Collection", "BC"); Collection certsColl = respCerts.getCertificates(null); if (!certsColl.isEmpty()) { fail("certReq(false) found certificates in response."); } } private void tokenEncodingTest( PrivateKey privateKey, X509Certificate cert, CertStore certs) throws Exception { TimeStampTokenGenerator tsTokenGen = new TimeStampTokenGenerator( privateKey, cert, TSPAlgorithms.SHA1, "1.2.3.4.5.6"); tsTokenGen.setCertificatesAndCRLs(certs); TimeStampRequestGenerator reqGen = new TimeStampRequestGenerator(); TimeStampRequest request = reqGen.generate(TSPAlgorithms.SHA1, new byte[20], BigInteger.valueOf(100)); TimeStampResponseGenerator tsRespGen = new TimeStampResponseGenerator(tsTokenGen, TSPAlgorithms.ALLOWED); TimeStampResponse tsResp = tsRespGen.generate(request, new BigInteger("23"), new Date(), "BC"); tsResp = new TimeStampResponse(tsResp.getEncoded()); TimeStampResponse tsResponse = new TimeStampResponse(tsResp.getEncoded()); if (!Arrays.areEqual(tsResponse.getEncoded(), tsResp.getEncoded()) || !Arrays.areEqual(tsResponse.getTimeStampToken().getEncoded(), tsResp.getTimeStampToken().getEncoded())) { fail(); } } private void testAccuracyZeroCerts( PrivateKey privateKey, X509Certificate cert, CertStore certs) throws Exception { TimeStampTokenGenerator tsTokenGen = new TimeStampTokenGenerator( privateKey, cert, TSPAlgorithms.MD5, "1.2"); tsTokenGen.setCertificatesAndCRLs(certs); tsTokenGen.setAccuracySeconds(1); tsTokenGen.setAccuracyMillis(2); tsTokenGen.setAccuracyMicros(3); TimeStampRequestGenerator reqGen = new TimeStampRequestGenerator(); TimeStampRequest request = reqGen.generate(TSPAlgorithms.SHA1, new byte[20], BigInteger.valueOf(100)); TimeStampResponseGenerator tsRespGen = new TimeStampResponseGenerator(tsTokenGen, TSPAlgorithms.ALLOWED); TimeStampResponse tsResp = tsRespGen.generate(request, new BigInteger("23"), new Date(), "BC"); tsResp = new TimeStampResponse(tsResp.getEncoded()); TimeStampToken tsToken = tsResp.getTimeStampToken(); tsToken.validate(cert, "BC"); // // check validation // tsResp.validate(request); // // check tstInfo // TimeStampTokenInfo tstInfo = tsToken.getTimeStampInfo(); // // check accuracy // GenTimeAccuracy accuracy = tstInfo.getGenTimeAccuracy(); assertEquals(1, accuracy.getSeconds()); assertEquals(2, accuracy.getMillis()); assertEquals(3, accuracy.getMicros()); assertEquals(new BigInteger("23"), tstInfo.getSerialNumber()); assertEquals("1.2", tstInfo.getPolicy()); // // test certReq // CertStore store = tsToken.getCertificatesAndCRLs("Collection", "BC"); Collection certificates = store.getCertificates(null); assertEquals(0, certificates.size()); } private void testAccuracyWithCertsAndOrdering( PrivateKey privateKey, X509Certificate cert, CertStore certs) throws Exception { TimeStampTokenGenerator tsTokenGen = new TimeStampTokenGenerator( privateKey, cert, TSPAlgorithms.MD5, "1.2.3"); tsTokenGen.setCertificatesAndCRLs(certs); tsTokenGen.setAccuracySeconds(3); tsTokenGen.setAccuracyMillis(1); tsTokenGen.setAccuracyMicros(2); tsTokenGen.setOrdering(true); TimeStampRequestGenerator reqGen = new TimeStampRequestGenerator(); reqGen.setCertReq(true); TimeStampRequest request = reqGen.generate(TSPAlgorithms.SHA1, new byte[20], BigInteger.valueOf(100)); assertTrue(request.getCertReq()); TimeStampResponseGenerator tsRespGen = new TimeStampResponseGenerator(tsTokenGen, TSPAlgorithms.ALLOWED); TimeStampResponse tsResp = tsRespGen.generate(request, new BigInteger("23"), new Date(), "BC"); tsResp = new TimeStampResponse(tsResp.getEncoded()); TimeStampToken tsToken = tsResp.getTimeStampToken(); tsToken.validate(cert, "BC"); // // check validation // tsResp.validate(request); // // check tstInfo // TimeStampTokenInfo tstInfo = tsToken.getTimeStampInfo(); // // check accuracy // GenTimeAccuracy accuracy = tstInfo.getGenTimeAccuracy(); assertEquals(3, accuracy.getSeconds()); assertEquals(1, accuracy.getMillis()); assertEquals(2, accuracy.getMicros()); assertEquals(new BigInteger("23"), tstInfo.getSerialNumber()); assertEquals("1.2.3", tstInfo.getPolicy()); assertEquals(true, tstInfo.isOrdered()); assertEquals(tstInfo.getNonce(), BigInteger.valueOf(100)); // // test certReq // CertStore store = tsToken.getCertificatesAndCRLs("Collection", "BC"); Collection certificates = store.getCertificates(null); assertEquals(2, certificates.size()); } private void testNoNonse( PrivateKey privateKey, X509Certificate cert, CertStore certs) throws Exception { TimeStampTokenGenerator tsTokenGen = new TimeStampTokenGenerator( privateKey, cert, TSPAlgorithms.MD5, "1.2.3"); tsTokenGen.setCertificatesAndCRLs(certs); TimeStampRequestGenerator reqGen = new TimeStampRequestGenerator(); TimeStampRequest request = reqGen.generate(TSPAlgorithms.SHA1, new byte[20]); assertFalse(request.getCertReq()); TimeStampResponseGenerator tsRespGen = new TimeStampResponseGenerator(tsTokenGen, TSPAlgorithms.ALLOWED); TimeStampResponse tsResp = tsRespGen.generate(request, new BigInteger("24"), new Date(), "BC"); tsResp = new TimeStampResponse(tsResp.getEncoded()); TimeStampToken tsToken = tsResp.getTimeStampToken(); tsToken.validate(cert, "BC"); // // check validation // tsResp.validate(request); // // check tstInfo // TimeStampTokenInfo tstInfo = tsToken.getTimeStampInfo(); // // check accuracy // GenTimeAccuracy accuracy = tstInfo.getGenTimeAccuracy(); assertNull(accuracy); assertEquals(new BigInteger("24"), tstInfo.getSerialNumber()); assertEquals("1.2.3", tstInfo.getPolicy()); assertEquals(false, tstInfo.isOrdered()); assertNull(tstInfo.getNonce()); // // test certReq // CertStore store = tsToken.getCertificatesAndCRLs("Collection", "BC"); Collection certificates = store.getCertificates(null); assertEquals(0, certificates.size()); } }