如何在限制性字符集下将字节数组转换为字符串?

时间:2015-05-07 06:09:26

标签: java

我想将加密哈希值应用于IP号码,并将哈希值放在字符集中,并且#34; abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789 _"。

到目前为止我的试验:

MD5:      [B@6d6f6e28
US ASCII: :???RN???z?}k^?
Hex:      3A8BB1881E524EDFEFE67AFF7D6B5E9D
Base64:   OouxiB5STt/v5nr/fWtenQ==
Binary:   00111010100010111011000110001000000111100101001001001110110111111110111111100110011110101111111101111101011010110101111010011101

输出:

    String secret = "secret";  //config file, do not store in code
    Set existingMdBase64Alt = new HashSet(Arrays.asList("OouxiB5STt_v5nr_", "ouxiB5STt_v5nr_f"));
    String ipWithSecret = secret + "123.123.123.123";
    byte[] ipBytes = ipWithSecret.getBytes(StandardCharsets.UTF_8);
    MessageDigest md = MessageDigest.getInstance("MD5");
    byte[] mdBytes = md.digest(ipBytes);
    String mdBase64 = Base64.encodeBase64String(mdBytes);
    String mdBase64Alt = mdBase64.replace("+","_").replace("/","_" );
    System.out.println("Debug: " + mdBase64Alt.substring(0, 16));
    while (mdBase64Alt.length() > 16 && existingMdBase64Alt.contains(mdBase64Alt.substring(0, 16))){
        mdBase64Alt = mdBase64Alt.substring(1);
        System.out.println("Debug: " + mdBase64Alt.substring(0, 16));
    }
    System.out.println("Final: " + mdBase64Alt.substring(0, 16));

除了十六进制之外,甚至没有任何东西可以接受。我的可用字母比十六进制字母大得多,因为我必须处理16个字符的长度限制,所以我希望哈希字符串更短。

我有什么建议可以实现这个目标吗?

答案 我稍微修改了John的答案,所以很有信心。这里的代码也有点处理冲突:

<p><br data-mce-bogus="1"></p>

1 个答案:

答案 0 :(得分:4)

一般情况下,不要重新发明轮子:使用base64。这是一般的“短于十六进制,但仍然可打印的ASCII”解决方案。有各种base64选项可供选择,具体取决于您使用的Java版本等。如果您使用的核心框架中没有任何内容,我喜欢iharder.net public domain implementation

但是,这不是真的会帮助你。 MD5哈希值是16个字节 - 所以除非你有256个字符可供使用(用一个字符表示每个字节),你最终会得到超过16个字符,这只是因为你的信息量很大重新尝试代表。

正如评论中所述,IPv4地址只有4个字节。坦率地说,散列不会掩盖它,因为散列整个地址空间显然是可行的......

相关问题