EldoS | Feel safer!

Software components for data protection, secure storage and transfer

Certificate Validation

Also by EldoS: CallbackRegistry
A component to monitor and control Windows registry access and create virtual registry keys.
#4245
Posted: 11/07/2007 06:09:48
by Nuno Guedes (Basic support level)
Joined: 08/13/2007
Posts: 87

Hi,

i am trying to validate the signing certificate presente in a signature.

I read the information in the support:
Quote
So the algorithm of complete validation of the certificate is

1. Call ElCustomCertStorage.Validate().
2. If Validate() method reports that the certificate is valid, use ElCustomCertStorage.GetIssuerCertificate to find issuer certificate.
3. If Issuer certificate was found, goto (1) (validate it).
4. If Issuer certificate was not found or certificate being validated is self-signed, check that the certificate is trusted (usually certificates located in CA and ROOT storages of WinCertStorage are trusted).
5. If certificate is not among trusted certificates, warn the user.
6. If certificate is not valid, warn the user.
7. Check that the certificate is not included into certificate revocation list (see below). If it is, warn the user.


For first phase:
Code
TElCustomCertStorage storage = new TElCustomCertStorage();
TElX509Certificate cert = new TElXML509Certificate();

cert = ((TElXMLKeyInfoX509Data) Verifier.Signature.KeyInfo[3]).Certificate;

storage.Add(cert,true);


i use KeyInfo[3] because its where is the X509Certificate, its only for test, i will implement a "for cycle".

After "storage.add" the storage continue empty.

What am i doing wrong?

thanks
#4248
Posted: 11/07/2007 11:27:04
by Nuno Guedes (Basic support level)
Joined: 08/13/2007
Posts: 87

humm, i supose that i can´t use it directly.
So i use a TElWinCertStorage.

Now i am testing, i signed a xml file with MY certificate "FactoryX" and include it on signature "signingCertificate" and KeyData element.

The structure of certificates is:
ROOT (ROOT) -> CAPortugal (CA) -> CACentralZone (CA) -> FactoryX (MY)

i develop this code for testing:
Code
            TElCustomCertStorage certStorage = new TElCustomCertStorage();
            TElX509Certificate cert = new TElX509Certificate();
            TElXMLKeyInfo info = Verifier.Signature.KeyInfo;
            TElWinCertStorage win = new TElWinCertStorage();
            
            int state = -1;
            
            for (int i = 0; i < info.Count; i++)
            {
                if (info[i] is TElXMLKeyInfoX509Data)
                {
                    cert = ((TElXMLKeyInfoX509Data)info[i]).Certificate;
                    win.SystemStores.Text = "My";
                    win.Validate(cert, ref state, XAdESVerifier.SigningTime);
                    break;
                }
            }

            mmXML.Text = cert.IssuerName.CommonName + "--->" + cert.SubjectName.CommonName + " ";

            switch (state)
            {
                case 0:
                    mmXML.Text = mmXML.Text + "Validated ";
                    break;
                case 1:
                    mmXML.Text = mmXML.Text + "Bad Data ";
                    break;
                case 2:
                    mmXML.Text = mmXML.Text + "Revoked ";
                    break;
                case 4:
                    mmXML.Text = mmXML.Text + "Not Yet Valid ";
                    break;
                case 8:
                    mmXML.Text = mmXML.Text + "Expired ";
                    break;
                case 16:
                    mmXML.Text = mmXML.Text + "Invalid Signature ";
                    break;
                case 32:
                    mmXML.Text = mmXML.Text + "Unknow CA ";
                    break;
            }

            if (state != 0)
                return;

            int index = -2;

            win.SystemStores.Text = "CA";

            while (index != -1)
            {
                index = win.GetIssuerCertificate(cert);

                if (index >= 0)
                {
                    cert = win.get_Certificates(index);
                    win.Validate(cert, ref state, DateTime.Now);

                    mmXML.Text = mmXML.Text + cert.IssuerName.CommonName + "--->" + cert.SubjectName.CommonName + " ";

                    switch (state)
                    {
                        case 0:
                            mmXML.Text = mmXML.Text + "Validated ";
                            break;
                        case 1:
                            mmXML.Text = mmXML.Text + "Bad Data ";
                            break;
                        case 2:
                            mmXML.Text = mmXML.Text + "Revoked ";
                            break;
                        case 4:
                            mmXML.Text = mmXML.Text + "Not Yet Valid ";
                            break;
                        case 8:
                            mmXML.Text = mmXML.Text + "Expired ";
                            break;
                        case 16:
                            mmXML.Text = mmXML.Text + "Invalid Signature ";
                            break;
                        case 32:
                            mmXML.Text = mmXML.Text + "Unknow CA ";
                            break;
                    }
                    if (state != 0)
                        return;
                }
            }
            index = -2;

            [COLOR=red]win.SystemStores.Text = "ROOT";[/COLOR]

            while (index != -1)
            {
                index = win.GetIssuerCertificate(cert);

                if (index >= 0)
                {
                    cert = win.get_Certificates(index);
                    win.Validate(cert, ref state, DateTime.Now);

                    mmXML.Text = mmXML.Text + cert.IssuerName.CommonName + "--->" + cert.SubjectName.CommonName + " ";

                    switch (state)
                    {
                        case 0:
                            mmXML.Text = mmXML.Text + "Validated ";
                            break;
                        case 1:
                            mmXML.Text = mmXML.Text + "Bad Data ";
                            break;
                        case 2:
                            mmXML.Text = mmXML.Text + "Revoked ";
                            break;
                        case 4:
                            mmXML.Text = mmXML.Text + "Not Yet Valid ";
                            break;
                        case 8:
                            mmXML.Text = mmXML.Text + "Expired ";
                            break;
                        case 16:
                            mmXML.Text = mmXML.Text + "Invalid Signature ";
                            break;
                        case 32:
                            mmXML.Text = mmXML.Text + "Unknow CA ";
                            break;
                    }
                    if (state != 0)
                        return;
                }
            }

