2015-02-07 60 views
0

我必須在加密圖像(Stegnography)中嵌入文本。我搜索並找到了在圖像中嵌入文本的代碼。但我必須首先加密圖像並將文本嵌入到此加密圖像中。我的嘗試如下。從java中的圖像讀取加密字節

/* 
* 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()此加密的字節。寫入所述圖像和所述字節之前的加密的字節[] []看完圖像後總是不一樣

+0

但是在將圖像寫入文件之前,我從BufferedImage獲得了額外的16字節,您提到過。所以我認爲問題可能出現在ImageIO.write()或ImageIO.read()中,無論如何謝謝你的評論 @ Reti43 – TBN 2015-02-07 17:31:53

+0

「隱寫術是在另一個文件中隱藏文件,消息,圖像或視頻的藝術或做法,消息,圖片或視頻。「如果你認爲你需要加密圖像來執行隱寫術,那麼你完全不在路上。 – 2015-02-07 17:41:35

+0

您是否第一次將郵件嵌入到運營商中,然後加密了運營商?爲什麼你甚至要加密載體圖像? 「* image無法從字節*中識別」是什麼意思? – Reti43 2015-02-07 18:22:46

回答

1

所以這裏發生了什麼。假設尺寸爲WxH的原始圖像。由於每個像素有3個字節,因此您的圖像orgnlimagebytes的字節數爲S = 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轉換成一個字節數組時,你會得到所有的S'元素。

該圖像只有WxH RGB像素,所以如果您嘗試將其保存到圖像文件,這就是您要保存的所有內容。您不會保存緩衝區引用中的任何附加字節。所以當你保存並加載圖像並將其轉換爲字節數組時,expectedbytes3,你會得到預期的字節數,應該是S


這解釋了在保存到文件之前和之後加密字節數組的意外不一致性。但是,除了加密方法,爲什麼你甚至要加密封面圖像?如果您在將消息隱藏在圖像中之前對其進行了加密,那麼在有人設法檢測並提取消息的情況下提供額外的安全性是有意義的。加密封面圖像的像素值意味着大幅改變它們,這引入了明顯的變化。

+0

http://stackoverflow.com/questions/28396404/save-encrypted-image-bytes-to-file-and-recover-to-原始圖像在爪哇 – TBN 2015-02-08 16:54:08

+0

由於書面語言質量差,這篇論文很難理解,但從來沒有談及AES加密。 – Reti43 2015-02-08 17:05:50