0

I have the following code in Delphi XE2 to Encrypt and Decrypt a String.

What is wrong is that I get different encrypt Results ? I need to read and write some string in both languages Delphi and C++, and I do not want use a DLL writing in Delphi to do It in C++

function CryptString(Const  Input: string; password : AnsiString;  Encrypt: Boolean) : string;
const
  BufferSize=1024*1024;
var
  StreamSource  : TStringStream;
  StreamDest    : TStringStream;
  CRYPTPROV     : HCRYPTPROV;
  CRYPTHASH     : HCRYPTHASH;
  CRYPTKEY      : HCRYPTKEY;
  Buffer        : LPBYTE;
  BytesIn       : DWORD;
  Final         : Boolean;

  Encoder     : TIdEncoderMIME;
  Decoder     : TIdDecoderMIME;
  DestStream  : TStringStream;
begin
  CryptAcquireContext(CRYPTPROV, nil, MS_DEF_DH_SCHANNEL_PROV, PROV_RSA_FULL, CRYPT_VERIFYCONTEXT);
  try
      //create a valid key  based in the password
      if not CryptCreateHash(CRYPTPROV, CALG_SHA1, 0, 0, CRYPTHASH) then RaiseLastOSError;
      try
        if not CryptHashData(CRYPTHASH, @Password[1], Length(Password), 0) then RaiseLastOSError;
        if not CryptDeriveKey(CRYPTPROV,  CALG_RC4, CRYPTHASH, 0, CRYPTKEY)  then RaiseLastOSError;
      finally
        CryptDestroyHash(CRYPTHASH);
      end;

      StreamSource          := TStringStream.Create(Input);
      StreamSource.Position := 0;
      StreamDest            := TStringStream.Create;
      try
        GetMem(Buffer, BufferSize);
        try

          if not Encrypt then
          begin
            //decode the string using base64
            Decoder := TIdDecoderMIME.Create(nil);
            try
              DestStream := TStringStream.Create;
              try
                StreamDest.Position:=0;
                Decoder.DecodeBegin(DestStream);
                Decoder.Decode(StreamSource);
                Decoder.DecodeEnd;
                StreamSource.Clear;
                DestStream.Position:=0;
                StreamSource.CopyFrom(DestStream,DestStream.Size);
                StreamSource.Position:=0;
              finally
                FreeAndNil( DestStream);
              end;
            finally
             FreeAndNil(  Decoder);
            end;

          end;


            repeat
              BytesIn   := StreamSource.Read(Buffer^, BufferSize);
              Final     := (StreamSource.Position >= StreamSource.Size);
              if Encrypt then  begin
               if not CryptEncrypt(CRYPTKEY, 0, Final, 0, Buffer, BytesIn, BytesIn) then
                  RaiseLastOSError;
              end
              else if not CryptDecrypt(CRYPTKEY, 0, Final, 0, Buffer, BytesIn) then
                    RaiseLastOSError;

              StreamDest.Write(Buffer^, BytesIn);
            until Final;


          //encode the string using base64
          if Encrypt then
          begin
            Encoder := TIdEncoderMIME.Create(nil);
            try
              DestStream:=TStringStream.Create;
              try
                StreamDest.Position:=0;
                Encoder.Encode(StreamDest,DestStream);
                Result := DestStream.DataString;
              finally
               FreeAndNil( DestStream);
              end;
            finally
               FreeAndNil(Encoder);
            end;
          end
          else
          Result:= StreamDest.DataString;


        finally
         FreeMem(Buffer, BufferSize);
        end;

      finally
       FreeAndNil( StreamSource);
       FreeAndNil( StreamDest);
      end;
  finally
    CryptReleaseContext(CRYPTPROV, 0);
  end;
end;

I found the following code in C++ to make the same thing, but the encryption results are different.

int main()
{
    const char* passw = "teste";
    const char* toencrypt = "sa";


    HCRYPTPROV hProv;
    HCRYPTHASH hHash;
    HCRYPTKEY hKey;
    DWORD todwSize = (DWORD)strlen(toencrypt);
    PBYTE pBuffer;

    CryptAcquireContext(&hProv, NULL, NULL , PROV_RSA_FULL, CRYPT_VERIFYCONTEXT);

    CryptCreateHash(hProv, CALG_SHA1 , 0, 0, &hHash);
    CryptHashData(hHash, (BYTE*)passw, strlen(passw), 0);
    CryptDeriveKey(hProv, CALG_RC4, hHash, 0, &hKey);
    CryptDestroyHash(hHash);
    //--------------------------------------------------------------------

    pBuffer = (BYTE *)malloc(todwSize);
    strcpy((char*)pBuffer, toencrypt);

    CryptEncrypt(hKey, 0, TRUE, 0, pBuffer, &todwSize, todwSize);
    PBYTE pBreturn = pBuffer;
    const char* message = (const char*)pBreturn;
    printf("%s", message);
    system("pause");

    //--------------------------------------------------------------------

    DWORD dwSize = (DWORD)strlen(message);
    PBYTE depBuffer;


    depBuffer = (BYTE *)malloc(1460);
    strcpy((char*)depBuffer, message);



    CryptDecrypt(hKey, 0, TRUE, 0, depBuffer, &dwSize);



    CryptDestroyKey(hKey);
    CryptDestroyHash(hHash);

    CryptReleaseContext(hProv, 0);
    if (GetLastError() != 0)
    {
        printf("%d", GetLastError());
    }
    PBYTE depBreturn = depBuffer;
    printf("%s", (const char*)depBreturn);
    printf("\n%d", strlen(message));
    return 0;
}
Nasreddine Galfout
  • 2,550
  • 2
  • 18
  • 36
  • 3
    Unrelated: Congratulations on a question that deserves two language tags. There should be a badge for this. – user4581301 Nov 03 '17 at 22:40
  • Strongly recommend wrapping the Delphi code into a compilable program to fight off No MCVE down and close votes. – user4581301 Nov 03 '17 at 22:42
  • 1
    The encrypted data is not a C-style string, so trying to `printf` it with `%s` or passing it to `strlen` makes no sense. Did you read the docs for `CryptEncrypt` -- particularly where it tells you how to determine the length of the ciphertext? – David Schwartz Nov 03 '17 at 22:43
  • I'm noob in c++ you can be more specific ? – Rodrigo Zimmermann Nov 03 '17 at 22:53
  • 1
    Wow, what horrible Delphi code to read, it's all error recovery and that is hiding the work code. – zaph Nov 03 '17 at 23:14
  • @Rodrigo: David tells you to read the docs for `CryptEncrypt` to see how to determine the length of the ciphertext. That is pretty specific. – Rudy Velthuis Nov 04 '17 at 07:44
  • In XE2, `Input` is a `UnicodeString`, while in the C++ code, a single-byte string is encoded. **Different inputs cause different outputs**. And the lengths are not correct either: use something like `PChar(Password), Length(Password) * SizeOf(Char)`. – Rudy Velthuis Nov 04 '17 at 10:47
  • 2
    @zaph It's better than the C++ code which doesn't check for any errors and leaks memory... – J... Nov 04 '17 at 11:04
  • 1
    It is the way the code is written, the deep nesting, the size of the function ( over 100 lines). Combining encryption and decryption in one function makes it hard to follow. It needs to be broken into several functions. – zaph Nov 04 '17 at 12:33
  • 1
    "I found the following code in C++". There's your problem in a nutshell. Blindly copying code without trying to understand it seldom works. This is the point where you have to face up to some responsibilities. You can't program like this. Like the band of monkeys hoping to type the complete works of Shakespeare. Do some legwork. Learn about encryption. Understand your code. – David Heffernan Nov 05 '17 at 08:04
  • I found problem in Codes, the problem is the code In Delphi convert Output to base64 string and the code in c++ no make this conversion, I'm write code to convert result in base64 string in c++, I will do It and after I will post the code – Rodrigo Zimmermann Nov 05 '17 at 12:53

