使用 Blowfish 时如何修复 Java 中的 NoSuchAlgorithmException?

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/5763723/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-10-30 12:38:30  来源:igfitidea点击:

How to fix the NoSuchAlgorithmException in Java when using Blowfish?

javaencryptionblowfish

提问by Tamer

So I'm writing a program to encrypt and decrypt text files but I seem to be always getting this error when I use an encrypthion other than "Blowfish" (e.g. "Blowfish/CBC/PKCS5Padding"). The excepthiong I get is:

所以我正在编写一个程序来加密和解密文本文件,但是当我使用“Blowfish”以外的加密(例如“Blowfish/CBC/PKCS5Padding”)时,我似乎总是遇到这个错误。我得到的例外是:

Exception in thread "main" java.security.NoSuchAlgorithmException: Blowfish/CBC/PKCS5Padding KeyGenerator not available
    at javax.crypto.KeyGenerator.<init>(DashoA13*..)
    at javax.crypto.KeyGenerator.getInstance(DashoA13*..)
    at Encryptor.<init>(Encryptor.java:87)
    at Encryptor.main(Encryptor.java:30)

A portion of my code:

我的代码的一部分:

import java.security.MessageDigest;
import java.security.SecureRandom;

import javax.crypto.Cipher;
import javax.crypto.spec.IvParameterSpec;
import javax.crypto.spec.SecretKeySpec;

public class Encryptor2 {
    private IvParameterSpec ivSpec;
    private SecretKeySpec keySpec;
    private Cipher cipher;

    public static void main(String[] args) throws Exception {
        Encryptor2 e = new Encryptor2(
                "averylongtext!@$@#$#@$#*&(*&}{23432432432dsfsdf");
        String enc = e.encrypt("john doe");
        String dec = e.decrypt(enc);
    }

    public Encryptor2(String pass) throws Exception {
        // setup AES cipher in CBC mode with PKCS #5 padding
        cipher = Cipher.getInstance("AES/CBC/PKCS5Padding");

        // setup an IV (initialization vector) that should be
        // randomly generated for each input that's encrypted
        byte[] iv = new byte[cipher.getBlockSize()];
        new SecureRandom().nextBytes(iv);
        ivSpec = new IvParameterSpec(iv);

        // hash keyString with SHA-256 and crop the output to 128-bit for key
        MessageDigest digest = MessageDigest.getInstance("SHA-256");
        digest.update(pass.getBytes());
        byte[] key = new byte[16];
        System.arraycopy(digest.digest(), 0, key, 0, key.length);
        keySpec = new SecretKeySpec(key, "AES");
    }

    public String encrypt(String original) throws Exception {
        cipher.init(Cipher.ENCRYPT_MODE, keySpec, ivSpec);
        byte[] encrypted = cipher.doFinal(original.getBytes("UTF-8"));
        System.out.println("encrypted: `" + new String(encrypted) + "`");
        return new String(encrypted);
    }

    public String decrypt(String encrypted) throws Exception {
        cipher.init(Cipher.DECRYPT_MODE, keySpec, ivSpec);
        byte[] decrypted = cipher.doFinal(encrypted.getBytes("UTF-8"));
        System.out.println("decrypted: `" + new String(decrypted, "UTF-8")
                + "`");
        return new String(decrypted, "UTF-8");
    }
}

But now it fails with Input length must be multiple of 16 when decrypting with padded cipher

但现在它失败了 Input length must be multiple of 16 when decrypting with padded cipher

回答by WhiteFang34

The additional parameters that you're specifying with the algorithm are meant for Cipher. For KeyGeneratorand SecretKeySpecyou only specify the algorithm. The other parameters are for the cipher mode of operation and padding to be used. For example, if you're using Blowfish in CBC mode with PKCS #5 padding you want:

您使用算法指定的其他参数适用于Cipher. 对于KeyGenerator并且SecretKeySpec您只指定算法。其他参数用于密码操作模式和要使用的填充。例如,如果您在 CBC 模式下使用带有 PKCS #5 填充的 Blowfish,则需要:

KeyGenerator keyGen = KeyGenerator.getInstance("Blowfish");
Cipher cipher = Cipher.getInstance("Blowfish/CBC/PKCS5Padding");

See Encrypting and Decrypting Using Java: Unable to get same outputfor an example. It uses the same mode and padding as you have. The only difference is that uses AES instead of Blowfish, however it works exactly the same.

有关示例,请参阅使用 Java 加密和解密:无法获得相同的输出。它使用与您相同的模式和填充。唯一的区别是使用 AES 而不是 Blowfish,但它的工作原理完全相同。