java.security.InvalidAlgorithmParameterException:在RC6和RC2中

时间:2013-01-12 18:54:59

标签: java encryption cryptography

我是安全新手,我尝试了很多删除异常(代码下方)。 RC2和RC6密码都给出了这个例外。输入应为128位String,密钥为128位,输出应为128位密文。

import java.security.spec.AlgorithmParameterSpec;
import javax.crypto.Cipher;
import javax.crypto.spec.IvParameterSpec;
import javax.crypto.spec.SecretKeySpec;
import java.util.*;

public class RC2Encrypt
{
    public static void main(String args []) throws Exception
    {
        Scanner s=new Scanner(System.in);
        System.out.println("Enter PlainTextString:");
        String input=s.nextLine();

        System.out.println();
        System.out.println("Enter 16 digit key:");
        String strPassword=s.nextLine();

        SecretKeySpec key = new SecretKeySpec(strPassword.getBytes(), "RC2");
        AlgorithmParameterSpec paramSpec = new IvParameterSpec(strPassword.getBytes());
        Cipher cipher =  Cipher.getInstance("RC2");
        cipher.init(Cipher.ENCRYPT_MODE, key, paramSpec);

        byte[] encrypted = cipher.doFinal(input.getBytes());

        String b1 = new String(encrypted);
        System.out.println("Original string: " + input);
        System.out.println("Encrypted string: " + b1);
    }
}

这将产生以下异常:

Exception in thread "main" java.security.InvalidAlgorithmParameterException: Wrong IV    length: must be 8 bytes long
    at com.sun.crypto.provider.SunJCE_f.a(DashoA13*..)
    at com.sun.crypto.provider.RC2Cipher.engineInit(DashoA13*..)
    at javax.crypto.Cipher.a(DashoA13*..)
    at javax.crypto.Cipher.a(DashoA13*..)
    at javax.crypto.Cipher.init(DashoA13*..)
    at javax.crypto.Cipher.init(DashoA13*..)
    at RC2Encrypt.main(RC2Encrypt.java:40) 

2 个答案:

答案 0 :(得分:1)

我肯定会推荐一种不同的算法,因为RC2非常弱。据我所知,没有与JRE捆绑的RC6支持。

您可以按如下方式使用TDES:

SecretKeySpec key = new SecretKeySpec(keyBytes, "DESede");
IvParameterSpec ivSpec = new IvParameterSpec(ivBytes);
Cipher cipher = Cipher.getInstance("DESede/CBC/PKCS5Padding");
cipher.init(Cipher.ENCRYPT_MODE, key, ivSpec);
byte[] encrypted = cipher.doFinal(input.getBytes());

请注意,您需要指定一个由随机字节组成的initialisation vector,当然您的密钥(如代码中所示)。此外,TDES需要128位或192位密钥。

答案 1 :(得分:0)

您的代码存在多个问题。

最重要的是你混淆了字符和字节。你必须知道 - 这是关于二进制和后面的文本编码 - 以及 - 这是关于将二进制编码为可读文本。

如果您希望8个字节由16个字符编码,那么这意味着您需要执行十六进制解码(每个字节使用两个字符)。最好的方法是使用Apache公共编解码器库或Bouncy Castle库。我建议使用后者,因为它包含更多的加密算法 - 包括RC6。最好的方法是使用Bouncy Castle提供程序来实现加密功能。

好的,所以用键和IV解决了部分,现在用于纯文本。纯文本必须是二进制编码的。不幸的是,您现在使用的是平台默认字符集。这意味着如果要与其他系统(或其他应用程序,甚至在您自己的PC上,如果它使用其他字符集)交换它,则会遇到兼容性问题。要删除此问题,您应自行指定编码,例如使用String.getBytes(Charset.forName("UTF-8"))或Java 7以后String.getBytes(StandardCharsets.UTF_8)。对构造函数执行相同的操作。

此外,您确实不应该为密钥和IV使用相同的字节。 IV用于加密具有相同密钥的多个密文,而不会引入安全漏洞。例如。攻击者可以知道第一个不那么秘密的密文包含“是”这个词。然后下一个密码块出现并包含完全相同的字节;很明显,发件人再次发送了“是”这个词。如果IV被更改,攻击者将会看到完全不同的密文 - 尽管流密码的长度仍然是3个字节。

最后,密钥和IV应该是随机生成的 - 可能在过去的某个时间。如果需要密码而不是密钥,则应使用PBKDF(基于密码的密钥派生函数)作为次优替换。但我认为这可能是一个更高级的话题。