Java 实现MD5,追加位1和0
所以我不确定我是否做对了。我在这里使用伪代码: 它说:Java 实现MD5,追加位1和0,java,algorithm,md5,implementation,Java,Algorithm,Md5,Implementation,所以我不确定我是否做对了。我在这里使用伪代码: 它说: //Pre-processing: append "1" bit to message append "0" bits until message length in bits ≡ 448 (mod 512) append length to message 在java中,我是否能够将消息转换为字节数组。然后通过获取字符串长度*8来获取位数。然后执行类似于448-(#位+1)mod 512)的操作来获取要附加到的0位的数量 然后将该字节数
//Pre-processing:
append "1" bit to message
append "0" bits until message length in bits ≡ 448 (mod 512)
append length to message
在java中,我是否能够将消息转换为字节数组。然后通过获取字符串长度*8来获取位数。然后执行类似于448-(#位+1)mod 512)
的操作来获取要附加到的0位的数量
然后将该字节数组复制到另一个数组,但在第一个字节中填充0,然后填充1
例如:
字符串是746位
然后我会做448-((746+1)mod 512)=213
所以我需要用213“0”位和1“1”位填充字符串
那么我的数组应该是
byteArr[0] = 0x00
byteArr[1] = 0x00
...
byteArr[27] = 000001(Rest of message bits)
byteArr[n] = Rest of the bytes from message
我怎样才能知道1去了哪里?基本上,如果我附加1位,我怎么知道它是否会创建一个短的
有没有更简单的方法或其他方法可以做到这一点?有一种更简单的方法可以做到这一点:只需使用Java SE API为您提供的
旁注:Java中的字符串包含字符,而不是字节。不要使用术语“字符串”来指代二进制消息。使用术语字节数组 位必须附加到消息的末尾,而不是开头。在将消息填充到448位mod 512之后,您必须附加消息的长度(不带填充位)。
但只要这不是一个练习,就应该使用前面没有提到的算法 你说的是腌制一个土豆条 我就是这样做的
public static byte[] getSecure8ByteSalt(){
SecureRandom random = null;
try {
random = SecureRandom.getInstance("SHA1PRNG");
byte [] bSalt = new byte[8];
random.nextBytes(bSalt);
return bSalt;
} catch (NoSuchAlgorithmException e) {
log.error(e.getMessage(),e);
}
return new byte[]{
(byte)0xA9, (byte)0x9B, (byte)0xC8, (byte)0x32,
(byte)0x56, (byte)0x34, (byte)0xE3, (byte)0x03
};
}
调用salt的方法称为哈希:
private void hash(String passwd, int hashType){
byte[] bSalt = new byte[8];
try {
if(this.salt == null){
bSalt = getSecure8ByteSalt();
}
else{
bSalt = base64ToByte(salt);
}
} catch (IOException e1) {
log.error(e1.getMessage(),e1);
return;
}
byte[] bDigest=null;
try {
bDigest = getHash(ITERATION_NUMBER,passwd,bSalt,hashType);
} catch (NoSuchAlgorithmException e) {
log.error(e.getMessage(),e);
}
String sDigest = byteToBase64(bDigest);
if(this.salt == null)
setSalt(byteToBase64(bSalt));
setPasswordHash(sDigest);
}
字节到基64方法:
public static byte[] base64ToByte(String data) throws IOException {
BASE64Decoder decoder = new BASE64Decoder();
return decoder.decodeBuffer(data);
}
public static String byteToBase64(byte[] data){
BASE64Encoder endecoder = new BASE64Encoder();
return endecoder.encode(data);
}
getHash方法:
private byte[] getHash(int iterationNb, String password, byte[] salt, int hashType) throws NoSuchAlgorithmException {
MessageDigest digest = MessageDigest.getInstance(HASH_TYPE[hashType]);
digest.reset();
digest.update(salt);
byte[] input = null;
try {
input = digest.digest(password.getBytes("UTF-8"));
} catch (UnsupportedEncodingException e) {
log.error(e.getMessage(),e);
}
for (int i = 0; i < iterationNb; i++) {
digest.reset();
input = digest.digest(input);
}
return input;
}
private byte[]getHash(int iterationNb,字符串密码,byte[]salt,int hashType)抛出NoSuchAlgorithmException{
MessageDigest=MessageDigest.getInstance(哈希类型[hashType]);
reset();
文摘.最新情况(salt);
字节[]输入=null;
试一试{
输入=digest.digest(password.getBytes(“UTF-8”);
}捕获(不支持的编码异常e){
log.error(e.getMessage(),e);
}
for(int i=0;i
当其他人被抓到时,“append”表示添加到末尾。因此,您真正想要的是消息后面的一个0x80字节,然后是一堆0字节,直到字节总数小于64的倍数8。如果您实现加密算法,您应该养成一个好习惯,将官方规范作为实现的蓝图。尽管维基百科很棒,但我仍然不会依赖它来实现安全关键算法。当然,除了官方规范之外,还可以使用它。所以我会从其他来源开始,并且只会从其他来源获得“灵感”
RFC1321甚至包含了一个C语言的实现,您也可以检查一下。关于填充步骤,他们说
3.1第1步。附加填充位
消息被“填充”(扩展),因此其长度(以位为单位)为
与448全等,模512。也就是说,消息被扩展为
它距离512位的倍数只有64位。
始终执行填充,即使消息的长度为
已经等于448,模512
填充按如下方式执行:将单个“1”位附加到
消息,然后追加“0”位,以便
填充消息与448(模512)一致。总之,至少
追加至少一位,最多512位
这意味着您必须先附加1,然后用剩余的0填充,而不是反过来。要填充的剩余位(包括“1”)将始终是8的倍数,因为您的输入是位长度也是8倍数的字节。假设你必须填充128位。这意味着1加127 0位。总共是16(16*8=128)字节的填充,其中第一个字节的最高位设置为1,即第一个字节将变为0x80,其余为0x00。这意味着您可以将填充步骤简化为
- n=要填充的字节总数=位中的余数除以8
- 将0x80附加到邮件中
- 将n-1倍0x00附加到消息
MD5
。当然,我建议您用盐腌的最低限度的SHA256。在我下面的代码中,您可以传递MD5
或SHA-512
或SHA-256
任何内容,但是MD5
(128位)远不如SHA-1
(160位)安全<代码>SHA-256(256位)。您可以使用更安全的TripleDES
。@Ali是的,我知道SHA和MD5的区别以及如何使用它们。我想实现MD5的算法。不过还是要感谢。这里要实现的关键点(除了追加意味着结束这一事实之外):MD5和其他哈希函数是在位上定义的,而不是在字节上定义的。理论上你可以