最近在做文本处理,使用MD5 生成一段文字的MD5哈希长度为32位也即128个0-1序列。
由于需要对这个MD5值进行循环移位,显然普通的 int 是不行的,所以使用 BigInteger。但是在使用BigInteger进行移位的过程,生成的0-1 序列长度 莫名其妙的减少。如图:
生成MD5 哈希码代码如下:
public class MD5 { public final static String MD5(String s){ char hexDigits[]={'0','1','2','3','4','5','6','7','8','9','A','B','C','D','E','F'}; try{ byte[] biInput=s.getBytes(); //获得MD5 摘要算法的MessageDigest对象 MessageDigest mdInst=MessageDigest.getInstance("MD5"); //使用指定的字节更新摘要 mdInst.update(biInput); //获得密文 byte[] md=mdInst.digest(); int j=md.length; char str[]=new char[j*2]; int k=0; for(int i=0;i<j;i++) { byte byte0=md[i]; str[k++]=hexDigits[byte0>>>4&0xf]; str[k++]=hexDigits[byte0&0xf]; } return new String(str); }catch(Exception e){ e.printStackTrace(); return null; } } public String MD5ToBinary(String s){ StringBuilder a=new StringBuilder(); return a.toString(); }
将生成的MD5哈希码(128位)转换为相应的 BigInteger,其中的file为需要转换的文件
BigInteger all_md5 =new BigInteger(MD5.MD5(file),16);
接下来对生成的MD5 的BigInteger 循环移位16次,生成16个不同哈希。注意此时移位过程中生成的0-1序列,最开始是有128位,然后一边移位一边减少。如图:
通过观察输出结果,发现位数缩减的主要原因是:如果生成的0-1序列首位是0(可能有多个), 从这个序列再还原到BigInteger时 原数就发生了变化,而下一步的移位是以上一步为基础,导致越到后面位数越少。
/** * 循环移位16次获得16个指纹,并将所有指纹加入到列表中 */ for (int i = 0; i < 16; i++) { String d =CircleLeftmoveBit(all_md5,8); all_md5=new BigInteger(d,2); fingerList.add(d); } return fingerList; } } /** * 先讲MD5哈希值变成2进制字符串表示,然后截取前num位和尾部,改变两截的放置顺序即可完成循环移位 * @param in 传入的需要循环移位的BigInteger * @param num 需要移位位数 * @return 返回移位完成的2进制字符串 */ public static String CircleLeftmoveBit(BigInteger in,int num){ String tmp=in.toString(2); //返回MD5哈希的2进制表示串 /** * 由于BigInteger 自动省略了前面的0,所以我们需要补全 */ int zero_num=128-tmp.length(); for(int i=0;i<zero_num;i++) { tmp+="0"; } String bit_s=""; String s1=tmp.substring(0, num); String s2=tmp.substring(num, tmp.length()); bit_s=s2+s1; return bit_s; }
修改之后: