0

I would like to limit the length of the encrypted output code like 8 or 10 or 12 character etc.

I have created the very small encrypted coed using he "Advanced Encryption Standard (AES)" with Cryptography.SymmetricAlgorithm.IV.

But the result of the Encrypted code as example below:

Input Password = "090400551"

Converted Output = "mkopj3WFb6RZMp34urFLew==" // This should be half the length

I want to reduce the length of 8 to 12 character. Any C# cryptography library or algorithm would be fine

using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Security.Cryptography;
using System.Text;
using System.Threading.Tasks;

namespace AnotherEncryption
{
    class Encryption
    {

        public static class Global
        {
            // set password
            public const string strPassword = "090400551";   
            public const String strPermutation = "Secure1234";
            public const Int32 bytePermutation1 = 0x78;
            public const Int32 bytePermutation2 = 0x56;
            public const Int32 bytePermutation3 = 0x34;
            public const Int32 bytePermutation4 = 0x88;
        }

        static void Main(string[] args)
        {
            Console.Title = "Secure Password v2";
            Console.WriteLine("Output---");
            Console.WriteLine("");

            Console.WriteLine("Password:  " + Global.strPassword);

            string strEncrypted = (Encrypt(Global.strPassword));
            Console.WriteLine("Encrypted: " + strEncrypted);

            string strDecrypted = Decrypt(strEncrypted);
            Console.WriteLine("Decrypted: " + strDecrypted);

            //mkopj3WFb6RZMp34urFLew==

            Console.ReadKey();
        }

        public static string Encrypt(string strData)
        {
            byte[] test = Encoding.UTF8.GetBytes(strData);
            return Convert.ToBase64String(Encrypt(test));
        }

        public static string Decrypt(string strData)
        {
            return Encoding.UTF8.GetString(Decrypt(Convert.FromBase64String(strData)));

        }

        // encrypt
        public static byte[] Encrypt(byte[] strData)
        {
            PasswordDeriveBytes passbytes =
            new PasswordDeriveBytes(Global.strPermutation,
            new byte[] { Global.bytePermutation1,
                         Global.bytePermutation2,
                         Global.bytePermutation3,
                         Global.bytePermutation4
            });

            MemoryStream memstream = new MemoryStream();
            Aes aes = new AesManaged(); 

            aes.Key = passbytes.GetBytes(aes.KeySize / 8);
            aes.IV = passbytes.GetBytes(aes.BlockSize / 8);  

            CryptoStream cryptostream = new CryptoStream(memstream, aes.CreateEncryptor(), CryptoStreamMode.Write);
            cryptostream.Write(strData, 0, strData.Length);
            cryptostream.Close();
            return memstream.ToArray();
        }

        // decrypt
        public static byte[] Decrypt(byte[] strData)
        {
            PasswordDeriveBytes passbytes =
            new PasswordDeriveBytes(Global.strPermutation,
            new byte[] { Global.bytePermutation1,
                         Global.bytePermutation2,
                         Global.bytePermutation3,
                         Global.bytePermutation4
            });

            MemoryStream memstream = new MemoryStream();
            Aes aes = new AesManaged();
            aes.Key = passbytes.GetBytes(aes.KeySize / 8);
            aes.IV = passbytes.GetBytes(aes.BlockSize / 8);

            CryptoStream cryptostream = new CryptoStream(memstream,
            aes.CreateDecryptor(), CryptoStreamMode.Write);
            cryptostream.Write(strData, 0, strData.Length);
            cryptostream.Close();
            return memstream.ToArray();
        }

    }
}
skt
  • 449
  • 14
  • 32
  • It's the conversion to base 64 string that makes the output longer than the input. – 500 - Internal Server Error Oct 10 '19 at 10:55
  • AES is a block-based cipher with a block size of 128 bits, or 16 bytes. You're not going to get output which isn't a multiple of 16 bytes. – canton7 Oct 10 '19 at 10:59
  • Hi Any other algorithm or library other then AES for getting the password with less character ? – skt Oct 10 '19 at 11:05
  • 1
    Why are you encrypting a password to begin with? The most typical scenario is that you want to hash a password, not encrypt it. – Lasse V. Karlsen Oct 10 '19 at 11:08
  • Hi I need the encrypted password not by Hash. But the length of the Password are very long and difficult to enter by the user. I am creating in Xamarin Form (Android Mobile Platform). On mobile more then 20 character is too long. – skt Oct 10 '19 at 11:12
  • So you want to store a password (using which alphabet?) of 20 characters to be stored in 8 to 12 bytes after encryption? – Maarten Bodewes Oct 10 '19 at 16:20

1 Answers1

0

If you put Rijndael into CFB mode with a block size of 8, then it acts as a stream cipher - for every byte you put in, you get a byte out again.

public static void Main(string[] args)
{
    var algorithm = new RijndaelManaged()
    {
        Mode = CipherMode.CFB,

        // This is the equivalent of BlockSize in CFB mode. We set it to 8 (bits) to prevent any buffering of data 
        // while waiting for whole blocks.
        FeedbackSize = 8,
    };

    // Don't hard-code in real life, obviously
    var key = new byte[32];
    var iv = new byte[16];

    var input = new byte[] { 1, 2, 3 };

    byte[] result;
    using (var ms = new MemoryStream())
    {
        using (var cryptoStream = new CryptoStream(ms, algorithm.CreateEncryptor(key, iv), CryptoStreamMode.Write))
        {
            cryptoStream.Write(input, 0, input.Length);
        }
        result = ms.ToArray();
    }
}

Note that this only appears to work on .NET Framework - .NET Core doesn't seem to support CFB (see this GitHub issue).


Note that encryption doesn't prevent tampering! People can't read your plaintext message, but they can very easily change the ciphertext to control what it gets decrypted to. Stream ciphers tend to be particularly vulnerable to this. If you need to stop someone controlling what the encrypted output decrypts into, then you need a signature.

Also note that you should not use the same IV across multiple messages. Create a random IV, and transfer it alongside your message, frequently as the first 2 bytes.

canton7
  • 37,633
  • 3
  • 64
  • 77
  • You're also forgetting to store the IV, and without a unique IV this method of encryption leaks data. – Maarten Bodewes Oct 10 '19 at 16:03
  • @Maarten I'm saying absolutely nothing about how the IV should be treated. I'm aware that the OP is not handling the IV properly: feel free to make your own answer explaining this. I've added a short note to the bottom of my answer. – canton7 Oct 10 '19 at 16:04
  • 3
    With CBC (the default mode used in the question) however you only leak minimal information if the first 16 bytes are identical. With CFB and the same IV you leak almost all the information, i.e. all passwords (!) – Maarten Bodewes Oct 10 '19 at 16:11
  • *`FeedbackSize = 8`* - They should probably use the full block size for the feedback. – jww Oct 18 '19 at 15:24
  • @jww Am I correct in recalling that if you increase `FeedbackSize`, then your output will be a multiple of this? That is, you could get an output which is longer than the input? – canton7 Oct 18 '19 at 15:28