【问题标题】:Reading encrypted bytes from an image in java从java中的图像中读取加密字节
【发布时间】:2015-04-07 15:50:44
【问题描述】:

我必须在加密图像中嵌入文本(隐写术)。我用谷歌搜索并找到了在图像中嵌入文本的代码。但是我必须首先加密图像并将文本嵌入到这个加密的图像中。我的尝试如下。

/*
 * To change this template, choose Tools | Templates
 * and open the template in the editor.
 */
package tbn;

import java.awt.Graphics2D;
import java.awt.Point;
import java.awt.Transparency;
import java.awt.image.BufferedImage;
import java.awt.image.ColorModel;
import java.awt.image.ComponentColorModel;
import java.awt.image.DataBuffer;
import java.awt.image.DataBufferByte;
import java.awt.image.Raster;
import java.awt.image.WritableRaster;
import java.io.File;
import java.io.IOException;
import java.security.InvalidKeyException;
import java.security.NoSuchAlgorithmException;
import java.security.SecureRandom;
import java.util.logging.Level;
import java.util.logging.Logger;
import javax.crypto.BadPaddingException;
import javax.crypto.Cipher;
import javax.crypto.IllegalBlockSizeException;
import javax.crypto.KeyGenerator;
import javax.crypto.NoSuchPaddingException;
import javax.crypto.SecretKey;
import javax.imageio.ImageIO;

/**
 *
 * @author user
 */
public class DbtClass {

    public static void main(String[] args) {
        try {
            BufferedImage orgnlimage = ImageIO.read(new File("parrruuuuu.png"));
            orgnlimage = user_space(orgnlimage);
            byte[] orgnlimagebytes = get_byte_data(orgnlimage);
            byte[] encryptedbytes = encrypt(orgnlimagebytes, "abc");
            BufferedImage encryptedimage = toImage(encryptedbytes, orgnlimage.getWidth(), orgnlimage.getHeight());
            ImageIO.write(encryptedimage, "png", new File("encrypted.png"));

            /////////////////////////////////////////////////////////////////////
            /////////////////////////////////////////////////////////////////////

            byte[] encryptedbytes2 = get_byte_data(encryptedimage);
            System.out.println("encryptedbytes before writing: "+encryptedbytes2.length);

            BufferedImage encryptedimage3 = ImageIO.read(new File("encrypted.png"));
            byte[] encryptedbyte3 = get_byte_data(encryptedimage3);
            System.out.println("encryptedbytes after writing: "+encryptedbyte3.length);


        } catch (IOException ex) {
            Logger.getLogger(DbtClass.class.getName()).log(Level.SEVERE, null, ex);
        }
    }

    public static BufferedImage user_space(BufferedImage image) {
        //create new_img with the attributes of image
        BufferedImage new_img = new BufferedImage(image.getWidth(), image.getHeight(), BufferedImage.TYPE_3BYTE_BGR);
        Graphics2D graphics = new_img.createGraphics();
        graphics.drawRenderedImage(image, null);
        graphics.dispose(); //release all allocated memory for this image
        return new_img;
    }

    public static byte[] get_byte_data(BufferedImage image) {
        WritableRaster raster = image.getRaster();
        DataBufferByte buffer = (DataBufferByte) raster.getDataBuffer();
        return buffer.getData();
    }

    public static byte[] encrypt(byte[] orgnlbytes, String key) {
        byte[] encbytes = null;
        try {
            Cipher cipher = Cipher.getInstance("AES");
            KeyGenerator keyGen = KeyGenerator.getInstance("AES");
            SecureRandom random = SecureRandom.getInstance("SHA1PRNG");
            // cryptograph. secure random 
            random.setSeed(key.getBytes());

            keyGen.init(128, random);
            // for example
            SecretKey secretKey = keyGen.generateKey();
            cipher.init(Cipher.ENCRYPT_MODE, secretKey);
            encbytes = cipher.doFinal(orgnlbytes);
        } catch (NoSuchAlgorithmException ex) {
            Logger.getLogger(DbtClass.class.getName()).log(Level.SEVERE, null, ex);
        } catch (NoSuchPaddingException ex) {
            Logger.getLogger(DbtClass.class.getName()).log(Level.SEVERE, null, ex);
        } catch (InvalidKeyException ex) {
            Logger.getLogger(DbtClass.class.getName()).log(Level.SEVERE, null, ex);
        } catch (IllegalBlockSizeException ex) {
            Logger.getLogger(DbtClass.class.getName()).log(Level.SEVERE, null, ex);
        } catch (BadPaddingException ex) {
            Logger.getLogger(DbtClass.class.getName()).log(Level.SEVERE, null, ex);
        }
        return encbytes;
    }