1 Answers1

0

This code bellow Show how Encrypt string, decrypt string, and encrypt string and decrypt string convert to base64 like Delphi code above do. in Vc++ Part of this code is based on CryptEncrypt does not encrypt whole text

#include "stdafx.h"
#include <atlenc.h>
#include <atlstr.h>
#include <locale.h>


static const unsigned char pr2six[256] =
{
    /* ASCII table */
    64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64,
    64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64,
    64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 62, 64, 64, 64, 63,
    52, 53, 54, 55, 56, 57, 58, 59, 60, 61, 64, 64, 64, 64, 64, 64,
    64,  0,  1,  2,  3,  4,  5,  6,  7,  8,  9, 10, 11, 12, 13, 14,
    15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 64, 64, 64, 64, 64,
    64, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 36, 37, 38, 39, 40,
    41, 42, 43, 44, 45, 46, 47, 48, 49, 50, 51, 64, 64, 64, 64, 64,
    64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64,
    64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64,
    64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64,
    64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64,
    64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64,
    64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64,
    64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64,
    64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64
};

int Base64decode_len(const char *bufcoded)
{
    int nbytesdecoded;
    register const unsigned char *bufin;
    register int nprbytes;

    bufin = (const unsigned char *)bufcoded;
    while (pr2six[*(bufin++)] <= 63);

    nprbytes = (bufin - (const unsigned char *)bufcoded) - 1;
    nbytesdecoded = ((nprbytes + 3) / 4) * 3;

    return nbytesdecoded + 1;
}

int Base64decode(char *bufplain, const char *bufcoded)
{
    int nbytesdecoded;
    register const unsigned char *bufin;
    register unsigned char *bufout;
    register int nprbytes;

    bufin = (const unsigned char *)bufcoded;
    while (pr2six[*(bufin++)] <= 63);
    nprbytes = (bufin - (const unsigned char *)bufcoded) - 1;
    nbytesdecoded = ((nprbytes + 3) / 4) * 3;

    bufout = (unsigned char *)bufplain;
    bufin = (const unsigned char *)bufcoded;

    while (nprbytes > 4) {
        *(bufout++) =
            (unsigned char)(pr2six[*bufin] << 2 | pr2six[bufin[1]] >> 4);
        *(bufout++) =
            (unsigned char)(pr2six[bufin[1]] << 4 | pr2six[bufin[2]] >> 2);
        *(bufout++) =
            (unsigned char)(pr2six[bufin[2]] << 6 | pr2six[bufin[3]]);
        bufin += 4;
        nprbytes -= 4;
    }

    /* Note: (nprbytes == 1) would be an error, so just ingore that case */
    if (nprbytes > 1) {
        *(bufout++) =
            (unsigned char)(pr2six[*bufin] << 2 | pr2six[bufin[1]] >> 4);
    }
    if (nprbytes > 2) {
        *(bufout++) =
            (unsigned char)(pr2six[bufin[1]] << 4 | pr2six[bufin[2]] >> 2);
    }
    if (nprbytes > 3) {
        *(bufout++) =
            (unsigned char)(pr2six[bufin[2]] << 6 | pr2six[bufin[3]]);
    }

    *(bufout++) = '\0';
    nbytesdecoded -= (4 - nprbytes) & 3;
    return nbytesdecoded;
}

static const char basis_64[] =
"ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/";

int Base64encode_len(int len)
{
    return ((len + 2) / 3 * 4) + 1;
}

