gpt4 book ai didi

java - 我的异或加密不适用于复杂文件

转载 作者:塔克拉玛干 更新时间:2023-11-02 08:57:11 25 4
gpt4 key购买 nike

只是为了好玩,我一直在尝试制作一个文件加密器,它对 128 位 key 进行按位异或加密。它似乎适用于使用某些编辑器的纯文本文件,但对于其他和更复杂的文件,我遇到了“文件损坏”错误。如果我对一个文本文件进行两次加密,在 Gedit 中它会像它应该的那样显示原始文件的内容,但在记事本中,我只会得到一大堆问号。

我用 Java 编写了这段代码,但是加密部分非常通用。 key 的形式为 8 个 16 位字符的数组:

char[] key = {26372, 15219, 53931, 50406, 26072, 23469, 25002, 37812};

为了加密文件,我有一个运行这段代码的循环:

builder.append((char)(bR.read() ^ key[pos++]));
if(pos == 8) pos = 0; //returns to first position in key

这会使用 BufferedReader 从文件中读取下一个字符,将其与键中的下一个字符进行异或并将其附加到 StringBuilder。

完整代码如下:

import java.awt.BorderLayout;
import java.awt.Toolkit;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.io.BufferedReader;
import java.io.BufferedWriter;
import java.io.File;
import java.io.FileReader;
import java.io.FileWriter;
import java.io.IOException;

import javax.swing.JButton;
import javax.swing.JFileChooser;
import javax.swing.JFrame;
import javax.swing.JOptionPane;
import javax.swing.JPanel;
import javax.swing.JProgressBar;
import javax.swing.JScrollPane;
import javax.swing.JTextArea;
import javax.swing.SwingUtilities;
import javax.swing.SwingWorker;
import javax.swing.UIManager;


