简体   繁体   中英

Add salt to data to be encrypted?

Suppose a small amount of data is being encrypted with AES using a 256 key / IV. The data encrypted could be known. For example:

abcdefghijklmno|axXXyyYY343433553353afsafaadfafdfsafsf|2013-01-01T00:00:00

The first two parts (if you break the data on the pipe character) rarely change. the last part, a date / time does change but not often. I've noticed that varying the date but not the first part of the message results in a cypher text which starts out the same all the time, presumably because the plain text is the same to start off.

Does this open me up to any kind of attacks against the encryption algorithm? Would I gain anything by prepending a salt value to the beginning of the plain text?

I'm using the AesManaged class to generate the IV / Key and encrypt / decrypt the plain text, if that makes a difference.

To solve this problem, normally the IV is generated randomly for each cypertext and prepended not encrypted to the encrypted data. In this way every encrypted data is different from the others.

In code it should be

string str = "abcdefghijklmno|axXXyyYY343433553353afsafaadfafdfsafsf|2013-01-01T00:00:00";
byte[] data = Encoding.UTF8.GetBytes(str);
byte[] key = new byte[] { 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15 }; // Your random key, I hope more random!

byte[] encrypted;

// Encrypt

using (var am = new AesManaged())
using (var rng = new RNGCryptoServiceProvider())
{
    am.Key = key;

    var iv = new byte[am.BlockSize / 8];
    rng.GetBytes(iv);
    am.IV = iv;

    using (var encryptor = am.CreateEncryptor())
    using (var ms = new MemoryStream())
    {
        ms.Write(iv, 0, iv.Length);

        using (var encStream = new CryptoStream(ms, encryptor, CryptoStreamMode.Write))
        {
            encStream.Write(data, 0, data.Length);
        }

        encrypted = ms.ToArray();
    }
}

// Decrypt

string str2;

using (var am = new AesManaged())
using (var ms = new MemoryStream(encrypted))
{
    am.Key = key;

    var iv = new byte[am.BlockSize / 8];
    ms.Read(iv, 0, iv.Length);
    am.IV = iv;

    using (var decryptor = am.CreateDecryptor())
    using (var decStream = new CryptoStream(ms, decryptor, CryptoStreamMode.Read))
    using (var ms2 = new MemoryStream())
    {
        decStream.CopyTo(ms2);

        str2 = Encoding.UTF8.GetString(ms2.GetBuffer(), 0, (int)ms2.Length);
    }
}

Note that in general IV reuse cause a weakness in encryption. See for example the wiki :

For CBC and CFB, reusing an IV leaks some information about the first block of plaintext, and about any common prefix shared by the two messages. For OFB and CTR, reusing an IV completely destroys security.[6]

This is one of the primary purposes of the IV. You should generate a random IV for each message that you send (if you're already doing that, something must be wrong in your code).

AES256 should mix data in blocks of 256 bits (32 bytes). Since you have a long leading text (>32 bytes) that rarely changes you will have poor performance using encryption method. You can fix this but beginning the plaintext string with something that changes frequently as long as it changes within the first 32 bytes. You can do this be creating some random seed and actual useful data.

The purpose of seeding is so that "known" strings will not generate recognizable patterns once encrypted. This is the exact problem you will have, so you need to seed you data or at least use volatile data near the beginning of your plaintext.

EDIT: I saw I had a negatives and wondered why. First, by performance I was intending to refer to the quality of the encryption, not execution time. And I accidentally said seed when I meant salt. A minor mistakes, but I see why the negatives. I am leaving my answer because it is the only once that explains (or at attempts to explain) that the salt (or at least something) that changes frequently really needs to appear with the 32 bytes plaintext block fed to AES-256. Salting is usually required if your encrypted data is subject to dictionary attacks (such as passwords), which seem unlikely for the OP, but your encrypted data should never be "predictable", which is why the OP should salt with data within the first 32 bytes.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM