2016-08-21 27 views
1

小小的背景:我在做笑脸挑战,我完成了https://cryptopals.com/sets/1/challenges/1,但意识到我没有学到我想要学习(或编码)的东西。编码/解码字节在Java中如何工作?

我正在使用Apache Commons Codec库进行Hex和Base64编码/解码。目标是解码十六进制字符串并将其重新编码为Base64。页面底部的“提示”表示“始终对原始字节进行操作,从不对编码字符串进行操作,只能使用十六进制和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中取得一个字符串,然后得到它的字节,我将如何将这些字节编码为十六进制?例如,下面的代码剪断变为 “你好”(这是可读英国),以每个字符的字节值:

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吗?

+0

'(byte)sChar [i]'在那里你有数据丢失。字节是8位,字符是16.没有文本,但是编码文本。字符串是UTF-16代码单元的统计序列,每个Unicode代码点需要一个或两个代码单元。如果你想要一个字节数组,请选择你的编码,并确保它是已知的。然后只要问你的编码给你一个字符串的字节。 Java会让你把自己的编码器加入到这个中,如果这就是你想要写的东西。 –

+0

感谢您指出数据丢失,这可能会解决我遇到的问题#4 – appills

回答

2

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

不会。您一次取两个字符2,将字符'0'转换为数字值0,将字符'1'转换为数字值1,...,字符'a'(或'A',具体取决于您想要支持的编码)到数字值10,...,字符'f'或'F'到数字值15.

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

ASCII与此算法无关。

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

+0

由于无意义的问题而删除了以前的评论。我通过“第一数字值”了解你的意思;我正在查看源代码,谢谢! – appills

+0

抱歉等了很长时间才能接受您的答案! – appills