Solved

Decryption of windows generated encrypted string

Posted on 2013-11-20
13
728 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
Is Your Active Directory as Secure as You Think?

More than 75% of all records are compromised because of the loss or theft of a privileged credential. Experts have been exploring Active Directory infrastructure to identify key threats and establish best practices for keeping data safe. Attend this month’s webinar to learn more.

 
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

Is Your Active Directory as Secure as You Think?

More than 75% of all records are compromised because of the loss or theft of a privileged credential. Experts have been exploring Active Directory infrastructure to identify key threats and establish best practices for keeping data safe. Attend this month’s webinar to learn more.

Question has a verified solution.

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

Variable is a place holder or reserved memory locations to store any value. Which means whenever we create a variable, indirectly we are reserving some space in the memory. The interpreter assigns or allocates some space in the memory based on the d…
Windows programmers of the C/C++ variety, how many of you realise that since Window 9x Microsoft has been lying to you about what constitutes Unicode (http://en.wikipedia.org/wiki/Unicode)? They will have you believe that Unicode requires you to use…
The goal of the video will be to teach the user the concept of local variables and scope. An example of a locally defined variable will be given as well as an explanation of what scope is in C++. The local variable and concept of scope will be relat…
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.

895 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

13 Experts available now in Live!

Get 1:1 Help Now