EldoS | Feel safer!

Software components for data protection, secure storage and transfer

Signing binary files using TElMessageSigner

Also by EldoS: Callback File System
Create virtual file systems and disks, expose and manage remote data as if they were files on the local disk.
#18069
Posted: 11/03/2011 09:20:25
by ingbabic  (Standard support level)
Joined: 09/27/2011
Posts: 114

I have done something like this and it works, but I am not aware of eventual problems:
Code
public string Signer
{
  get
  {
    string signer = null;
    byte[] serialNumber = m_cmsMessage.get_Signatures(m_signatureIndex).SigningCertificate.get_CertIDs(0).SerialNumber;
    for (int i = 0; i < m_cmsMessage.Certificates.Count;i++ )
    {
      TElX509Certificate certificate = m_cmsMessage.Certificates.get_Certificates(i);
      if (SBUtils.Unit.CompareArr(serialNumber, certificate.SerialNumber) == 0)
      {
          signer = certificate.SubjectName.CommonName;
          break;
      }
    }
      return signer;
  }
}
#18070
Posted: 11/03/2011 09:50:39
by Ken Ivanov (EldoS Corp.)

Your code is not correct enough:

First, there is no guarantee that the SigningCertificate attribute will have been included to the signature by the author.

Second, serial number is not globally unique, therefore there might be collisions between several different certificates sharing the same serial number.

The correct method of looking up the signing certificate would be to search for the certificate with a particular <issuer, serial number> pair OR a subject key identifier, depending on the exact format of TElCMSSignature.Signer reference. You will find the relevant code snippet below. Although it gets use of Delphi notation, the code will be mostly the same for any CLR language.

Code
  
  function FindCertInStorage(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 Sig.Signer.Issuer.IssuerType = itIssuerAndSerialNumber then
      begin
        Lookup.IssuerRDN.Assign(Sig.Signer.Issuer.Issuer);
        Lookup.SerialNumber := Sig.Signer.Issuer.SerialNumber;
        Lookup.Criteria := lcIssuer or lcSerialNumber;
      end
      else
      begin
        Lookup.Criteria := lcSubjectKeyIdentifier;
        Lookup.SubjectKeyIdentifier := Sig.Signer.Issuer.SubjectKeyIdentifier;
      end;
      Index := St.FindFirst(Lookup);
      if Index >= 0 then
        Result := St.Certificates[Index];
    finally
      FreeAndNil(Lookup);
    end;
  end;
#18071
Posted: 11/03/2011 12:10:17
by ingbabic  (Standard support level)
Joined: 09/27/2011
Posts: 114

Unfortunatelly, some of this what you showed in code doesn't exist in .NET. Here are the problems:
TSBLookupOption (where loMatchAll exists) enum doesn't exist in SBCustomCertStorage namespace
TSBLookupCriterion enum (where lcIssuer or lcSerialNumber exists) doesn't exist in SBCustomCertStorage namespace

therefore I had to use hardcoded values in code.

and major problem
Lookup.IssuerRDN is readonly property in .NET (can't assign to it)

The best I could do is this:
Code
private TElX509Certificate FindCertificate(TElCustomCertStorage storage)
{
  TElCertificateLookup lookup = null;
  int index = -1;
  TElX509Certificate result = null;

  if (storage != null)
  {
    try
    {
      lookup = new TElCertificateLookup();
      TElCMSSignature signature = m_cmsMessage.get_Signatures(m_signatureIndex);
      lookup.Options = 2;
      if (signature.Signer.IssuerType == SBPKCS7.TSBPKCS7IssuerType.itIssuerAndSerialNumber)
      {
        lookup.Criteria = 1025;
        //lookup.IssuerRDN = signature.Signer.Issuer; <-- IssuerRDN is readonly!!
        lookup.SerialNumber = signature.Signer.SerialNumber;
      }
      else
      {
        lookup.Criteria = 128;
        lookup.SubjectKeyIdentifier = signature.Signer.SubjectKeyIdentifier;
      }
      index = storage.FindFirst(lookup);
      if (index >= 0)
        result = storage.get_Certificates(index);
    }
    finally
    {
      lookup.Dispose();
      lookup = null;
    }
  }
  return result;
}


Am i missing something?
#18072
Posted: 11/03/2011 12:18:21
by Vsevolod Ievgiienko (EldoS Corp.)

Quote
therefore I had to use hardcoded values in code.

In .NET these constants are integers not enums. You can use pre-defined constants: SBCustomCertStorage.Unit.loMatchAll and (SBCustomCertStorage.Unit.lcIssuer | SBCustomCertStorage.Unit.lcSerialNumber).

Quote
//lookup.IssuerRDN = signature.Signer.Issuer; <-- IssuerRDN is readonly!!

Use lookup.IssuerRDN.Assign(signature.Signer.Issuer) as in Delphi code instead.
#18073
Posted: 11/03/2011 13:08:56
by ingbabic  (Standard support level)
Joined: 09/27/2011
Posts: 114

Thanks, that's worked!
Also by EldoS: BizCrypto
Components for BizTalk® and SQL Server® Integration Services that let you securely store and transfer information in your business automation solutions.

Reply

Statistics

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