Solved

Decryption of windows generated encrypted string

Posted on 2013-11-20
13
711 Views
Last Modified: 2013-11-26
I have the following C#.Net code that encrypts/decrypts on windows boxes without issue. What I need to do is encrypt a string using this code on a Windows server and create an exe to decrypt the string on a unix machine (which is where I need some help). I am happy to use perl, python, C or C++ but I am not sure how to go abaout decrpting in any of these languages.

public static string Encrypt(string plainText) 
   {
      RijndaelManaged key = GetKey();
      byte[] plainTextBytes = Encoding.UTF8.GetBytes(plainText);
      using (ICryptoTransform encryptor = key.CreateEncryptor()) 
      {
         using (MemoryStream memoryStream = new MemoryStream()) 
         {
            using (CryptoStream cryptoStream = new CryptoStream(memoryStream, encryptor, CryptoStreamMode.Write)) 
            {
               cryptoStream.Write(plainTextBytes, 0, plainText.Length);
               cryptoStream.FlushFinalBlock();
               return Convert.ToBase64String(memoryStream.ToArray());
            }
         }
      }
   }

   public static string Decrypt(string encryptedString) 
   {

      if (string.IsNullOrEmpty(encryptedString)) 
      {
         return encryptedString;
      }

      RijndaelManaged key = GetKey();
      byte[] encryptedData = Convert.FromBase64String(encryptedString);
      using (ICryptoTransform decryptor = key.CreateDecryptor(key.Key, key.IV)) 
      {
         using (MemoryStream memoryStream = new MemoryStream(encryptedData)) 
         {
            using (CryptoStream cryptoStream = new CryptoStream(memoryStream, decryptor, CryptoStreamMode.Read)) 
            {
               byte[] plainText = new byte[encryptedData.Length];
               int decryptedCount = cryptoStream.Read(plainText, 0, plainText.Length);
               return Encoding.UTF8.GetString(plainText, 0, decryptedCount);
            }
         }
      }
   }

   //Create encryption key
   private static RijndaelManaged GetKey() 
   {
      var vault = (VaultSection)ConfigurationManager.GetSection("Vault");
      RijndaelManaged key = new RijndaelManaged();
      byte[] bp = Encoding.UTF8.GetBytes(vault.Password);
      byte[] bs = Encoding.UTF8.GetBytes(vault.Salt);
      PasswordDeriveBytes p = new PasswordDeriveBytes(bp, bs);
      key.IV = p.GetBytes(key.BlockSize / 8);
      key.Key = p.GetBytes(key.KeySize / 8);
      return key;
   }

Open in new window

0
Comment
Question by:Michael74
  • 5
  • 5
  • 3
13 Comments
 
LVL 86

Expert Comment

by:jkr
ID: 39664789
As for UN*X/C++, you should be fine with Crypto++ - see http://www.cryptopp.com/
I use that library a lot (on Windows, Linux and OS X), and even though it might be a little bit hard to become acquainted with it, it's worth the time because of all the diversity it offers. And yes, it of course supports Rijndael.
0
 
LVL 86

Expert Comment

by:jkr
ID: 39666606
BTW, you will find a straightfoward example on how to use that at http://www.cryptopp.com/wiki/Advanced_Encryption_Standard

AutoSeededRandomPool rnd;

// Generate a random key
SecByteBlock key(0x00, AES::DEFAULT_KEYLENGTH);
rnd.GenerateBlock( key, key.size() );  // In your case, you'd load it from a file

// Generate a random IV
byte iv[AES::BLOCKSIZE];
rnd.GenerateBlock(iv, AES::BLOCKSIZE);

char plainText[] = "Hello! How are you.";
int messageLen = (int)strlen(plainText) + 1;

//////////////////////////////////////////////////////////////////////////
// Encrypt

CFB_Mode<AES>::Encryption cfbEncryption(key, key.size(), iv);
cfbEncryption.ProcessData((byte*)plainText, (byte*)plainText, messageLen);

//////////////////////////////////////////////////////////////////////////
// Decrypt

CFB_Mode<AES>::Decryption cfbDecryption(key, key.size(), iv);
cfbDecryption.ProcessData((byte*)plainText, (byte*)plainText, messageLen);

Open in new window

0
 
LVL 14

Accepted Solution

by:
jb1dev earned 500 total points
ID: 39667123
You can always run your C# application on linux if you have the mono (.NET) framework/runtime installed.

I have modified your program slightly and added an example so you can see the encryption occur.

using System;
using System.IO;
using System.Text;
using System.Security.Cryptography;

namespace ExchCrypt_Example {

    class ExchCrypt {

