11

Here's the encryption method:

public static byte[] Encrypt(byte[] plaintext, byte[] key)
{
    using (var aes = Aes.Create())
    {
        aes.BlockSize = 128;
        aes.Mode = CipherMode.ECB;
        aes.Padding = PaddingMode.None;

        var iv = new byte[16];
        for (int i = 0; i < iv.Length; i++)
            iv[i] = 0;
        aes.IV = iv;

        var encryptor = aes.CreateEncryptor(key, aes.IV);
        using(var target = new MemoryStream())
        using (var cs = new CryptoStream(target, encryptor, CryptoStreamMode.Write))
        {
            using (var source = new StreamWriter(cs))
                source.Write(plaintext);
            return target.ToArray();
        }
    }
}

And how I'm calling it:

var key = new byte[16] { 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 };
var plaintext = new byte[16] { 128, 0, 112, 0, 96, 0, 80, 0, 64, 0, 48, 0, 32, 0, 16, 0 };

But it keeps throwing an exception at source.Write(plaintext) that says it's not a complete block? I'm using a 16 byte/ 128 bit array with the block size set to 128. I don't understand what's wrong?

Also, just to head off any suggestions that ECB is bad etc, this is not for production, I'm just playing around.

John Saunders
  • 160,644
  • 26
  • 247
  • 397
ConditionRacer
  • 4,418
  • 6
  • 45
  • 67

5 Answers5

12

StreamWriter writes UTF8 text characters to a stream.
You're writing plaintext.ToString() as text for the ciphertext.

This returns "System.Byte[]", which does not translate into 16 bytes of UTF8.

SLaks
  • 868,454
  • 176
  • 1,908
  • 1,964
  • 6
    @Justin984 He's saying if you already have a byte array, you don't need to use a `StreamWriter`, because that is for turning strings into byte arrays with a certain encoding (UTF-8 by default). Just write your bytes to the stream directly with [`Stream.Write()`](http://msdn.microsoft.com/en-us/library/system.io.memorystream.write(v=vs.110).aspx). – Brian Rogers Oct 27 '13 at 03:36
9

I believe the problem to be padding mode. Unless your text to be encrypted is for sure divisible by BlockSize (in bits, or BlockSize / 8 in bytes), you should specify a PaddingMode other than None.

see the post here for example code

Community
  • 1
  • 1
ZagNut
  • 1,431
  • 15
  • 20
2

I changed the function to this:

public static byte[] Encrypt(byte[] plaintext, byte[] key)
{
    using (var aes = Aes.Create())
    {
        aes.BlockSize = 128;
        aes.Mode = CipherMode.ECB;
        aes.Padding = PaddingMode.None;

        var encryptor = aes.CreateEncryptor(key, new byte[16]);
        using(var target = new MemoryStream())
        using (var cs = new CryptoStream(target, encryptor, CryptoStreamMode.Write))
        {
            cs.Write(plaintext, 0, plaintext.Length);
            return target.ToArray();
        }
    }
}
ConditionRacer
  • 4,418
  • 6
  • 45
  • 67
2

From what I have experienced and fixed this issue, I missed to encrypt the field that it is complaining about, I was only decrypting it. It was saving a plain clear text and trying to decrypt it. So just make sure that the field that is complaining about is encrypted first. Thanks

Pidoski
  • 21
  • 4
  • I got the same issue, which raised a question how to figure out if file is encrypted. It's not so easy, may require AES-Encrypt-then-MAC process.. – sam sergiy klok May 30 '23 at 05:03
-7

This is valid for PowerShell: This could happen if you encrypted the password without using -key option. To fix it encrypt it using -key option:

ConvertFrom-SecureString -key $key