【发布时间】: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