【发布时间】:2018-04-07 18:57:12
【问题描述】:
我正在尝试用 Java 加密和解密一条消息,但总是遇到同样的错误:
java.security.InvalidKeyException:密钥太长,无法展开
我正在尝试模拟从服务器向客户端发送加密消息。
第一个:客户端生成私钥和公钥。
2nd 客户端将公钥发送给服务器。
3rd:服务器生成对称 AES 密钥。
4t:服务器用他的 AES 密钥加密他想发送给客户端的文本。
5e:服务器使用从客户端收到的公钥加密 AES 密钥。
6e:服务器将加密文本和加密后的 AES 密钥发送给客户端。
7e:客户端用他的私钥解密 AES 密钥。
8e:客户端使用解密后的 AES 密钥对从服务器接收到的文本进行解密。
public class Test {
private static SecretKey secretKey;
private static KeyPair keyPair;
private static final String STRINGTOENCRYPT = "This is a test";
private static String stringEncripted;
private static String keyEncripted;
public static final byte[] IV_PARAM = {0x00, 0x01, 0x02, 0x03,
0x04, 0x05, 0x06, 0x07,
0x08, 0x09, 0x0A, 0x0B,
0x0C, 0x0D, 0x0E, 0x0F};
public static void main(String[] args) {
generateKeys();
}
private static void generateKeys() {
secretKey = generateSecretKey(128);
keyPair = generateKeyPair(512);
stringEncripted = encriptString(STRINGTOENCRYPT);
keyEncripted = encriptKey(keyPair.getPublic());
decryptString();
}
private static void decryptString() {
Cipher cipher = null;
Key keyDecrypted = null;
try {
cipher = Cipher.getInstance("RSA/ECB/PKCS1Padding");
cipher.init(Cipher.UNWRAP_MODE, keyPair.getPrivate());
keyDecrypted = cipher.unwrap(keyEncripted.getBytes(), "AES", Cipher.SECRET_KEY);
cipher = Cipher.getInstance("AES/CBC/PKCS5Padding");
IvParameterSpec iv = new IvParameterSpec(IV_PARAM);
cipher.init(Cipher.DECRYPT_MODE, keyDecrypted, iv);
byte[] stringDecryptedBytes = cipher.doFinal(stringEncripted.getBytes());
String stringDecrypted = new String(stringDecryptedBytes);
System.out.println(stringDecrypted);
} catch (Exception e) {
e.printStackTrace();
}
}
private static KeyPair generateKeyPair(int lenght) {
KeyPair keyPublicAndPrivate = null;
try {
KeyPairGenerator keyGen = KeyPairGenerator.getInstance("RSA");
keyGen.initialize(lenght);
keyPublicAndPrivate = keyGen.genKeyPair();
} catch (Exception ex) {
ex.printStackTrace();
}
return keyPublicAndPrivate;
}
private static SecretKey generateSecretKey(int lenght) {
SecretKey sKey = null;
if ((lenght == 128) || (lenght == 192) || (lenght == 256)) {
try {
KeyGenerator kgen = KeyGenerator.getInstance("AES");
kgen.init(lenght);
sKey = kgen.generateKey();
} catch (NoSuchAlgorithmException ex) {
ex.printStackTrace();
}
}
return sKey;
}
private static String encriptString(String stringtoencrypt) {
byte[] stringtoencryptBytes = stringtoencrypt.getBytes();
Cipher cipher = null;
String stringEncrypted = null;
try {
cipher = Cipher.getInstance("AES/CBC/PKCS5Padding");
IvParameterSpec iv = new IvParameterSpec(IV_PARAM);
cipher.init(Cipher.ENCRYPT_MODE, secretKey, iv);
byte[] stringEncryptedBytes = cipher.doFinal(stringtoencryptBytes);
stringEncrypted = new String(cipher.doFinal(stringtoencryptBytes), "UTF-8");
} catch (Exception e) {
e.printStackTrace();
}
return stringEncrypted;
}
private static String encriptKey(PublicKey aPublic) {
String keyEncryptedString = null;
try {
Cipher cipher = Cipher.getInstance("RSA/ECB/PKCS1Padding");
cipher.init(Cipher.WRAP_MODE, aPublic);
byte[] keyEncriptedBytes = cipher.wrap(secretKey);
keyEncryptedString = new String(keyEncriptedBytes, "UTF-8");
} catch (Exception e) {
e.printStackTrace();
}
return keyEncryptedString;
}
}
知道为什么会这样吗?
【问题讨论】:
-
尝试用私钥解密aes密钥..
-
已经改变了,但我得到了同样的错误
-
这可能不是导致错误的原因,但我希望你知道现在 512 位 RSA 很容易被破解。您应该使用at least 2048 bit RSA keys,并且最好使用更长的时间。
-
请完整的堆栈跟踪以及它出现在代码中的位置。不是在 cmets 中,而是在问题中。
-
现代(计算机)加密(AES 和 RSA,以及许多其他东西,如 SHA2)产生包含明显随机位的字节,而不是有效的字符代码。尝试将这些字节“解码”为 Java
String,然后再恢复它们通常是行不通的。最好使用字节或无损编码,如 hex 或 base64;如果您必须使用原始字符,请尝试“charset”ISO-8859-1,它将所有八位字节值 (0-255) 标识映射到 Unicode 块 0,但在大多数 JVM 实例上不是默认值
标签: java encryption