EldoS | Feel safer!

Software components for data protection, secure storage and transfer

[Java] PKCS7/CADES countersignatures

Also by EldoS: Solid File System
A virtual file system that offers a feature-rich storage for application documents and data with built-in compression and encryption.
#26853
Posted: 10/16/2013 09:10:28
by Mickaël Bénès (Standard support level)
Joined: 02/26/2013
Posts: 74

Hey,

Thanks for the clear answer, I understand better now.

So, how can I do to get the signer certificate of a signature/countersignature if the TElCMSSignature.GetCertificateValues() is empty ?

I tried something like that but in some cases it doesn't work.
Code
private TElX509Certificate _getSigningX509Cert(TElCMSSigningCertificate CMSsignerCert, TElCustomCertStorage signerCertStorage) throws Exception {
      TElX509Certificate signerCert = null;
      
      for (int i = 0; i < signerCertStorage.GetCount(); i++) {
         if (CMSsignerCert.Corresponds(signerCertStorage.GetCertificate(i))) {
            signerCert = signerCertStorage.GetCertificate(i);
            break;
         }
      }
      
      return signerCert;
   }


I'd like to add something. For the needs of our application, I have to be able to verify our old PKCS7 signatures, made with Bouncycastle. It seemed to work with TElMessageVerifier but not with TElSignedCMSMessage. Well in fact it works, it's just that I can't verify the certificate so maybe there is something missing in the signature that TElSignedCMSMessage needs.

Sorry if it's not very clear. ^^
#26860
Posted: 10/17/2013 03:40:59
by Ken Ivanov (EldoS Corp.)

Hello Bénès,

Quote
So, how can I do to get the signer certificate of a signature/countersignature if the TElCMSSignature.GetCertificateValues() is empty?

First, you should not take as a fact that the signing certificate will at all be included in the signature. Sometimes signers do not put their certificates to the signatures, so the verifier needs to look them up in their local environment (e.g. system-wide certificate stores).

Even when including the certificates, the signer can put them in two different locations: (1) a blob-wide certificates store, and a (2) a signature-wide certificate-values store. You should browse both stores when looking for the signer's certificate and its chain.

To identify the signing certificate in the list, please use the TElCertificateLookup class together with the certificate identifier returned by the TElCMSSignature.Signer property. In Object Pascal, the corresponding code has the following look:
Code
function FindCertInStorage(Signer : TElPKCS7Signer; St : TElCustomCertStorage) : TElX509Certificate;
var
  Lookup : TElCertificateLookup;
  Index : integer;
begin
  Result := nil;
  if St = nil then
    Exit;
  Lookup := TElCertificateLookup.Create(nil);
  try
    Lookup.Options := [loMatchAll];
    if Signer.Issuer.IssuerType = itIssuerAndSerialNumber then
    begin
      Lookup.IssuerRDN.Assign(Signer.Issuer.Issuer);
      Lookup.SerialNumber := Signer.Issuer.SerialNumber;
      Lookup.Criteria := [lcIssuer, lcSerialNumber];
    end
    else
    begin
      Lookup.Criteria := [lcSubjectKeyIdentifier];
      Lookup.SubjectKeyIdentifier := Signer.Issuer.SubjectKeyIdentifier;
    end;
    Index := St.FindFirst(Lookup);
    if Index >= 0 then
      Result := St.Certificates[Index];
  finally
    FreeAndNil(Lookup);
  end;
end;
#26863
Posted: 10/17/2013 04:48:54
by Mickaël Bénès (Standard support level)
Joined: 02/26/2013
Posts: 74

Nice, it works perfectly ! Thank you.

Have another problem though (yeah, I'm annoying :P). About the old signature system we (the company I work for) have (made with Bouncycastle). The TElCMSSignature.Validate() says that the signature is invalid (csvInvalid). So I tried to use TElMessageVerifier instead and I had two cases :

1. If I use the same TElFileStream that the one I use to open my TElSignedCMSMessage, then TElMessageVerifier.Verify() returns the error code 8198 (I checked in the doc', it means that the message passed to Decrypt/Verify routine is not valid PKCS7 message).

2. If I create another TElFileStream (with the same signature file), then my signature is correctly validated.

I don't know if you'll be able to give me an answer since you have nothing to do with Bouncycastle, but I can give you the p7s file that I'm talking about if you need it to check something.
#26864
Posted: 10/17/2013 04:53:29
by Vsevolod Ievgiienko (EldoS Corp.)

Most likelly you don't reset TElFileStream position using its SetPosition method. Just call SetPosition(0) before passing the stream to TElMessageVerifier.Verify.
#26865
Posted: 10/17/2013 06:15:24
by Mickaël Bénès (Standard support level)
Joined: 02/26/2013
Posts: 74

Yep you are right, thanks !

Do you have any idea why TElCMSSignature.Validate() doesn't validate the signature and TElMessageVerifier.Verify() does ?
#26881
Posted: 10/18/2013 01:49:41
by Vsevolod Ievgiienko (EldoS Corp.)

Quote
Do you have any idea why TElCMSSignature.Validate() doesn't validate the signature and TElMessageVerifier.Verify() does ?

Its hard to say why this happens without seeing the signed message. It would be great if your will write a small sample that reproduces this problem and send it via Helpdesk, so we could run it locally and see what exactly happens.

As CMS is not the same standard as PKCS#7 (TElMessageVerifier deals with PKCS#7) but is build based on it the problem may be in some standard differences.
#26907
Posted: 10/21/2013 04:28:20
by Mickaël Bénès (Standard support level)
Joined: 02/26/2013
Posts: 74

Hello !

As seen in the help desk, now I can correctly verify all my signatures. I just have an issue with getting the signature certificates.
I use the method that Ken Ivanov gave me, but when the file is countersigned, the method always returns the first certificate in the storage, wether it's the same certificate issuer or not.

Here is the method (that I translated in Java from Pascal) :
Code
private TElX509Certificate _findCertInStorage(TElPKCS7Issuer issuer, TElCustomCertStorage certStorage) throws Exception {
      TElX509Certificate cert      = null; // Représentera le certificat de signature.
      TElCertificateLookup lookup   = null; // Va permettre de retrouver le certificat de signature.
      int index               = 0; // L'index du certificat de signature dans le TElCustomCertStorage.
      
      try {
         /*
          * Définition des options du TElCertificateLookup.
          */
         lookup = new TElCertificateLookup();
         lookup.SetOptions(SBCustomCertStorage.loMatchAll);
         
         if (issuer.GetIssuerType() == TSBPKCS7IssuerType.itIssuerAndSerialNumber) {
            lookup.GetIssuerRDN().Assign(issuer.GetIssuer());
            lookup.SetSerialNumber(issuer.GetSerialNumber());
            lookup.SetCriteria(SBCustomCertStorage.lcIssuer);
            lookup.SetCriteria(SBCustomCertStorage.lcSerialNumber);
         }
         else {
            lookup.SetCriteria(SBCustomCertStorage.lcSubjectKeyIdentifier);
            lookup.SetSubjectKeyIdentifier(issuer.GetSubjectKeyIdentifier());
         }
         
         index = certStorage.FindFirst(lookup);
         if (index >= 0) { // Certificat trouvé.
            cert = certStorage.GetCertificate(index);
         }
      }
      catch (Exception e) {
         throw e;
      }
      finally {
         if (lookup != null) {
            lookup.Free();
            lookup.Destroy();
         }
      }
      
      return cert;
   }


And I call it like this :
Code
TElX509Certificate signerCert = this._findCertInStorage(TElCMSSignature.GetSigner(), TElSignedCMSMessage.GetCertificates());


Maybe I did something wrong ?
#26908
Posted: 10/21/2013 04:34:55
by Vsevolod Ievgiienko (EldoS Corp.)

The next line

Quote
Lookup.Criteria := [lcIssuer, lcSerialNumber];


is translated to Java incorrectly. Should be:

Quote
lookup.SetCriteria(SBCustomCertStorage.lcIssuer | SBCustomCertStorage.lcSerialNumber);
#27025
Posted: 10/29/2013 05:21:49
by Mickaël Bénès (Standard support level)
Joined: 02/26/2013
Posts: 74

Hey ! Forgot to tell you that it perfectly works. Thank you !
Also by EldoS: CallbackProcess
A component to control process creation and termination in Windows and .NET applications.

Reply

Statistics

Topic viewed 5258 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!