我有一个AES 128位加密方法来加密消息。但它不会加密超过45个字符的邮件。因此,我想我是否可以通过将长度超过45个字符的消息拆分为45个字符或数组列表的数组来实现,然后我一次加密每个块。
所以,如果我有一个长90的消息,我应该有两个大小为45的数组(或者大小为2的数组,每个大小为45chars)。或者是一个arraylist来做到这一点。如果我有一个长180的消息,那么我应该有一个4个数组的块。
更新:所以我最初的问题是无法在客户端 - 服务器聊天中使用AES加密发送长消息。
以下是AES实施的代码,但没有任何填充或IV。
首先我有一个客户;谁发送使用下面的AESmsgEncryption类加密的消息。
客户端类
public void send(String sendMessage) {
userName = GUI.getUserName();
//each index of the array will contain a substring of the send message (maximum length 45 char)
if (sendMessage.length() > 45) {
// String [] arrayOfStrings = new String[sendMessage.length()/45];
int sizeOfArray = sendMessage.length()/45;
System.out.println("CANT SEND MESSAGES LONGER THAN 45");
} else {
String ciphertext = msgAESEnDe.encryptAES(sendMessage, scrtkey);
System.out.println(userName + ": " + ciphertext + " <-- encrypted before sending");
out.println(userName + "#ciphertext$" + ciphertext);
out.flush();
}
}
一旦客户端发出消息,接收器就会接收它(加密)并将其发送回在线客户端。一旦在线客户端收到加密的文本消息,他们使用以下代码解密消息在客户端类中的另一个接收方法
String username = recMessage.substring(0, recMessage.indexOf(' '));
String ciphertxtWithNoName = recMessage.substring(recMessage.indexOf(':') + 2);
scrtkey = new SecretKeySpec(secrtKeyByte, "AES");
String plaintext = msgAESEnDe.decryptedPlain(ciphertxtWithNoName, scrtkey);
System.out.println(username +" " + plaintext +" <-- after decryption");
//current time
String time = log.format(new Date());
// Displaying received message.
ClientGUI.TA_CONVERSATION.append(time+ " ["+username.substring(0, username.length()-1) + "]: " + plaintext + "\n");
所以在AESmsgEncryption类中我有一个方法如下;
public final String encryptAES(final String plaintext, SecretKey key) {
String ciphertext = new String();
try {
Cipher cipher = Cipher.getInstance("AES");
cipher.init(Cipher.ENCRYPT_MODE, key);
byte[] bytePlaintext = plaintext.getBytes();
byte[] byteCiphertext = cipher.doFinal(bytePlaintext);
ciphertext = new BASE64Encoder().encode(byteCiphertext);
} catch (NoSuchAlgorithmException e) {
System.out.println("NoSuchAlgorithmException: " + e);
} catch (NoSuchPaddingException e) {
System.out.println("NoSuchPaddingException: " + e);
} catch (InvalidKeyException e) {
e.printStackTrace();
System.out.println("InvalidKeyException: " + e);
} catch (IllegalBlockSizeException e) {
System.out.println("IllegalBlockSizeException: " + e);
} catch (BadPaddingException e) {
System.out.println("BadPaddingException: " + e);
}
return ciphertext;
}
public final String decryptedPlain(String ciphertext, SecretKey key) {
try {
Cipher cipher = Cipher.getInstance("AES");
cipher.init(Cipher.DECRYPT_MODE, key);
byte [] decodedValue = new Base64().decode(ciphertext.getBytes());
plaintext = cipher.doFinal(decodedValue);
} catch (NoSuchAlgorithmException e) {
System.out.println("NoSuchAlgorithmException: " + e);
} catch (NoSuchPaddingException e) {
System.out.println("NoSuchPaddingException: " + e);
} catch (InvalidKeyException e) {
System.out.println("InvalidKeyException: " + e);
} catch (IllegalBlockSizeException e) {
System.out.println("IllegalBlockSizeException: " + e);
} catch (BadPaddingException e) {
System.out.println("BadPaddingException: " + e);
}
return new String(plaintext);
}
AES密钥在服务器端生成并使用RSA加密发送,然后发送到每个客户端,这就是为什么在客户端我必须将调用中的scrtkey提供给encryptAES和decryptedPlain方法。
重申我的问题;上面的代码不能发送超过45个字符的消息,如何让它发送超过45个字符的消息?如果我需要使用填充和IV,服务器应该发送IV和密钥,对吗?
我希望上面的描述很清楚。
我怎么能在JAVA中做到这一点?
由于
答案 0 :(得分:1)
您获得的这种填充通常与密码的任何限制无关。这是因为:
最后一个是最有可能的,如果你使用随机的IV或密钥,它很可能是随机发生的。在这种情况下,拆分字符串可能只是暂时隐藏问题而不是解决问题。
如果将密文作为字符串数据处理,则应使用base 64编码。确保加密方法之后和解密方法之前的完整密文(以字节为单位)相同,方法是将其视为十六进制字符串。
AES可以轻松加密千兆字节的信息(尽管安全性取决于用例和操作模式)。不需要拆分明文。
答案 1 :(得分:0)
我认为你可以这样:
int length=input.length();
for(int i=0; i<length; i+=45) {
encrypt(input.substring(i, i+45<=length ? i+45 : length ));
}
关于i+45<=length ? i+45 : length
格式为expression ? if yes : if no
检查是否i+45 <= length
为真时:从i
到i+45
的子串
false时:从i
到结尾(length
)
如果您不进行此项检查,则会收到StringIndexOutOfBoundsException
类型的错误消息。 (除非你的输入正好是45,90,135等字节长)
更多信息:here