Sign a document by SmartCard on the .NET client and verify on the SQL 2005 server
Hi!
I'm working on the following application:In the client application (written in C#) an user signs a document by private key, stored on chip card. Signed document and the signature are stored into database on SQL 2005 server.
There is my client code for demonstration:
Client application sample:
| |
System.Data.SqlClient.SqlConnection conn =new System.Data.SqlClient.SqlConnection("Data Source=localhost;Initial Catalog=Test;Integrated Security=True"); conn.Open(); try { CspParameters csp =new CspParameters(1, "Schlumberger Cryptographic Service Provider"); csp.KeyNumber=1;// Initialize an RSACryptoServiceProvider object using // the CspParameters object. RSACryptoServiceProvider rsa = new RSACryptoServiceProvider(csp); // Create some data to sign. string text = "plain text to sign"; // Sign the data using the Smart Card CryptoGraphic Provider. byte[] sig = rsa.SignData(Encoding.Unicode.GetBytes(text), "SHA1");
Console.WriteLine("Signature:\t" + BitConverter.ToString(sig));
// Write to db SqlCommand cmd = new SqlCommand("insert into signed (data, sign) values (@data, @sign) ", conn); SqlParameter parData = new SqlParameter("@data", text); cmd.Parameters.Add(parData); SqlParameter parSign = new SqlParameter("@sign", sig); cmd.Parameters.Add(parSign); cmd.ExecuteNonQuery(); // Verify the data using the Smart Card CryptoGraphic Provider. bool verified = rsa.VerifyData(Encoding.Unicode.GetBytes(text), "SHA1", sig); Console.WriteLine("Verified:\t" + verified); } finally { conn.Close(); }
|
The document and the signature are stored into the Signed table in the Test database:
| |
use [Test] CREATETABLE [dbo].[signed]( [id] [int]IDENTITY(1,1)NOTNULL, [data] [nvarchar](50)COLLATE Czech_CI_ASNULL, [sign] [varbinary](max)NULL, CONSTRAINT [PK_signed]PRIMARYKEYCLUSTERED )ON [PRIMARY]
|
Now I want check signature validity on server side.
I found the certificate stored on my chip card in certificate store Current User/Personal/Certificates (the Certificates MMC snapin). I exported it into the binary DER encoded file (cer extension).
Then I imported this certificate into the database [Test] using CREATE CERTIFICATE statement:
| |
CREATECERTIFICATE testCert FROMFILE='c:\temp\My Test Certificate.cer'
|
Now, I want to verify signature by theVerifySignedByCert() statement:
| |
select VerifySignedByCert( Cert_ID('testCert'), data, [sign])as verifiedFROM signed
|
The VerifySignedByCert returns 0. I don't understand WHY?
WHAT'S WRONG?
Please help me!
Thankyou
Fipil.
[9829 byte] By [
Fipil] at [2008-2-25]
Laurentiu, thanks for response.
I changed the sample client code to direct using private key from selected certificate.
But, it doesn't work even if i changed the hash algorithm to MD5 too.
Here is the changed code:
| |
System.Data.SqlClient.SqlConnection conn = new System.Data.SqlClient.SqlConnection("Data Source=localhost;Initial Catalog=Test;Integrated Security=True"); conn.Open(); try { // Open the My certificate store. X509Store storeMy = new X509Store(StoreName.My, StoreLocation.CurrentUser); storeMy.Open(OpenFlags.ReadOnly); X509Certificate2Collection certs=X509Certificate2UI.SelectFromCollection (storeMy.Certificates, "Selection", "Select a certificate", X509SelectionFlag.SingleSelection); X509Certificate2 cert=certs[0]; storeMy.Close(); // Initialize an RSACryptoServiceProvider object using // the certificate PrivateKey RSACryptoServiceProvider rsa = (RSACryptoServiceProvider)cert.PrivateKey;
// Create some data to sign. string text = "plain text to sign"; // Sign the data using the Smart Card CryptoGraphic Provider. byte[] sig = rsa.SignData(Encoding.Unicode.GetBytes(text), "MD5"); Console.WriteLine("Signature:\t" + BitConverter.ToString(sig));
// Write to db SqlCommand cmd = new SqlCommand("insert into signed (data, sign) values (@data, @sign) ", conn); SqlParameter parData = new SqlParameter("@data", text); cmd.Parameters.Add(parData); SqlParameter parSign = new SqlParameter("@sign", sig); cmd.Parameters.Add(parSign); cmd.ExecuteNonQuery(); // Verify the data using the Smart Card CryptoGraphic Provider. bool verified = rsa.VerifyData(Encoding.Unicode.GetBytes(text), "MD5", sig); Console.WriteLine("Verified:\t" + verified); } finally { conn.Close(); }
|
What's wrong?
Thanks!
Fipil
I can't try signing using SignWithCert, because the private key of the certificate is stored on the chip card. SQL server didn't use the key and a resulting signature is NULL.
But, I'll try creating another certificate with private key stored on the machine certificate store.
Writting my own CLR function is good idea, I'll try it.
thanks a lot!
Fipil
Hi brothers ! I'm having the same problem to access the private key of the certificate stored on the chip card.
If i access the private key of a certificate with private key stored on the machine certificate store it works well.....but in the case of the chip card, when i read the X509Certificate2.PrivateKey property, i receive a System.Security.Cryptography.CryptographicException: There are more data available.
If some of you discover something about it, please post here !
thanks !!!