import java.security.MessageDigest;
import java.security.NoSuchAlgorithmException;
public class JavaMD5 {
public static void main(String[] args) {
String passwordToHash = "MyPassword123";
String generatedPassword = null;
try {
MessageDigest md = MessageDigest.getInstance("MD5");
md.update(passwordToHash.getBytes());
byte[] bytes = md.digest();
StringBuilder sb = new StringBuilder();
for (int i = 0; i < bytes.length; i++) {
sb.append(Integer.toString((bytes[i] & 0xff) + 0x100, 16).substring(1));
}
generatedPassword = sb.toString();
} catch (NoSuchAlgorithmException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
System.out.println(generatedPassword);
}
}
这一行是问题所在:
sb.append(Integer.toString((bytes[i] & 0xff) + 0x100, 16).substring(1));
每个部分在这个结构中做了什么????
谢谢,我很抱歉因为我不喜欢Java。
答案 0 :(得分:6)
据推测,大部分代码都是明确的,这里唯一的谜是这个表达式:
(bytes[i] & 0xff) + 0x100
第一部分:
bytes[i] & 0xff
将位置i
处的字节扩展为int
值,位位置为8-31,零。在Java中,byte
数据类型是有符号整数值,因此扩展符号扩展了该值。如果没有& 0xff
,大于0x7f的值将最终为负int
值。其余的是相当明显的:它增加了0x100,它只是打开索引8处的位(因为它在(bytes[i] & 0xff)
中保证为0。然后由...转换为十六进制String
值致电Integer.toString(..., 16)
。
首先添加0x100然后剥离1(由substring(1)
调用完成,从位置1开始到结束)的原因是保证最终结果中有两个十六进制数字。否则,低于0x10的字节值在转换为十六进制时将最终成为一个字符的字符串。
这是否具有争议性是否所有表现更好(当然不是更清晰):
sb.append(String.format("%02x", bytes[i]));
答案 1 :(得分:4)
翻译成十六进制字符串是一种非常混乱的方式。
& 0xFF
执行二进制AND,导致返回值介于0和255之间(无论如何总是一个字节)+ 0x100
在结果中添加256以确保结果始终为3位Integer.toString(src, 16)
将整数转换为带有螺旋16(十六进制).substring(1)
删除第一个字符(第2步中的1
)因此,这是一种将字节转换为始终为2个字符的十六进制字符串的非常精细和混淆的方法。