Re: .NET Crypto Classes Interoperability with Win32 Crypto APIs

From: Rajesh Sampath (rajeshs_at_ctd.hcltech.com)
Date: 07/08/03


Date: Tue, 8 Jul 2003 02:19:12 -0700


Ivan,
 Thank you so much. That really did the trick!!
Thanks and Regards
Rajesh Sampath

>-----Original Message-----
>Rajesh -
>the problem is that the key you are using in the managed
code is different
>from what you are using in the C++ implementation. When
you are calling
>UnicodeEncoding.GetBytes all it does is giving you the
bytes representing
>the characters you are feeding into it. In the C++ code
you are using
>CryptDeriveKey which derives the key by doing complex
processing based on
>the hash of the string you are feeding in. To fix this
problem in managed
>code you can use class PasswordDeriveBytes and its method
called
>CryptDeriveKey to get the functionality matching that of
the unmanaged code.
>Hope this helps.
>--Ivan
>This posting is provided "AS IS" with no warranties, and
confers no rights.
>
>
>"Rajesh Sampath" <rajeshs@ctd.hcltech.com> wrote in
message
>news:22a001c33f02$0fc9e540$a601280a@phx.gbl...
>> Hi,
>>
>> I don't know if this is the right forum to post this
>> query, but any help will be greatly appreciated.
>>
>> I use the RC2CryptoServiceProvider class to perform a
>> symmetric encryption with a hard-coded key value. I
expect
>> a string to be encrypted by a .NET application in this
>> manner and the same shall be decrypted by a C++ (Win32)
>> application using the same algorithm, but using Win32
>> APIs.
>>
>> The following scenarios work fine.
>>
>> 1. Encryption and Decryption with .NET
>> RC2CryptoServiceProvider class (or any other managed
>> crypto class, for that matter) works fine.
>>
>> 2. Encryption and Decryption with Win32 APIs with
CALG_RC2
>> algorithm works fine too.
>>
>> But, when i encrypt a string using .NET classes and try
to
>> decrypt it using Win32 APIs, i get some problems. The
same
>> holds good for Win32 Encryption & .NET decryption too.
>>
>> I've pasted the source i had used for your reference.
>>
>> C# code
>>
>> /**********************************************/
>> using System;
>> using System.IO;
>> using System.Security.Cryptography;
>> using System.Text;
>> using System.Resources;
>> using System.Collections;
>>
>> namespace MySampleCryptoApp
>> {
>> /// <summary>
>> /// Summary description for Class1.
>> /// </summary>
>> class Class1
>> {
>> [STAThread]
>> static void Main(string[] args)
>> {
>> Encrypt();
>> Decrypt();
>> }
>>
>> private static void Encrypt()
>> {
>> RC2CryptoServiceProvider RCCrypto
>> = new RC2CryptoServiceProvider();
>> RCCrypto.Mode = CipherMode.CBC;
>> RCCrypto.KeySize = 40;
>> RCCrypto.EffectiveKeySize = 40;
>> RCCrypto.BlockSize = 64;
>>
>> UnicodeEncoding UE = new
>> UnicodeEncoding();
>> byte[] Key = UE.GetBytes
>> ("abcdefgh");
>>
>> byte[] IV = {0x00, 0x00,0x00,
>> 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00,
>> 0x00,0x00, 0x00};
>>
>>
>> FileStream oFStream = new
>> FileStream
>>
(@"E:\Users\SRajesh\Tekies\RnD\DotNet\SampleCryptoApp\Outpu
>> t.txt", FileMode.OpenOrCreate, FileAccess.Write);
>>
>> //Create a CryptoStream, pass it
>> the NetworkStream, and encrypt
>> //it with the RC2Crypto class.
>> CryptoStream CryptStream = new
>> CryptoStream(oFStream,
>> RCCrypto.CreateEncryptor
>> (Key, IV),
>> CryptoStreamMode.Write);
>>
>>
>> //Create a StreamWriter for easy
>> writing to the
>> //file stream.
>> StreamWriter SWriter = new
>> StreamWriter(CryptStream);
>>
>> long lLength = oFStream.Length;
>> //Write to the stream.
>> SWriter.WriteLine("How is it???");
>>
>> //Inform the user that the message
>> was written
>> //to the stream.
>> Console.WriteLine("The message was
>> sent.");
>>
>> //Close all of the connections.
>> SWriter.Close();
>> CryptStream.Close();
>> oFStream.Close();
>>
>> }
>>
>> private static void Decrypt()
>> {
>> UnicodeEncoding UE = new
>> UnicodeEncoding();
>> byte[] Key = UE.GetBytes
>> ("abcdefgh");
>>
>> byte[] IV = {0x00, 0x00,0x00,
>> 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00,
>> 0x00,0x00, 0x00};
>>
>> FileStream oFStream = new
>> FileStream
>>
(@"E:\Users\SRajesh\Tekies\RnD\DotNet\SampleCryptoApp\Outpu
>> t.txt", FileMode.Open, FileAccess.Read);
>>
>> //Create a new instance of the
>> RC2Crypto class
>> // and decrypt the stream.
>>
>> RC2CryptoServiceProvider RCCrypto
>> = new RC2CryptoServiceProvider();
>> RCCrypto.Mode = CipherMode.CBC;
>> RCCrypto.KeySize = 40;
>> RCCrypto.EffectiveKeySize = 40;
>> RCCrypto.BlockSize = 64;
>>
>> //Create a CryptoStream, pass it
>> the NetworkStream, and decrypt
>> //it with the Rijndael class using
>> key and IV.
>> CryptoStream CryptStream = new
>> CryptoStream(oFStream,
>> RCCrypto.CreateDecryptor
>> (Key, IV),
>> CryptoStreamMode.Read);
>>
>> //Read the stream.
>> StreamReader SReader = new
>> StreamReader(CryptStream);
>>
>> //Display the message.
>> Console.WriteLine("The decrypted
>> original message: {0}", SReader.ReadToEnd());
>>
>> //Close the streams.
>> CryptStream.Close();
>> SReader.Close();
>> oFStream.Close();
>>
>>
>> }
>> }
>> }
>> /**********************************************/
>>
>> Here is the C++ Win32 code
>>
>> /**********************************************/
>>
>> // SampleCryptoNativeApp.cpp : Defines the entry point
for
>> the console application.
>> //
>>
>>
>> #include "stdafx.h"
>> #include "windows.h"
>> #include <wincrypt.h>
>> #include <TCHAR.h>
>>
>> int main(int argc, char* argv[])
>> {
>>
>> BOOL bResult;
>> HCRYPTPROV hProv;
>> HCRYPTHASH hHash;
>> HCRYPTKEY hKey;
>>
>> char pEncryptedString[100];
>> memset(pEncryptedString, 0,100);
>>
>> FILE *fp = fopen
>>
("E:\\Users\\SRajesh\\Tekies\\RnD\\DotNet\\SampleCryptoApp\
>> \Output.txt", "rb");
>> fscanf(fp, "%s", &pEncryptedString);
>> fclose(fp);
>>
>>
>> int nLen = strlen(pEncryptedString);
>>
>> BYTE *pByte = NULL;
>> pByte = new BYTE[100];
>> memset(pByte, 0, 100);
>> memcpy(pByte, pEncryptedString, nLen);
>>
>> DWORD dwError;
>>
>> bResult = CryptAcquireContext( &hProv,
>> NULL, //generates default (username)
keystore,
>> MS_ENHANCED_PROV,
>> PROV_RSA_FULL,
>> CRYPT_NEWKEYSET);
>> if(!bResult)
>> dwError = GetLastError();
>>
>>
>> bResult = CryptAcquireContext(&hProv, NULL,
>> MS_DEF_PROV, PROV_RSA_FULL, CRYPT_VERIFYCONTEXT);
>> //bResult = CryptAcquireContext(&hProv, NULL,
>> MS_ENHANCED_PROV, PROV_RSA_FULL, CRYPT_VERIFYCONTEXT);
>> if(!bResult)
>> dwError = GetLastError();
>>
>> bResult = CryptCreateHash(hProv, CALG_MD5, 0, 0,
>> &hHash);
>> if(!bResult)
>> dwError = GetLastError();
>>
>> BYTE pByteBaseData[] =
>> {97,0,98,0,99,0,100,0,101,0,102,0,103,0,104,0};
>> int nKeyLen = 16;
>>
>>
>> bResult = CryptHashData(hHash, pByteBaseData,
>> (DWORD) nKeyLen, 0);
>> if(!bResult)
>> dwError = GetLastError();
>>
>> //bResult = CryptDeriveKey(hProv, CALG_RC2, hHash,
>> CRYPT_CREATE_SALT, &hKey);
>> bResult = CryptDeriveKey(hProv, CALG_RC2, hHash,
>> CRYPT_NO_SALT, &hKey);
>> if(!bResult)
>> dwError = GetLastError();
>>
>> BYTE pByteIV[] = {0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0};
>> bResult = CryptSetKeyParam(hKey,KP_IV, pByteIV, 0);
>> if(!bResult)
>> dwError = GetLastError();
>>
>> char pToEncryptString[] = "How is it???";
>> //TCHAR pToEncryptString[] = L"How is it???";
>> BYTE *pToEncryptBuffer = new BYTE[100];
>> memset(pToEncryptBuffer, 0, 100);
>> memcpy(pToEncryptBuffer, pToEncryptString, strlen
>> (pToEncryptString));
>>
>> DWORD dwInputLen = strlen(pToEncryptString);
>> bResult = CryptEncrypt(hKey, NULL, TRUE, 0,
>> pToEncryptBuffer, &dwInputLen, 16);
>> if(!bResult)
>> dwError = GetLastError();
>>
>> fp = fopen
>>
("E:\\Users\\SRajesh\\Tekies\\RnD\\DotNet\\SampleCryptoNati
>> veApp\\Win32Output.txt", "w");
>> for(int nIndex = 0; nIndex < (int) dwInputLen;
>> nIndex++)
>> {
>> fprintf(fp, "%c", pToEncryptBuffer
>> [nIndex]);
>> }
>> fclose(fp);
>>
>> DWORD dwOutputLen = nLen;
>>
>> bResult = CryptDecrypt(hKey, NULL, TRUE, 0, pByte,
>> &dwOutputLen);
>> if(!bResult)
>> dwError = GetLastError();
>>
>> bResult = CryptDecrypt(hKey, NULL, TRUE, 0,
>> pToEncryptBuffer, &dwOutputLen);
>> if(!bResult)
>> dwError = GetLastError();
>>
>> return 0;
>> }
>>
>> /**********************************************/
>>
>> When i try to decrypt the string encrypted using .NET, i
>> get an error (2148073487).
>>
>> Any help in sorting this out would be appreciated. The
>> last option i have is to use PInvoke to call the Win32
>> APIs themselves in .NET.
>>
>> Thanx & Rgds
>> Rajesh Sampath,
>> Project Lead,
>> HCL Technologies,
>> Chennai
>>
>>
>>
***********************************************************
>> ************
>> Disclaimer:
>> This document is intended for transmission to the named
>> recipient only. If you are not that person, you should
>> note that legal rights reside in this document and you
are
>> not authorized to access, read, disclose, copy, use or
>> otherwise deal with it and any such actions are
prohibited
>> and may be unlawful. The views expressed in this
document
>> are not necessarily those of HCL Technologies Ltd.
Notice
>> is hereby given that no representation, contract or
other
>> binding obligation shall be created by this e-mail,
which
>> must be interpreted accordingly. Any representations,
>> contractual rights or obligations shall be separately
>> communicated in writing and signed in the original by a
>> duly authorized officer of the relevant company.
>>
***********************************************************
>> ************
>> .
>>
>>
>
>
>.
>



Relevant Pages

  • RE: Using Win32 CryptDecrypt to Decrypt RijndaelManaged
    ... I figured out how to use RijndaelManaged with AES in the C++ app. ... C++ crypto WILL successfully decrypt the .NET generated ... I am trying to write a Win32 app that can decrypt that string using the ... I can get both to encrypt and decrypt successfully in their own projects, ...
    (microsoft.public.platformsdk.security)
  • Re: Encrypt and Decrypt a file using .NET 2.0?
    ... public static string GenerateKey() ... DES des = DES.Create; ... // Distribute this key to the user who will decrypt this file. ... // Get the Key for the file to Encrypt. ...
    (microsoft.public.dotnet.languages.csharp)
  • Re: Encrypt and Decrypt a file using .NET 2.0?
    ... public static string GenerateKey() ... using (CryptoStream cryptoStream = new CryptoStream(outFile, ... // Distribute this key to the user who will decrypt this file. ... // Get the Key for the file to Encrypt. ...
    (microsoft.public.dotnet.languages.csharp)
  • Re: Decryptionfailed to bring original text back....
    ... cryptography, but now using them on web.config, any idea, I like to ... There isn't really much reason to encrypt a .NET string with ... what happen when you decrypt the encrypted ...
    (microsoft.public.dotnet.security)
  • RE: 2007 User Level Security
    ... encrypted string. ... the way I use it is to encrypt user names and passwords and store the ... Dim prp As Property ... Dim dbs As Object, prp As Variant ...
    (microsoft.public.access.modulesdaovba)