Image Steganography

Steganography is a technique to hide confidential information in public information. By using the characteristics of image files, we can hide some information that we want to deliberately hide or information that proves identity and copyright in image files. For example, the early popular technology of spreading some download links and seed files hidden in picture files, and the accurate positioning of personal information through employee screenshots in the “mooncake event” of an Internet company’s internal forum can all be classified as Image Steganography. This paper mainly introduces some common image steganography techniques and their Implementation methods in Python.

Metadata modification

Images are made up of pixels, but image files need to store some additional description information besides the information of pixels. In the case of a common JPEG image, the file format specifies certain characters to mark a particular metadata starting point, as shown below:

The EXIF flag, which is often used to store the information about the shooting device, is stored in the APPn flag bit. To read a JPEG image in binary format, you can see the start (SOI), end (EOI) symbols of the file:

with open("input.jpg"."rb") as f:
    f_bytes = f.read()
    print( f_bytes[:2])print( f_bytes[-2:)# OUTPUT
""" b'\xff\xd8' b'\xff\xd9' """ 
Copy the code

In binary format, you can append information directly to the image file:

txt = 'hello PyHub! '

# code
with open("out_append.jpg"."wb") as f:
    with open("input.jpg"."rb") as ff:
        f.write(f_bytes[sos:])
        f.write('hello PyHub! '.encode())
        
# decoding
with open("out_append.jpg"."rb") as f:
    content = f.read()
    eoi = content.find(b'\xff\xd9')
    print(content[eoi+2:].decode()) 

 # OUTPUT
 "" "hello PyHub! "" " 
Copy the code

The method of metadata modification can be done without any loss of image quality, but at the same time, it is the most vulnerable to attack. Most image uploading applications will clean the image content to remove unnecessary metadata to protect user privacy.

Bit operation

The second method is to modify the specific image data. The principle is to make use of the rich information of the image itself, and the overall visual effect will not be affected in the case of a small amount of modification (tampering). The most common method is the Least Significant Bit (LSB), which has many variants, but its core idea is that the use of the lowest Significant Bit has little impact on the pixel value, and the visual effect of the medium pixel after tampering has little impact.

For example, we can binary a simple watermark image to get a picture with only 0/1 representation:

from PIL import Image
import numpy as np
from matplotlib import pyplot as plt

logo = Image.open("logo.jpg").convert("L")
logo_bin = np.where( np.array(logo) > 128.1.0).astype(np.uint8)

Copy the code

base = Image.open("input.jpg")
# lowest order is 0
base_lsb = np.bitwise_and(base, 0xFE)
# Splice logo to lowest order (one channel, 3 channels can be left)
logo_h, logo_w = logo_bin.shape
base_lsb[:logo_h, :logo_w, 0] += logo_bin

# decoding
base_decode = np.bitwise_and(base_lsb[:,:,0].1)
Copy the code

The above example only takes up the lowest bit of information in the original image’s single channel, or the original image and the hidden image can be split 50/50, the principle is the same.

Please refer to: github.com/kelvins/ste…

Bits on image data for operation method are many, such as by modifying the parity of lowest value, direct store binary encoding (www.geeksforgeeks.org/image-based)… ; Or resegment the image by bit, and so on.

Obviously, steganography by manipulating the image data will modify the visual quality of the image to some extent, and for images that are not rich in content (such as large areas of solid color background), this method is easy to give away.

Frequency domain watermarking

In addition to pixel (spatial domain) operations, operations can also be performed in the frequency domain. The principle is to add watermark to the data in the frequency domain after Fourier transform is performed:

# Original, 1-1
base = Image.open("input.jpg").convert("L")

base_fft = np.fft.fft2(np.array(base))
base_ffs = np.fft.fftshift(base_fft)

# Create watermark
fnt = ImageFont.truetype("Cyberway Riders.otf".40)
wm = Image.new("L", base.size, (0))
ImageDraw.Draw(wm).text((0.0), "PyHub", font=fnt, fill=(255))
wm_arr = np.array(wm)
# Reverse generates centrosymmetry, figure 1-2
fft_wm_arr = (np.flip(wm_arr) + wm_arr).astype(np.uint8)

# Overlay watermark, Figure 1-3
base_ffs.real[fft_wm_arr == 255] = 255

# Inverse Fourier transform, Figure 2-1
base_reversed = np.real( np.fft.ifft2( np.fft.ifftshift(base_ffs) ) )
# Decode the figure after inverse transformation (encoding), as shown in Figure 2-2
base_decode = np.clip(np.fft.fftshift( np.fft.fft2(base_reversed)).real, 0.255)

# The difference between the coded image and the original one, see Figure 2-2
base_reversed - np.array(base) 
Copy the code

The above method is relatively simple and rough, which directly adds a watermark to a specific region in the frequency domain. The actual effect may cause great damage to the original image. A more accurate method should be to encode the watermark image, so that the watermark image is evenly distributed in each frequency. . The method of modifying the frequency domain has less influence on the visual effect of the image and has better restoration effect in the face of various image rewriting attacks.

Deep learning

Everything can be deeply learned.

Through the PapersWithCode website, we can see some studies that try to use deep learning methods to carry out Image steganography. For example, this paper adopts the adjunct generative network (GAN) model to encode Data into the Image:

You can install the author’s pre-trained model by PIP install Steganogan:

steganogan encode input.jpg "Hi PyHub" -o out_gan.jpg 
Copy the code

The effect is as follows: