0

I was trying to learn more about Encryption with this thread and I changed a couple things as was mentioned on comments.

The Exception occurs when it tries to convert a valueBytes to Byte which was weird cu'z, the valueBytes already is a byte[] !

From

byte[] vectorBytes = GetBytes<ASCIIEncoding>(_vector);
byte[] saltBytes = GetBytes<ASCIIEncoding>(_salt);
byte[] valueBytes = GetBytes<UTF8Encoding>(value);

To

byte[] vectorBytes = Encoding.ASCII.GetBytes(_vector);
byte[] saltBytes = Encoding.ASCII.GetBytes(_salt);
byte[] valueBytes = Encoding.UTF8.GetBytes(value);

To encrypt, works fine but decrypt..

private static int _iterations = 2;
    private static int _keySize = 256;

    private static string _hash = "SHA1";
    private static string _salt = "aselrias38490a32"; // Random
    private static string _vector = "8947az34awl34kjq"; // Random


    public static string Encrypt(string value, string password)
    {
        return Encrypt<AesManaged>(value, password);
    }
    public static string Encrypt<T>(string value, string password)
        where T : SymmetricAlgorithm, new()
    {
        byte[] vectorBytes = Encoding.ASCII.GetBytes(_vector);
        byte[] saltBytes = Encoding.ASCII.GetBytes(_salt);
        byte[] valueBytes = Encoding.UTF8.GetBytes(value);

        byte[] encrypted;
        using (T cipher = new T())
        {
            PasswordDeriveBytes _passwordBytes =
                new PasswordDeriveBytes(password, saltBytes, _hash, _iterations);
            byte[] keyBytes = _passwordBytes.GetBytes(_keySize / 8);

            cipher.Mode = CipherMode.CBC;

            using (ICryptoTransform encryptor = cipher.CreateEncryptor(keyBytes, vectorBytes))
            {
                using (MemoryStream to = new MemoryStream())
                {
                    using (CryptoStream writer = new CryptoStream(to, encryptor, CryptoStreamMode.Write))
                    {
                        writer.Write(valueBytes, 0, valueBytes.Length);
                        writer.FlushFinalBlock();
                        encrypted = to.ToArray();
                    }
                }
            }
            cipher.Clear();
        }
        return Convert.ToBase64String(encrypted);
    }

    public static string Decrypt(string value, string password)
    {
        return Decrypt<AesManaged>(value, password);
    }
    public static string Decrypt<T>(string value, string password) where T : SymmetricAlgorithm, new()
    {
        byte[] vectorBytes = Encoding.ASCII.GetBytes(_vector);
        byte[] saltBytes = Encoding.ASCII.GetBytes(_salt);
        byte[] valueBytes = Encoding.UTF8.GetBytes(value);

        byte[] decrypted;
        int decryptedByteCount = 0;

        using (T cipher = new T())
        {
            PasswordDeriveBytes _passwordBytes = new PasswordDeriveBytes(password, saltBytes, _hash, _iterations);
            byte[] keyBytes = _passwordBytes.GetBytes(_keySize / 8);

            cipher.Mode = CipherMode.CBC;

            try
            {
                using (ICryptoTransform decryptor = cipher.CreateDecryptor(keyBytes, vectorBytes))
                {
                    using (MemoryStream from = new MemoryStream(valueBytes))
                    {
                        using (CryptoStream reader = new CryptoStream(from, decryptor, CryptoStreamMode.Read))
                        {
                            decrypted = new byte[valueBytes.Length];
                            decryptedByteCount = reader.Read(decrypted, 0, decrypted.Length);
                        }
                    }
                }
            }
            catch (Exception ex)
            {
                return String.Empty;
            }

            cipher.Clear();
        }
        return Encoding.UTF8.GetString(decrypted, 0, decryptedByteCount);
    }
Nathiel Barros
  • 685
  • 2
  • 11
  • 25
  • 1
    In Decrypt method *byte[] valueBytes = Encoding.UTF8.GetBytes(value);* is wrong. Read the linked answer again – Sir Rufo Jul 16 '17 at 07:00

2 Answers2

3

At the end of Encrypt you're writing return Convert.ToBase64String(encrypted);. You would need to reverse this process during decryption which you're not currently doing: byte[] valueBytes = Encoding.UTF8.GetBytes(value);

Change it to byte[] valueBytes = Convert.FromBase64String(value);.


Security issues:

The IV must be unpredictable (read: random) and the salt must be random. Don't use a static IV and salt, because that makes the cipher deterministic and therefore not semantically secure. An attacker who observes ciphertexts can determine when the same message prefix was sent before. The IV and salt are not secret, so you can send them along with the ciphertext. Usually, they are simply prepended to the ciphertext and sliced off before decryption.

It is better to authenticate your ciphertexts so that attacks like a padding oracle attack are not possible. This can be done with authenticated modes like GCM or EAX, or with an encrypt-then-MAC scheme.

Artjom B.
  • 61,146
  • 24
  • 125
  • 222
1

I would not use ASCII encoding to convert from a byte[] to a string. The encryption is going to give you byte values ranging from 0 to 255. These values do not directly translate to strings using the ASCII encoder which maps those values into a string based on the ASCII table. If you need to get a byte[] converted to string, you should use Convert.ToBase64String.

https://msdn.microsoft.com/en-us/library/dhx0d524(v=vs.110).aspx

This will convert the byte[] into printable characters (A-Za-z1-10+/) that can then be converted back into a byte[] for decrypting.

mageos
  • 1,216
  • 7
  • 15