tags:

views:

317

answers:

1

Hi All,

I am trying to send some encrypted data from my SharePoint site to my company's PeopleSoft site. The PeopleSoft folks insist that I have to use the OpenSSL library for my encryption. I have downloaded and installed the OpenSSL.Net project from SourceForge.

For my purposes, I need to simply encrypt a string with AES. I know how to do this with the System.Security.Cryptography library, but am having a very difficult time translating this to the OpenSSL.Net side. Very frustrating, since I can see everything that I think I need in Intellisense!

Does anybody have an example of performing string encryption/decryption with AES using the OpenSSL.Net wrapper?

Thanks!

-Nick

A: 

Here is the sample which works for me. I simplified it by using copy-paste but should not matter.

I'm using text password due to compatibility with JS library but open SSL itself supports direct usage of byte[] Key and IV so it's up to you what to use.

In order to switch binary data into the string just use

Encoding.UTF8.GetBytes() and Encoding.UTF8.GetString()

to convert back and forth.

    public Byte[] Encrypt(Byte[] data, String password)
    {
        //Just random 8 bytes for salt
        var salt = new Byte[] {1, 2, 3, 4, 5, 6, 7, 8};

        using (var cc = new CipherContext(Cipher.AES_256_CBC))
        {
            //Constructing key and init vector from string password
            byte[] passwordBytes = Encoding.UTF8.GetBytes(password);
            byte[] iv;
            byte[] key = cc.BytesToKey(MessageDigest.MD5, salt, passwordBytes, 1, out iv);

            var memoryStream = new MemoryStream();

            //Performing encryption thru unmanaged wrapper
            var aesData = cc.Crypt(data, key, iv, true);

            //Append salt so final data will look Salted___SALT|RESTOFTHEDATA
            memoryStream.Write(Encoding.UTF8.GetBytes("Salted__"), 0, 8);
            memoryStream.Write(salt, 0, 8);
            memoryStream.Write(aesData, 0, aesData.Length);

            return memoryStream.ToArray();
        }
    }

    public Byte[] Decrypt(String password, Byte[] encryptedData)
    {
        byte[] salt = null;
        //extracting salt if presented
        if (encryptedData.Length > 16)
        {
            if (Encoding.UTF8.GetString(encryptedData).StartsWith("Salted__"))
            {
                salt = new Byte[8];
                Buffer.BlockCopy(encryptedData, 8, salt, 0, 8);
            }
        }

        //Removing salt from the original array
        int aesDataLength = encryptedData.Length - 16;
        byte[] aesData = new byte[aesDataLength];
        Buffer.BlockCopy(encryptedData, 16, aesData, 0, aesDataLength);


        using (var cc = new CipherContext(Cipher.AES_256_CBC))
        {
            //Constructing key and init vector from string password and salt
            byte[] passwordBytes = Encoding.UTF8.GetBytes(password);
            byte[] iv;
            byte[] key = cc.BytesToKey(MessageDigest.MD5, salt, passwordBytes, 1, out iv);

            //Decrypting
            return cc.Decrypt(aesData, key, iv, 0);

        }


    }
Alex Krupnov
Those are some highly random eight bytes for the salt ;)
Nate Bross
Well, random enough to answer the question as this is indeed not a live code:)
Alex Krupnov
My implementation is based off of this example. I'm using the Cipher.AES_256_CBC context but if my password is < 16 bytes when cc.Crypt is called it throws an exception. Because it's trying to write the encrypted data which is 16 bytes into the 8 byte buffer it creates. Did you encounter this? I'm using OpenSSL.Net 0.4.4 and I'm using a SHA1 message digest.
Jeff Alexander