HiveBrain v1.2.0
Get Started
← Back to all entries
patternpythonMinor

Steganography with AES encryption

Submitted by: @import:stackexchange-codereview··
0
Viewed 0 times
withencryptionsteganographyaes

Problem

I created a small program that hides arbitrary files in png images using steganography - it encodes the files in the two least significant bits of every channel, so using a 4-channel png we can encode one byte per pixel.

I also wanted to hide the presence of secret data by encrypting it, and, in effect, making it indistinguishable from random noise to make it impossible to prove there is any data at all hidden in the image without a valid key.

I would like to know if the method I'm using is safe and robust, and if there is anything I should have done better. I'm using a python library called cryptography to do the encryption. It would be also nice to know what attacks (if any) my code could be vulnerable to.

The whole code of my program can be found here.

Here are the functions that do the encryption and decryption. The idea is that the password string you pass to the program is turned into a large key using a key derivation function.

```
def encrypt(data, password, padding=0):
"""Encrypts data using the password.
Encrypts the data using the provided password using the cryptography module.
The password is converted into a base64-encoded key which is then used in a
symmetric encryption algorithm.
"""

if padding < 0:
print "Image too small to encode the file. \
You can store 1 byte per pixel."
exit()

password = bytes(password)

#Use key stretching to generate a secure key
kdf = PBKDF2HMAC(
algorithm=hashes.SHA256(),
length=32,
salt=bytes(password),
iterations=100000,
backend=default_backend())

key = kdf.derive(bytes(password))

nonce = os.urandom(16)

cipher = Cipher(algorithms.AES(key),\
modes.CTR(nonce), backend=default_backend())
enc = cipher.encryptor()
ct = enc.update(data) + enc.finalize()

#Add padding if needed
ct += os.urandom(padding-16)

#add nonce to data to allow decryption later (nonce does not need to be

Solution

For cases like this:

if padding < 0:
        print "Image too small to encode the file. \
You can store 1 byte per pixel."
        exit()


It's probably better to define a custom exception and raise that:

class SizeError(Exception):
    pass

...

if padding < 0 :
    raise SizeError("Image too small to encode the file. \
    You can store 1 byte per pixel.")


I'm no security expert, but is it ok to use the string you want to encode as salt in kdf? This looks like security through obscurity (because it means you just double the input before encrypting).

Code Snippets

if padding < 0:
        print "Image too small to encode the file. \
You can store 1 byte per pixel."
        exit()
class SizeError(Exception):
    pass

...

if padding < 0 :
    raise SizeError("Image too small to encode the file. \
    You can store 1 byte per pixel.")

Context

StackExchange Code Review Q#136401, answer score: 2

Revisions (0)

No revisions yet.