public class Encryptor implements Runnable {

/**
* @param args
*/
public static void main(String[] args) {
try {
SwingUtilities.invokeAndWait(new Encryptor());
} catch(Exception e) {
e.printStackTrace();
}
}

JFrame frame;
JButton bCancel, bEncrypt;
JTextArea statusArea;
JScrollPane statusScroll;
JProgressBar progressBar;
String fileContents, fileType, fileName;
EncryptSwingWorker encryptWorker;
char[] key = {
26372, 15219, 53931, 50406, 26072, 23469, 25002, 37812};

public void run() {

try {
UIManager.setLookAndFeel(UIManager.getSystemLookAndFeelClassName());
} catch(Exception e) {}

frame = new JFrame();

statusArea = new JTextArea();
statusArea.setEditable(false);
statusScroll = new JScrollPane(statusArea);
progressBar = new JProgressBar();
progressBar.setValue(0);

bCancel = new JButton("Cancel");
bCancel.setEnabled(false);
bCancel.addActionListener(new ActionListener() {

@Override
public void actionPerformed(ActionEvent arg0) {
int option = JOptionPane.showOptionDialog(frame,
"Are you sure you want to cancel?",
"Warning", JOptionPane.YES_NO_OPTION,
JOptionPane.QUESTION_MESSAGE, null,
null, null
);
if(option == 0) {
encryptWorker.cancel(true);
statusArea.append("Encryption cancelled\n");
progressBar.setValue(0);
progressBar.setIndeterminate(false);
bCancel.setEnabled(false);
bEncrypt.setEnabled(true);
}
}

});
bEncrypt = new JButton("Encrypt file...");
bEncrypt.addActionListener(new ActionListener() {

@Override
public void actionPerformed(ActionEvent e) {
encryptWorker = Encryptor.this.new EncryptSwingWorker();
encryptWorker.execute();
}

});

JPanel top = new JPanel(new BorderLayout());
top.add(bEncrypt, BorderLayout.CENTER);
top.add(bCancel, BorderLayout.EAST);
frame.getContentPane().add(top, BorderLayout.NORTH);
frame.getContentPane().add(statusScroll, BorderLayout.CENTER);
frame.getContentPane().add(progressBar, BorderLayout.SOUTH);

frame.setSize(200, 150);
frame.setResizable(false);
frame.setTitle("sEncryptor");
frame.setVisible(true);
frame.setDefaultCloseOperation(JFrame.DISPOSE_ON_CLOSE);
frame.setIconImage(Toolkit.getDefaultToolkit().getImage("encryptor.png"));
}

void encrypt() throws IOException {
JFileChooser fc = new JFileChooser();
int returnVal = fc.showOpenDialog(frame);

if(returnVal == JFileChooser.APPROVE_OPTION) {
if(fc.getSelectedFile() == null) {
JOptionPane.showOptionDialog(frame,
"You did not select a file",
"File Open Error",
JOptionPane.DEFAULT_OPTION,
JOptionPane.WARNING_MESSAGE, null,
null, null
);
encrypt();
return;
}

bCancel.setEnabled(true);
bEncrypt.setEnabled(false);

fileName = fc.getSelectedFile().getPath();

statusArea.append("Calculating size...\n");
progressBar.setIndeterminate(true);
int size = (int)(new File(fileName).length() / 32);
progressBar.setIndeterminate(false);
progressBar.setMaximum(size);

BufferedReader bR = new BufferedReader(new FileReader(fc.getSelectedFile()));
StringBuilder builder = new StringBuilder();

statusArea.append("Encrypting...\n");
int pos = 0;
for(double d = 0; bR.ready(); d += 0.03125) {
if(encryptWorker.isCancelled()) return;
progressBar.setValue((int)d);
builder.append((char)(bR.read() ^ key[pos++]));
if(pos == 8) pos = 0;
}

progressBar.setValue(0);
progressBar.setIndeterminate(true);

fileContents = builder.toString();
bR.close();
statusArea.append("Encryption finished\n");
progressBar.setIndeterminate(false);
}
}

void save(String file) throws IOException {
statusArea.append("Saving...\n");
progressBar.setIndeterminate(true);
BufferedWriter bW = new BufferedWriter(new FileWriter(file));
bW.write(fileContents);
bW.close();
progressBar.setIndeterminate(false);
statusArea.append("Done!\n");
}

void saveAs() throws IOException {
JFileChooser fc = new JFileChooser();
int returnVal = fc.showSaveDialog(frame);

if(returnVal == JFileChooser.APPROVE_OPTION) {
if(fc.getSelectedFile() == null) {
JOptionPane.showOptionDialog(frame,
"You did not select a file",
"File Open Error",
JOptionPane.DEFAULT_OPTION,
JOptionPane.WARNING_MESSAGE, null,
null, null
);
saveAs();
return;
}

save(fc.getSelectedFile().getPath());
}
}

class EncryptSwingWorker extends SwingWorker<Void, Void> {

@Override
protected Void doInBackground() throws Exception {
encrypt();
if(EncryptSwingWorker.this.isCancelled()) return null;
bCancel.setEnabled(false);
while(true) {
Object[] options = {"Override", "Save As...", "Cancel"};
int option = JOptionPane.showOptionDialog(frame,
"Override existing file?",
"Save", JOptionPane.YES_NO_CANCEL_OPTION,
JOptionPane.QUESTION_MESSAGE, null,
options, options[0]
);
if(option == 0)
try {
save(fileName);
} catch(IOException e1) {
e1.printStackTrace();
}
else if(option == 1)
try {
saveAs();
} catch(IOException e1) {
e1.printStackTrace();
}
else {
int option1 = JOptionPane.showOptionDialog(frame,
"The encryption will be lost if you continue\n" +
"Are you sure you want to cancel?",
"Warning", JOptionPane.YES_NO_OPTION,
JOptionPane.QUESTION_MESSAGE, null,
null, null
);
if(option1 == 1) continue;
break;
}
break;
}
fileContents = "";
bEncrypt.setEnabled(true);
return null;
}

}
}

我的代码中是否遗漏了什么,或者对整个文件进行异或运算会导致问题吗?

最佳答案

明白了。问题出在文件编码中,一如既往:)。永远,永远,依赖于默认编码 - 它最终会适得其反。

因为 ReaderWriter 类是为纯文本输入/输出而创建的,所以它会变得困惑。在这种情况下,Writer 不知道如何处理它获取的各种整数并最终失败。当你修复Writer时,你也必须修复Reader,因为加密的数据可能不是只有有效字符...

最佳解决方案是忽略字符,使用字节和 FileInputStream , FileOutputStream (如有必要,由他们的 Buffered 兄弟包装),因为它们是用来处理二进制数据的。这样,您最终将准确读取/写入您打算读取/写入的数据。尝试自己破解它,这是一个很好的教训。如果您遇到困难,请查看 here .

最简单的解决方案是只更改两行。请注意,它再次仅适用于文本文件!说真的,不要把随机数和可打印字符混在一起。

BufferedReader bR = new BufferedReader(new FileReader(fc.getSelectedFile()));

BufferedReader bR = new BufferedReader(new InputStreamReader(new FileInputStream(fc.getSelectedFile()), "UTF-8"));

BufferedWriter bW = new BufferedWriter(new FileWriter(file));

BufferedWriter bW = new BufferedWriter(new OutputStreamWriter(new FileOutputStream(file), "UTF-8"));

关于java - 我的异或加密不适用于复杂文件,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/11006555/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com