Крипто API <-> .NET RSA совместимость - PullRequest
0 голосов
/ 29 марта 2009

У меня есть неуправляемое приложение, которое генерирует ключ шифрования RC4 с использованием Crypto API. Это неуправляемое приложение шифрует некоторые данные с помощью этого ключа RC4. Существует также неуправляемое приложение на стороне клиента, которое использует этот ключ RC4 для расшифровки информации.

Однако для этого клиентского приложения мы отправляем сеансовый ключ -> ключ RC4, зашифрованный с использованием открытого ключа RSA, сгенерированного на стороне клиента (SIMPLEBLOB). Раньше генерация зашифрованного ключа сеанса выполнялась с использованием неуправляемого кода, но теперь его необходимо преобразовать в C #, поскольку существует требование для запуска этого кода из веб-приложения с частичным доверием.

Ключ генерируется с помощью

CryptGenKey(hProv, CALG_RC4, KEY_LENGTH | CRYPT_EXPORTABLE, &hKey);

Экспортируется в файловую систему с помощью

CryptExportKey(hKey, 0, OPAQUEKEYBLOB, 0, lpBuffer, &nSize);

(обратите внимание, я смог экспортировать простой текстовый ключ, используя эту статью http://www.codeproject.com/KB/security/plaintextsessionkey.aspx)

Открытый ключ клиента создается с использованием

CryptGetUserKey(hProv, AT_KEYEXCHANGE, &hKeyPair);

Открытый ключ клиента экспортируется с использованием

CryptExportKey(hKeyPair, 0, PUBLICKEYBLOB, 0, lpData, &nSize);

Ключ сеанса создается на стороне сервера с использованием

  1. открытый ключ клиента импортируется с использованием

    CryptImportKey (hProv, lpData, nSize, NULL, 0 и hPublicKey

  2. Ключ сеанса генерируется путем шифрования RC4 с использованием открытого ключа клиента для генерации формата SIMPLEBLOB

    CryptExportKey (hKey, hPublicKey, SIMPLEBLOB, 0, lpData, & nSize);

Теперь мое требование состоит в том, чтобы описанные выше шаги (шаги 1 и 2) были в управляемой версии, и вот что я делаю:

// Прочитать данные ключа в виде простого текста, которые были извлечены с использованием статьи проекта кода byte [] keyMaterial = File.ReadAllBytes (@ "C: \ keyMaterial.txt");

// Импортировать открытый ключ клиента

CspParameters cspParams = new CspParameters();
            cspParams.KeyContainerName = "Container Name";
            cspParams.KeyNumber = (int)KeyNumber.Exchange;
            cspParams.ProviderType = 1;
            cspParams.ProviderName = "Microsoft Enhanced Cryptographic Provider v1.0";
            cspParams.Flags = CspProviderFlags.UseMachineKeyStore;

            RSACryptoServiceProvider rsaClient = new RSACryptoServiceProvider(cspParams);   
            rsaClient.ImportCspBlob(File.ReadAllBytes(@"C:\client.key"));

//Generate a SIMPLEBLOB session key
byte[] session = GetRC4SessionBlobFromKey(keyMaterial, rsaClient);



//Encrypt a key using public key and write it in a SIMPLEBLOB format
public byte[] GetRC4SessionBlobFromKey(byte[] keyData, RSACryptoServiceProvider publicKey)
        {  
            using(MemoryStream ms = new MemoryStream())  
            using(BinaryWriter w = new BinaryWriter(ms))
            {   
                w.Write((byte) 0x01); // SIMPLEBLOB    
                w.Write((byte) 0x02); // Version 2    
                w.Write((byte) 0x00); // Reserved    
                w.Write((byte) 0x00); // Reserved    
                w.Write(0x00006801);  // ALG_ID = RC4 for the encrypted key.
                w.Write(0x0000a400);  // CALG_RSA_KEYX    

                w.Write(publicKey.Encrypt(keyData, false));
                w.Flush();

                return ms.ToArray();  
            }
        }

Это генерирует тот же размер данных, что и его неуправляемая версия, но не генерирует правильный ключ сеанса SIMPLEBLOB, как при выполнении шага 1 и 2 неуправляемой версии. Что я делаю не так в этом коде?

1 Ответ

1 голос
/ 08 декабря 2010

Я здесь новичок, но я только что прочитал в документации MSDN следующее:

Взаимодействие с Microsoft Cryptographic API (CAPI)

В отличие от реализации RSA в неуправляемом CAPI, класс RSACryptoServiceProvider меняет порядок зашифрованного массива байтов после шифрования и перед расшифровкой. По умолчанию данные, зашифрованные классом RSACryptoServiceProvider, не могут быть расшифрованы функцией CAPI CryptDecrypt, а данные, зашифрованные методом CAPI CryptEncrypt, не могут быть расшифрованы классом RSACryptoServiceProvider.

Если вы не компенсируете обратное упорядочение при взаимодействии между API, класс RSACryptoServiceProvider генерирует исключение CryptographicException.

Может ли это быть проблемой?

...