认证 – Java – PBKDF2与HMACSHA256作为PRF

前端之家收集整理的这篇文章主要介绍了认证 – Java – PBKDF2与HMACSHA256作为PRF前端之家小编觉得挺不错的,现在分享给大家,也给大家做个参考。
我被赋予了为我们的项目创建一个登录API的任务,我应该使用PBKDF2与HMACSHA256作为PRF.明文密码使用MD5散列,然后馈入PBKDF2以生成派生密钥.问题是,我无法获得与项目文档告诉我相同的输出.

这是Java中的PBKDF2实现:

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,DK,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,U_i,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,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 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 test vectors来验证实现的正确性,并且全部检出.我不知道为什么我使用MD5散列密码不能得到相同的结果.

参数:

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

使用“foobar”作为明文密码,预期结果如下:

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

我得到的

PWHash = 3858f62230ac3c915f300c664312c63f
PWKey = 0bd0c7d8339df2c66ce4b6e1e91ed3f1

解决方法

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

猜你在找的Java相关文章