我的XOR加密的java类实现出错了 我是java新手,但C++和C语言非常流利,尤其是C语言。我知道如何在C和C++中进行异或加密。问题是我用Java编写的实现xor加密的算法似乎产生了错误的结果。结果通常是一堆空格,我确信这是错误的。下面是一节课: public final class Encrypter { public static String EncryptString(String input, String key) { int length; int index = 0, index2 = 0; byte[] ibytes = input.getBytes(); byte[] kbytes = key.getBytes(); length = kbytes.length; char[] output = new char[ibytes.length]; for(byte b : ibytes) { if (index == length) { index = 0; } int val = (b ^ kbytes[index]); output[index2] = (char)val; index++; index2++; } return new String(output); } public static String DecryptString(String input, String key) { int length; int index = 0, index2 = 0; byte[] ibytes = input.getBytes(); byte[] kbytes = key.getBytes(); length = kbytes.length; char[] output = new char[ibytes.length]; for(byte b : ibytes) { if (index == length) { index = 0; } int val = (b ^ kbytes[index]); output[index2] = (char)val; index++; index2++; } return new String(output); } }

我的XOR加密的java类实现出错了 我是java新手,但C++和C语言非常流利,尤其是C语言。我知道如何在C和C++中进行异或加密。问题是我用Java编写的实现xor加密的算法似乎产生了错误的结果。结果通常是一堆空格,我确信这是错误的。下面是一节课: public final class Encrypter { public static String EncryptString(String input, String key) { int length; int index = 0, index2 = 0; byte[] ibytes = input.getBytes(); byte[] kbytes = key.getBytes(); length = kbytes.length; char[] output = new char[ibytes.length]; for(byte b : ibytes) { if (index == length) { index = 0; } int val = (b ^ kbytes[index]); output[index2] = (char)val; index++; index2++; } return new String(output); } public static String DecryptString(String input, String key) { int length; int index = 0, index2 = 0; byte[] ibytes = input.getBytes(); byte[] kbytes = key.getBytes(); length = kbytes.length; char[] output = new char[ibytes.length]; for(byte b : ibytes) { if (index == length) { index = 0; } int val = (b ^ kbytes[index]); output[index2] = (char)val; index++; index2++; } return new String(output); } },java,encryption,xor,Java,Encryption,Xor,Java中的字符串是Unicode,Unicode字符串不是像ASCII字符串那样的字节的通用持有者 您获取一个字符串并将其转换为字节,而无需指定所需的字符编码,因此您得到的是平台默认编码—可能是US-ASCII、UTF-8或其中一个Windows代码页 然后对这些字节执行算术/逻辑运算。(我没看过你在这里做什么——你说你知道算法。) 最后,您将获取这些转换后的字节,并尝试将它们转换回字符串,也就是说,转换回字符。同样,您还没有指定字符编码(但是您将得到与将字符转换为字节相同的结果,所以这没关系

Java中的字符串是Unicode,Unicode字符串不是像ASCII字符串那样的字节的通用持有者

您获取一个字符串并将其转换为字节,而无需指定所需的字符编码,因此您得到的是平台默认编码—可能是US-ASCII、UTF-8或其中一个Windows代码页

然后对这些字节执行算术/逻辑运算。(我没看过你在这里做什么——你说你知道算法。)

最后,您将获取这些转换后的字节,并尝试将它们转换回字符串,也就是说,转换回字符。同样,您还没有指定字符编码(但是您将得到与将字符转换为字节相同的结果,所以这没关系),但是,最重要的是

除非您的平台默认编码使用每个字符一个字节(例如US-ASCII),否则并非所有生成的字节序列都表示有效字符

因此,这里有两条建议:

  • 不要将字符串用作字节的一般持有者
  • 在字节和字符之间转换时,始终指定字符编码

  • 在这种情况下,如果专门使用US-ASCII作为编码,您可能会获得更大的成功。编辑:最后一句不是真的(见下面的评论)。回到上面的第1点!当需要字节时,请使用字节,而不是字符。

    如果使用非ascii字符串作为键,则会得到非常奇怪的结果。KB数组中的字节将为负。符号扩展意味着val将显示为负数。然后,转换为字符将生成FF80-FFFF范围内的字符


    这些字符肯定不可打印,根据您检查输出的方式,可能会显示“框”或其他替换字符。

    并非所有字符都可打印加密数据应视为二进制,不再是文本。如果加密,则解密文本,它输出正确吗?@Peter Well总是有Windows-1252-base64的私生子;)或者ISO-8859-1更好地使用
    byte[]
    来扩展这个答案,
    byte[]
    String
    更适合存储字节。要将字节写入stdout,请使用
    System.out.write(myByteArray)
    。ASCII字符还假定第8位为0,这对于二进制数据显然不是真的。而且很多扩展页面(OEM页面或MS称之为..ASCII+上面的128个字符和一些其他符号)也不能处理整个范围。Afaik唯一可以处理所有8位输入的编码是Windows-1252,甚至指定为保留一些位置为空。Windows总是在那里分配一些控制标志,所以它通常可以工作。但总的来说:倒数第二句话很重要:不要使用字符串来存储字节数据。。如果你真的要用base64+1来评论Voo。ASCII不是字节的持有者。ASCII仅定义128点,而不是256点。@dty:“至少在Java中,US-ASCII字符集是一个8位字符集。”[sic]一点也不。ASCII(US-ASCII)定义128个代码点。ASCII通常在最高位设置为零的字节上表示。而且它肯定是一个“8位字符集”。是的,你必须处理它,让它抛出一个异常,而不是简单地替换字符。就我个人而言,我认为这应该是默认的。现在你有了一些无声的失败。