【问题标题】:File Encryption Using RSA使用 RSA 加密文件
【发布时间】:2015-02-07 12:32:53
【问题描述】:

我正在尝试实现 RSA 算法。我想加密图像。问题是解密完成后,文件无法读取。我不知道问题到底出在哪里。这是RSA的实现:

import java.awt.image.BufferedImage;
import java.math.BigInteger;
import java.util.Random;
import java.io.*;
import java.nio.file.Files;
import java.nio.file.Path;
import java.nio.file.Paths;
import java.util.logging.Level;
import java.util.logging.Logger;
import javax.imageio.ImageIO;


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

private Random r;
 public RSA() {
    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 static void main (String[] args) throws IOException
       {

RSA rsa = new RSA();   

      byte[] bytesImage= rsa.readBytesFromFile(new File(
            "F:\\calla.jpg"));
      //readBytesFromFile: method to read file as bytes


 byte[] encrypted = rsa.encrypt(bytesImage);    
     writeBytesToFile(new File(
            "F:\\encryptedcalla.jpg"),encrypted );
  //writeBytesToFile: method to write as bytes

// decrypt
    byte[] decrypted = rsa.decrypt(encrypted); 
     writeBytesToFile(new File(
            "F:\\decryptedcalla.jpg"),decrypted );


}

这是加密的方法:

    // Encrypt image
 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;

} 

读写的方法描述在这里:http://www.java2s.com/Code/Java/File-Input-Output/Readfiletobytearrayandsavebytearraytofile.htm

【问题讨论】:

  • 我不得不问你为什么要编写自己的加密代码。如果不是用于图像解密只是尝试编写加密的借口的玩具项目,我强烈建议使用(更安全的)预先编写的实现。
  • 我必须通过我的实现来测试它。
  • 呃,到底测试什么?
  • 此外,逐字节加密是不安全的(它等同于替换密码,它对已知明文攻击非常失败,而对选择明文攻击完全失败)
  • 1) 使用混合加密 2) 教科书 RSA 完全损坏。

标签: java encryption cryptography rsa


【解决方案1】:

正如你所说,问题在于这一步:

encryptedImage[i]= (BigInteger.valueOf(image[i])).modPow(e, N).byteValue();

问题是,modPow() 返回一个 1024 位数字,而您正试图将其填充到一个 8 位字节中。你不能这样做而不丢失一些信息,如果你丢失了任何信息,那么你将无法解密消息。

RSA 是数学密码学:您必须将消息编码为数字,然后通过计算将该数字转换为不同数字(即modPow(e, N))的函数进行加密。然后你必须传输整个加密的消息号。

消息的接收者获取加密的号码并通过解密函数modPow(d, N)运行它,它应该返回原始号码,然后可以将其转换回原始消息。

但收件人必须获得完整的 1024 位数字才能进行解密。

如果您使用 RSA 加密图像的每个单独字节,那么对于加密算法中的每个字节,您必须向接收者发送一个 1024 位数据包。然后接收方可以解密该数据包,并提取原始字节。

或者,您可以一次加密两个字节,或十个字节,或 100 个字节;但你不能做的是让“数据包”小于 1024 位。

【讨论】:

  • 如果你的意思是你不能做的是让“数据包”小于 1024 位,那么单个 RSA 调用的消息必须大于1024 位,那么将无法恢复消息。它必须是 1024 位,但值必须小于 N。这就是为什么使用 padding 时将第一个字节设置为 0x00 并填充到 1024 位。
  • @james large 正如我从您的回答中了解到的那样,我已经更改了加密和解密方法:这是加密方法:' public BigInteger[] encrypt (byte[] image){ BigInteger[] encryptedImage = 新的 BigInteger[image.length]; for (int i =0 ; i
  • @ArtjomB。你是对的。当我说“将您的消息编码为数字”时,我没有解释填充。我试图传达的想法是,从本质上讲,RSA 算法不会加密 messages,它会加密 numbers,而且你不能只发送部分的加密号码,并期望在另一端恢复部分原始号码。您必须发送整个号码。知道这么多的人应该能够弄清楚填充的必要性以及在明文和数字和密文之间转换的细节,反之亦然。
  • 因此,加密方法将采用字节数组并返回 BigInteger 数组。而解密方法将采用 BigInteger 数组并返回应该是原始字节的字节数组。
  • 加密方法:public BigInteger[] encrypt (byte[] image){ BigInteger[] encryptedImage = new BigInteger[image.length]; for (int i =0 ; i&lt; image.length; i++){ encryptedImage[i]= (BigInteger.valueOf(image[i])).modPow(e, N); } return encryptedImage; }解密方法:public byte[] decrypt(BigInteger[] image) { byte[] decryptedImage = new byte[image.length]; for (int i =0 ; i&lt; image.length; i++){ decryptedImage[i]= (image[i]).modPow(d, N).byteValue(); } return decryptedImage; }应该返回原始字节。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2011-09-12
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2012-04-07
  • 2019-05-08
相关资源
最近更新 更多