        public static string Encrypt(string plainText) 
        {
            RijndaelManaged key = GetKey();
            byte[] plainTextBytes = Encoding.UTF8.GetBytes(plainText);
            using (ICryptoTransform encryptor = key.CreateEncryptor()) 
            {
                using (MemoryStream memoryStream = new MemoryStream()) 
                {
                    using (CryptoStream cryptoStream = new CryptoStream(memoryStream, encryptor, CryptoStreamMode.Write)) 
                    {
                        cryptoStream.Write(plainTextBytes, 0, plainText.Length);
                        cryptoStream.FlushFinalBlock();
                        return Convert.ToBase64String(memoryStream.ToArray());
                    }
                }
            }
        }

        public static string Decrypt(string encryptedString) 
        {

            if (string.IsNullOrEmpty(encryptedString)) 
            {
                return encryptedString;
            }
        
            RijndaelManaged key = GetKey();
            byte[] encryptedData = Convert.FromBase64String(encryptedString);
            using (ICryptoTransform decryptor = key.CreateDecryptor(key.Key, key.IV)) 
            {
                using (MemoryStream memoryStream = new MemoryStream(encryptedData)) 
                {
                    using (CryptoStream cryptoStream = new CryptoStream(memoryStream, decryptor, CryptoStreamMode.Read)) 
                    {
                    byte[] plainText = new byte[encryptedData.Length];
                    int decryptedCount = cryptoStream.Read(plainText, 0, plainText.Length);
                    return Encoding.UTF8.GetString(plainText, 0, decryptedCount);
                    }
                }
            }
        }

        // Create encryption key
        private static RijndaelManaged GetKey() 
        {
            RijndaelManaged key = new RijndaelManaged();

            key.Key     = System.Text.Encoding.ASCII.GetBytes(
                                "abcdefghijklmnopabcdefghijklmnop");
            key.IV      = System.Text.Encoding.ASCII.GetBytes(
                                "0123456789abcdef");

            return key;
        }

        public static void Main() {
            string original = "The quick brown fox";
            string encrypted = Encrypt(original);
            string unencrypted = Decrypt(encrypted);

            Console.WriteLine("Original:    {0}", original);
            Console.WriteLine("Encrypted:   {0}", encrypted);
            Console.WriteLine("Unencrypted: {0}", unencrypted);
        }

    }
}

Open in new window


Example:

exch@exch:~/procs$ mono ExchCrypt.exe 
Original:    The quick brown fox
Encrypted:   I4aW+jwnVmLU+Pg3mp+K/6ghV80QTwRCHUnLiv2EVsA=
Unencrypted: The quick brown fox
exch@exch:~/procs$ 

Open in new window


If however your requirements do not allow for the mono framework installed on your Linux OS, you can do as jkr suggests and use CryptoPP

Here is an example of how to do that, using C++ and the same keys. Put together from a few examples I found around the net.

#include <iostream>
#include "cryptopp/modes.h"
#include "cryptopp/rijndael.h"
#include "cryptopp/filters.h"
#include "cryptopp/base64.h"

using namespace CryptoPP;
using namespace std;

string encrypt(const string& str_in, const string& key, const string& iv)
{

    std::string str_out;
    CBC_Mode<Rijndael>::Encryption encryption(  (byte*)key.c_str(),    
                                                key.length(), 
                                                (byte*)iv.c_str() );
    StringSource encryptor(
        str_in, 
        true,
        new StreamTransformationFilter(encryption,
            new Base64Encoder(new StringSink(str_out), false ) )
    );

    return str_out;
}


string decrypt(const string& str_in, const string& key, const string& iv)
{

    std::string str_out;    
    CBC_Mode<Rijndael>::Decryption decryption(  (byte*)key.c_str(), 
                                                key.length(), 
                                                (byte*)iv.c_str() );

    StringSource decryptor(
        str_in, 
        true,
        new Base64Decoder(
            new StreamTransformationFilter(decryption,
                new StringSink(str_out))
        )
    );

    return str_out;
}

int main(int argc, char** argv) {

    string key  = "abcdefghijklmnopabcdefghijklmnop";
    string IV   = "0123456789abcdef";

    string original = "The quick brown fox";

    cout << "Original:    " << original << endl;  

    string encrypted = encrypt(original, key, IV);
    cout << "Encrypted:   " << encrypted << endl;  

    string decrypted = decrypt(encrypted, key, IV);
    cout << "Decrypted:   " << decrypted << endl;   
}

Open in new window


Compile with:
gcc CryptoRijn.cpp -lstdc++ -lcrypto++ -o CryptoRijn

Open in new window


It has the same hard coded keys as the C# example, so you can compare the encrypted result:

exch@exch:~/procs$ ./CryptoRijn 
Original:    The quick brown fox
Encrypted:   I4aW+jwnVmLU+Pg3mp+K/6ghV80QTwRCHUnLiv2EVsA=
Decrypted:   The quick brown fox
exch@exch:~/procs$ 

