Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to get Information from a security token with C#

Tags:

c#

pki

sign

I need to enable my applications' users to sign their approvals with their personal USB security token.

I've managed to sign data but I haven't been able to get the information of who's token has been used to do so.

Here is the code I have so far:

CspParameters csp = new CspParameters(1, "SafeNet RSA CSP");
csp.Flags = CspProviderFlags.UseDefaultKeyContainer;            
RSACryptoServiceProvider rsa = new RSACryptoServiceProvider(csp);
// Create some data to sign. 
byte[] data = new byte[] { 0, 1, 2, 3, 4, 5, 6, 7 };
Console.WriteLine("Data         : " + BitConverter.ToString(data));
// Sign the data using the Smart Card CryptoGraphic Provider.            
byte[] sig = rsa.SignData(data, "SHA1");            
Console.WriteLine("Signature    : " + BitConverter.ToString(sig));

There is a field in token's information called "Token Name". How can I access that field in order to validate which token has been used to sign the approval?

enter image description here

Additional info and update:

  • "Token name" always match owner's name (the user who owns the usb token)
  • It seems like it can't be done, maybe there is a web service or something I need to call in order to get the information directly from the cert authority.
like image 671
daniloquio Avatar asked Feb 28 '13 14:02

daniloquio


1 Answers

When I had originally asked the question my understanding of digital certificates was very basic, so the question wasn't properly asked. Now I understand that I needed to access a certificate from a smart card device, query its attributes and test if the user could enter the right PIN for it.

Here is the code I used to do so:

//Prompt the user with the list of certificates on the local store.
//The user have to select the certificate he wants to use for signing.
//Note: All certificates form the USB device are automatically copied to the local store as soon the device is plugged in.
X509Store store = new X509Store(StoreLocation.CurrentUser);
store.Open(OpenFlags.ReadOnly);
X509CertificateCollection certificates = X509Certificate2UI.SelectFromCollection(store.Certificates,
                                                                                "Certificados conocidos",
                                                                                "Por favor seleccione el certificado con el cual desea firmar",
                                                                                X509SelectionFlag.SingleSelection
                                                                                );
store.Close();
X509Certificate2 certificate = null;
if (certificates.Count != 0)
{
    //The selected certificate
    certificate = (X509Certificate2)certificates[0];
}
else
{
    //The user didn't select a certificate
    return "El usuario canceló la selección de un certificado";
}
//Check certificate's atributes to identify the type of certificate (censored)
if (certificate.Issuer != "CN=............................., OU=................., O=..., C=US")
{
    //The selected certificate is not of the needed type
    return "El certificado seleccionado no corresponde a un token ...";
}
//Check if the certificate is issued to the current user
if (!certificate.Subject.ToUpper().Contains(("E=" + pUserADLogin + "@censoreddomain.com").ToUpper()))
{
    return "El certificado seleccionado no corresponde al usuario actual";
}
//Check if the token is currently plugged in
XmlDocument xmlDoc = new XmlDocument();
XmlElement element = xmlDoc.CreateElement("Content", SignedXml.XmlDsigNamespaceUrl.ToString());
element.InnerText = "comodin";
xmlDoc.AppendChild(element);
SignedXml signedXml = new SignedXml();
try
{
    signedXml.SigningKey = certificate.PrivateKey;
}
catch
{
    //USB Token is not plugged in
    return "El token no se encuentra conectado al equipo";
}
DataObject dataObject = new DataObject();
dataObject.Data = xmlDoc.ChildNodes;
dataObject.Id = "CONTENT";
signedXml.AddObject(dataObject);
Reference reference = new Reference();
reference.Uri = "#CONTENT";
signedXml.AddReference(reference);
//Attempt to sign the data. The user will be prompted to enter his PIN
try
{
    signedXml.ComputeSignature();
}
catch
{
    //User didn't enter the correct PIN
    return "Hubo un error confirmando la identidad del usuario";
}
//The user has signed with the correct token
return String.Format("El usuario {0} ha firmado exitosamente usando el token con serial {1}", pUserADLogin, certificate.SerialNumber);

Sources:

http://stormimon.developpez.com/dotnet/signature-electronique/ (en Francais) https://www.simple-talk.com/content/print.aspx?article=1713 (in English)

like image 172
daniloquio Avatar answered Sep 17 '22 23:09

daniloquio