int Base64encode(char *encoded, const char *string, int len)
{
    int i;
    char *p;

    p = encoded;
    for (i = 0; i < len - 2; i += 3) {
        *p++ = basis_64[(string[i] >> 2) & 0x3F];
        *p++ = basis_64[((string[i] & 0x3) << 4) |
            ((int)(string[i + 1] & 0xF0) >> 4)];
        *p++ = basis_64[((string[i + 1] & 0xF) << 2) |
            ((int)(string[i + 2] & 0xC0) >> 6)];
        *p++ = basis_64[string[i + 2] & 0x3F];
    }
    if (i < len) {
        *p++ = basis_64[(string[i] >> 2) & 0x3F];
        if (i == (len - 1)) {
            *p++ = basis_64[((string[i] & 0x3) << 4)];
            *p++ = '=';
        }
        else {
            *p++ = basis_64[((string[i] & 0x3) << 4) |
                ((int)(string[i + 1] & 0xF0) >> 4)];
            *p++ = basis_64[((string[i + 1] & 0xF) << 2)];
        }
        *p++ = '=';
    }

    *p++ = '\0';
    return p - encoded;
}

bool encryptStr(const char *pSourceTxt,const char* pKey,  int length, char * pEncryptTxt)
{
    HCRYPTPROV hProv;
    HCRYPTHASH hHash;
    HCRYPTKEY hKey;
    DWORD todwSize = (DWORD)strlen(pSourceTxt), needSize;
    PBYTE pBuffer;
    char *txtBuf = (char *)_alloca(todwSize + 1);


    if (CryptAcquireContext(&hProv, NULL, NULL, PROV_RSA_FULL, CRYPT_VERIFYCONTEXT))
    {
        if (CryptCreateHash(hProv, CALG_SHA1, 0, 0, &hHash))
        {
            if (CryptHashData(hHash, (BYTE*)pKey, (DWORD)strlen(pKey), 0) &&
                CryptDeriveKey(hProv, CALG_RC4, hHash, 0, &hKey))
            {
                if (CryptEncrypt(hKey, 0, TRUE, 0, NULL, &(needSize = todwSize), 0))
                {
                    memcpy(pBuffer = (BYTE *)_alloca(needSize), pSourceTxt, todwSize);

                    if (CryptEncrypt(hKey, 0, TRUE, 0, pBuffer, &todwSize, needSize))
                    {

                        txtBuf[todwSize] = NULL;
                        memcpy(txtBuf, pBuffer, todwSize);
                        memcpy(pEncryptTxt, txtBuf, todwSize + 1);
                    }
                }
                CryptDestroyKey(hKey);
            }
            CryptDestroyHash(hHash);
        }
        CryptReleaseContext(hProv, 0);
    }



    return true;
}

bool encryptStrBase64(const char *pSourceTxt, const char* pKey, int length, char * pEncryptTxt)
{
    HCRYPTPROV hProv;
    HCRYPTHASH hHash;
    HCRYPTKEY hKey;
    DWORD todwSize = (DWORD)strlen(pSourceTxt), needSize;
    PBYTE pBuffer;
    char *txtBuf = (char *)_alloca(todwSize + 1);


    if (CryptAcquireContext(&hProv, NULL, NULL, PROV_RSA_FULL, CRYPT_VERIFYCONTEXT))
    {
        if (CryptCreateHash(hProv, CALG_SHA1, 0, 0, &hHash))
        {
            if (CryptHashData(hHash, (BYTE*)pKey, (DWORD)strlen(pKey), 0) &&
                CryptDeriveKey(hProv, CALG_RC4, hHash, 0, &hKey))
            {
                if (CryptEncrypt(hKey, 0, TRUE, 0, NULL, &(needSize = todwSize), 0))
                {
                    memcpy(pBuffer = (BYTE *)_alloca(needSize), pSourceTxt, todwSize);

                    if (CryptEncrypt(hKey, 0, TRUE, 0, pBuffer, &todwSize, needSize))
                    {

                        txtBuf[todwSize] = NULL;
                        memcpy(txtBuf, pBuffer, todwSize);
                        char *txtEncode64 = (char *)_alloca(strlen(pEncryptTxt));
                        Base64encode(txtEncode64, txtBuf,  todwSize);
                        memcpy(pEncryptTxt, txtEncode64, todwSize +100);
                    }
                }
                CryptDestroyKey(hKey);
            }
            CryptDestroyHash(hHash);
        }
        CryptReleaseContext(hProv, 0);
    }



    return true;
}

