我正在eclipse上用java编写一个程序,该程序处理使用AES算法查找消息的解密 key ,该算法由从0到MAX_VALUE的数字组成的16位数字组成,其余数字均为0。后来我提出了代码。
private String name;
private int in;
private int end;
private final String FORMAT = String.format("%%0%dd", 16);
private final String KEYWORD = "come";
public Soldier(String name, int in, int end) {
super(name);
this.name = name;
this.in = in;
this.end = end;
}
private boolean found(File f) {
try {
BufferedReader br = new BufferedReader(new InputStreamReader(new FileInputStream(f)));
String line = null;
line = br.readLine();
while(line!=null) {
if(line.contains(KEYWORD)) {
br.close();
return true;
}
line = br.readLine();
}
br.close();
return false;
} catch(Exception e) {
return false;
}
}
public void run() {
File encryptedFile = new File("document.encrypted");
File decryptedFile = new File(nome+".decrypted");
for(int i=in;i<end;i++) {
if(this.isInterrupted())
break;
String key = String.format(FORMAT, i);
try {
CryptoUtils.decrypt(key, encryptedFile, decryptedFile);
try {
if(found(decryptedFile)) {
System.out.println("Key found: "+ key + " Thread: "+name);
this.interrupt();
break;
}
} catch(NumberFormatException e) {
e.printStackTrace();
}
} catch(Exception ex) {
System.out.println("Tested key: "+ key + "Thread n: "+ name);
continue;
}
}
}
这是包含 run 方法的类。
private static final String ALGORITHM = "AES";
private static final String TRANSFORMATION = "AES";
public static void encrypt(String key, File inputFile, File outputFile) throws CryptoException {
doCrypto(Cipher.ENCRYPT_MODE, key, inputFile, outputFile);
}
public static void decrypt(String key, File inputFile, File outputFile) throws CryptoException {
doCrypto(Cipher.DECRYPT_MODE, key, inputFile, outputFile);
}
private static void doCrypto(int cipherMode, String key, File inputFile, File outputFile) throws CryptoException {
try {
Key secretKey = new SecretKeySpec(key.getBytes(), ALGORITHM);
Cipher cipher = Cipher.getInstance(TRANSFORMATION);
cipher.init(cipherMode, secretKey);
try (CipherOutputStream out = new CipherOutputStream(new BufferedOutputStream(new FileOutputStream(outputFile)), cipher)) {
Files.copy(inputFile.toPath(), out);
}
} catch(Exception ex) {
throw new CryptoException("Error encrypting/decrypting file", ex);
}
}
这是解密类。
private static final long serialVersionUID = 2850972529362612601L;
public CryptoException(String message, Throwable throwable) {
super(message, throwable);
}
这是解密出错时引发的异常。但是,可以通过在屏幕上打印 run 方法中所测试的键号来管理此异常。然后我显示错误的堆栈跟踪。
decrittazione.CryptoException: Error encrypting/decrypting file
at decrittazione.CryptoUtils.doCrypto(CryptoUtils.java:42)
at decrittazione.CryptoUtils.decrypt(CryptoUtils.java:23)
at decrittazione.Soldier.run(Soldato.java:50)
Caused by: javax.crypto.BadPaddingException: Given final block not properly padded. Such issues can arise if a bad key is used during decryption.
at java.base/com.sun.crypto.provider.CipherCore.unpad(CipherCore.java:975)
at java.base/com.sun.crypto.provider.CipherCore.fillOutputBuffer(CipherCore.java:1056)
at java.base/com.sun.crypto.provider.CipherCore.doFinal(CipherCore.java:853)
at java.base/com.sun.crypto.provider.AESCipher.engineDoFinal(AESCipher.java:446)
at java.base/javax.crypto.Cipher.doFinal(Cipher.java:2208)
at decrittazione.CryptoUtils.doCrypto(CryptoUtils.java:36)
... 2 more
Soldier s1 = new Soldier("1", 0, /*endNumber*/);
Soldier s2 = new Soldier("2", /*inNumber*/, /*endNumber*/);
Soldier s3 = new Soldier("3", /*inNumber*/, /*endNumber*/);
Soldier s4 = new Soldier("4", /*inNumber*/, /*endNumber*/);
Soldier s5 = new Soldier("5", /*inNumber*/, /*endNumber*/);
Soldier s6 = new Soldier("6", /*inNumber*/, /*endNumber*/);
Soldier s7 = new Soldier("7", /*inNumber*/, /*endNumber*/);
Soldier s8 = new Soldier("8", /*inNumber*/, /*endNumber*/);
Soldier s9 = new Soldier("9", /*inNumber*/, /*endNumber*/);
Soldier s10 = new Soldier("10", /*inNumber*/, /*endNumber*/);
Soldier s11 = new Soldier("11", /*inNumber*/, /*endNumber*/);
Soldier s12 = new Soldier("12", /*inNumber*/, /*endNumber*/);
Soldier s13 = new Soldier("13", /*inNumber*/, /*endNumber*/);
Soldier s14 = new Soldier("14", /*inNumber*/, /*endNumber*/);
Soldier s15 = new Soldier("15", /*inNumber*/, 2147483647);
s1.start();
s2.start();
s3.start();
s4.start();
s5.start();
s6.start();
s7.start();
s8.start();
s9.start();
s10.start();
s11.start();
s12.start();
s13.start();
s14.start();
s15.start();
while(true) {
if(s1.isInterrupted() || s2.isInterrupted() || s3.isInterrupted() || s4.isInterrupted() || s5.isInterrupted() || s6.isInterrupted() || s7.isInterrupted() || s8.isInterrupted() || s9.isInterrupted() || s10.isInterrupted() || s11.isInterrupted() || s12.isInterrupted() || s13.isInterrupted() || s14.isInterrupted() || s15.isInterrupted()) {
s1.interrupt();
s2.interrupt();
s3.interrupt();
s4.interrupt();
s5.interrupt();
s6.interrupt();
s7.interrupt();
s8.interrupt();
s9.interrupt();
s10.interrupt();
s11.interrupt();
s12.interrupt();
s13.interrupt();
s14.interrupt();
s15.interrupt();
break;
}
}
}
最后这是主要方法。
这段代码使用我选择的键和我在 Windows 上选择的消息执行测试,没有任何问题。通过切换到始终在 Eclipse 上的 MacOS(相同版本、相同的 JDK 等),而不是在测试 key 时,程序无法解密消息并继续使用后续 key ,直到它们耗尽为止,因此不是所需的结果。
如果我没能很好地解释自己,我很抱歉,但我不知道还能如何解释这件事。我很抱歉,即使它不是世界上最好的代码,但我是一个初学者。
最佳答案
我不确定是什么导致了您的问题,但我知道 inputStream.read(inputBytes);
不能保证填充 inputBytes 数组。这就是为什么该方法返回一个计数,告诉您实际读取了多少字节。
如果您使用的是 Java 9 或更高版本,则最好使用 inputBytes = inputStream.readAllBytes();
。
如果任何文件很大,将整个内容读入内存将会损害性能。大于 2 GB 的文件根本无法放入字节数组中。
解决这个问题的方法是使用 CipherOutputStream :
Key secretKey = new SecretKeySpec(key.getBytes(), ALGORITHM);
Cipher cipher = Cipher.getInstance(TRANSFORMATION);
cipher.init(cipherMode, secretKey);
try (CipherOutputStream out = new CipherOutputStream(
new BufferedOutputStream(
new FileOutputStream(outputFile)), cipher)) {
Files.copy(inputFile.toPath(), out);
}
关于java - MacOS 多线程问题?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/59447224/