在Silverlight中访问X509Store

本文关键字:X509Store 访问 Silverlight | 更新日期: 2023-09-27 18:21:34

我目前正在开发一个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吗?或者有更好的方法来做我想做的事吗?

提前谢谢。

在Silverlight中访问X509Store

有两种可能的方法可以实现您想要的功能:


通过P/Invoke的CryptoAPI

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

  • 它相当不友好(让我想起了以前的C/C++好日子)
  • 您需要对低级系统结构和操作(如指针)进行操作
  • 您需要将这种样式用于证书检索和签名计算

文件参考:

  • MSDN CryptoApi

通过这种方式,我设法获得了在我的智能卡上注册的证书的句柄(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。请参阅文章在Silverlight中重用.NET程序集。我还没有测试过。潜在的问题可能是.NET安全端加密是在mscorlib和System.security中内置的,转换这些库可能不那么容易(甚至根本不可能)。