在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吗?或者有更好的方法来做我想做的事吗?
提前谢谢。
有两种可能的方法可以实现您想要的功能:
通过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中内置的,转换这些库可能不那么容易(甚至根本不可能)。