2

~/Cipher/nsdl/crypto 中的所有文件都可以在这里找到 用 gcj 编译的 java 文件,请参阅 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).");
        }
    }
}
}
4

2 回答 2

2

密码 ,ecipher未初始化,IllegalStateException当您尝试使用它时,它会抛出一个,就好像它是在 中初始化的一样ENCRYPT_MODE

请注意您catchBlockCrypt. 它正在捕获没有消息的异常,并将“null”打印到System.err. 而不是中止执行——也许是通过从构造函数中抛出一个异常——你继续航行。

替换System.err.println(e.getMessage())e.printStackTrace()或至少System.err.println(e)应该为您提供更多详细信息。我的猜测是ecipher.init()抛出异常,因为您提供的是 32 位 IV 而不是 64 位。

于 2008-11-26T08:09:22.577 回答
0

也许查看javax.crypto.Cipher 的源代码有助于理解这一点?即使在源代码中找到错误消息,我也无法弄清楚。祝你好运!

于 2008-11-26T05:09:09.430 回答