EldoS | Feel safer!

Software components for data protection, secure storage and transfer

getting the certificate of a signature on TElSignedCMSMessage

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.
#12204
Posted: 01/27/2010 04:51:36
by Christoph Moar (Standard support level)
Joined: 08/28/2009
Posts: 46

Hi,

I am trying to read all the signatures of a signed message in order to display some information to the user. The information comes from the certificate of the signer (distinguished name etc), as well as the timestamp of the signature itself.

That's what I tried, but it doesn't work since aSignature->CertificateRefs->CertIDCount is null.

If I loop directly over the Certificates (instead of the Signatures) of the TELSignedCMSMessage, I can get the certificates i think, but then I will be missing the signature timestamp, right?

Have a look at this code, can you give me a hint what the right proceeding would be?



// setup an empty signed message
std::auto_ptr<TElSignedCMSMessage> aMessage(new TElSignedCMSMessage(0));
std::auto_ptr<TFileStream> aInSignatureStream(new TFileStream(aSignatureFileName, fmOpenRead | fmShareDenyWrite));
aMessage->Open(aInSignatureStream.get(), 0);

// get all signatures
int aSignatureCount = aMessage->SignatureCount;
for(int i=0; i<aSignatureCount; i++)
{
____TElCMSSignature* aSignature = aMessage->Signatures[i];
____if(aSignature)
____{
________int aPublicKeyCertificateCount = aSignature->CertificateRefs->CertIDCount;
________for(int j=0; j<aPublicKeyCertificateCount; j++)
________{
____________// now get the certificate for this signature
____________TElCMSSignerIdentifier* aRef = aSignature->CertificateRefs->CertIDs[j];
____________if(aRef)
____________{
________________TElCMSHash* aHash = aRef->Hash;
________________if(aHash)
________________{
____________________TElX509Certificate* aCertificate;
____________________std::auto_ptr<TElCertificateLookup> aLookup(new TElCertificateLookup(0));
____________________aLookup->CertificateHashAlgorithm = aHash->HashAlgorithm;
____________________aLookup->CertificateHash = aHash->HashValue;
____________________int i = aMessage->Certificates->FindFirst(aLookup.get());
____________________if(i >= 0)
____________________{
________________________aCertificate = aMessage->Certificates->Certificates[i];

________________________// read the certificate information and add the signature timestamp
________________________// readCertificateInformation(aCertificate, aSignatureInformation);
________________________// aSignatureInformation.aSignatureTimestamp = aSignature->SigningTime.DateTimeString();
________________________// pushback this information
________________________// aSignatures.push_back(aSignatureInformation);
____________________}
____________}
________}
____}
}
#12205
Posted: 01/27/2010 05:03:33
by Christoph Moar (Standard support level)
Joined: 08/28/2009
Posts: 46

That's a workaround I tried, but I do not really trust the fact the certificates and signatures come in the same order, what do you think?

// setup an empty signed message
std::auto_ptr<TElSignedCMSMessage> aMessage(new TElSignedCMSMessage(0));
std::auto_ptr<TFileStream> aInSignatureStream(new TFileStream(aSignatureFileName, fmOpenRead | fmShareDenyWrite));
aMessage->Open(aInSignatureStream.get(), 0);

// get all signatures
int aCertificateCount = aMessage->Certificates->Count;
int aSignatureCount = aMessage->SignatureCount;
for(int i=0; i<aCertificateCount; i++)
{
____// read the certificate information and add the signature timestamp
____TElX509Certificate* aCertificate = aMessage->Certificates->Certificates[i];
____SignatureInformation aSignatureInformation;
____readCertificateInformation(aCertificate, aSignatureInformation);

____// try to add the signature information
____if(aCertificateCount == aSignatureCount)
____{
________TElCMSSignature* aSignature = aMessage->Signatures[i];
________aSignatureInformation.aSignatureTimestamp = aSignature->SigningTime.DateTimeString();
____}

____// pushback this information
____aSignatures.push_back(aSignatureInformation);
}
#12206
Posted: 01/27/2010 05:14:51
by Ken Ivanov (EldoS Corp.)

CertificateRefs is not the property you need here. This property represents the corresponding attribute of the CMS message and is usually used in long-term signatures.

The Signer property of the TElCMSSignature object identifies the certificate that was used to create the signature (via the <issuer, serial number> pair, usually referred to as "certificate identifier"). Having such an identifier, you can look for the actual certificates in the TElSignedCMSMessage.Certificates list. Please note, that (a) the signer may omit putting the signing certificate to the signature -- you will have to find one locally in this case using the provided certificate identifier, and (b) there can be a number of certificates in TElSignedCMSMessage.Certificates list (e.g., forming the chain from the signing certificate up to the root one).
#12207
Posted: 01/27/2010 05:22:53
by Christoph Moar (Standard support level)
Joined: 08/28/2009
Posts: 46

Great, thanks.
I was trying to do that. So now I take issuerrdn and serialnumber from the signature and do a lookup in the certificates to find the certificate.

There seems to be a problem in SBCustomCertStorage.hpp.
The properties IssuerRDN and SubjectRDN are not accessible (private), and the __property only has a {read=FIssuerRDN} statement.
I tried to patch the hpp File, adding the {write=FIssuerRDN} statement, and doing a lookup.

Patched Code (added write= statement)
__property Sbrdn::TElRelativeDistinguishedName* IssuerRDN = {read=FIssuerRDN, write=FIssuerRDN};
__property Sbrdn::TElRelativeDistinguishedName* SubjectRDN = {read=FSubjectRDN, write=FSubjectRDN};


But i do not get the results yet.
Do I have to set something special before I do certificates->FindFirst?

That's what I tried:
std::auto_ptr<TElCertificateLookup> aLookup(new TElCertificateLookup(0));
aLookup->IssuerRDN = aIssuer;
aLookup->SerialNumber = aSerialNumber;
int i = aMessage->Certificates->FindFirst(aLookup.get());

i returns -1, even though the certificate exists.
Do I need some further options, or is my patch not working?
#12208
Posted: 01/27/2010 05:25:43
by Christoph Moar (Standard support level)
Joined: 08/28/2009
Posts: 46

Ooops. I missed to add

aLookup->Criteria << lcIssuer << lcSerialNumber;

the "bug" in SBCustomCertStorage.hpp remains though.
Can you fix it in the next release?

Thanks
#12209
Posted: 01/27/2010 05:32:17
by Ken Ivanov (EldoS Corp.)

Quote
The properties IssuerRDN and SubjectRDN are not accessible (private), and the __property only has a {read=FIssuerRDN} statement.

That is how it was designed. Please use TElRelativeDistinguishedName.Assign() method to copy the contents of one RDN to another.
#12210
Posted: 01/27/2010 05:37:31
by Christoph Moar (Standard support level)
Joined: 08/28/2009
Posts: 46

Oh, i see. Thanks.
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.

Reply

Statistics

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