Welcome to Experts Exchange

Add your voice to the tech community where 5M+ people, just like you, are talking about what matters.

  • Help others & share knowledge
  • Earn cash & points
  • Learn & ask questions
Solved

Decryption of windows generated encrypted string

Posted on 2013-11-20
13
740 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
Active Directory Webinar

We all know we need to protect and secure our privileges, but where to start? Join Experts Exchange and ManageEngine on Tuesday, April 11, 2017 10:00 AM PDT to learn how to track and secure privileged users in Active Directory.

 
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
 
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

Active Directory Webinar

We all know we need to protect and secure our privileges, but where to start? Join Experts Exchange and ManageEngine on Tuesday, April 11, 2017 10:00 AM PDT to learn how to track and secure privileged users in Active Directory.

Question has a verified solution.

If you are experiencing a similar issue, please ask a related question

Suggested Solutions

A set of related code is known to be a Module, it helps us to organize our code logically which is much easier for us to understand and use it. Module is an object with arbitrarily named attributes which can be used in binding and referencing. …
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…
The goal of this video is to provide viewers with basic examples to understand and use switch statements in the C programming language.
The viewer will learn how to use the return statement in functions in C++. The video will also teach the user how to pass data to a function and have the function return data back for further processing.

829 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