如上所述,Java中的UTF-16LE存在问题。当我运行代码时,它通常会正确加密,解密和打印消息。有时会丢失两个加密字符,而有时会打印出非英语字符,例如希腊语等。
这是一堂课,确实让我的教授难堪,对错误的任何帮助将不胜感激。
/*This program was written by me for my professors class.
该程序的目的是使用XOR加密对消息进行加密,
用相同的方法解密,为这些方法生成一个密码本。* /
import java.security.*;
public class Crypto
{
public static void main(String[] args) throws Exception
{
Crypto c = new Crypto();
byte[]codebook = null;
String message = "";
System.out.println("Generating codebook");
codebook = c.makeCodebook(14);
System.out.println();
System.out.println("Now Encrypting");
System.out.println("This is the contents of the Encrypted Message: ");
message = c.crypt("1234567", codebook);
System.out.println();
System.out.println("Now Decrypting");
System.out.println("This is the contents of the Decrypted Message");
message = c.crypt(message, codebook);
System.out.println();
System.out.println("Your message is: ");
System.out.println(message);
}//publis static void main(String [] args)
//Encrypts or decrypts message against the codebook assuming the appropriate length
public String crypt (String message, byte [] codebook) throws Exception
{
//Take the message and put it into an array of bytes.
//This array of bytes is what will be XORed against the codebook
byte[] cryptedMessage = message.getBytes("UTF-16LE");
byte[] result = new byte[14];
message = "";
System.out.println(message.length());
System.out.println(cryptedMessage.length);
System.out.println(result.length);
//Let's see the contents of encryptedMessage
for(int i = 0; i< cryptedMessage.length; i++)
{
System.out.print(cryptedMessage[i]+" ");
}//for(int i = 0; i< encryptedMessage.length; i++)
System.out.println();
//XOR codebook and encryptedMessage
System.out.println("This is the message using XOR:");
for(int i = 0; i<result.length; i++)
{
//since XOR has return type of an int, we cast it to a byte
result[i] = (byte)(((byte)(codebook[i])) ^ ((byte)(cryptedMessage[i])));
System.out.print(result[i]+" ");
}//while(result[i]!=0)
//output
System.out.println();
//output
System.out.println(message.length());
System.out.println(cryptedMessage.length);
System.out.println(result.length);
return new String(result, "UTF-16LE");
}//public String crypt (String message, byte [] codebook) throws Exception
//Creates truly random numbers and makes a byte array using those truly random numbers
public byte [] makeCodebook (int length) throws Exception
{
SecureRandom SecureRandom = new SecureRandom();//instance of SecureRandom named random
byte[] codebook = null;
codebook = new byte[length];
SecureRandom.nextBytes(codebook);//generate bytes using the byte[]codebook
//output
System.out.println("This is the contents of the codebook: ");
for(int i = 0; i < codebook.length;i++)
{
System.out.print(codebook[i]+" ");
}//for(int i = 0; i < codebook[i];i++)
//output
System.out.println();
return codebook;
}//public byte [] MakeCodebook (int length) throws Exception
}//Public class Crypto
最佳答案
问题可能是因为对随机数据的XOR
偶尔会产生输出,当解释为UTF-16LE字节序列时,该输出不会表达有效的字符集。
与其尝试将密文解释为UTF-16LE字符串,不如考虑在生成密文字节并返回生成的以base64编码的字符串后,仅对其进行base64编码。然后在解密时,对输入字符串进行base64解码以获取密文字节,执行XOR以获取您的纯文本字节,然后通过将纯文本字节解释为UTF-16LE序列,从纯文本字节创建纯文本字符串。
更新后可回复以下评论,而不必担心空间不足。
如我所说,您可以对密文字节进行base64编码。这在Java中当然是可行的。 commons编解码器库具有执行此操作的方法,搜索将找到其他方法。如果不允许使用外部库,请使用自己的方法将任意字节转换为保证有效的某种东西编码的字节。
例如,您可以将密文中的每个字节分成高4位和低4位。因此,每个字节将产生一对值,每个值的范围为0-15。然后,通过将'A'
的ASCII码添加到这些数字,可以从每个字节产生2字节的序列。这不是很有效,但是可以完成工作。