before the red line the output is:
Code
CAZonaCentro--->EmpresaX Validated
CAPortugal--->CAZonaCentro Validated
ROOT--->CAPortugal Validated


but after processing the red line the cert is corrupted.

I supose that getIssuerCertificate should return a ROOT selfsign certificate right?

what´s wrong?

thanks
#4249
Posted: 11/07/2007 11:48:11
by Dmytro Bogatskyy (EldoS Corp.)

Quote
After "storage.add" the storage continue empty.

Is the "cert" value is not null? In case if there are several X509Certificate under one X509Data, then you should check the CertStorage property.
Quote
storage.Add(cert,true);

Use a TElMemoryCertStorage, not a TElCustomCertStorage (this is an abstract class, should be marked so).
And try passing second parameter as false. The certificate loaded from xml data mustn't contain a private key.
#4250
Posted: 11/07/2007 11:56:56
by Nuno Guedes (Basic support level)
Joined: 08/13/2007
Posts: 87

Quote
Bogatskyy wrote:
Quote
After "storage.add" the storage continue empty.

Is the "cert" value is not null? In case if there are several X509Certificate under one X509Data, then you should check the CertStorage property.

cert is not null.
ok, i was only checking the only presence for testing purpose

Quote
Bogatskyy wrote:
Quote
storage.Add(cert,true);

Use a TElMemoryCertStorage, not a TElCustomCertStorage (this is an abstract class, should be marked so).
And try passing second parameter as false. The certificate loaded from xml data mustn't contain a private key.

with memoryCertStorage the add works fine.
#4251
Posted: 11/07/2007 12:11:35
by Dmytro Bogatskyy (EldoS Corp.)

Quote
but after processing the red line the cert is corrupted.

For example, the cert is from "CA".
Then you change the system store to "ROOT", and try to validate it. But cert object became invalid because you changed a system store.
So, you will need to use several different TElWinCertStorage objects.
#4252
Posted: 11/07/2007 12:26:48
by Nuno Guedes (Basic support level)
Joined: 08/13/2007
Posts: 87

hummm ok.
I created 3 winCertStorages (MY,CA and ROOT) and it works.

I don´t know what is the correct way to do certificate validation.
I take the certificates presents in the KeyInfo element, add them to MemoryCertStorage and start with the validation of the first, get the issuercertificate and validate them.... until dont exist a issuercertificate on memorycertstorage?
then i find that issuer on winCertStorage? starting on CA SystemStorage?

thanks
#4253
Posted: 11/07/2007 13:19:08
by Dmytro Bogatskyy (EldoS Corp.)

The simplest way is to create one storage that contain certificates from MY, CA and ROOT.
And then validate using that storage.
Because, theoretically, the certificate chain could be like this: CA->ROOT->CA->UserCertificate
Then, in the end you should get the self-signed certificate (check cert.SelfSigned property).
If the self-signed certificate in the ROOT system store (use winRoot.IndexOf(..) method) then it trusted, other way warn user.
#4263
Posted: 11/08/2007 10:27:48
by Nuno Guedes (Basic support level)
Joined: 08/13/2007
Posts: 87

thanks

as i understand what i had read, the keyInfo element could contain some of the certificates used, because verifier user may haven´t them.
signingcertificate information reference to certificate used to sign and that info should serve to find the certficate in memStorage.
right?

now my algorith is:
- Load Certificates from WinCertStorage to memStorage
- Get certificates from KeyInfo element, if they aren´t present in memStorage add them
- Get signingcertificate information
- Find certificate on memStorage
- If exists
- Validate from bottom to up
- when not exists issuercertificate verificate if is selfsigned and is trust (presence in CA or ROOT)

this is for verifying that Keyinfo certificates are or not in the memcertstorage already
Code
for (int i = 0; i < info.Count; i++)
            {
                if (info[i] is TElXMLKeyInfoX509Data)
                {
                    cert = ((TElXMLKeyInfoX509Data)info[i]).Certificate;
                    if (memCertStorage.IndexOf(cert) == -1)
                    {
                        memCertStorage.Add(cert, false);
                    }
                }
            }


