Decrypted string returns "Length of the data to decrypt is invalid"

112 views Asked by At

I'm using the following snippet of code to encrypt and decrypt a string and save it to an Azure database.

public class EncryptPassword
{
    private static byte[] key = { 123, 217, 19, 11, 24, 26, 85, 45, 114, 184, 27, 162, 37, 112, 222, 209, 241, 24, 175, 144, 173, 53, 196, 29, 24, 26, 17, 218, 131, 236, 53, 209 };
    private static byte[] vector = { 146, 64, 191, 111, 23, 3, 113, 119, 231, 121, 221, 112, 79, 32, 114, 156 };
        private ICryptoTransform encryptor, decryptor;
        private UTF8Encoding encoder;

        public EncryptPassword()
        {
            RijndaelManaged rm = new RijndaelManaged();
            encryptor = rm.CreateEncryptor(key, vector);
            decryptor = rm.CreateDecryptor(key, vector);
            encoder = new UTF8Encoding();
        }

        public string Encrypt(string unencrypted)
        {
            return Convert.ToBase64String(Encrypt(encoder.GetBytes(unencrypted)));
        }

        public string Decrypt(string encrypted)
        {
            return encoder.GetString(Decrypt(Convert.FromBase64String(encrypted)));
        }

        public byte[] Encrypt(byte[] buffer)
        {
            return Transform(buffer, encryptor);
        }

        public byte[] Decrypt(byte[] buffer)
        {
            return Transform(buffer, decryptor);
        }

        protected byte[] Transform(byte[] buffer, ICryptoTransform transform)
        {
            MemoryStream stream = new MemoryStream();
            using (CryptoStream cs = new CryptoStream(stream, transform, CryptoStreamMode.Write))
            {
                cs.Write(buffer, 0, buffer.Length);
            }
            return stream.ToArray();
        }
    }

The problem is that in the Transform(byte[] buffer, ICryptoTransform transform) method, I'm getting the error "Length of the data to decrypt is invalid", and I don't understand why.

1

There are 1 answers

1
Jossef Harush Kadouri On BEST ANSWER

Don't store passwords

even if you encrypt them. the best practice is to store the password's hash using a known hash algorithm (SHA256 for example) + using a random salt

For example:

public static string GeneratePasswordHash(string password, string salt)
{
   Byte[] passwordBytes = Encoding.UTF8.GetBytes(password + salt);
   Byte[] hashedBytes = new SHA256CryptoServiceProvider().ComputeHash(passwordBytes);
   return BitConverter.ToString(hashedBytes).Replace("-", String.Empty);
}

usage

public bool Authenticate(username, password)
{
    User user = // Get user info  -> Users.SelectSingle(x=>x.Username.Equals(username))
    string calculatedHash = GeneratePasswordHash(password, user.Salt);
    return user.HashedPassword.Equals(calculatedHash);
}

play with it @ tutorialspoint.com

http://goo.gl/34e1ve

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

class Program
{
    public static string GeneratePasswordHash(string password, string salt)
    {
       Byte[] passwordBytes = Encoding.UTF8.GetBytes(password + salt);
       Byte[] hashedBytes = new SHA256CryptoServiceProvider().ComputeHash(passwordBytes);
       return BitConverter.ToString(hashedBytes).Replace("-", String.Empty);
    }
    
    
    static void Main()
    {
        // Get from Database
        var user = new {
            HashedPassword = "C0918DCF45AFE4CB00363A7C70920841EB76AE522CAA3AA5EED3C5A020870C21",
            Salt = "apjsdm/2ascxz" // Make it random every time
        };
        
        // The password you want to verify
        string password = "12345";
        string calculatedHash  = GeneratePasswordHash(password, user.Salt);
        
        if (user.HashedPassword.Equals(calculatedHash))
        {
            Console.WriteLine("Valid Password");    
        }
        else
        {
            Console.WriteLine("Invalid Password");    
        }
    }
}