TLDR:我缺少的边缘情况是什么,或者我的算法中将Base64字符串转换为Hex字符串是否有错误?
我最近决定尝试Matasano Crypto Challenges,但无论出于何种原因,我决定尝试编写第一个挑战而不使用库来转换Hex和Base64字符串 .
我已经设法让Hex到Base64转换工作,但是从输出中可以看出,当我尝试将Base64转换回Hex时会有轻微的异常(例如,将Base64的最后四个值与Hex输出进行比较) ) .
十六进制为Base64:应打印:SSdtIGtpbGxpbmcgeW91ciBicmFpbiBsaWtlIGEgcG9pc29ub3VzIG11c2hyb29t实际打印:SSdtIGtpbGxpbmcgeW91ciBicmFpbiBsaWtlIGEgcG9pc29ub3VzIG11c2hyb29t的Base64到十六进制:应打印:49276d206b696c6c696e6720796f757220627261696e206c696b65206120706f69736f6e6f7573206d757368726f6f6d实际打印:49276d206b696c6c696e6720796e717220627261696e206c696b65206120706e69732e6e6f3573206c717328726f2e6d
我使用https://conv.darkbyte.ru/来检查我的一些值,并假设该站点上的代码是正确的,似乎我的问题是从Base64获取Base10表示,而不是从Base10到Hex:
十进制等效我的输出:73,39,109,32,107,105,108,108,105,110,103,32,121,110,113,114,32,98,114,97,105,110, 32,108,105,107,101,32,97,32,112,110,105,115,46,110,111,53,115,32,108,113,115,40,114,111,46, 109站点输出:73,39,109,32,107,105,108,108,105,110,103,32,121,111,117,114,32,98,114,97,105,110,32, 108,105,107,101,32,97,32,112,111,105,115,111,110,111,117,115,32,109,117,115,104,114,111,111,109
似乎所有带错误的值都聚集在40-60和100-120之间,但我不确定从那里到底要去哪里 . 我猜测有一些边缘情况我会注意处理,但我不确定那会是什么 .
相关代码:
private static final Character[] base64Order = new Character[] { 'A', 'B', 'C', 'D', 'E', 'F', 'G', 'H', 'I', 'J',
'K', 'L', 'M', 'N', 'O', 'P', 'Q', 'R', 'S', 'T', 'U', 'V', 'W', 'X', 'Y', 'Z', 'a', 'b', 'c', 'd', 'e',
'f', 'g', 'h', 'i', 'j', 'k', 'l', 'm', 'n', 'o', 'p', 'q', 'r', 's', 't', 'u', 'v', 'w', 'x', 'y', 'z',
'0', '1', '2', '3', '4', '5', '6', '7', '8', '9', '+', '/', };
private static final Character[] hexOrder = new Character[] { '0', '1', '2', '3', '4', '5', '6', '7', '8', '9', 'a',
'b', 'c', 'd', 'e', 'f' };
public static String base64ToHex(String base64) throws Exception {
if (base64.length() % 4 != 0 || base64.contains("[^a-zA-Z0-9\\+/]"))
throw new Exception("InputNotBase64");
else {
int charValue = 0;
int index = 0;
String hex = "";
BitSet bits = new BitSet();
for (int i = 0; i < base64.length(); i++) {
charValue = base64.charAt(i);
// get actual value from ASCII table
if (charValue > 64 && charValue < 91)
charValue -= 65;
if (charValue > 96 && charValue < 123)
charValue -= 71;
/// loop that adds to the BitSet reads right-to-left, so reverse
// the bits and then shift
charValue = Integer.reverse(charValue << 24) & 0xff;
charValue >>= 2;
// append binary values to the BitSet
while (charValue != 0L) {
if (charValue % 2 != 0) {
bits.set(index);
}
index++;
charValue >>= 1;
}
// account for trailing 0s
while (index % 6 != 0) {
index++;
}
}
// read 8-bit integer value for hex-value lookup
String temp;
int remainder;
for (int i = 0; i < index; i++) {
charValue = (charValue | (bits.get(i) ? 1 : 0));
if ((i + 1) % 8 == 0) {
temp = "";
while (charValue != 0L) {
remainder = charValue % 16;
temp = hexOrder[remainder] + temp;
charValue /= 16;
}
hex += temp;
}
charValue <<= 1;
}
return hex;
}
}
1 回答
您忘记在代码中处理以下字符:'0','1','2','3','4','5','6','7','8','9',' ','/'如果替换以下代码
通过
哪里
一切正常
此外,当您使用字符而不是幻数时,代码更易读
在这种情况下,发现问题更容易
因为你问我正在提出可能的改进来加速计算 .
准备下表并初始化一次
现在您可以通过简单的操作替换您的if / else链
使用这个我写的方法比你的方法快几倍
我认为这段代码更快,主要是因为简单的转换为十六进制 . 如果您想要并且需要它,您可以测试它 .
要测试速度,您可以使用以下构造
示例结果是
但它只是近似值 . 当您首先检查Ver1而将Ver2检查为第二个时,结果可能会略有不同 . 另外,对于不同的javas(第6,7,8)以及用于启动java的不同设置,结果可能不同