title: Crypto API <-> .NET RSA interoperability
body: <p>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. </p>
  
  <p>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.</p>
  
  <p>Key is generated using</p>
  
  <pre><code>CryptGenKey(hProv, CALG_RC4, KEY_LENGTH | CRYPT_EXPORTABLE, &amp;hKey);
  </code></pre>
  
  <p>It is exported into the file system using</p>
  
  <pre><code>CryptExportKey(hKey, 0, OPAQUEKEYBLOB, 0, lpBuffer, &amp;nSize);
  </code></pre>
  
  <p>(note I was able to export the the plain text key using this article 
  <a href="http://www.codeproject.com/KB/security/plaintextsessionkey.aspx" rel="nofollow noreferrer">http://www.codeproject.com/KB/security/plaintextsessionkey.aspx</a>)</p>
  
  <p>Client public key is created using </p>
  
  <pre><code>CryptGetUserKey(hProv, AT_KEYEXCHANGE, &amp;hKeyPair);
  </code></pre>
  
  <p>Client public key is exported using</p>
  
  <pre><code>CryptExportKey(hKeyPair, 0, PUBLICKEYBLOB, 0, lpData, &amp;nSize);
  </code></pre>
  
  <p>Session Key is created at the server side using</p>
  
  <ol>
  <li><p>client public key is imported using </p>
  
  <p>CryptImportKey(hProv, lpData, nSize, NULL, 0, &amp;hPublicKey</p></li>
  <li><p>Session Key is generated by encryting the RC4 using the client public key to generate a SIMPLEBLOB format</p>
  
  <p>CryptExportKey(hKey, hPublicKey, SIMPLEBLOB, 0, lpData, &amp;nSize);</p></li>
  </ol>
  
  <p>Now my requirement is to have the above steps (step 1 &amp; 2) in a managed version and here is what i am doing :</p>
  
  <p>//Read the plain text key data that was extracted using the code project article
      byte[] keyMaterial = File.ReadAllBytes(@"C:\keyMaterial.txt"); </p>
  
  <p>// Import the client public key</p>
  
  <pre><code>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();  
              }
          }
  </code></pre>
  
  <p>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?</p>