Open in new window

0
 
LVL 23

Author Comment

by:Michael74
ID: 39668112
@jb1dev

I am getting the error "Illegal instruction (core dumped)" at the line    
CBC_Mode<Rijndael>::Decryption decryption(  (byte*)key.c_str(),
                                                key.length(),
                                                (byte*)iv.c_str() );

Note: To get it to compile I needed to use
$ g++ CryptoRijn.cpp -lstdc++ -lcryptopp -o CryptoRijn

if this makes any difference
0
 
LVL 14

Expert Comment

by:jb1dev
ID: 39670132
I've also compiled with g++.
I do not see this on my system.

Have you modified the hard coded key/iv? (Note what I provided was not base64 encoded.)
What OS are you using?
What version of lib cryptopp are you using and how did you download, install, and possibly build it?

Do all of the shared object libraries look correct in "ldd CryptoRijn"?

exch@exch:~/procs$ ldd CryptoRijn
      linux-vdso.so.1 =>  (0x00007fff691fe000)
      libstdc++.so.6 => /usr/lib/x86_64-linux-gnu/libstdc++.so.6 (0x00007f689c62d000)
      libcrypto++.so.9 => /usr/lib/libcrypto++.so.9 (0x00007f689bf31000)
      libgcc_s.so.1 => /lib/x86_64-linux-gnu/libgcc_s.so.1 (0x00007f689bd1a000)
      libc.so.6 => /lib/x86_64-linux-gnu/libc.so.6 (0x00007f689b951000)
      libpthread.so.0 => /lib/x86_64-linux-gnu/libpthread.so.0 (0x00007f689b734000)
      libm.so.6 => /lib/x86_64-linux-gnu/libm.so.6 (0x00007f689b42e000)
      /lib64/ld-linux-x86-64.so.2 (0x00007f689c95b000)
exch@exch:~/procs$
0
 
LVL 23

Author Comment

by:Michael74
ID: 39673664
OK finally figured out what went wrong. The current version of cygwin installs g++ 4.8 which is not supported. Luckily I still had an older version of Cygwin tucked away and when installed this and recompiled Cryptopp it worked.

I can now move forward with testing and update when I have more info

cheers

Michael
0
6 Surprising Benefits of Threat Intelligence

All sorts of threat intelligence is available on the web. Intelligence you can learn from, and use to anticipate and prepare for future attacks.

 
LVL 23

Author Comment

by:Michael74
ID: 39673670
OK, now it is working as expected. Thank you
0
 
LVL 86

Expert Comment

by:jkr
ID: 39674926
Um, sorry, but wasn't it me who suggested crypto++ first?
0
 
LVL 23

Author Comment

by:Michael74
ID: 39676192
@jkr
Yes you did suggest it but the question related to having encryption between c# on windows and Unix. jb1dev supplied a complete solution and so I awarded him the points.
0
 
LVL 86

Expert Comment

by:jkr
ID: 39676196
Another complete solution was already appended as a code snippet in my first comment, one day earlier. His code snippet does exactly the same, and the site rules suggest that you'd usually split them.
0
 
LVL 14

Expert Comment

by:jb1dev
ID: 39676246
I am fine with points being split.
I did do a lot of work on this creating full, compilable examples in both C# and C++.
0
 
LVL 23

Author Comment

by:Michael74
ID: 39676706
@jkr
My question specifically requested that I need decrypt values encrypted with the code I provided.
jb1dev provided this and so I stand by my points allocation
0
 
LVL 86

Expert Comment

by:jkr
ID: 39679841
No problem then.
0

Featured Post

Enabling OSINT in Activity Based Intelligence

Activity based intelligence (ABI) requires access to all available sources of data. Recorded Future allows analysts to observe structured data on the open, deep, and dark web.

Join & Write a Comment

Suggested Solutions

Flask is a microframework for Python based on Werkzeug and Jinja 2. This requires you to have a good understanding of Python 2.7. Lets install Flask! To install Flask you can use a python repository for libraries tool called pip. Download this f…
This is a short and sweet, but (hopefully) to the point article. There seems to be some fundamental misunderstanding about the function prototype for the "main" function in C and C++, more specifically what type this function should return. I see so…
The goal of the tutorial is to teach the user how to use functions in C++. The video will cover how to define functions, how to call functions and how to create functions prototypes. Microsoft Visual C++ 2010 Express will be used as a text editor an…
The viewer will be introduced to the member functions push_back and pop_back of the vector class. The video will teach the difference between the two as well as how to use each one along with its functionality.

708 members asked questions and received personalized solutions in the past 7 days.

Join the community of 500,000 technology professionals and ask your questions.

Join & Ask a Question

Need Help in Real-Time?

Connect with top rated Experts

11 Experts available now in Live!

Get 1:1 Help Now