Wrox Programmer Forums

Need to download code?

View our list of code downloads.

Go Back   Wrox Programmer Forums > Java > Other Java > BOOK: Beginning Cryptography with Java
Password Reminder
Register
| FAQ | Members List | Calendar | Search | Today's Posts | Mark Forums Read
BOOK: Beginning Cryptography with Java
This is the forum to discuss the Wrox book Beginning Cryptography with Java by David Hook; ISBN: 9780764596339
Welcome to the p2p.wrox.com Forums.

You are currently viewing the BOOK: Beginning Cryptography with Java section of the Wrox Programmer to Programmer discussions. This is a community of tens of thousands of software programmers and website developers including Wrox book authors and readers. As a guest, you can read any forum posting. By joining today you can post your own programming questions, respond to other developers’ questions, and eliminate the ads that are displayed to guests. Registration is fast, simple and absolutely free .
DRM-free e-books 300x50
Reply
 
Thread Tools Search this Thread Display Modes
  #1 (permalink)  
Old September 15th, 2009, 09:51 AM
Registered User
 
Join Date: Aug 2007
Location: , , .
Posts: 6
Thanks: 0
Thanked 0 Times in 0 Posts
Default problems while verifying embedded timestamp in signature

Hello!

I have a p7m file generated using the BC provider. The certificate used for signing is a self signed certificate.

My signed file is generated using the following code
Code:
        List<X509Certificate> certList = new ArrayList<X509Certificate>();
        certList.add(getCertificate(alias));
        CertStore certstore = CertStore.getInstance("Collection", new CollectionCertStoreParameters(certList), "BC");
        CMSSignedDataGenerator signer = new CMSSignedDataGenerator();
        signer.addSigner(getPK(alias), getCertificate(alias), CMSSignedDataGenerator.DIGEST_SHA1);
        signer.addCertificatesAndCRLs(certstore);
        
        CMSProcessable cmsUnsigned = new CMSProcessableByteArray(unsignedBytes);
        CMSSignedData signedData = signer.generate(cmsUnsigned, true, "BC");
        
        MessageDigest messageDigest = MessageDigest.getInstance("SHA1");
        messageDigest.update(unsignedBytes);
        byte hash[] = messageDigest.digest();
        
        signedData = addTimestamp(signedData, getTimeStampToken(1, hash));
After generating the signed file, I'm adding the timestamp from a TSA, using the addTimestamp method; the timestamp token is read using the getTimeStampToken method. Here is the listing of the 2 methods

Code:
    private static TimeStampToken getTimeStampToken(int TSA, byte[] digest) throws Exception {
        Security.addProvider (new org.bouncycastle.jce.provider.BouncyCastleProvider());

        PostMethod post = null;
        switch (TSA) {
        case 1:
            post = new PostMethod("http://www.edelweb.fr/cgi-bin/service-tsp");
            break;

        case 2:
            post = new PostMethod("http://tsp.iaik.at/tsp/TspRequest");
            break;


        case 3:
            post = new PostMethod("http://ns.szikszi.hu:8080/tsa");
            break;
        case 4:
            post = new PostMethod("http://time.certum.pl/");
            break;
        }

        TimeStampRequestGenerator reqGen = new TimeStampRequestGenerator();
        //request TSA to return certificate
        reqGen.setCertReq (true);
        //make a TSP request this is a dummy sha1 hash (20 zero bytes) and nonce=100
        TimeStampRequest request =
            reqGen.generate(TSPAlgorithms.SHA1,
//                    new byte[20], BigInteger.valueOf(100));
                    digest, BigInteger.valueOf(100));

        byte[] enc_req = request.getEncoded();
        ByteArrayInputStream bais = new ByteArrayInputStream(enc_req);
        post.setRequestBody(bais);
        post.setRequestContentLength (enc_req.length);
        post.setRequestHeader("Content-type","application/timestamp-query");

        HostConfiguration hc = new HostConfiguration();
        hc.setProxy("proxy.stfd.ro", 3128);

        HttpClient http_client = new HttpClient();
        http_client.executeMethod(hc, post);
        InputStream in = post.getResponseBodyAsStream();


        //read TSP response
        TimeStampResponse resp = new TimeStampResponse (in);
        resp.validate (request);
        System.out.println ("Timestamp validated");

        TimeStampToken  tsToken = resp.getTimeStampToken();
        SignerId signer_id = tsToken.getSID();


        BigInteger cert_serial_number = signer_id.getSerialNumber();

        System.out.println ("Signer ID serial "+signer_id.getSerialNumber());
        System.out.println ("Signer ID issuer "+signer_id.getIssuerAsString());


        CertStore cs = tsToken.getCertificatesAndCRLs ("Collection", "BC");


        Collection certs = cs.getCertificates (null);


        Iterator iter = certs.iterator();
        X509Certificate certificate = null;
        while (iter.hasNext()) {
            X509Certificate cert = (X509Certificate)iter.next();
            
            if (cert_serial_number != null) {
                if (cert.getSerialNumber().equals (cert_serial_number)) {
                    System.out.println ("using certificate with serial: "+cert.getSerialNumber());
                    certificate = cert;
                }
            } else {
                if (certificate == null) {
                    certificate = cert;
                }
            }
            System.out.println ("Certificate subject dn "+cert.getSubjectDN());
            System.out.println ("Certificate serial "+cert.getSerialNumber());
        }
        
        tsToken.validate(certificate, "BC");
        
        System.out.println ("TS info "+tsToken.getTimeStampInfo().getGenTime());
        System.out.println ("TS info "+tsToken.getTimeStampInfo().getAccuracy());
        System.out.println ("TS info "+tsToken.getTimeStampInfo().getNonce());
        return tsToken;
    }
Code:
    private static CMSSignedData addTimestamp(CMSSignedData signedData, TimeStampToken tok) throws Exception {
        Collection ss = signedData.getSignerInfos().getSigners();
        SignerInformation si = (SignerInformation) ss.iterator().next();
        
        ASN1InputStream asn1InputStream = new ASN1InputStream (tok.getEncoded());
        DERObject tstDER = asn1InputStream.readObject();
        DERSet ds = new DERSet(tstDER);
        Attribute a = new Attribute(new DERObjectIdentifier("1.2.840.113549.1.9.16.2.14"), ds);
        ASN1EncodableVector dv = new ASN1EncodableVector();
        dv.add(a);
        AttributeTable at = new AttributeTable(dv);
        si = SignerInformation.replaceUnsignedAttributes(si, at);
        ss.clear();
        ss.add(si);
        SignerInformationStore sis = new SignerInformationStore(ss);
        signedData = CMSSignedData.replaceSigners(signedData, sis);
        return signedData;
    }
The timestamp is set as an unsigned attribute, as stated in RFC3161, appendix A.

My problem is that when I try to verify as stated in the same RFC,
Quote:
The value of messageImprint field within TimeStampToken shall be a
hash of the value of signature field within SignerInfo for the signedData being time-stamped.
the following code returns false
Code:
    private boolean verifyTimestamp(CMSSignedData signature, TimeStampToken tto) throws Exception{
        System.out.println("******************************** start verify timestamp");
        
        readTimestampToken(signature);
        
        byte[] hashB = null;
        byte[] hashC = null;
        
        hashC = getHash(this.signedHash);
        
        hashB = tto.getTimeStampInfo().getMessageImprintDigest();
        
        System.out.println("******************************** end verify timestamp");
        
        return Arrays.equals(hashB, hashC);
    }
The timestamp token is being read from the signed file
Code:
    private TimeStampToken readTimestampToken(CMSSignedData signature) throws Exception{
        TimeStampToken tto = null;
        SignerInformationStore signers = signature.getSignerInfos();
        Collection c = signers.getSigners();
        Iterator it = c.iterator();
        SignerInformation signer = (SignerInformation)it.next();
        AttributeTable attrs = signer.getUnsignedAttributes();
        this.signedHash = signer.getSignature();
        Attribute att = attrs.get(PKCSObjectIdentifiers.id_aa_signatureTimeStampToken);
        
        DEREncodable dob = att.getAttrValues().getObjectAt(0);
        CMSSignedData signedData = new CMSSignedData(dob.getDERObject().getEncoded());
        tto = new TimeStampToken(signedData);
        
        return tto;
        
    }
Any idea what the problem might be?
I believe that I'm doing something wrong is when generating the signature with the timestamp but I cannot find it...

Any help would be appreciated!

Thank you,
Alexandru
Reply With Quote
  #2 (permalink)  
Old September 21st, 2009, 08:26 AM
Registered User
 
Join Date: Aug 2007
Location: , , .
Posts: 6
Thanks: 0
Thanked 0 Times in 0 Posts
Default

problem solved

I had interpreting in the wrong way the RFC3161 that states that if adding the timestamp to a signature in a pkcs7 file the hash that needs to be sent to the TSA must be the hash of the signature field in the SignerInfo of the data.
Which is correct if I stay a little bit to think because the timestamp is for the signature, not for the unsigned data.

So, when creating the request for the TSA, the hash has to be the the hash for the signature.
Reply With Quote
  #3 (permalink)  
Old September 1st, 2015, 10:03 PM
Registered User
Points: 3, Level: 1
Points: 3, Level: 1 Points: 3, Level: 1 Points: 3, Level: 1
Activity: 0%
Activity: 0% Activity: 0% Activity: 0%
 
Join Date: Sep 2015
Posts: 1
Thanks: 0
Thanked 0 Times in 0 Posts
Default Help support

Quote:
Originally Posted by fulgerica View Post
problem solved

I had interpreting in the wrong way the RFC3161 that states that if adding the timestamp to a signature in a pkcs7 file the hash that needs to be sent to the TSA must be the hash of the signature field in the SignerInfo of the data.
Which is correct if I stay a little bit to think because the timestamp is for the signature, not for the unsigned data.

So, when creating the request for the TSA, the hash has to be the the hash for the signature.
You can post full code give me , thank you very much
Reply With Quote
Reply


Thread Tools Search this Thread
Search this Thread:

Advanced Search
Display Modes

Posting Rules
You may not post new threads
You may not post replies
You may not post attachments
You may not edit your posts

BB code is On
Smilies are On
[IMG] code is Off
HTML code is Off
Trackbacks are Off
Pingbacks are On
Refbacks are Off


Similar Threads
Thread Thread Starter Forum Replies Last Post
Problems transforming embedded html tags Brad Harrington XSLT 1 February 10th, 2009 04:53 PM
Verifying Username/Password...Please wait. cancer10 Classic ASP Databases 0 March 8th, 2007 01:19 AM
Verifying Zip Code Range stevenyoo321 Access VBA 1 February 5th, 2007 08:40 AM
Verifying uploaded File Size in Client-side Ushhh ASP.NET 1.0 and 1.1 Professional 5 August 30th, 2006 07:13 AM
Verifying Table Existence kpp01 Access 3 January 5th, 2005 07:23 AM



All times are GMT -4. The time now is 05:41 AM.


Powered by vBulletin®
Copyright ©2000 - 2019, Jelsoft Enterprises Ltd.
© 2013 John Wiley & Sons, Inc.