Доступ к магазину X509 в Silverlight

1

В настоящее время я разрабатываю приложение Silverlight для доступа к X509Store для подписывания данных с помощью закрытого ключа, встроенного в токен безопасности USB.

Я начал с приложения С#, которое работает следующим образом:

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());
    }
}

Этот метод отлично работает в приложении С#. Но когда я пытаюсь адаптировать его к Silverlight, X509Store, похоже, не реализован.

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

Я попытался применить DLL.NET Framework, но получил следующую ошибку:

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? Или есть лучшее средство для выполнения того, что я хочу сделать?

Заранее спасибо.

  • 0
    В приложении SL нет «текущего пользовательского хранилища», и сообщения об ошибках подтверждают это. Вам нужно найти способ конвертировать <code> string Cert_To_Use_b64 </ code> в <code> Certificate </ code>.
  • 0
    PS. Если MS не поддерживает его в SL, на bouncycastle.org/csharp есть криптоманьяки надувных замков
Показать ещё 8 комментариев
Теги:
silverlight
x509

1 ответ

3
Лучший ответ

Существует два возможных способа сделать то, что вы хотите:


CryptoAPI через P/Invoke

Мой кулак предполагал использовать собственную библиотеку Windows crypt32.dll (обычно называемую CryptoApi). Ведь System.Security.dll - это всего лишь управляемая оболочка (просмотр декомпилированного источника с помощью инструмента, такого как ILSpy, покажет вам, как MS его обертывает). Вы можете использовать его в Silverlight с P/Invoke при запуске с повышенным доверием (Properties → 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 в Silverlight. Я еще не тестировал его. Потенциальная проблема может заключаться в том, что шифрование конечной защиты.NET встроено глубоко в mscorlib и System.Security, и может быть не так просто преобразовать эти библиотеки (или даже вообще невозможно).

  • 0
    Спасибо за исчерпывающий и полезный ответ. Это действительно поможет моим будущим разработкам.

Ещё вопросы

Сообщество Overcoder
Наверх
Меню