Java:十六进制编码的字节通过base64解码

时间:2018-10-16 07:18:43

标签: java base64 hex encode

HEX(Base16)使用Base64对编码的字节进行解码而不会引发异常?如何区分是否仅使用base16编码器编码?

org.apache.commons.codec.binary.Base64.decodeBase64(bytesencodedwithHex);

当上述方法的字节是十六进制编码的数据时,该方法不会引发任何异常,也不会帮助标识它是十六进制编码的。 甚至org.apache.commons.codec.binary.Base64.Base64.isBase64(bytesencodedwithHex)也会返回true。

示例下面的字符串“ Hello”已用Hex编码,当我使用Base64解码时,它会带来一些废话。在这种情况下,我如何让客户知道他们使用了错误的解码器? :

System.out.println(new 
String(org.bouncycastle.util.encoders.Hex.encode("Hello".getBytes())));  

System.out.println(new String(org.bouncycastle.util.encoders.Base64.decode("48656c6c6f".getBytes())));   

2 个答案:

答案 0 :(得分:1)

每个十六进制字符串都是合法的Base64字符串。

十六进制编码为您提供了一个字符串,代表原始字符串的字节,由0-9和A-F组成。 Base64编码为您提供了一个字符串,该字符串对原始字符串进行了编码,并且仅由可打印字符(当然包括0-9,A-F)组成。

因此,每个由0-9,A-F组成的字符串都可以代表一个十六进制字符串,但也可以代表Base64字符串(恰好只有0-9,A-F)。

您将需要一种不同的方式来告诉用户所使用的编码。一个示例是将编码类型的结构与字符串一起发送,或发送原始字符串的长度(因此,如果解码后得到的长度错误,则这不是正确的编码模式)。

答案 1 :(得分:1)

有些字符串的基数是64或16,没有任何线索。

但是有一些线索:

  • 如果length()%2!= 0,则它必须是Base64。
  • 如果length()%3 == 1,则有6个虚假的位,不能为Base64。由于必须为Base16,所以甚至必须保持length()%2 == 0。
  • 所有字母都可能是大写或小写。
  • 缺少特殊的“数字” /+G-Zg-z

所以:

boolean probablyHex(String s) {
    if (s.endsWith("=")) { // Base64 padding char (optional).
        return false;
    }
    s = s.replaceAll("[^-_+/A-Za-z0-9]", ""); // MIME safe Base64 variant too.
    if (s.matches(".*[-_+/G-Zg-z].*")) {
        return false;
    }
    int n = s.length();
    if (n % 2 == 1) {
       return false;
    }
    if (n % 3 == 1) { // Spurious char with 6 bits data.
       return true;
    }
    // Very unlikely that it is Base64, but you might have a bias towards Base64:
    if (!s.equals(s.toUpperCase(Locale.US)) && !s.equals(s.toLowerCase(Locale.US)) {
        // Mixed cases in A-Fa-f:
        // For small texts that is significantly incoherent, meaning Base64.
        return n > 32;
    }
    return true;
}