tags:

views:

536

answers:

3

Hi all,
I'm trying to decrypt a file in unmanaged C++ that was previously encrypted with C# TripleDESCryptoServiceProvider. Unfortunately I do not have a clue how to do that with the Microsoft Crypt API (advapi32.lib). Here is the C# code that I use to encrypt the data:

private static void EncryptData(MemoryStream streamToEncrypt)
    {
        // initialize the encryption algorithm
        TripleDES algorithm = new TripleDESCryptoServiceProvider();

        byte[] desIV = new byte[8];
        byte[] desKey = new byte[16];

        for (int i = 0; i < 8; ++i)
        {
            desIV[i] = (byte)i;
        }

        for (int j = 0; j < 16; ++j)
        {
            desKey[j] = (byte)j;
        }

        FileStream outputStream = new FileStream(TheCryptedSettingsFilePath, FileMode.OpenOrCreate, FileAccess.Write);
        outputStream.SetLength(0);

        CryptoStream encStream = new CryptoStream(outputStream, algorithm.CreateEncryptor(desKey, desIV),
            CryptoStreamMode.Write);

        // write the encrypted data to the file
        encStream.Write(streamToEncrypt.ToArray(), 0, (int)streamToEncrypt.Length);

        encStream.Close();
        outputStream.Close();
    }

As you can see the Key and the IV is quite simple (just for testing purpose). So my question is, how do I decrypt that file in C++? I know that the TripleDESCryptoServiceProvider is just a wrapper for the Crypt API, so it cannot be that difficult to solve this problem.
Does anyone ever did something like that and can help me?
Thx Simon

+2  A: 

Unfortunately unmanaged CAPI (advapi32.lib) requires allot more code than what can be done with the System.Security.Cryptography namespace. MSDN has a CAPI example called “Decrypting a File” that shows all the steps and calls needed to achieve what you’re trying to do in your test app. It could be a good launching point for you. Sorry for not posting usable code to play with but when you take a look at the example code you’ll see why.

Mathew Leger
That is exactly what the problem is... It's a lot of code and it's hard to understand because the example uses another algorithm. So any code snippet that covers my problem would be helpful.
Simon Linder
A: 

If you cant use the .net runtimes in C++ a quick google search turned up this crypto library for C++ from my first glanceover it is not platform dependent so you could run this without needing to call advapi32.lib

Scott Chamberlain
Ok, I also tried that library with no success, here's some code:...// read filefread(buf, len, 1, fp);...BYTE pIV[] = {0,1,2,3,4,5,6,7};BYTE pKey[] = {0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15};const BYTE* lpData = (const BYTE*)(LPCTSTR)buf;size_t bufferSize = strlen(buf);BYTE* result = (BYTE *)malloc(bufferSize);CFB_FIPS_Mode<DES_EDE2>::Decryption decryption_DES_EDE2_CFB;decryption_DES_EDE2_CFB.SetKeyWithIV(pKey, sizeof(pKey), pIV, sizeof(pIV));decryption_DES_EDE2_CFB.ProcessString(result, lpData, bufferSize);
Simon Linder
+2  A: 

Once you get in the groove of things, CryptoAPI is relatively straightforward to use. The problem is doing it in a way that is compatible with other cryptography libraries (including .NET framework). I have successfully done this before, but it has been a while; the major sticking point is figuring out how to convert a plain text key into a format usable with CryptoAPI (which operates with "key blobs"). Luckily Microsoft has given us a working, if tedious, example. As for the CryptoAPI way of doing things, here is an example:

// 1. acquire a provider context.
// the Microsoft Enhanced provider offers the Triple DES algorithm.
HCRYPTPROV hProv = NULL;
if(CryptAcquireContext(&hProv, NULL, MS_ENHANCED_PROV, PROV_RSA_FULL, CRYPT_VERIFYCONTEXT))
{
    // 2. generate the key; see Microsoft KB link above on how to do this.
    HKEY hKey = NULL;
    if(ImportPlainTextSessionKey(hProv, lpKeyData, cbKeyData, CALG_3DES, &hKey))
    {
        // 3. set the IV.
        if(CryptSetKeyParam(hKey, KP_IV, lpIVData, 0))
        {
            // 4. read the encrypted data from the source file.
            DWORD cbRead = 0;
            while(ReadFile(hSourceFile, buffer, 8192, &cbRead, NULL) && cbRead)
            {
                // 5. decrypt the data (in-place).
                BOOL bFinal = cbRead < 8192 ? TRUE : FALSE;
                DWORD cbDecrypted = 0;
                if(CryptDecrypt(hKey, NULL, bFinal, 0, buffer, &cbDecrypted))
                {
                    // 6. write the decrypted data to the destination file.
                    DWORD cbWritten = 0;
                    WriteFile(hDestFile, buffer, cbDecrypted, &cbWritten, NULL);
                }
            }
        }
        CryptDestroyKey(hKey);
        hKey = NULL;
    }
    CryptReleaseContext(hProv, 0);
    hProv = NULL;
}
Luke
Thank you very much! Your code did the trick. I had only to combine the code from the link to the method ImportPlainTextSessionKey and everything worked.
Simon Linder