Можете ли вы выяснить, почему эта программа вызывает исключение IllegalStateException? - PullRequest
2 голосов
/ 26 ноября 2008

все файлы в ~ / Cipher / nsdl / crypto можно найти здесь Java-файлы, скомпилированные с помощью gcj, см. compile.sh

nmint@nqmk-mint ~/Cipher/nsdl/crypto $ echo test | ./cryptTest encrypt deadbeefdeadbeefdeadbeefdeadbeef deadbeef Blowfish CBC > test
null
Exception in thread "main" java.lang.IllegalStateException: cipher is not for encrypting or decrypting
   at javax.crypto.Cipher.update(libgcj.so.81)
   at javax.crypto.CipherOutputStream.write(libgcj.so.81)
   at nsdl.crypto.BlockCrypt.encrypt(cryptTest)
   at nsdl.crypto.cryptTest.main(cryptTest)

BlockCrypt.java:

package nsdl.crypto;

import java.io.*;
import java.security.spec.*;
import javax.crypto.*;
import javax.crypto.spec.*;

public class BlockCrypt {
Cipher ecipher;
Cipher dcipher;
byte[] keyBytes;
byte[] ivBytes;
SecretKey key;
AlgorithmParameterSpec iv;
byte[] buf = new byte[1024];

BlockCrypt(String keyStr, String ivStr, String algorithm, String mode) {
    try {
        ecipher = Cipher.getInstance(algorithm + "/" + mode + "/PKCS5Padding");
        dcipher = Cipher.getInstance(algorithm + "/" + mode + "/PKCS5Padding");

        keyBytes = hexStringToByteArray(keyStr);
        ivBytes = hexStringToByteArray(ivStr);

        key = new SecretKeySpec(keyBytes, algorithm);
        iv = new IvParameterSpec(ivBytes);

        ecipher.init(Cipher.ENCRYPT_MODE, key, iv);
        dcipher.init(Cipher.DECRYPT_MODE, key, iv);
    } catch (Exception e) {
        System.err.println(e.getMessage());
    }
}

public void encrypt(InputStream in, OutputStream out) {
    try {
        // out: where the plaintext goes to become encrypted
        out = new CipherOutputStream(out, ecipher);

        // in: where the plaintext comes from
        int numRead = 0;
        while ((numRead = in.read(buf)) >= 0) {
            out.write(buf, 0, numRead);
        }
        out.close();
    } catch (IOException e) {
        System.err.println(e.getMessage());
    }
}

public void decrypt(InputStream in, OutputStream out) {
    try {
        // in: where the plaintext come from, decrypted on-the-fly
        in = new CipherInputStream(in, dcipher);

        // out: where the plaintext goes
        int numRead = 0;
        while ((numRead = in.read(buf)) >= 0) {
            out.write(buf, 0, numRead);
        }
        out.flush();
        out.close();
    } catch (IOException e) {
        System.err.println(e.getMessage());
    }
}
public static byte[] hexStringToByteArray(String s) {
    int len = s.length();
    byte[] data = new byte[len / 2];
    for (int i = 0; i < len; i += 2) {
        data[i / 2] = (byte) ((Character.digit(s.charAt(i), 16) << 4)
        + Character.digit(s.charAt(i+1), 16));
    }
    return data;
}
}

cryptTest.java:

package nsdl.crypto;

import nsdl.crypto.BlockCrypt;

public class cryptTest {

public static void main (String args[]) {
    if (args.length != 5) {
        System.err.println("Usage: cryptTest (encrypt|decrypt) key iv algorithm mode");
        System.err.println("Takes input from STDIN. Output goes to STDOUT.");
    } else {
        String operation = args[0];
        String key = args[1];
        String iv = args[2];
        String algorithm = args[3];
        String mode = args[4];
        BlockCrypt blockCrypt = new BlockCrypt(key, iv, algorithm, mode);
        if (operation.equalsIgnoreCase("encrypt")) {
            blockCrypt.encrypt(System.in, System.out);
        } else if (operation.equalsIgnoreCase("decrypt")) {
            blockCrypt.decrypt(System.in, System.out);
        } else {
            System.err.println("Invalid operation. Use (encrypt|decrypt).");
        }
    }
}
}

Ответы [ 2 ]

2 голосов
/ 26 ноября 2008

Шифр ​​ecipher не инициализирован и выдает IllegalStateException, когда вы пытаетесь использовать его, как если бы он был инициализирован в ENCRYPT_MODE.

Обратите внимание на ваш блок catch в конструкторе BlockCrypt. Он перехватывает исключение без сообщения и выдает «null» в System.err. Вместо того, чтобы прервать выполнение - возможно, вызвав исключение из конструктора - вы продолжаете движение.

Замена System.err.println(e.getMessage()) на e.printStackTrace() или хотя бы System.err.println(e) должна дать вам больше деталей. Я предполагаю, что ecipher.init() вызывает исключение, потому что вы предоставляете 32-битный IV вместо 64 бит.

0 голосов
/ 26 ноября 2008

Возможно, поиск источника для javax.crypto.Cipher помогает это понять? Я не мог понять это, даже находя сообщение об ошибке в источнике. Удачи!

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...