EldoS | Feel safer!

Software components for data protection, secure storage and transfer

[Java] CAdES signature date issue

Also by EldoS: CallbackFilter
A component to monitor and control disk activity, track file and directory operations (create, read, write, rename etc.), alter file data, encrypt files, create virtual files.
#29980
Posted: 07/03/2014 03:04:15
by Vsevolod Ievgiienko (EldoS Corp.)

TElCMSSignature.SetSigningDate should be set in UTC format. Please try to set it next way and check if this helps:

Code
sig.SetSigningDate( SBUtils.DateTimeUtcNow() );
#29981
Posted: 07/03/2014 03:21:03
by Mickaël Bénès (Standard support level)
Joined: 02/26/2013
Posts: 74

Already tried it, same problem.

As Dmytro Bogatskyy said, there was an issue with Calendar.DST_OFFSET that was fixed but not released yet. So it currently won't help me. :/
#29982
Posted: 07/03/2014 03:23:36
by Eugene Mayevski (EldoS Corp.)

For now do the simple check -- call sig.SetSigningDate(some date), then compare sig.GetSigningTime() with what you passed to SetSigningDate. Do the values match?


Sincerely yours
Eugene Mayevski
#29984
Posted: 07/03/2014 03:52:30
by Mickaël Bénès (Standard support level)
Joined: 02/26/2013
Posts: 74

OK so I did two tests :

- first with SBUtils.DateTimeUtcNow() : value matches
- then with new Date() : value doesn't match, it is the value of SBUtils.DateTimeUtcNow()

Is it because I did :
Code
sig.SetSigningOptions( sig.GetSigningOptions() | SBMessages.soInsertSigningTime );
or that has nothing to do with my problem ?
#29985
Posted: 07/03/2014 04:10:39
by Vsevolod Ievgiienko (EldoS Corp.)

Quote
- first with SBUtils.DateTimeUtcNow() : value matches

This is the only correct usage case of the property and it works as expected.

Quote
- then with new Date() : value doesn't match

They should not as its not a correct usage case.

Quote
or that has nothing to do with my problem ?

soInsertSigningTime is turned on by default, so this change is not related to the problem.
#29986
Posted: 07/03/2014 04:16:36
by Mickaël Bénès (Standard support level)
Joined: 02/26/2013
Posts: 74

Yeah this is logical, but still the UTC date is wrong. So all I can do is wait for the next build of SecureBlackbox to be released ?
#29987
Posted: 07/03/2014 04:23:40
by Eugene Mayevski (EldoS Corp.)

There's some confusion here.

1. SigningTime property value must be in UTC. It's up to you how you convert local time to UTC and back. Our function seems to fail but you can write your own easily right now.

2. When reading the value of SigningTime property you should get the same value that you have put there.


Sincerely yours
Eugene Mayevski
#29988
Posted: 07/03/2014 06:25:42
by Mickaël Bénès (Standard support level)
Joined: 02/26/2013
Posts: 74

Yep I wrote one, two or three weeks ago. It wasn't well coded but was still working.
Now, I modified it based on the code of your method :
Code
public static Date getDateTimeUTCNow() {
   Calendar cal   = GregorianCalendar.getInstance();
   Date result   = cal.getTime();
   result.setTime( result.getTime() - cal.get(Calendar.ZONE_OFFSET) - cal.get(Calendar.DST_OFFSET) );
   
   return result;
}
When I test it, it gives me the right UTC datetime. But, when I sign with it and then verify the signature, the TElCMSSignature.GetSigningTime() doens't give me the time I have set (UTC) but UTC+1.

Here is my code, maybe I did something that changes altered the signing time or the signature :
Code
// Signing...
TElFileStream fs                  = null;
         TElCAdESSignatureProcessor processor   = new TElCAdESSignatureProcessor();
         TElSignedCMSMessage cms               = new TElSignedCMSMessage();
         
         try {
            fs = new TElFileStream(this._fileToSign.getAbsolutePath(), "r", true);
            cms.CreateNew(fs, 0, fs.GetLength());
            
            int indexNewSign   = cms.AddSignature();
            TElCMSSignature sig   = cms.GetSignature(indexNewSign);
            
            Date sigDate = DateUtil.getDateTimeUTCNow();
            
            System.out.println( "\nSigning date = " + sigDate + "\n" ); // Displays Thu Jul 03 11:18:45 CEST 2014 ==> good UTC time
            
            sig.ClearTimestamps();
            sig.ClearCountersignatures();
            sig.ClearValidationTimestamps();
            sig.SetSigningOptions( sig.GetSigningOptions() | SBMessages.soInsertSigningTime );
            sig.SetSigningTime( sigDate );
            sig.GetCommitmentTypeIndication().SetIncluded(true);
            sig.GetCommitmentTypeIndication().SetProofOfOrigin(true);
            sig.GetCommitmentTypeIndication().SetProofOfCreation(true);
            sig.SetUsePSS(false);
            
            processor.SetSignature(sig);
            processor.CreateBES(this._telX509Cert);
            
            File fileSig = new File(this._fileToSign.getAbsolutePath() + ".p7s");
            CAdES.saveCMS(cms, fileSig);
            
            System.out.println("Signature done !");
         }
         catch (Exception e) {
            throw e;
         }
         finally {
            if (fs != null) {
               fs.Free();
               fs.Destroy();
            }
            
            cms.Destroy();
            processor.Destroy();
         }