bool decryptStr(const char *pEncryptTxt, const char* pKey, int length, char * pDecryptTxt)
{
    HCRYPTPROV hProv;
    HCRYPTHASH hHash;
    HCRYPTKEY hKey;
    DWORD todwSize = (DWORD)strlen(pEncryptTxt);
    PBYTE pBuffer = (BYTE *)_alloca(todwSize);
    char *txtBuf = (char *)_alloca(todwSize + 1);


    if (CryptAcquireContext(&hProv, NULL, NULL, PROV_RSA_FULL, CRYPT_VERIFYCONTEXT))
    {
        if (CryptCreateHash(hProv, CALG_SHA1, 0, 0, &hHash))
        {
            if (CryptHashData(hHash, (BYTE*)pKey, (DWORD)strlen(pKey), 0) &&
                CryptDeriveKey(hProv, CALG_RC4, hHash, 0, &hKey))
            {
                memcpy(pBuffer, pEncryptTxt, todwSize);

                if (CryptDecrypt(hKey, 0, TRUE, 0, pBuffer, &todwSize))
                {

                    txtBuf[todwSize] = NULL;
                    memcpy(txtBuf, pBuffer, todwSize);
                    memcpy(pDecryptTxt, txtBuf, todwSize + 1);

                }

                CryptDestroyKey(hKey);
            }
            CryptDestroyHash(hHash);
        }
        CryptReleaseContext(hProv, 0);
    }


    return true;
}


bool decryptStrBase64(const char *pEncryptTxt, const char* pKey, int length, char * pDecryptTxt)
{
    HCRYPTPROV hProv;
    HCRYPTHASH hHash;
    HCRYPTKEY hKey;
    char *sourceTxt = (char *)_alloca(2048);
    Base64decode(sourceTxt, pEncryptTxt);

    DWORD todwSize = (DWORD)strlen(sourceTxt);
    PBYTE pBuffer = (BYTE *)_alloca(todwSize);
    char *txtBuf = (char *)_alloca(todwSize + 1);




    if (CryptAcquireContext(&hProv, NULL, NULL, PROV_RSA_FULL, CRYPT_VERIFYCONTEXT))
    {
        if (CryptCreateHash(hProv, CALG_SHA1, 0, 0, &hHash))
        {
            if (CryptHashData(hHash, (BYTE*)pKey, (DWORD)strlen(pKey), 0) &&
                CryptDeriveKey(hProv, CALG_RC4, hHash, 0, &hKey))
            {
                memcpy(pBuffer, sourceTxt, todwSize);

                if (CryptDecrypt(hKey, 0, TRUE, 0, pBuffer, &todwSize))
                {

                    txtBuf[todwSize] = NULL;
                    memcpy(txtBuf, pBuffer, todwSize);
                    memcpy(pDecryptTxt, txtBuf, todwSize + 1);

                }

                CryptDestroyKey(hKey);
            }
            CryptDestroyHash(hHash);
        }
        CryptReleaseContext(hProv, 0);
    }


    return true;
}



int main()
{
    char* encryptWord = "test word";
    char *encryptKey = "cryptkey";
    int encryptLen = strlen(encryptWord);
    char * txtEncrypt = (char *)_alloca(encryptLen+1);      


    //simple Encrypt TXT
    encryptStr(encryptWord, encryptKey, encryptLen,txtEncrypt);
    printf("Simple Encrypt %s \n", txtEncrypt);

    //Decrypt string 
    char* decryptTxt = (char *)_alloca(encryptLen + 1);
    decryptStr(txtEncrypt, encryptKey, encryptLen, decryptTxt);
    printf("Txt decrypted %s \n", decryptTxt);

    //Encrypt and Convert to Base64 like delphi Routine
    char* base64TxtEncrypt = (char*)_alloca(encryptLen + 100);//need aloc more size due base64 routine
    encryptStrBase64(encryptWord, encryptKey, encryptLen, base64TxtEncrypt);
    printf("Base64 txt encrypted %s \n", base64TxtEncrypt);


    //decrypt and Convert to original String like delphi Routine
    char* base64TxtDecrypt = (char*)_alloca(encryptLen + 100);
    decryptStrBase64( base64TxtEncrypt, encryptKey, strlen(base64TxtEncrypt) , base64TxtDecrypt);
    printf("Base64 txt Decrypted %s \n", base64TxtDecrypt);



    system("pause");

    return 0;
}

