views:

296

answers:

2

What is the C# equivalent to this CryptExportKey call?

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

and it would be nice if you can give a description on your C# code where

hKey, hPublicKey and SIMPLEBLOB (or their equivalent in C#) are being used

A: 

This is what I use?

    using System.Security.Cryptography;
    using System.Security.Cryptography.Xml;

    // retrieve from named keystore
    private void btnRetrieve_Click(object sender, RoutedEventArgs e)
    {
        string keyContainer = this.tbContainerName.Text;

        CspParameters parms = new CspParameters(1);
        parms.Flags = CspProviderFlags.UseMachineKeyStore;
        parms.KeyContainerName = keyContainer;
        parms.KeyNumber = 2;
        RSACryptoServiceProvider RsaCsp = new RSACryptoServiceProvider(parms);

        tbPubKeyBlob.Text = RsaCsp.ToXmlString(false);
    }

    // generate key pair
    private void btnCreateKeypair_Click(object sender, RoutedEventArgs e)
    {
        int keySize = 0;
        if (!System.Int32.TryParse(this.tbKeySize.Text, out keySize))
            keySize = 1024;
        byte[] key = Keys.GenerateKeyPair(keySize);

        RSACryptoServiceProvider RsaCsp = new RSACryptoServiceProvider();
        RsaCsp.ImportCspBlob(key);

        tbPubKeyBlob.Text = RsaCsp.ToXmlString(false);

    }
Cheeso
A: 

I think your best bet is handling it manually.

The SIMPLEBLOB format is

BLOBHEADER blobheader;
ALG_ID algid;
BYTE encryptedkey[rsapubkey.bitlen/8];

where BLOBHEADER is

BYTE   bType;
BYTE   bVersion;
WORD   reserved;
ALG_ID aiKeyAlg;

so something like this should do it (sorry, not tested):

public byte[] CryptExportKey(SymmetricAlgorithm key, RSA publicKey){
  using(MemoryStream ms = new MemoryStream())
  using(BinaryWriter w = new BinaryWriter(w)){
    w.Write((byte) 0x01); // SIMPLEBLOB
    w.Write((byte) 0x02); // Version 2
    w.Write((byte) 0x00); // Reserved
    w.Write((byte) 0x00); // Reserved
    if(key is Rijndael){
      w.Write(0x00006611);  // ALG_ID for the encrypted key.
    }else if (key is TripleDES && key.KeySizeValue == 192){
      w.Write(0x00006603);  // ALG_ID for the encrypted key.
    }else{
      throw new NotSupportedException("Look the value up on http://msdn.microsoft.com/en-us/library/aa375549%28VS.85%29.aspx");
    }
    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();
  }
}
Rasmus Faber