    public static BufferedImage toImage(byte[] imagebytes, int width, int height) {
        DataBuffer buffer = new DataBufferByte(imagebytes, imagebytes.length);
        WritableRaster raster = Raster.createInterleavedRaster(buffer, width, height, 3 * width, 3, new int[]{2, 1, 0}, (Point) null);
        ColorModel cm = new ComponentColorModel(ColorModel.getRGBdefault().getColorSpace(), false, true, Transparency.OPAQUE, DataBuffer.TYPE_BYTE);
        return new BufferedImage(cm, raster, true, null);
    }
}

在这里,我使用光栅类和 ImageIO.write() 编写了加密图像。然后使用 ImageIO.read() 从文件中读取此加密字节。写入图像之前的加密字节 [] 和读取后的字节 []图像完全不同

【问题讨论】:

  • 但是在将图像写入文件之前,从 BufferedImage 我得到了你提到的额外 16 个字节。所以我认为问题可能出在 ImageIO.write() 或 ImageIO.read() 中,谢谢您的评论@Reti43
  • “隐写术是将文件、消息、图像或视频隐藏在另一个文件、消息、图像或视频中的艺术或实践。”如果你认为你需要加密图像来执行隐写术,那么你就完全偏离了路线。
  • 您是先将消息嵌入到运营商中,然后再对运营商进行加密吗?为什么还要加密载体图像? “无法从字节中识别图像”是什么意思?
  • 加密后的图片写入前字节数和读取后字节数不一样@Reti43

标签: java image image-processing encryption steganography


【解决方案1】:

所以这就是发生的事情。假设大小为WxH 的原始图像。由于每个像素有 3 个字节,因此您的图像 orgnlimagebytesS = 3*W*H 字节。

现在您使用 AES 加密此图像,结果为 fixed block size of 16 bytes。如果S 不能被 16 整除,则会被填充为这样。如果它可以被 16 整除,则会添加另一个 16 字节的块。这里的重点是加密字节数组encryptedbytes 的大小比orgnlimagebytes 大。打电话给S'

现在您使用方法toImage 从这个字节数组中创建一个 BufferedImage。您创建一个encryptedbytes 的缓冲区,将其转换为光栅,然后等等等等。你最终会得到一个大小为WxH 的图像。然而,发生的事情是 BufferedImage 对象具有对具有S' 元素的缓冲区的引用。您只使用第一个 S 元素来构造图像的像素,但您仍然可以从缓冲区访问其余元素。因此,当您再次将 BufferedImage 转换为字节数组 encryptedbytes2 时,您将得到所有 S' 的元素数量。

该图像只有WxH RGB 像素,因此如果您尝试将其保存到图像文件中,您将只保存这些像素。您不会从缓冲区引用中保存任何额外的字节。因此,当您保存并加载图像并将其转换为字节数组 expectedbytes3 时,您会得到预期的字节数,应该是 S


这解释了加密字节数组在保存到文件之前和之后的意外不一致。但是,除了加密的方法,为什么还要对封面图进行加密呢?如果您在将消息隐藏在图像中之前对其进行加密以提高安全性,以防有人设法检测和提取消息,这将是有意义的。加密封面图像的像素值意味着彻底改变它们,这会带来明显的变化。

【讨论】:

猜你喜欢
  • 1970-01-01
  • 2014-02-13
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2016-12-21
  • 1970-01-01
  • 1970-01-01
  • 2011-12-18
相关资源
最近更新 更多