Java 将 45 个字符存储在新数组或 ArrayList AES 加密中

Java store 45 of characters in a new array or ArrayList AES encryption

我有一个 AES 128 位加密方法来加密消息。但它不会加密长度超过 45 个字符的消息。因此,我在想,如果我可以通过将超过 45 个字符的消息拆分为一个大小为 45 个字符的数组或数组列表来做到这一点,那么我一次加密每个块。

所以,如果我有一条长 90 的消息,我应该有两个大小为 45 的数组(或者大小为 2 且每个大小为 45 个字符的数组)。或一个数组列表来做到这一点。如果我有一条长 180 的消息,那么我应该有一个包含 4 个数组的块。

更新:所以我最初的问题是无法在客户端-服务器聊天中使用 AES 加密发送长消息。

以下是AES实现的代码,但其中没有任何填充或IV。

首先我有一个客户;谁发送使用下面的 AESmsgEncryption class 加密的消息。

客户class

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

        }
}

一旦客户端发出一条消息,接收方就会收到它(加密)并将其发送回在线客户端。在线客户端收到加密的文本消息后,他们使用以下代码解密消息 在客户端的另一种接收方法中 class

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 class 我有一个方法如下;

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 加密发送,然后发送到每个客户端,这就是为什么在客户端调用 encryptAES 和 decryptedPlain 方法时必须提供 scrtkey。

重述我的问题;上面的代码不能发送超过 45 个字符的消息,我怎样才能让它发送超过 45 个字符的消息?如果我需要使用填充和 IV,服务器应该将 IV 与密钥一起发送,对吗?

希望以上描述清楚

我如何在 JAVA 中做到这一点?

谢谢

我想你可以这样做:

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
当为真时:从 ii+45
的子字符串 当为 false 时:从 i 到末尾的子字符串 (length)

如果您不执行此检查,您将收到 StringIndexOutOfBoundsException 类型的错误。 (除非您的输入正好是 45、90、135 等字节长)

更多信息:here

您得到的这些填充通常与密码的任何限制无关。这是因为:

  1. 您在通信过程中丢失了数据;
  2. 您在 encoding/decoding 期间丢失了数据。

最后一个是最有可能的,如果您使用随机 IV 或密钥,它很可能是随机发生的。在那种情况下拆分字符串可能只是暂时隐藏问题而不是解决问题。

如果密文作为字符串数据处理,您应该使用 base 64 编码。通过将其视为十六进制字符串,确保以字节为单位的完整密文在加密方法之后和解密方法之前是相同的。

AES 可以轻松加密千兆字节的信息(尽管安全性取决于用例和操作模式)。拆分明文应该是没有必要的。