简体   繁体   English

当我使用 DES 算法时,我将 byte[] 转换为 String 并将这个 String 转换为 byte[],这两个 byte[] 变得不同

[英]When I use DES algorithm I convert byte[] to String and convert this String to byte[], and these two byte[] become different

When I use DES algorithm I convert byte[] to String and convert this String to byte[], and these two byte[] become different:当我使用 DES 算法时,我将 byte[] 转换为 String 并将这个 String 转换为 byte[],这两个 byte[] 变得不同:

String str = "lszzz";
String password = "12343213";
byte[] result = Des.encrypt(str.getBytes("utf-8"), password);
String res=new String(result,"utf-8");
System.out.println(result+" dividing line "+res.getBytes());

The running answer is运行的答案是

[B@182decdb dividing line [B@26f0a63f;

Why are these two byte[] different, and how can I can get the same byte[] ?为什么这两个byte[]不同,我怎样才能得到相同的byte[]

There are two issues here.这里有两个问题。

When you concatenate a String with a byte array (which you do twice in result + " dividing line " + res.getBytes() ) you are calling toString() on a byte[] .当您将 String 与字节数组连接时(您在result + " dividing line " + res.getBytes()中执行两次),您正在调用toString()上的byte[] When you call toString() on any array, you get a value of the form当你在任何数组上调用toString()时,你会得到一个表单的值

  [<internal-type-name>@<identity-hashcode>

This does not represent the contents of the array.这并不代表数组的内容 It represents the identity of the array.它表示数组的标识。

So, in this case, [B@182decdb dividing line [B@26f0a63f only tells you that these are byte arrays and that they are not the same object.所以,在这种情况下, [B@182decdb dividing line [B@26f0a63f只告诉你这些是字节 arrays,它们不是同一个 object。 It does not explain anything.它没有解释任何东西。

The second issue is that you can't treat an arbitrary byte sequence as a UTF-8 encoding.第二个问题是您不能将任意字节序列视为 UTF-8 编码。 Not every sequence of arbitrary bytes is a valid UTF-8 encoding.并非每个任意字节序列都是有效的 UTF-8 编码。

The Des.encrypt call is producing a byte array containing arbitrary binary bytes. Des.encrypt调用正在生成一个包含任意二进制字节的字节数组。 When you treat an array containing arbitrary bytes as UTF-8 encoded... and decode it into a String , the process is lossy.当您将包含任意字节的数组视为 UTF-8 编码...并将其解码为String时,该过程是有损的。 When you then take the String value in res and then attempt to encode it as UTF-8, it is unlikely that the bytes you will get will be the same as the bytes that you started with.然后,当您在res中获取String值并尝试将其编码为 UTF-8 时,您将获得的字节不太可能与您开始使用的字节相同。

The solution depends on what you are trying to do here:解决方案取决于您在此处尝试执行的操作:

  • If you want to store or transmit binary data as binary:如果您想以二进制形式存储或传输二进制数据:

    • use a BLOB database type使用BLOB数据库类型
    • use InputStream / OutputStream使用InputStream / OutputStream
    • possibly use DataInputStream / DataOutput or ObjectInputStream / ObjectOutputStream可能使用DataInputStream / DataOutputObjectInputStream / ObjectOutputStream
  • If you are trying to turn the encrypted data into a robust form that can be transmitted through a "text only" channel, use Base64 encoding.如果您尝试将加密数据转换为可通过“纯文本”通道传输的可靠形式,请使用Base64编码。

  • If want to pretend that your bytes are text, you could encode them as ISO-8859-1 aka LATIN-1.如果想假装你的字节是文本,你可以将它们编码为 ISO-8859-1 aka LATIN-1。 There is a 1-to-1 correspondence between the 256 codes of ISO-8859-1 and the first 256 Unicode codepoints. ISO-8859-1 的 256 个代码与前 256 个 Unicode 代码点之间存在一对一的对应关系。 So if you pretend that that your binary is ISO-8859-1, you can decode them to a string, encode them back to ISO-8859-1, and get the bytes that you started with.因此,如果您假装您的二进制文件是 ISO-8859-1,您可以将它们解码为字符串,将它们编码回 ISO-8859-1,然后获取您开始使用的字节。 (This is conceptually broken... but it works.) (这在概念上被打破了......但它有效。)


Now a strict reading of the ISO-8859-1 spec says that the "conceptually broken" approach should not work .现在,对 ISO-8859-1 规范的严格阅读表明,“概念上的破坏”方法不应该起作用 However, the following test code demonstrates that it does.但是,以下测试代码证明了它确实如此。

public class Test {
    public static void main (String[] args) throws Exception {
        byte[] data = new byte[256];
        for (int i = 0; i < 256; i++) {
            data[i] = (byte) i;
        }
        String s = new String(data, "ISO-8859-1");
        data = s.getBytes("ISO-8859-1");
        for (int i = 0; i < 256; i++) {
            if (data[i] != ((byte) i)) {
                System.out.println("mismatch: " +  data[i] + " != " +
                   ((byte) i));
            }
        }
    }
}

We can put this down to the way that the ISO-8859-1 encoder / decoder classes are implemented in Java.我们可以将其归结为 ISO-8859-1 编码器/解码器类在 Java 中实现的方式。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM