I am currently working on a python script that does image steganography, altering the least significant bit on each channel of the image. Now imagine encrypting a file with a bunch of null bytes, or if you want a more realistic scenario, text that has a lot of repeating sequences in it (whole words / characters); Analysing the LSB of every channel of every pixel of this image, will reveal certain patterns and the hidden message can be decrypted easily.

The ultimate goal would be to turn the data given in bits into something that looks like random noise, but can be decoded easily with the given key.

What is a (fast) way to achieve this ?

One idea I came up with after googling for a while is the following: Generate a random bit sequence, the same length as the data you want to hide, that is based on a specific seed/key. It can be generated again as often as you want supplying the same seed. Now xor the generated bit sequence with the data provided and use this hopefully random looking binary data as the basis for the pixel modifications.

Is this (more or less) secure from a cryptographic standpoint provided the evil decoder doesn't know the algorithm ?

  • $\begingroup$ you've got access to a cryptographic library implementing AES/CTR or ChaCha or Salsa20? $\endgroup$
    – SEJPM
    May 9 '15 at 13:46
  • $\begingroup$ Yes I do for AES and Salsa20. I've also found a ChaCha implementation, nothing official though. My main concern is speed. $\endgroup$
    – whiterock
    May 9 '15 at 13:54
  • $\begingroup$ Note that any reasonably good cipher should yield ciphertexts that are indistinguishable from random. $\endgroup$
    – yyyyyyy
    May 9 '15 at 13:55
  • 1
    $\begingroup$ AES is pretty fast. If the implementation supports AES-NI you'll get 3.5 cycles per byte (-> 1GB/s+ on x64 computers). Speed isn't a concern in modern crypto. (ChaCha and Salsa are also pretty fast) $\endgroup$
    – SEJPM
    May 9 '15 at 13:57
  • 1
    $\begingroup$ Keyfiles are usually used with some encryption programs requiring high security margins. (password managers, disk encryption utilities,...) A keyfile is an arbitrary file (may be generated with high entropy on purpose) that is shared among both parties (including yourself now and the future for standard encryption) and is used as (additional) part for key derivation. In short: You have a (secret) file (with random content probably) that will be hashed to get the symmetric key. This kind of file should be transported by another means than the message. $\endgroup$
    – SEJPM
    May 9 '15 at 14:19

What you described is to use a so-called "stram cipher".

Stream ciphers output a random sequence of bytes for the same Key/IV pair.

The usual usage of stream ciphers is to XOR the data with the stream to obtain the encrypted data. You may want to follow the same approach by replacing the LSBs by the bits that were output by the encryption procedure (Data XOR Stream). The data is confidential then and can not be deciphered.

If you use some well-known algorithm like ChaCha, Salsa20 or AES-CTR you don't even have to hide the algorithm, you can tell your adversaries that you use this algorithm and they still can't read the enciphered data. You only need to keep the Key and the IV secret. Note: Using stream ciphers will hide any patterns that might be in the plaintext.

But you're not done here.
An attacker can't read the information but he can still alter it. So he can tamper with the data you encrypted and using some nice bit-flips he can alter the transmitted data in a malicous way (like changing numbers). So you wan't to use some sort of authentication mechanism (Message-Authentication-Code = MAC).

The best approach is to use AES-GCM or ChaCha-Poly1305 to get both: Confidentiality and Integrity. These modes will generate tags (usually 128 bits) which you'd store at the end of the data and you'll be able to verify that the data hasn't been tampered.

  • $\begingroup$ Now what if I have to deliver the key along with or rather in the image file ? $\endgroup$
    – whiterock
    May 9 '15 at 14:00
  • $\begingroup$ please, if anyhow possible, never store key in plaintext. As you want to hide something in the image file I'd suggest you storing the IV in the image file and maybe a salt for a PBKDF and let the user enter a password from which (along with the salt) you derive the key to be used with the IV to decrypt and verify the data. $\endgroup$
    – SEJPM
    May 9 '15 at 14:01
  • $\begingroup$ I can't request a password unfortunately with this specific example. $\endgroup$
    – whiterock
    May 9 '15 at 14:04

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.