EldoS | Feel safer!

Software components for data protection, secure storage and transfer

Property connected or not card with selected certificate in reader

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.
#37153
Posted: 07/04/2016 09:20:45
by Marek Otulakowski (Basic support level)
Joined: 05/10/2016
Posts: 8

Hi,
Please help or give me any hint
I'm seaching a method in VCL XmlBlackbox component in Delphi which will return true or false (exist and connected SmartCard with selected certificate in reader)

Example in WinCrypt, like this:
Code
pProvKey := nil;
dwProvKeyInfoSize := 0;
CertGetCertificateContextProperty(cert, CERT_KEY_PROV_INFO_PROP_ID, pProvKey, @dwProvKeyInfoSize);
GetMem(pProvKey, dwProvKeyInfoSize);
if CertGetCertificateContextProperty(cert, CERT_KEY_PROV_INFO_PROP_ID, pProvKey, @dwProvKeyInfoSize) then
begin
  if CryptAcquireContextW(@hProvider, pProvKey^.pwszContainerName, pProvKey^.pwszProvName, pProvKey^.dwProvType, CRYPT_VERIFYCONTEXT) then
  begin
    Str := Str + 'SUCESS!';
  end else
  begin
    LastErr := GetLastError;
  end;   
end;
#37163
Posted: 07/06/2016 08:51:21
by Eugene Mayevski (EldoS Corp.)

Quote
m.otulakowski wrote:
I'm seaching a method in VCL XmlBlackbox component in Delphi which will return true or false (exist and connected SmartCard with selected certificate in reader)


Are you asking how to do this via CryptoAPI (TElWinCertStorage) or PKCS#11 ( TElPKCS11CertStorage)?

In general you can lookup the certificate in the storage using TElCertificateLookup class. There you can configure multiple certificate properties to lookup for.


Sincerely yours
Eugene Mayevski
#37176
Posted: 07/07/2016 05:24:02
by Marek Otulakowski (Basic support level)
Joined: 05/10/2016
Posts: 8

Hi,
We are using this code in our program:

Code
function ListaCertyfikatow : String;
Var I              : Integer;
    WinCertStorage : TElWinCertStorage;
    Cert           : TElX509Certificate;
    TP : TMessageDigest160;
Begin
  Result := EmptyStr;
  try
    WinCertStorage := TElWinCertStorage.Create(nil);
    WinCertStorage.SystemStores.Text := 'MY';
    for i := 0 to WinCertStorage.Count - 1 do
    begin
      Result := Result
              + 'SubjectName:' + sLineBreak
              + '   CommonName: ' + Cert.SubjectName.CommonName + sLineBreak
              + '   Country: ' + Cert.SubjectName.Country + sLineBreak
              + '   StateOrProvince: ' + Cert.SubjectName.StateOrProvince + sLineBreak
              + '   Locality: ' + Cert.SubjectName.Locality + sLineBreak
              + '   Organization: ' + Cert.SubjectName.Organization + sLineBreak
              + '   OrganizationUnit: ' + Cert.SubjectName.OrganizationUnit + sLineBreak
              + '   OrganizationUnit: ' + Cert.SubjectName.EMailAddress + sLineBreak;
      If Cert.KeyMaterial.Key.IsSecret      //Cert.KeyMaterial.SecretKey
        then Result := Result + 'SECRET KEY: YES' + sLineBreak
        Else Result := Result + 'SECRET KEY: NO'  + sLineBreak;
      If Cert.IsKeyValid
        then Result := Result + 'VALID: YES' + sLineBreak
        Else Result := Result + 'VALID: NO'  + sLineBreak;
      Result := Result + 'THUMB PRINT: ' + SBUtils.DigestToStr(Cert.GetHashSHA1) + sLineBreak;
      If Cert.PrivateKeyExists
        then Result := Result + 'PRIVATE KEY: YES' + sLineBreak
        Else Result := Result + 'PRIVATE KEY: NO'  + sLineBreak;
………………
    End;
End;

We are missing info about card with certificate.
Is reader is connected to PC?
Is this card with certificate is in reader?
What is type certificate? (HARDWARE or SOFTWARE)
This info you can get in .NET for example:

Code
public static X509Certificate2 GetFirstCertificateFromSmartCard(string certSubject)
{
   // Access Personal (MY) certificate store of current user
   X509Store my = new X509Store(StoreName.My, StoreLocation.CurrentUser);
   my.Open(OpenFlags.ReadOnly | OpenFlags.OpenExistingOnly);

   // Find the certificate we'll use to sign
   RSACryptoServiceProvider csp = null;
   foreach (X509Certificate2 cert in my.Certificates)
   {
      if (cert.Subject.Contains(certSubject) && cert.NotAfter > DateTime.Now)
      {
         // We found it.
         // Get its associated CSP and private key
         if (cert.HasPrivateKey)
         {
            csp = (RSACryptoServiceProvider)cert.PrivateKey;
            if (csp.CspKeyContainerInfo.HardwareDevice)
               return cert;
         }
      }
   }
   return null;
}


