Question

The simple blob that is generated using

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

does not match the one generated from the following code (note that client.key is the plain text key value of hKey found using http://www.codeproject.com/KB/security/plaintextsessionkey.aspx )

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

Why is that?

Was it helpful?

Solution

  1. The code in my original answer was not correct. You have to reverse the encrypted bytes. I have updated the answer to fix that problem.

  2. The code above is missing a "w.Write((byte) 0x00); // Reserved". It was not a mistake that my original answer had that line repeated.

  3. RSA PKCS#1 encryption (which is used inside the SIMPLEBLOB) is not deterministic. I.E. You will not get the same result by encrypting the same data twice.

So to sum up: Change the code above to:

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                    
    byte[] encryptedKey = publicKey.Encrypt(key.Key);
    byte[] reversedEncryptedKey = new byte[encryptedKey.Length];
    for(int i=0;i<encryptedKey.Length;i++){
      reversedEncryptedKey[i] = encryptedKey[encryptedKey.Length - 1 - i];
    }
    w.Write(reversedEncryptedKey); // encrypted key in LSB byte order

    w.Flush();                

    return ms.ToArray();              
  }        
}

and then check that it works by using CryptImportKey() to import the SIMPLEBLOB instead of trying to compare the result with CryptExportKey().

OTHER TIPS

I am unable to edit my own quesiton and therefore I am putting the content that you wanted me to attach here in this answer, I have screen capture of the images from the binary editor /immediate window in visual studio below

CryptExportKey - SIMPLEBLOB

CryptExportKey - SIMPLEBLOB http://img14.imageshack.us/img14/1926/cryptoexportkeysimplebl.jpg

KeyMaterial value in Debug Window

Key Material value in debug window http://img19.imageshack.us/img19/4138/keymaterialdebugwindow.jpg

Key Material value that is saved in file using the code project article

Key Material value that is saved in file using the code project article http://img243.imageshack.us/img243/7936/keymaterialfile.jpg

Session key value from GetRC4SessionBlobFromKey() (integer value of individual bytes separated by a comma)

Session key value from GetRC4SessionBlobFromKey http://img206.imageshack.us/img206/5620/sessionvaluefromgetrc4s.jpg

Thank you very much for looking into this and please let me know if there is any further info I can provide.

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top