java - 谁能告诉我在使用 RSA 的图像加密和解密过程中犯了什么错误

标签 java encryption cryptography

我将图像分割成一定数量的子图像,并对每个子图像进行加密和解密处理。之后,我将所有加密的字节存储到一个 jpg 文件中,并将解密的字节存储到另一个 jpg 文件中。 但我没有从解密的文件和原始图像中获得相同的字节。 代码如下。

import java.awt.Graphics2D;
import java.awt.image.BufferedImage;
import java.io.File;
import java.io.FileInputStream;
import java.io.IOException;
import java.math.BigInteger;

import javax.imageio.ImageIO;
public class ImageSplitTest {
    private static final BigInteger N = null;
    public ImageSplitTest() {
        // TODO Auto-generated constructor stub
    }

    public static void main(String[] args) throws IOException {
        // TODO Auto-generated method stub
        File file = new File("C:\\Users\\Shwetha\\workspace\\penguins.jpg"); // I have bear.jpg in my working directory  
        byte b[]=rsa1.readBytesFromFile(file);
        System.out.println("original image bytes"+ b);
        FileInputStream fis = new FileInputStream(file);  
        BufferedImage image = ImageIO.read(fis); //reading the image file  

        int rows = 2; //You should decide the values for rows and cols variables  
        int cols = 2;  
        int chunks = rows * cols;  

        int chunkWidth = image.getWidth() / cols; // determines the chunk width and height  
        int chunkHeight = image.getHeight() / rows;  
        int count = 0;  
        BufferedImage imgs[] = new BufferedImage[chunks]; //Image array to hold image chunks  
        for (int x = 0; x < rows; x++) {  
            for (int y = 0; y < cols; y++) {  
                //Initialize the image array with image chunks  
                imgs[count] = new BufferedImage(chunkWidth, chunkHeight, image.getType());  

                // draws the image chunk  
                Graphics2D gr = imgs[count++].createGraphics();  
                gr.drawImage(image, 0, 0, chunkWidth, chunkHeight, chunkWidth * y, chunkHeight * x, chunkWidth * y + chunkWidth, chunkHeight * x + chunkHeight, null);  
                gr.dispose();  
            }  
        }  
        System.out.println("Splitting done");  

        //writing mini images into image files  
        for (int i = 0; i < imgs.length; i++) {  
            ImageIO.write(imgs[i], "jpg", new File("img" + i + ".jpg"));  


        }  
        System.out.println("Mini images created");  
       rsa1 rsa=new rsa1();
        BufferedImage[] buffImages = new BufferedImage[chunks];  
        byte[] decrypted=null;
        byte[] bytesImage=null;
        for (int i = 0; i < imgs.length; i++) {  
         bytesImage= rsa.readBytesFromFile(new File(
                "img" + i + ".jpg"));
          //readBytesFromFile: method to read file as bytes


     byte[] encrypted = rsa.encrypt(bytesImage);    
         rsa.writeBytesToFile(new File(
                "C:\\Users\\Shwetha\\workspace\\encrypted.jpg"),encrypted );

      //writeBytesToFile: method to write as bytes

    // decrypt
         decrypted = rsa.decrypt(encrypted); 
        rsa. writeBytesToFile(new File(
                "C:\\Users\\Shwetha\\workspace\\decrypted1.jpg"),decrypted );
    }
     System.out.println("bytes from decryption"+decrypted);  
     System.out.println("bytes before encryption"+bytesImage);
}

}

readBytesFromFile、加密和解密方法存在于 rsa1 calss 中。

import java.io.BufferedOutputStream;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.math.BigInteger;
import java.util.Random;

public class rsa1 {
    private BigInteger p;
    private BigInteger q;
    private BigInteger N;
    private BigInteger phi;
    private static BigInteger e;
    private BigInteger d;
    private int bitlength = 1024;

    private Random r;
     public rsa1() {
        r = new Random();
        p = BigInteger.probablePrime(bitlength, r);
        q = BigInteger.probablePrime(bitlength, r);
        N = p.multiply(q);

        phi =   p.subtract(BigInteger.ONE).multiply(q.subtract(BigInteger.ONE));
        e = BigInteger.probablePrime(bitlength/2, r);
        System.out.println("e : "+e);

        while (phi.gcd(e).compareTo(BigInteger.ONE) > 0 && e.compareTo(phi) < 0 ) {
            e.add(BigInteger.ONE);
        }
       d = e.modInverse(phi);
     }

    public byte[] encrypt(byte[] image) {   
       byte[] encryptedImage = new byte[image.length];
      for (int i =0 ; i< image.length; i++){
          encryptedImage[i]= (BigInteger.valueOf(image[i])).modPow(e, N).byteValue(); 

       }   
        return encryptedImage;
    }
    public byte[] decrypt(byte[] image) {   
       byte[] decryptedImage = new byte[image.length];
       for (int i =0 ; i< image.length; i++){
           decryptedImage[i]= (BigInteger.valueOf(image[i])).modPow(d, N).byteValue();

        } 

        return decryptedImage;

        }
    public static byte[] readBytesFromFile(File file) throws IOException {
        InputStream is = new FileInputStream(file);

           // Get the size of the file
           long length = file.length();

           // You cannot create an array using a long type.
           // It needs to be an int type.
           // Before converting to an int type, check
           // to ensure that file is not larger than Integer.MAX_VALUE.
           if (length > Integer.MAX_VALUE) {
             throw new IOException("Could not completely read file " + file.getName() + " as it is too long (" + length + " bytes, max supported " + Integer.MAX_VALUE + ")");
           }

           // Create the byte array to hold the data
           byte[] bytes = new byte[(int)length];

           // Read in the bytes
           int offset = 0;
           int numRead = 0;
           while (offset < bytes.length && (numRead=is.read(bytes, offset, bytes.length-offset)) >= 0) {
               offset += numRead;
           }

           // Ensure all the bytes have been read in
           if (offset < bytes.length) {
               throw new IOException("Could not completely read file " + file.getName());
           }

           // Close the input stream and return bytes
           is.close();
           return bytes;
        // TODO Auto-generated method stub

     }


     }

谁能告诉我如何从解密的 jpg 文件或解密的字节中恢复我的原始图像。

最佳答案

在加密过程中您几乎丢弃了所有信息。如果您对单个字节的输入执行位大小为 1024 的 RSA,则结果将是 1024 位,而不是 8 位。因此,当您调用 byteValue() 时,您会丢弃包含重要信息的其他 1016 位。

由于您使用教科书 RSA(只是模幂),您的解密方法不会注意到。它也只会执行模幂运算,检索一些随机值,然后将其输入到 byteValue() 中。

您应该深入了解混合密码系统并使用 RSA OAEP 来创建用于图像加密的安全协议(protocol)。当前的协议(protocol)方式(包括安全性)存在致命缺陷。

关于java - 谁能告诉我在使用 RSA 的图像加密和解密过程中犯了什么错误,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/31750529/

相关文章:

c# - UWP:AES加密和解密

javascript - 使用 CryptoJS 解密 AES CFB 时有效字节数错误

使用 AES 的 Java 加密文件 - 最佳方法

java - 如何获取 Firestore 集合中所有文档的名称(字段)?

java - 什么是NullPointerException,我该如何解决?

c++ - 如何循环 Blowfish Crypto++

javascript - Ruby 和 JavaScript 之间的 RSA key 对加密/解密?

java - Neo4j 遍历 API 限制?

java - 将 .js、.css 文件提供给 html 模板时出现 spring-boot 404 错误

java - MySQL MD5 和 Java MD5 不相等