Warning: file_get_contents(/data/phpspider/zhask/data//catemap/0/mercurial/2.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Java 实现MD5,追加位1和0_Java_Algorithm_Md5_Implementation - Fatal编程技术网

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附加到消息

我知道Java中已经有了一个类,我不想使用它。我想自己实现MD5算法。这是为了我的理解。好啊除非您编辑您的答案以提及它,否则我将把我的答案留在这里,以避免其他类似的答案。好的,它将是“消息位”…例如00000001或“消息位”100000000。。。以0为例。我的意思是数组的设置方式,因此这些位将进入数组的末尾。我真的不明白1加在哪里了。像是在最后一个字节之后吗?它应该是[messagebits]1000000Xxxx,其中xxxx=“未添加消息的位(非字节)长度为64位小整数”(请参阅wiki)这不是对哈希进行盐析。这是使输入的最后一个块大小正确所必需的填充。用盐腌土豆条是不一样的。哈哈,这更有意义。我这么累的时候不应该这么做。当你说0x80时,这对我来说是有意义的。谢谢我不鼓励您使用
MD5
。当然,我建议您用盐腌的最低限度的SHA256。在我下面的代码中,您可以传递
MD5
SHA-512
SHA-256
任何内容,但是
MD5
(128位)远不如
SHA-1
(160位)安全<代码>SHA-256(256位)。您可以使用更安全的
TripleDES
。@Ali是的,我知道SHA和MD5的区别以及如何使用它们。我想实现MD5的算法。不过还是要感谢。这里要实现的关键点(除了追加意味着结束这一事实之外):MD5和其他哈希函数是在位上定义的,而不是在字节上定义的。理论上你可以