【问题标题】:How does encoding/decoding bytes work in Java?Java中的编码/解码字节如何工作?
【发布时间】:2016-12-27 20:21:16
【问题描述】:

背景知识:我正在做密码学挑战,我完成了https://cryptopals.com/sets/1/challenges/1,但意识到我没有学习我猜想学习(或编码)的东西。

我正在使用 Apache Commons Codec 库进行 Hex 和 Base64 编码/解码。目标是解码十六进制字符串并将其重新编码为 Base64。页面底部的“提示”表示 “始终对原始字节进行操作,从不对编码字符串进行操作。仅使用 hex 和 base64 进行漂亮打印。”

这是我的答案...

private static Hex forHex = new Hex();
private static Base64 forBase64 = new Base64();

public static  byte[] hexDecode(String hex) throws DecoderException {
    byte[] rawBytes = forHex.decode(hex.getBytes());
    return rawBytes;
}
public static byte[] encodeB64(byte[] bytes) {
    byte[] base64Bytes = forBase64.encode(bytes);
    return base64Bytes;
}

public static void main(String[] args) throws DecoderException {

String hex = "49276d206b696c6c696e6720796f757220627261696e206c696b65206120706f69736f6e6f7573206d757368726f6f6d";


//decode hex String to byte[]
byte[] myHexDecoded = hexDecode(hex);
String myHexDecodedString = new String(myHexDecoded);

//Lyrics from Queen's "Under Pressure"
System.out.println(myHexDecodedString);

//encode myHexDecoded to Base64 encoded byte[]
byte[] myHexEncoded = encodeB64(myHexDecoded);
String myB64String = new String(myHexEncoded);

//"pretty printing" of base64
System.out.println(myB64String);

}

...但我觉得我被骗了。我没有学习如何解码编码为十六进制的字节,也没有学习如何将“纯”字节编码为 Base64,我只是学会了如何使用库为我做一些事情。

如果我要在 Java 中获取一个字符串然后获取它的字节,我将如何将这些字节编码为十六进制?例如,以下代码片段将“Hello”(可读英文)转换为每个字符的字节值:

String s = "Hello";
char[] sChar = s.toCharArray();
byte[] sByte = new byte[sChar.length]
for(int i = 0; i < sChar.length; i++) {
    sByte[i] = (byte) sChar[i];
    System.out.println("sByte[" + i + "] = " +sByte[i]);
}

产生 sByte[0] = 72, sByte[1] = 101, sByte[2] = 108, sByte[3] = 108, sByte[4] = 111

让我们以 'o' 为例 - 我猜它的十进制版本是 111 - 我是否只取其十进制版本并将其更改为十六进制版本?

如果是这样,要解码,我是否一次只取十六进制字符串 2 中的字符,将它们分解为十进制值,然后转换为 ASCII?会一直是ASCII吗?

【问题讨论】:

  • (byte) sChar[i] 你有数据丢失。 byte 是 8 位,char 是 16。没有文本,只有编码文本。字符串是 UTF-16 代码单元的计数序列,每个 Unicode 代码点需要其中的一个或两个。如果您想要一个字节数组,请选择您的编码并确保它是已知的。然后只需要求您的编码为您提供字符串的字节。如果你想学写的话,Java 会让你把自己的编码器放进去。
  • 感谢您指出数据丢失,这可能会解决我在挑战 #4 中遇到的问题

标签: java encoding hex byte decoding


【解决方案1】:

要解码,我是否一次只取十六进制字符串 2 中的字符,将它们分解为十进制值,然后转换为 ASCII?会一直是ASCII吗?

没有。您一次取字符 2,将字符“0”转换为数值 0,将字符“1”转换为数值 1,...,字符“a”(或“A”,取决于哪个要支持的编码)到数值 10,...,字符 'f' 或 'F' 到数值 15。

然后将第一个数值乘以 16,然后将其与第二个数值相加,得到字节的无符号整数值。然后将无符号整数值转换为有符号字节。

ASCII 与此算法无关。

要了解它在实践中是如何完成的,因为 commons-codec 是开源的,你可以看看它的实现。

【讨论】:

  • 因为毫无意义的问题删除了之前的评论。我理解您所说的“第一个数值”;我现在正在看源代码,谢谢!
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2013-05-25
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2020-06-24
  • 2014-01-05
  • 2019-03-20
相关资源
最近更新 更多