And finally the conversion of this code to c#, and mission end

using System;
using System.Collections.Generic;
using System.Linq;
using System.Runtime.InteropServices;
using System.Text;


namespace CryptCsharpNativo
{

    class Program
    {

        public const uint PROV_RSA_FULL = 1;
        public const uint CRYPT_VERIFYCONTEXT = 0xF0000000;
        public const uint CRYPT_NEWKEYSET = 0x00000008;
        public enum ALG_ID
        {
            CALG_MD5 = 0x00008003,
            CALG_RC4 = 0x00006801,
            CALG_SHA1 = 0x00008004
        }
        [DllImport("advapi32.dll")]
        [return: MarshalAs(UnmanagedType.Bool)]
        public static extern bool CryptAcquireContext(out IntPtr phProv, string pszContainer, string pszProvider, uint dwProvType, uint dwFlags);
        [DllImport("advapi32.dll")]
        [return: MarshalAs(UnmanagedType.Bool)]
        public static extern bool CryptCreateHash(IntPtr hProv, ALG_ID Algid, IntPtr hKey, uint dwFlags, out IntPtr phHash);
        [DllImport("advapi32.dll")]
        [return: MarshalAs(UnmanagedType.Bool)]
        public static extern bool CryptHashData(IntPtr hHash, byte[] pbData, int dwDataLen, uint dwFlags);
        [DllImport("advapi32.dll")]
        [return: MarshalAs(UnmanagedType.Bool)]
        public static extern bool CryptDeriveKey(IntPtr hProv, ALG_ID Algid, IntPtr hBaseData, uint dwFlags, ref IntPtr phKey);
        [DllImport("advapi32.dll")]
        [return: MarshalAs(UnmanagedType.Bool)]
        public static extern bool CryptDestroyHash(IntPtr hHash);

        [DllImport("advapi32.dll")]
        [return: MarshalAs(UnmanagedType.Bool)]
        public static extern bool CryptEncrypt(IntPtr hKey, IntPtr hHash, [MarshalAs(UnmanagedType.Bool)]bool Final, uint dwFlags, byte[] pbData, ref int pdwDataLen);

        [DllImport("advapi32.dll")]
        [return: MarshalAs(UnmanagedType.Bool)]
        public static extern bool CryptDecrypt(IntPtr hKey, IntPtr hHash, [MarshalAs(UnmanagedType.Bool)]bool Final, uint dwFlags, byte[] pbData, ref int pdwDataLen);
        [DllImport("advapi32.dll")]
        [return: MarshalAs(UnmanagedType.Bool)]
        public static extern bool CryptDestroyKey(IntPtr hKey);
        [DllImport("advapi32.dll")]
        [return: MarshalAs(UnmanagedType.Bool)]
        public static extern bool CryptReleaseContext(IntPtr hProv, uint dwFlags);

        const uint NTE_BAD_KEYSET = 0x80090016;

