将消息发送到 IP 地址后进行 AES 解密

AES decryption after sending message to IP address

所以我正在制作一个应用程序,可以将安全消息发送到指定的 IP 地址。我正在使用 AES 来加密消息,那部分效果很好。我能够在发送消息之前加密消息并解密它。但是,当我尝试解密从服务器收到的消息时,我无法解密它。它以加密形式显示。

我收到此错误 "java.lang.NumberFormatException: Invalid int: "ne"",我认为这可能与字符编码有关?通过网络发送字符串时是否以任何方式对其进行了更改?

以下是可能与该问题相关的片段。

public static String encrypt(String seed, String cleartext)
        throws Exception {
    byte[] rawKey = getRawKey(seed.getBytes());
    byte[] result = encrypt(rawKey, cleartext.getBytes());
    return toHex(result);
}

public static String decrypt(String seed, String encrypted)
        throws Exception {
    byte[] rawKey = getRawKey(seed.getBytes());
    byte[] enc = toByte(encrypted);
    byte[] result = decrypt(rawKey, enc);
    return new String(result);
}


public static byte[] toByte(String hexString) {
    int len = hexString.length() / 2;
    byte[] result = new byte[len];
    for (int i = 0; i < len; i++)
        result[i] = Integer.valueOf(hexString.substring(2 * i, 2 * i + 2),
                16).byteValue();
    return result;
}

public static String toHex(byte[] buf) {
    if (buf == null)
        return "";
    StringBuffer result = new StringBuffer(2 * buf.length);
    for (int i = 0; i < buf.length; i++) {
        appendHex(result, buf[i]);
    }
    return result.toString();
}

这是我对要显示的消息进行解密的地方。

while (!goOut) {
    if (dataInputStream.available() > 0) {
        incoming = dataInputStream.readUTF();

        if(encrypt == true) {
            try{
                msgLog += AESHelper.decrypt(seed,incoming);
            } catch (Exception e) {
                e.printStackTrace();
            }

        } else msgLog += incoming;



        MainActivity.this.runOnUiThread(new Runnable() {

            @Override
            public void run() {
                chatMsg.setText(msgLog);
            }
        });

这是加密消息:

OnClickListener buttonEncryptOnClickListener = new OnClickListener()   {
        public void onClick(View v) {
            if (chatClientThread == null) {
                return;
            }
            if (editTextSay.getText().toString().equals("")) {
                return;
            }

            if(!editTextSay.getText().toString().equals("")){

                String message = editTextSay.getText().toString();
                encrypt = true;
                int secLvl = Integer.parseInt(editTextSecurity.getText().toString());

                String encryptedMsg;
                try {
                     encryptedMsg = AESHelper.encrypt(seed, message);
                    textEncryptedmsg.setText(encryptedMsg);
                    textEncryptedmsg.setVisibility(View.VISIBLE);

                } catch (Exception e) {
                    e.printStackTrace();

                }

            }

        }
    };

这是发送消息:

OnClickListener buttonSendOnClickListener = new OnClickListener() {

        @Override
        public void onClick(View v) {
            if (editTextSay.getText().toString().equals("")) {
                return;
            }

            if(chatClientThread==null){
                return;
            }

            if (encrypt == true){

                chatClientThread.sendMsg(textEncryptedmsg.getText().toString() + "\n");
            } else {
                chatClientThread.sendMsg(editTextSay.getText().toString() + "\n");
            }

            editTextSay.setText("");
            textEncryptedmsg.setText("");
            textDecryptedmsg.setText("");
            encrypt = false;
            incomingmsg.setVisibility(View.VISIBLE);
        }

    };

我假设您以十六进制编码的形式发送密文。 DataInputStream#readUTF() 读取 single Unicode character from the stream。由于您要发送十六进制字符,这意味着可以从两个这样的 Unicode 字符构造一个密文字节。

问题在于 AES 对块进行运算。尝试分别解密每个 "half" 字节是行不通的。

您需要将解密方法重写为

  • 使用流式解密或
  • 读取整个密文,一口气解密

如果你想尝试流式解密,那么你基本上有两个选择:


这是一个(伪代码)示例,在尝试解密之前先阅读整个内容:

StringBuilder incoming = new StringBuilder();
while (!goOut && ) {
    incoming.append(dataInputStream.readUTF());
}
if(encrypt == true) {
    try{
        msgLog += AESHelper.decrypt(seed, incoming.toString());
    } catch (Exception e) {
        e.printStackTrace();
    }
} else msgLog += incoming;

我在不使用 CipherInputStream 的情况下找到了解决问题的方法。 每当我加密一条消息并发送它时,encryption/decryption 算法不会解密从服务器收到的消息。由于输出的加密消息与我发送的消息相同,我将传入的加密消息打印到 TextView 中,然后将 TextView 复制到 String 中并解密,现在效果很好。

 while (!goOut) {


            if (dataInputStream.available() > 0) {

                final String incoming = dataInputStream.readUTF();



                MainActivity.this.runOnUiThread(new Runnable() {

                    @Override
                    public void run() {

                        incomingmsg.setText(incoming);
                        mustDecrypt = incomingmsg.getText().toString();



                        if (encrypt)
                            try {
                                mustDecrypt = AESHelper.decrypt(seed, mustDecrypt);
                                msgLog += mustDecrypt;

                            } catch (Exception e){
                                e.printStackTrace();
                            }
                            else msgLog += mustDecrypt;




                        chatMsg.setText(msgLog);
                    }
                });
            }