Re: Help : XML Signature with private key in smart card

From: J-P Meunier (fuimens_at_yahoo.fr)
Date: 05/12/03


Date: Mon, 12 May 2003 11:45:43 +0200


Ivan,

I need to give the user the ability to choose the signing key from smart
card or from the local machine store. For that I use CAPICOM to display all
certificates registred and when the user choose one I determine if it is on
store or on the card
depending on the CSP value (Certificate.PrivateKey.ProviderName)

This is the only way I have found to distinguish between keys located in the
registry and those on smart cards, but it requires a test on hard coded
values of CSP. Is there any other way to perform this test ?

> Perhaps in cases where it generates a new key you don't have a key
> suitable for signing in your key container (e.g.only have a AT_KEYEXCHANGE
> key). If the key is already there it should not be generating new keys,
that
> is, if you are able to sign with a particular smart card once you should
be
> able to verify the signature every time you insert this card.
How can I test if the key is not suitable to signature ? I would like to
avoid creating keys on user smart cards when the key is provided cannot be
used for signature.

Thank you

J-P

> You are right, rds.SignData does not do XML dsig, and as I said in my
> message you will need to modify your XML signing code to get rid of the
X509
> stuff and insert the part of my sample that retrieves the RSA object tied
to
> a smart card. Once you have the right RSA object (which my sample shows
how
> to get) you can assign it to SignedXml.SigningKey and proceed with
creating
> XML dsig as you normally do.
>
> --Ivan
> This posting is provided "AS IS" with no warranties, and confers no
rights.
>
>
> "J-P Meunier" <fuimens@yahoo.fr> wrote in message
> news:OiNSvBMFDHA.3324@tk2msftngp13.phx.gbl...
> > Ivan,
> >
> > Thank you for your post.
> >
> > I have 2 remarks:
> > 1) the instruction "RSACryptoServiceProvider rsa = new
> > RSACryptoServiceProvider(csp);", used with the same flags and class
> > properties sometimes generates a key in the card and sometimes seems to
> use
> > the key already located in the card.
> > Is this the normal behaviour ? Have I missed a flag or property !?
> > Any explanation about this will be very helpful.
> >
> > 2) rsa.SignData() doesn't support XML Digital Signature while my need is
> to
> > perform XML D-Signature using the private key in a smart card.
> >
> > Regards,
> >
> > J-P
> >
> > "Ivan Medvedev [MS]" <ivanmed@online.microsoft.com> a écrit dans le
> message
> > de news: eLfuiLLFDHA.2396@TK2MSFTNGP12.phx.gbl...
> > > J-P -
> > > I threw a little sample together that shows how to create an RSA
object
> > tied
> > > to a smart card and sign with it. In your code you can drop the X509
> part
> > > and take the code from the sample that creates an RSA object wich you
> > would
> > > set to SignedXml.SigningKey.
> > > You may need to change the provider name in the CspParameters
> constructor
> > to
> > > match the particular smartcard you are using.
> > > Hope this helps.
> > > --Ivan
> > >
> > > -------------------------------------------------------
> > > cut ------------------------------------------------------
> > > using System;
> > > using System.Security.Cryptography;
> > >
> > > class SCSign
> > > {
> > > [STAThread]
> > > static void Main(string[] args)
> > > {
> > > // the 1st parameter comes from
> > > HKLM\Software\Microsoft\Cryptography\Defaults\Provider Types
> > > // the 2nd parameter comes from
> > > HKLM\Software\Microsoft\Cryptography\Defaults\Provider
> > > CspParameters csp = new CspParameters(1, "Schlumberger
Cryptographic
> > > Service Provider");
> > > csp.Flags = CspProviderFlags.UseDefaultKeyContainer;
> > >
> > > RSACryptoServiceProvider rsa = new RSACryptoServiceProvider(csp);
> > >
> > > byte[] data = new byte[] {0,1,2,3,4,5,6,7};
> > >
> > > Console.WriteLine("Data : " + BitConverter.ToString(data));
> > >
> > > byte[] sig = rsa.SignData(data, "SHA1");
> > >
> > > Console.WriteLine("Signature : " + BitConverter.ToString(sig));
> > >
> > > bool verified = rsa.VerifyData(data, "SHA1", sig);
> > >
> > > Console.WriteLine("Verified : " + verified);
> > > }
> > > }
> > >
> > > -------------------------------------------------------
> > > cut ------------------------------------------------------
> > >
> > > This posting is provided "AS IS" with no warranties, and confers no
> > rights.
> > > Use of included script samples are subject to the terms specified at
> > > http://www.microsoft.com/info/cpyright.htm
> > >
> > >
> > >
> > > "J-P Meunier" <fuimens@yahoo.fr> wrote in message
> > > news:#W4aw#9EDHA.1552@TK2MSFTNGP12.phx.gbl...
> > > > hi all,
> > > >
> > > > I want to sign a local file with XML Signature using a private key
> > located
> > > > in a smart card.
> > > >
> > > > I am able to sign with private keys located in local registry with
the
> > > > following testing code:
> > > >
> > > >
> > > >
> > > > using FCLX509 = System.Security.Cryptography.X509Certificates;
> > > > using WSEX509 = Microsoft.Web.Services.Security.X509;
> > > > string subjectname = "CN=Admin";
> > > > string storename ="MY";
> > > > WSEX509.X509CertificateStore.StoreLocation location =
> > > > WSEX509.X509CertificateStore.StoreLocation.CurrentUser;
> > > > WSEX509.X509CertificateStore.StoreProvider provider =
> > > > WSEX509.X509CertificateStore.StoreProvider.System;
> > > > WSEX509.X509CertificateStore store = new
> > > > WSEX509.X509CertificateStore(provider, location, storename);
> > > > bool fopen = store.OpenRead();
> > > > WSEX509.X509CertificateCollection cers =
> > > > store.FindCertificateBySubjectName(subjectname);
> > > > foreach ( FCLX509.X509Certificate FCLcer in cers)
> > > > {
> > > > WSEX509.X509Certificate cer = new
> > > > WSEX509.X509Certificate(FCLcer.GetRawCertData());
> > > > AsymmetricAlgorithm private_key = cer.Key;
> > > >
> > > > // getting private key
> > > > RSA rsaKeyPair = cer.Key;
> > > >
> > > > SignedXml signedXml = new SignedXml();
> > > > signedXml.SigningKey = rsaKeyPair;
> > > >
> > > > XmlDocument objdocument = new XmlDocument();
> > > > objdocument.Load("CreditCardInfo.xml");
> > > >
> > > > DataObject dataObject = new DataObject();
> > > > dataObject.Data = objdocument.ChildNodes;
> > > > dataObject.Id = "CreditCardInfo";
> > > > signedXml.AddObject(dataObject);
> > > >
> > > > Reference reference = new Reference();
> > > > reference.Uri = "#CreditCardInfo";
> > > > signedXml.AddReference(reference);
> > > >
> > > > signedXml.ComputeSignature();
> > > > }
> > > >
> > > >
> > > > But when the private key associated to the certificate "cer", the
> > > > instruction "RSA rsaKeyPair = cer.Key" fails, which is expected
> because
> > > > smart cards generally don't allow private key exporting.
> > > >
> > > >
> > > > So I tried the following code to "retrieve" the private key in the
> smart
> > > > card:
> > > >
> > > > CspParameters cp = new CspParameters();
> > > > cp.ProviderName = "Gemplus GemSAFE Card CSP";
> > > > cp.Flags = CspProviderFlags.UseMachineKeyStore;
> > > > RSACryptoServiceProvider rsaKeyPair = new
> > > RSACryptoServiceProvider(cp);
> > > >
> > > > But this generates private key on the smart card !?
> > > >
> > > > So how can I use the smart card CSP (as Gemplus GemSAFE Card CSP) to
> > sign
> > > > with the private key in the smart card ?
> > > >
> > > > Thanks
> > > >
> > > >
> > >
> > >
> >
> >
>
>