        public static string decryptStr(string pSourceTxt, string pKey)
        {
            IntPtr hCryptProv;
            IntPtr hKey = IntPtr.Zero;
            IntPtr hHash;
            int dwCount = 0;           
            byte[] key = Encoding.ASCII.GetBytes(pKey);
            int datalen = pSourceTxt.Length;

            // Get a handle to the default provider. 
            if (!CryptAcquireContext(out hCryptProv, null, null, PROV_RSA_FULL, CRYPT_VERIFYCONTEXT))
            {
                return "";
            }

            // Decrypt the file with a session key derived from a password. 

            // Create a hash object. 
            if (!CryptCreateHash(hCryptProv, ALG_ID.CALG_SHA1, IntPtr.Zero, 0, out hHash))
                return "";

            // Hash in the password data. 
            if (!CryptHashData(hHash, key, key.Length, 0))
                return "";

            // Derive a session key from the hash object. 
            if (!CryptDeriveKey(hCryptProv, ALG_ID.CALG_RC4, hHash, 0, ref hKey))
                return "";

            // Destroy the hash object. 
            if (!(CryptDestroyHash(hHash)))
                return "";
            hHash = IntPtr.Zero;


            byte[] originalCrypt = Convert.FromBase64String(pSourceTxt);

            if (!CryptDecrypt(hKey, IntPtr.Zero, true, 0, originalCrypt, ref datalen))
                return "";


            datalen = dwCount;

            // Destroy session key. 
            if (hKey != IntPtr.Zero)
            {
                if (!(CryptDestroyKey(hKey)))
                    return "";
            }

            // Release provider handle. 
            if (hCryptProv != IntPtr.Zero)
            {
                if (!(CryptReleaseContext(hCryptProv, 0)))
                    return "";
            }

            return Encoding.ASCII.GetString(originalCrypt);
        } // end Decryptfile

        public static string encryptStr(string pSourceTxt, string pKey)
        {
            IntPtr hCryptProv;
            IntPtr hKey = IntPtr.Zero;
            IntPtr hHash;
            int dwCount = 0;
            byte[] sourceTxt = Encoding.ASCII.GetBytes(pSourceTxt);
            byte[] key = Encoding.ASCII.GetBytes(pKey);
            int datalen = pSourceTxt.Length;

            // Get a handle to the default provider. 
            if (!CryptAcquireContext(out hCryptProv, null, null, PROV_RSA_FULL, CRYPT_VERIFYCONTEXT))
            {
                    return "";
            }

            // Decrypt the file with a session key derived from a password. 

            // Create a hash object. 
            if (!CryptCreateHash(hCryptProv, ALG_ID.CALG_SHA1, IntPtr.Zero, 0, out hHash))
                return "";

            // Hash in the password data. 
            if (!CryptHashData(hHash, key, key.Length, 0))
                return "";

            // Derive a session key from the hash object. 
            if (!CryptDeriveKey(hCryptProv, ALG_ID.CALG_RC4 , hHash, 0, ref hKey))
                return "";

            // Destroy the hash object. 
            if (!(CryptDestroyHash(hHash)))
                return "";
            hHash = IntPtr.Zero;

            if (!CryptEncrypt(hKey, IntPtr.Zero, true, 0, null, ref datalen))
                return "";

            if (!CryptEncrypt(hKey, IntPtr.Zero, true, 0, sourceTxt, ref datalen))
                return "";

            string base64 = Convert.ToBase64String(sourceTxt);


            datalen = dwCount;

            // Destroy session key. 
            if (hKey != IntPtr.Zero)
            {
                if (!(CryptDestroyKey(hKey)))
                    return "";
            }

            // Release provider handle. 
            if (hCryptProv != IntPtr.Zero)
            {
                if (!(CryptReleaseContext(hCryptProv, 0)))
                    return "";
            }

            return base64;
        } // end encryptfile


        static void Main(string[] args)
        {

            string encryptTxt = "Teste Crypt";
            string key = "teste123";

            string encryptStr = Program.encryptStr(encryptTxt, key);

            string decryptStr = Program.decryptStr(encryptStr, key);


            Console.Write("Encrypt String with Base64 = {0} \n" ,  encryptStr);

            Console.Write("Decrypted String with base64 = {0}", decryptStr);

            Console.ReadLine();
        }
    }
}