Crypto API ‹-› Совместимость с .NET RSA

У меня есть неуправляемое приложение, которое генерирует ключ шифрования 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 неуправляемой версии. Что я делаю неправильно в этом коде?


person Community    schedule 29.03.2009    source источник


Ответы (1)


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

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

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

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

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

person BillJam    schedule 08.12.2010