We are asking You for a info where are the examples in XMLBlackBox (VCL) module. We could'n find them with class TEICertificateLookup.

Best regards,
Marek
#37177
Posted: 07/07/2016 06:21:59
by Eugene Mayevski (EldoS Corp.)

You are asking about "if (csp.CspKeyContainerInfo.HardwareDevice)" line, don't you?

Unfortunately we don't ave such functionality and I even have no idea, how it's implemented in .NET. In PKCS#11 it's available, of course.

Maybe you can just check for presence of PrivateKey


Sincerely yours
Eugene Mayevski
#37178
Posted: 07/07/2016 07:28:15
by Marek Otulakowski (Basic support level)
Joined: 05/10/2016
Posts: 8

In the bellow example from XMLBlackBox used method SIGN to XML file:

Code
if Assigned(Cert) then
begin
  if Handler is TElXMLSOAPSignatureHandler then
   TElXMLSOAPSignatureHandler(Handler).Sign(Cert, True)
  else if Handler is TElXMLWSSSignatureHandler then
   TElXMLWSSSignatureHandler(handler).Sign(Cert, wecInBinarySecurityToken)
  else
   // TElXMLSOAPBaseSignatureHandler
   Handler.Sign(SignatureNode as TElXMLDOMElement, Cert, True);
End

As far as we understand the method must read the value of the private key from the given certificate located on the cryptographic card. Can we use a similar mechanism to verify the presence of the card with a certificate in the reader? As a result, when you attempt to read private key create an exception in the absence of the card in the reader and based on this we can get the result we need.
Unfortunately, we do not have the possibility of deeper decoding method in this version TRIAL. Therefore, we ask a few lines of code sample code that shows the solution to our problem.

Best regards,
Marek
#37180
Posted: 07/07/2016 08:39:23
by Eugene Mayevski (EldoS Corp.)

Quote
m.otulakowski wrote:
As far as we understand the method must read the value of the private key from the given certificate located on the cryptographic card.


The cryptocard doesn't let one *read* the key. The whole essence of the cryptocard is to protect private and secret keys. What the card does is let you perform the operation with the key without extracting it.

Quote
m.otulakowski wrote:
Can we use a similar mechanism to verify the presence of the card with a certificate in the reader? As a result, when you attempt to read private key create an exception in the absence of the card in the reader and based on this we can get the result we need.


Basically TElX509Certificate.PrivateKeyExists property does this - it would return false if there's no card in the slot. But the behavior is dependent on the hardware and drivers, so you need to do the tests yourself.


Sincerely yours
Eugene Mayevski
#37199
Posted: 07/08/2016 02:58:26
by Marek Otulakowski (Basic support level)
Joined: 05/10/2016
Posts: 8

Thank you for your suggestion but in the our case SmartCard method
Code
TElX509Certificate.PrivateKeyExists
always return True (if Card is in the reader or not)
We tested on SmartCard models
http://www.certum.pl/certum/cert,oferta_karta_kryptograficzna_cryptocertum_3_2.xml
and
http://www.cryptotech.com.pl/Produkty/CryptoCard_Carbon,content.html

in the previous code .NET works fine

Best Regards,
Marek
#37218
Posted: 07/08/2016 13:21:31
by Ken Ivanov (EldoS Corp.)

Hi Marek,

While it is not clear enough what is causing such kind of weird behaviour in your environment (as PrivateKeyExists only maps the private key existence flag it gets from the token's CSP, its behaviour should be consistent with that of HasPrivateKey), you might try some workarounds to address the issue.

In particular, you can try converting your TElX509Certificate object to .NET X509Certificate2 one with its ToX509Certificate2() method, and applying your csp.CspKeyContainerInfo.HardwareDevice-based approach to the created object to identify whether its origin is a smart card.

The reverse approach would be obtaining an X509Certificate2 object with .NET means, and converting it to TElX509Certificate with the latter's FromX509Certificate() method after the smart card availability check.

Ken
#37224
Posted: 07/09/2016 08:14:53
by Marek Otulakowski (Basic support level)
Joined: 05/10/2016
Posts: 8

Hello,
Thank you for your answer, but in my solution I'm limited to the use of code entirely in Delphi. Temporarily I applied the workaround using WinCrypt from the first post and it works correctly. However, in the future should be able to find such a feature in the API VCL XmlBlackBox.
Just that there will be a method which will answer the question whether it is possible to read (ready to sign) the indicated certificate search by, eg. fingerprint or not.

Regards,
Marek
#37225
Posted: 07/09/2016 11:45:00
by Ken Ivanov (EldoS Corp.)

Hi Marek,

Thank you for the clarification.

I am afraid the 'solution' used in your first post is not a proper solution, and the fact that it works for you is only a result of coincidence / implementation specifics. While you can use that approach to do the job with your tokens, it is unlikely that it will return the expected result with different token models.

Still, if you only need to support those two particular token models, your approach would probably be a good solution for you.

Ken
Also by EldoS: Rethync
The cross-platform framework that simplifies synchronizing data between mobile and desktop applications and servers and cloud storages

Reply

Statistics

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