Code
// Saves the CMS.
public static void saveCMS(TElSignedCMSMessage cms, File fileToSaveIn) throws Exception {
      TElFileStream fs = null;
      try {
         fs = new TElFileStream(fileToSaveIn.getAbsolutePath(), "rw", true);
         cms.Save(fs);
      }
      catch (Exception e) {
         throw new Exception("Couldn't save (counter) signature, an error occured : " + e.getMessage()) ;
      }
      finally {
         if (fs != null) {
            fs.Free();
            fs.Destroy();
         }
      }
   }
Code
// Verifying the signature...
TElFileStream fsCMS                  = null; // La filestream du fichier de signature.
         TElFileStream fsData               = null; // La file stream du fichier signé.
         TElSignedCMSMessage cms               = new TElSignedCMSMessage(); // Va contenir la (les) signature(s).
         TElCAdESSignatureProcessor processor   = new TElCAdESSignatureProcessor(); // Va permettre de vérifier les données CAdES.
         
         try {
            fsCMS                        = new TElFileStream(this._fileSignature.getAbsolutePath(), "r", true);
            fsData                        = new TElFileStream(this._fileSigned.getAbsolutePath(), "r", true);
            cms.Open(fsCMS, fsData, 0, 0);
            int nbSign                     = cms.GetSignatureCount();
            TElCustomCertStorage cmsCertStorage   = cms.GetCertificates();
            
            System.out.println("Number of certificates in the CMS : " + cmsCertStorage.GetCount());
            
            if (nbSign != 0) {
               System.out.println("\t" + nbSign + " found...");

               for (int i = 0; i < nbSign; i++) {
                  System.out.println("Vérification de la signature n°" + (i + 1) + " :\n");

                  TElCMSSignature sig               = cms.GetSignature(i);
                  int nbCounterSig               = sig.GetCountersignatureCount();
                  Date sigDate                  = DateUtil.convertDateUTCToLocaleDate( sig.GetSigningTime() );
//                  Date sigDate                  = sig.GetSigningTime();
                  TSBCMSSignatureValidity sigVal      = sig.Validate();
                  
                  System.out.println( "\nSigning date = " + sig.GetSigningTime() ); // Displays Thu Jul 03 12:18:45 CEST 2014 ==> UTC+1
                  System.out.println( "Signing date converted = " + sigDate + "\n" ); // Displays Thu Jul 03 14:18:45 CEST 2014 ==> UTC+3, which is normal since I added two hours (UTC offset of timezone Europe/Paris) to it
                  
                  if (sigVal == TSBCMSSignatureValidity.csvValid) { // Vérification des données CMS...
                     
                     processor.SetSignature( sig );
                     processor.SetIgnoreChainValidationErrors( true );
                     
                     TSBCAdESSignatureValidity cadesVal = processor.Validate();
                     if (cadesVal == TSBCAdESSignatureValidity.asvValid) { // Vérification des données CAdES...
                        // CAdES signature OK.
                     }
                     else {
                        // CAdES signature not OK...
                     }
                  }
                  else {
                     // CMS signature not OK.
                  }
            }
            else {
            }
         }
         catch (Exception e) {
            throw e;
         }
         finally {
            if (fsCMS != null) {
               fsCMS.Free();
               fsCMS.Destroy();
            }
            
            if (fsData != null) {
               fsData.Free();
               fsData.Destroy();
            }
            
            cms.Destroy();
            processor.Destroy();
         }
Code
public static Date convertDateUTCToTimeZone(Date date, TimeZone tz) {
      if (tz == null) {
         tz = TimeZone.getDefault();
      }
      
      int tzOffset   = (tz.getOffset(date.getTime()) / 1000) / 3600;
      Calendar cal   = GregorianCalendar.getInstance();
      cal.setTime(date);
      cal.add(Calendar.HOUR_OF_DAY, tzOffset);
      
      return cal.getTime();
   }

public static Date convertDateUTCToLocaleDate(Date date) {
      return convertDateUTCToTimeZone(date, "");
   }
#29990
Posted: 07/03/2014 07:32:12
by Vsevolod Ievgiienko (EldoS Corp.)

We found out the reason of the problem.

You are setting signature time here:

Code
sig.SetSigningTime( sigDate );


and then call

Code
processor.CreateBES(this._telX509Cert);


But CreateBES resets signing time value using problematic SBUtils.UTCNow() method.

What you can do before the fixed version will be released is to handle TElCAdESSignatureProcessor.OnBeforeSign event and change signing time inside the handler.
#29991
Posted: 07/03/2014 09:41:21
by Mickaël Bénès (Standard support level)
Joined: 02/26/2013
Posts: 74

Perfect now it works ! Thank you very much.

I post the code if someone needs it someday :
Code
TElCAdESSignatureProcessor.SetOnBeforeSign( new TSBCAdESBeforeSignEvent(this._onBeforeSign) );
Code
private TSBCAdESBeforeSignEvent.Callback _onBeforeSign = new TSBCAdESBeforeSignEvent.Callback() {
      
      @Override
      public void TSBCAdESBeforeSignEventCallback(TObject sender, TElCMSSignature sig, TElX509Certificate sigCert, TElCustomCertStorage sigCertStorage) {
         Date sigDate = DateUtil.getDateTimeUTCNow();
         sig.SetSigningTime( sigDate );
         
         System.out.println( sigDate );
      }
   };
Also by EldoS: CallbackProcess
A component to control process creation and termination in Windows and .NET applications.

Reply

Statistics

Topic viewed 3012 times

Number of guests: 1, registered members: 0, in total hidden: 0




|

Back to top

As of July 15, 2016 EldoS Corporation will operate as a division of /n software inc. For more information, please read the announcement.

Got it!