SgDotNet
Singapore Professional .NET User Group -For Cool Developers

Error Signing with a key stored in a smart card using X509Certificate2 class

rated by 0 users
This post has 3 Replies | 1 Follower

Top 500 Contributor
Posts 8
Senshodan Posted: 01-26-2006 6:16 PM
Hi all,

Let's see if somebody can help about the following issue:

I'm using the following code to create a signedXML object:

uint hCertStore = Crypt32.CertOpenSystemStore(0, "My");
uint pCertContext = Crypt32.CertEnumCertificatesInStore(hCertStore, (uint)0);
// MyCert points to a key stored in a SmartCard
X509Certificate2 MyCert = new X509Certificate2(pCertContext);
SignedXml signedXml = new SignedXml();
signedXml.SigningKey = cert.PrivateKey;

And then I got the exception "There are more data available".

I have also tried to do the same using a more low level API:
CspParameters csp = new CspParameters(1, "Schlumberger Cryptographic Service Provider");
RSACryptoServiceProvider rsa = new RSACryptoServiceProvider(csp);

And it works, BUT the problem is that I don't want to use the default key container but the container where the private key associated to my Cert is stored. I can custom this property doing the following:

csp.KeyContainerName = "My container name";

But then, when doing RSACryptoServiceProvider rsa = new RSACryptoServiceProvider(csp); I get the same error ( There are more data available). So the point is that I can use the smart card for signing but not a specific key which is not valid for my case because I want to use the key associated with a certificate.

Any further idea? I am a bit desesperated so I will pay a Beer [B] if someone helps me to solve that problem . Wink [;)]

Thanks in advance.
Ivan.



replied on 01-27-2006 11:10 PM

http://forums.microsoft.com/MSDN/ShowPost.aspx?PostID=207279&SiteID=1

From what I understand from the above link is that the Private Key of the certificate stored in SmartCard is not easily readable.

You will have to enter PIN to be able to extract the PrivateKey from the certificate.

As explained in that forum, one of the techniques would be to use Win32 API, CryptAcquireCertificatePrivateKey ,  from Crypto32.dll.

Another technique would be to construct the RSACryptoServiceProvider with CspParameters structure which contains the name of the smart card CSP.

Try it out and let us know if it is working.  I don't have SmartCard reader so I have not tested this solution. Embarrassed [:$]

Hope it gives you some idea to get started.Idea [I]

Maung Maung

Top 500 Contributor
Posts 8
As I was unable to use X509Certificate2 for signing from a SC I tried 
your suggestion about using a lower level API, so I have used the following code:

CspParameters CSPParam = new CspParameters();
CSPParam.KeyContainerName = "MY";
CSPParam.ProviderName = DATAKEY_RSA_SCARD_PROV; //Smart card CSP

//"Datakey class="iAs">RSA CSP"
CSPParam.ProviderType = (int)CryptoCom.PROV_RSA_FULL;
CSPParam.KeyNumber = 2; // (int)KeyNumber.Signature;
RSACryptoServiceProvider Key = new RSACryptoServiceProvider(CSPParam);

Now comes the surprise, this code works perfectly on Visual studio 2003,
but trying to use the same code, with the same smartcard and the same
CSP on visual studio 2005 I got also the error:
"More class="iAs">data is available".
Anyone knows what is the problem?
If there is no solution for that problem, is somebody knows how can I use
.net 1.1 instead of .net 2.0 on Visual Studio 2005 please let me know.

Thanks a lot in advance.
Not Ranked
Posts 1

this code on .Net1.1 works perfectly fine with a Datakey M 330 smart card on SCM's SCR 335 reader!

Public

 

Sub New()

 

Dim prms As CspParameters = New CspParameters(1, "Datakey RSA CSP")

prms.Flags = CspProviderFlags.UseDefaultKeyContainer

 

prms.KeyNumber = 2

 

Try

rsa =

New RSACryptoServiceProvider(prms)

rsa = rsa.Create()

privParms = rsa.ExportParameters(

True)

pubParms = rsa.ExportParameters(

False)

 

Catch ex As Exception

 

If Not rsa Is Nothing Then rsa = Nothing

 

Finally

 

End Try

 

End Sub

 

Public Function Sign(ByVal EncryptString As String) As Byte()

 

Dim enc As UTF8Encoding = New UTF8Encoding

 

Dim encd As Byte() = enc.GetBytes(EncryptString)

 

Try

 

Dim hsh As New SHA1Managed

encd = hsh.ComputeHash(encd)

encd = rsa.SignHash(encd, CryptoConfig.MapNameToOID("SHA1"))

encd = rsa.SignData(encd, "SHA1")

'rsa.Encrypt(encd, True)

 

Catch ex As Exception

 

If Not rsa Is Nothing Then

rsa.Clear()

rsa =

Nothing

 

End If

 

Finally

 

If Not rsa Is Nothing Then

rsa.Clear()

rsa =

Nothing

 

End If

 

End Try

 

Return encd

 

End Function

this code when ported to .net 3.5 throws the error "More Data Available". I don't know why MS is not responding to the problem in .Net 2.0 /3.5!

Page 1 of 1 (4 items) | RSS
Copyright SgDotNet 2004-2009
Powered by Community Server (Commercial Edition), by Telligent Systems