0

i have server running on azure, after hours of debugging i changed the azure to run on 64 bit machine and now when i try to encrypt or decrypt i have this error: "invalid length for a base-64 char array or string" what could it be? (when i run local tests all works)

using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Security.Cryptography;
using System.Text;
using System.Web;

namespace Server
{
    public class Crypto
    {
        static readonly string PasswordHash = "P@@Sw0rd";
        static readonly string SaltKey = "S@LT&KEY";
        static readonly string VIKey = "@1B2c3D4e5F6g7H8";

        public static string Encrypt(string plainText)
        {
            byte[] plainTextBytes = Encoding.UTF8.GetBytes(plainText);

            byte[] keyBytes = new Rfc2898DeriveBytes(PasswordHash, Encoding.ASCII.GetBytes(SaltKey)).GetBytes(256 / 8);
            var symmetricKey = new RijndaelManaged() { Mode = CipherMode.CBC, Padding = PaddingMode.Zeros };
            var encryptor = symmetricKey.CreateEncryptor(keyBytes, Encoding.ASCII.GetBytes(VIKey));

            byte[] cipherTextBytes;

            using (var memoryStream = new MemoryStream())
            {
                using (var cryptoStream = new CryptoStream(memoryStream, encryptor, CryptoStreamMode.Write))
                {
                    cryptoStream.Write(plainTextBytes, 0, plainTextBytes.Length);
                    cryptoStream.FlushFinalBlock();
                    cipherTextBytes = memoryStream.ToArray();
                    cryptoStream.Close();
                }
                memoryStream.Close();
            }

            StringBuilder crypt = new StringBuilder(Convert.ToBase64String(cipherTextBytes));
            if (crypt.Length > 0)
            {
                for (int i = 0; i < 3; i++)
                {
                    if (crypt[crypt.Length - 1 - i] == '=')
                    {
                        crypt[crypt.Length - 1 - i] = '*';
                    }
                    else break;
                }
            }
            return crypt.ToString();
        }

        public static string Decrypt(string encryptedText)
        {
            StringBuilder crypt = new StringBuilder(encryptedText);
            if (crypt.Length > 0)
            {
                for (int i = 0; i < 3; i++)
                {
                    if (crypt[crypt.Length - 1 - i] == '*')
                    {
                        crypt[crypt.Length - 1 - i] = '=';
                    }
                    else break;
                }
            }
            byte[] cipherTextBytes = Convert.FromBase64String(crypt.ToString());
            byte[] keyBytes = new Rfc2898DeriveBytes(PasswordHash, Encoding.ASCII.GetBytes(SaltKey)).GetBytes(256 / 8);
            var symmetricKey = new RijndaelManaged() { Mode = CipherMode.CBC, Padding = PaddingMode.None };

            var decryptor = symmetricKey.CreateDecryptor(keyBytes, Encoding.ASCII.GetBytes(VIKey));
            var memoryStream = new MemoryStream(cipherTextBytes);
            var cryptoStream = new CryptoStream(memoryStream, decryptor, CryptoStreamMode.Read);
            byte[] plainTextBytes = new byte[cipherTextBytes.Length];

            int decryptedByteCount = cryptoStream.Read(plainTextBytes, 0, plainTextBytes.Length);
            memoryStream.Close();
            cryptoStream.Close();
            return Encoding.UTF8.GetString(plainTextBytes, 0, decryptedByteCount).TrimEnd("\0".ToCharArray());
        }
    }
}
Artjom B.
  • 61,146
  • 24
  • 125
  • 222
  • The IV must be unpredictable (read: random). Don't use a static IV (`VIKey`), 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 is not secret, so you can send it along with the ciphertext. Usually, it is simply prepended to the ciphertext and sliced off before decryption. – Artjom B. Jun 05 '17 at 19:11
  • Check [this](https://stackoverflow.com/questions/2925729/invalid-length-for-a-base-64-char-array). It might be a primary key base64 format issue – Liquid Core Aug 27 '18 at 09:22

1 Answers1

0

After tested your code on my Azure Web App(x64 platform), I found it worked good on my side. Here is my test code.

public ActionResult TestCrypto()
{
    string encryptedText = Crypto.Encrypt("123456");
    string text = "Encrypted Text : " + encryptedText + "<br/>";
    string originalText = Crypto.Decrypt(encryptedText);
    text += "Origial Text : " + originalText;
    return Content(text);
}

Here is the result I got from server.

enter image description here

I suggest you test the upper code in your server and post the result.

invalid length for a base-64 char array or string

The exception often occurs when decrypting the encrypted text. If you store the encrypted text in a database, sometimes the encrypted text lost some data due to the column used to store the data doesn't have enough space. For example, the column type which you defined is nvarchar(32) and the length of encrypted text is 56 which is more than 32. Please make sure the encrypted text haven't been changed before you decrypt it.

Amor
  • 8,325
  • 2
  • 19
  • 21