-1

我是安全新手,我尝试了很多来删除异常(在代码下方)。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) 
4

2 回答 2

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());

请注意,您确实需要指定一个由随机字节组成的初始化向量,当然不是您的密钥(就像在您的代码中一样)。此外,TDES 需要 128 位或 192 位密钥。

于 2013-01-12T19:41:15.150 回答
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 用于使用相同的密钥加密多个密文,而不会引入安全漏洞。例如,攻击者可以知道第一个不那么秘密的密文包含单词“yes”。然后下一个密码块出现并包含完全相同的字节;显然,发件人再次发送了“是”这个词。如果 IV 被更改,攻击者将看到一个完全不同的密文——尽管对于流密码来说它仍然是 3 个字节长。

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

于 2013-01-13T13:10:44.693 回答