tags:

views:

760

answers:

0

I have a unmanaged application that is generates an RC4 encryption key using Crypto API. This unmanaged application encrypts some data using this RC4 key. There is also a client side unmanaged application that uses this RC4 key to decrypt information.

However, for this client app we're sending a session key -> the RC4 key encrytped using an RSA public key that was generated at the client side(SIMPLEBLOB). The generation of the encrypted session key used to be done using unmanaged code but now that has to be converted to C# because there is a requirement to run this code from a web application under partial trust.

Key is generated using

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

It is exported into the file system using

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

(note I was able to export the the plain text key using this article http://www.codeproject.com/KB/security/plaintextsessionkey.aspx)

Client public key is created using

CryptGetUserKey(hProv, AT_KEYEXCHANGE, &hKeyPair);

Client public key is exported using

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

Session Key is created at the server side using

  1. client public key is imported using

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

  2. Session Key is generated by encryting the RC4 using the client public key to generate a SIMPLEBLOB format

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

Now my requirement is to have the above steps (step 1 & 2) in a managed version and here is what i am doing :

//Read the plain text key data that was extracted using the code project article byte[] keyMaterial = File.ReadAllBytes(@"C:\keyMaterial.txt");

// Import the client public key

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

This generates the same size of data as its unmanaged version but it doesn't generate the correct SIMPLEBLOB session key as when diong step 1 and 2 of the unmanaged version. What am I doing wrong in this code?