在Silverlight中访问X509Store

时间:2014-09-11 12:43:05

标签: c# silverlight x509

我目前正在开发一个Silverlight应用程序,以便访问X509Store,使用嵌入USB安全令牌中的私钥对数据进行签名。

我从一个以这种方式工作的C#应用​​程序开始:

public byte[] SignData(byte[] HashTosign, string Cert_To_Use_b64)
{
    byte[] Signature = null;

    X509Store store = new X509Store(StoreName.My, StoreLocation.CurrentUser);
    store.Open(OpenFlags.ReadOnly | OpenFlags.OpenExistingOnly);
    X509Certificate2Collection collection = (X509Certificate2Collection)store.Certificates;
    store.Close();

    try {
        foreach (X509Certificate2 Certificate in collection) {

            if (ToBase64(Certificate.RawData) == Cert_To_Use_b64) {

                RSACryptoServiceProvider Rsa = new RSACryptoServiceProvider();
                Rsa = (RSACryptoServiceProvider)Certificate.PrivateKey;

                try {
                    RSACryptoServiceProvider aesRsa = new RSACryptoServiceProvider();
                    string strPk = Certificate.PrivateKey.ToXmlString(true);
                    aesRsa.FromXmlString(strPk);
                    Signature = aesRsa.SignHash(HashTosign, CryptoConfig.MapNameToOID("SHA256"));


                } catch (Exception ex) {
                    Throw new exception("FAILURE : " + ex.Message());
                }


                lgSignature = Signature.Length;
                return 0;
            }
        }
    } catch (CryptographicException ex) {
        Throw new exception("FAILURE : " + ex.Message());
    } catch (Exception ex) {
        Throw new exception("FAILURE : " + ex.Message());
    }
}

该方法在C#应用程序中运行良好。但是当我尝试将其改编为Silverlight时,X509Store似乎没有实现。

The name “X509Store” does not exist in the namespace System.Security.Cryptography. Are you missing an assembly reference?

我尝试应用.NET Framework DLL但出现以下错误:

It is not possible to add a reference to System.Security.dll because it was not created with the Silverlight runtime. Silverlight projects only work with Silverlight assemblies.

我可以将System.Security.dll程序集重新创建到Silverlight吗?或者有更好的方法来做我想做的事情吗?

提前致谢。

1 个答案:

答案 0 :(得分:3)

有两种方法可以做你想做的事:


通过P / Invoke

CryptoAPI

我的第一个猜测是使用本机Windows库crypt32.dll(通常称为CryptoApi)。毕竟System.Security.dll只是一个托管包装器(使用像ILSpy这样的工具浏览反编译源将向您展示MS如何包装它)。当您在提升信任(属性 - > Silverlight - >需要提升信任)和管理员权限(能够打开证书存储区)中运行时,您可以在带有P / Invoke的Silverlight中使用它。然而,有几个缺点:

  • 这是非常不友好的(让我回到旧的好的C / C ++日)
  • 您需要在低级系统结构和操作(如指针)上运行
  • 您需要将此样式用于证书检索和签名计算

文档参考:

这样我就设法获得了在我的智能卡上注册的证书的句柄(IntPtr指针):

using System;
using System.Runtime.InteropServices;

namespace SilverlightX509Store
{
    public static class CapiNative
    {
        public const string MY = "MY";
        public const uint PKCS_7_ASN_ENCODING = 0x00010000;
        public const uint X509_ASN_ENCODING = 0x00000001;
        public const uint CERT_FIND_SUBJECT_STR = 0x00080007;
        public const int ACCESS_DENIED = 5;

        [DllImport("crypt32.dll", CharSet = CharSet.Auto, SetLastError = true)]
        public static extern IntPtr CertOpenSystemStore(
            IntPtr hCryptProv,
            string storename);

        [DllImport("crypt32.dll", SetLastError = true)]
        public static extern IntPtr CertFindCertificateInStore(
            IntPtr hCertStore,
            uint dwCertEncodingType,
            uint dwFindFlags,
            uint dwFindType,
            [In, MarshalAs(UnmanagedType.LPWStr)]String pszFindString,
            IntPtr pPrevCertCntxt);
    }

    public class CapiWrapper
    {
        public IntPtr FindCert(string subject)
        {
            IntPtr storeHandle = CapiNative.CertOpenSystemStore(
                IntPtr.Zero, 
                CapiNative.MY);

            if (Marshal.GetLastWin32Error() == CapiNative.ACCESS_DENIED)
            {
                return IntPtr.Zero;
            }

            IntPtr certHandle = CapiNative.CertFindCertificateInStore(
                storeHandle,
                CapiNative.PKCS_7_ASN_ENCODING | CapiNative.X509_ASN_ENCODING,
                0,
                CapiNative.CERT_FIND_SUBJECT_STR,
                "subject to find",
                IntPtr.Zero);

            return certHandle;
        }
    }
}

将.NET dll转换为符合Silverlight的

似乎有一种方法可以将.NET库转换为SL。见文章Reusing .NET Assemblies in Silverlight。 我还没有测试过它。潜在的问题可能是.NET安全端加密深入到mscorlib和System.Security中,转换这些库可能并不那么容易(甚至根本不可能)。