Java - 使用 HMACSHA256 作为 PRF 的 PBKDF2 [英] Java - PBKDF2 with HMACSHA256 as the PRF

查看:28
本文介绍了Java - 使用 HMACSHA256 作为 PRF 的 PBKDF2的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我的任务是为我们的项目创建一个登录 API,我应该使用带有 HMACSHA256 的 PBKDF2 作为 PRF.使用 MD5 对纯文本密码进行哈希处理,然后将其输入 PBKDF2 以生成派生密钥.问题是,我无法获得与项目文档告诉我的相同的输出.

I've been given the task of creating a Login API for our project and I'm supposed to use PBKDF2 with HMACSHA256 as the PRF. The plain text password is hashed using MD5 and then fed into the PBKDF2 to generate a derived key. The problem is, I'm not able to get the same output as what the project documentation is telling me.

这是 PBKDF2 的 Java 实现:

Here's the PBKDF2 Implementation in Java:

public class PBKDF2
{
    public static byte[] deriveKey( byte[] password, byte[] salt, int iterationCount, int dkLen )
        throws java.security.NoSuchAlgorithmException, java.security.InvalidKeyException
    {
        SecretKeySpec keyspec = new SecretKeySpec( password, "HmacSHA256" );
        Mac prf = Mac.getInstance( "HmacSHA256" );
        prf.init( keyspec );

        // Note: hLen, dkLen, l, r, T, F, etc. are horrible names for
        //       variables and functions in this day and age, but they
        //       reflect the terse symbols used in RFC 2898 to describe
        //       the PBKDF2 algorithm, which improves validation of the
        //       code vs. the RFC.
        //
        // dklen is expressed in bytes. (16 for a 128-bit key)

        int hLen = prf.getMacLength();   // 20 for SHA1
        int l = Math.max( dkLen, hLen); //  1 for 128bit (16-byte) keys
        int r = dkLen - (l-1)*hLen;      // 16 for 128bit (16-byte) keys
        byte T[] = new byte[l * hLen];
        int ti_offset = 0;
        for (int i = 1; i <= l; i++) {
            F( T, ti_offset, prf, salt, iterationCount, i );
            ti_offset += hLen;
        }

        if (r < hLen) {
            // Incomplete last block
            byte DK[] = new byte[dkLen];
            System.arraycopy(T, 0, DK, 0, dkLen);
            return DK;
        }
        return T;
    } 


    private static void F( byte[] dest, int offset, Mac prf, byte[] S, int c, int blockIndex ) {
        final int hLen = prf.getMacLength();
        byte U_r[] = new byte[ hLen ];
        // U0 = S || INT (i);
        byte U_i[] = new byte[S.length + 4];
        System.arraycopy( S, 0, U_i, 0, S.length );
        INT( U_i, S.length, blockIndex );
        for( int i = 0; i < c; i++ ) {
            U_i = prf.doFinal( U_i );
            xor( U_r, U_i );
        }

        System.arraycopy( U_r, 0, dest, offset, hLen );
    }

    private static void xor( byte[] dest, byte[] src ) {
        for( int i = 0; i < dest.length; i++ ) {
            dest[i] ^= src[i];
        }
    }

    private static void INT( byte[] dest, int offset, int i ) {
        dest[offset + 0] = (byte) (i / (256 * 256 * 256));
        dest[offset + 1] = (byte) (i / (256 * 256));
        dest[offset + 2] = (byte) (i / (256));
        dest[offset + 3] = (byte) (i);
    } 

    // ctor
    private PBKDF2 () {}

}

我使用了此处找到的测试向量 PBKDF2-HMAC-SHA2 测试向量 验证实现的正确性,并全部检查出来.我不知道为什么我不能使用 MD5 哈希密码获得相同的结果.

I used test vectors found here PBKDF2-HMAC-SHA2 test vectors to verify the correctness of the implementation and it all checked out. I'm not sure why I couldn't the same results with an MD5 hashed password.

参数:

Salt: 000102030405060708090A0B0C0D0E0F101112131415161718191A1B1C1D1E1F
Iterations Count: 1000
DKLen: 16 (128-bit derived key)

使用foobar"作为明文密码,预期结果为:

Using "foobar" as the plaintext password, the expected results are:

PWHash = MD5(PlaintextPassword) = 3858f62230ac3c915f300c664312c63f
PWKey = PBKDF2(PWHash, Salt, IterationsCount, DKLen) = 33C37758EFA6780C5E52FAB3B50F329C

我得到了什么:

PWHash = 3858f62230ac3c915f300c664312c63f
PWKey = 0bd0c7d8339df2c66ce4b6e1e91ed3f1

推荐答案

迭代次数应该是 4096,而不是 1000.

The iterations count was supposed to 4096, not 1000.

这篇关于Java - 使用 HMACSHA256 作为 PRF 的 PBKDF2的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