in this space will be the code for find the certificate referenced by signingcertificate.
I can´t get the certificate because i tried it comparing the serial number (in a for cycle) but all the certificates created by CertDemo have 0 as serial number. Exists another method for doing this?

Code
            
while (true)
            {
                memCertStorage.Validate(cert, ref state, DateTime.Now);
                mmXML.Text = mmXML.Text + cert.IssuerName.CommonName + "--->" + cert.SubjectName.CommonName + " " + state + "\n";
                index = memCertStorage.GetIssuerCertificate(cert);
                if (index >= 0)
                {
                    cert = memCertStorage.get_Certificates(index);
                }
                else
                {
                    if (cert.SelfSigned && ((cert.StorageName == "ROOT") || (cert.StorageName == "CA")))
                    {
                        terminouBem = true;
                        break;
                    }
                    else
                    {
                        terminouBem = false;
                        break;
                    }
                }

            }

            if (terminouBem)
            {
                mmXML.Text = mmXML.Text + "SUCESSO";
            }


i used
Code
cert.StorageName == "ROOT"
because i am doing verification on a webservice. Any problem using this?

thanks
#4265
Posted: 11/08/2007 13:31:53
by Dmytro Bogatskyy (EldoS Corp.)

Quote
as i understand what i had read, the keyInfo element could contain some of the certificates used, because verifier user may haven´t them.
signingcertificate information reference to certificate used to sign and that info should serve to find the certficate in memStorage.
right?

I think, this should help:
http://www.w3.org/TR/xmldsig-core/ see: 4.4.4
And:
Code
SigningCertificate. This property contains an unambiguous reference to the signer's
certificate, formed by its identifier and the digest value of the certificate. Its usage is particularly
important when a signer holds a number of different certificates containing the same public key, to avoid
claims by a verifier that the signature implies another certificate with different semantics. This is also
important when the signer holds different certificates containing different public keys in order to provide
the verifier with the correct signature verification data. Finally, it is also important in case the issuing key
of the CA providing the certificate would be compromised.

Quote
now my algorith is

Seems, to be ok.
Quote
all the certificates created by CertDemo have 0 as serial number.

To generate certificate with a serial number using CertDemo:
In buttonGenerate_Click method, set CreatedCert.SerialNumber property.
Quote
Exists another method for doing this?

To search for a certificate in CertificateStorage use FindFirst/FindNext methods.
http://www.eldos.com/documentation/sb...first.html

Quote
cert.StorageName == "ROOT", Any problem using this?

Should be fine.
#4274
Posted: 11/09/2007 10:00:50
by Nuno Guedes (Basic support level)
Joined: 08/13/2007
Posts: 87

thanks for all.

i have 2 more questions:

Finding the certificate referenced by SigningCertificate element
Code
TElCertificateLookup lookUp = new TElCertificateLookup();
            lookUp.SerialNumber = Verifier.Signature.QualifyingProperties.SignedProperties.SignedSignatureProperties.SigningCertificate[0].IssuerSerial.SerialNumber;
            lookUp.CertificateHash = Verifier.Signature.QualifyingProperties.SignedProperties.SignedSignatureProperties.SigningCertificate[0].CertDigest.DigestValue;
            lookUp.Criteria = SBCustomCertStorage.Unit.lcCertificateHash | SBCustomCertStorage.Unit.lcSerialNumber;
            lookUp.Options = SBCustomCertStorage.Unit.loExactMatch | SBCustomCertStorage.Unit.loMatchAll;

            index = memCertStorage.FindFirst(lookUp);

if i only add serialnumber to criteria or set options for ExactMatch only, it returns a index. But when searching for serialnumber and CertHash it returns -1.
Searching only by serialnumber it´s not correct right? For examplo, 2 CA can give the same serialnumber for two certificates.

this is signing certificate element
Code
- <SigningCertificate>
- <Cert>
- <CertDigest>
  <ds:DigestMethod Algorithm="http://www.w3.org/2000/09/xmldsig#sha1" />
  <ds:DigestValue>WI8rXFtLkUxiCYOJP1f6xKs0pbs=</ds:DigestValue>
  </CertDigest>
- <IssuerSerial>
  <ds:X509IssuerName>C=PT, ST=Lisboa, L=Lisboa, O=CAZonaCentro, OU=CAZonaCentro, CN=CAZonaCentro</ds:X509IssuerName>
  <ds:X509SerialNumber>8949253169487676052</ds:X509SerialNumber>
  </IssuerSerial>
  </Cert>
  </SigningCertificate>



When validating the certificates from bottom to up, on the first call of memCertStorage.Validate(cert, ref reason, date) method, the date should be the signingTime present in Object element, right?
When validating an issuercertificate the date should be the "valid from" date of the child certificate??

thanks for all
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.

Reply

Statistics

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