我是安全新手,我尝试了很多删除异常(代码下方)。 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)
答案 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)
您的代码存在多个问题。
最重要的是你混淆了字符和字节。你必须知道character-encoding - 这是关于二进制和后面的文本编码 - 以及encoding - 这是关于将二进制编码为可读文本。
如果您希望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(基于密码的密钥派生函数)作为次优替换。但我认为这可能是一个更高级的话题。