java - MacOS 多线程问题?

标签 java multithreading eclipse macos

我正在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/

相关文章:

multithreading - 线程池多队列作业调度算法

Android、Eclipse、Google_Play_Services_Lib - 尝试导入项目并出现错误

java - 计算字符串中的出现次数并删除重复项

java - 当我们使用Thread的join方法时,前一个线程如何再次启动

java - 如何在java中创建一个元素数组?

java - 如果我加入已终止(死亡)的线程怎么办

java - 有什么方法可以从 Eclipse 自动生成 ant build.xml 文件?

android - 我应该关注 Eclipse 控制台区域中的 DDMS 消息吗?

java - PhantomJS 驱动程序未单击页面中的元素,但未引发错误

java - 为什么 read() 的返回类型是整数?