[prev in list] [next in list] [prev in thread] [next in thread] 

List:       bouncycastle-crypto-dev
Subject:    Re: [dev-crypto] Problem with TimeStampToken verification
From:       Hubert Kario <hka () qbs ! com ! pl>
Date:       2012-12-12 16:31:51
Message-ID: 2594615.KU2GV8mBUf () k85hala03
[Download RAW message or body]


On Tuesday 11 of December 2012 17:35:07 Hubert Kario wrote:
> In short, when I
> 
> * set "now" to be 20 hours ago
> * create certificates (CA + TSA) that were valid at this past "now" time
> * but are not valid any more
> * and use code below
> 
> I get an Exception with "verifier not valid at signingTime" message and
> attached stack trace.
> 
> Upon closer inspection, it looks like the SignerInformation.getSigningTime()
> in SingerInformation.java:609 returns real "now" time, not the signingTime
> from token. Few lines below, the TSA certificate is required to be valid at
> that time so something doesn't look right.
> 
> When I run tsToken.getTimeStampInfo().getGenTime(); before verification, it
> returns valid time...

The problem is caused by the fact that BC adds *two* time stamps to the token,
the first one inside the RFC 3161 token and the second one in CMS signature
(the signed attributes of CMS signature) that signs the token itself.

The attribute signingTime is added by getAttributes() method in
DefaultSignedAttributeTableGenerator.java:104 by
createStandardAttributeTable().

We can override it by providing AttributeTable with signingTime to
DefaultSignedAttributeTableGenerator() constructor but it's hardly intuitive...

In the end, to get SignerInforGenerator, one needs to construct it manually:

        JcaSignerInfoGeneratorBuilder sigBuilder =
				new JcaSignerInfoGeneratorBuilder(
						new JcaDigestCalculatorProviderBuilder().setProvider("BC").build());

        Hashtable<ASN1ObjectIdentifier, Attribute> signedAttr =
                new Hashtable<ASN1ObjectIdentifier, Attribute>();
        Attribute attr = new Attribute(CMSAttributes.signingTime,
                new DERSet(new Time(now)));
        signedAttr.put(attr.getAttrType(), attr);
        AttributeTable signedAttributeTable = new AttributeTable(signedAttr);

        sigBuilder.setSignedAttributeGenerator(new \
DefaultSignedAttributeTableGenerator(signedAttributeTable));

        SignerInfoGenerator signerInfoGen = sigBuilder.build(
                new JcaContentSignerBuilder("SHA1withRSA").setProvider("BC")
                        .build(tsaCert.getPrivateKey()), tsaCert
                        .getCertificate());

instead of automatically:

        SignerInfoGenerator signerInfoGen = new JcaSimpleSignerInfoGeneratorBuilder()
            .build("SHA1withRSA", tsaCert.getPrivateKey(), tsaCert.getCertificate());

While my use case is a bit unorthodox, it's not hard to imagine a dedicated
machine working as a TSA that uses external time source (atomic clock, GPS)
that is only available to Java and not used to set system time. Time Stamps
created on such system will fail such strict verification as BC is performing.

It's an open question whatever the CMS signature should contain the same time
as the timestamp inside *or* CMS signature verificator should ignore
signingTime in CMS when validating RFC 3161 timestamp. IMHO the first fix is
necessary, the second mearly optional.

Either way, I'm a bit short on time, so I won't be proposing patches to fix
it, sorry.

Regards,
-- 
Hubert Kario
QBS - Quality Business Software
02-656 Warszawa, ul. Ksawerów 30/85
tel. +48 (22) 646-61-51, 646-74-24
www.qbs.com.pl


["smime.p7s" (application/pkcs7-signature)]

[prev in list] [next in list] [prev in thread] [next in thread] 

Configure | About | News | Add a list | Sponsored by KoreLogic