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.
Hope it gives you some idea to get started.
Maung Maung
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 sameCSP 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.
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!
Public
Sub New()
Dim prms As CspParameters = New CspParameters(1, "Datakey RSA CSP") prms.Flags = CspProviderFlags.UseDefaultKeyContainer
prms.Flags = CspProviderFlags.UseDefaultKeyContainer
prms.KeyNumber = 2
Try
rsa =
New RSACryptoServiceProvider(prms) rsa = rsa.Create() privParms = rsa.ExportParameters(
rsa = rsa.Create()
privParms = rsa.ExportParameters(
True) pubParms = rsa.ExportParameters(
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)
Dim hsh As New SHA1Managed encd = hsh.ComputeHash(encd) encd = rsa.SignHash(encd, CryptoConfig.MapNameToOID("SHA1")) encd = rsa.SignData(encd, "SHA1")
encd = hsh.ComputeHash(encd)
encd = rsa.SignHash(encd, CryptoConfig.MapNameToOID("SHA1"))
encd = rsa.SignData(encd, "SHA1")
'rsa.Encrypt(encd, True)
If Not rsa Is Nothing Then
rsa.Clear()
Nothing
End If
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!