Java中的PBKDF2与Bouncy Castle vs.NET Rfc2898DeriveBytes?

Java中的PBKDF2与Bouncy Castle vs.NET Rfc2898DeriveBytes?,java,aes,bouncycastle,unsigned,pbkdf2,Java,Aes,Bouncycastle,Unsigned,Pbkdf2,我有一些C代码,它使用PBKDF2生成密钥 //byte[] salt = new RNGCryptoServiceProvider().GetBytes(salt); byte[] salt = new byte[] { 19, 3, 248, 189, 144, 42, 57, 23 }; // for testing byte[] bcKey = new Rfc2898DeriveBytes("mypassword", salt, 8192).GetBytes(32); 这个很好用。我

我有一些C代码,它使用PBKDF2生成密钥

//byte[] salt = new RNGCryptoServiceProvider().GetBytes(salt);
byte[] salt = new byte[] { 19, 3, 248, 189, 144, 42, 57, 23 }; // for testing

byte[] bcKey = new Rfc2898DeriveBytes("mypassword", salt, 8192).GetBytes(32);
这个很好用。我正试图用Bouncy Castle在Java中实现同样的功能。无法让它工作(Java缺少无符号类型这一事实使它更加烦人)

SecureRandom random=new SecureRandom();
字节[]salt=u2s(新的int[]{19,3,248,189,144,42,57,23});
//随机。下一个字节(盐);
PBEParametersGenerator generator=新的PKCS5S2ParametersGenerator();
generator.init(PBEParametersGenerator.PKCS5PasswordToUTF8Bytes((“BLK”+password.toCharArray()),salt,keyTransformationRounds);
KeyParameter params=(KeyParameter)生成器。生成的驱动参数(keyLengthBits);
字节[]bcKey=params.getKey();
int[]bcKeyU=s2u(bcKey);
System.out.println(新字符串(Base64.encode(bcKey),“UTF-8”);
//帮助器函数,因为Java没有无符号类型
//
//编辑:这些函数不正确。
//有关正确的版本,请参见下面的答案。
//
静态字节[]u2s(int[]unsignedArray)引发IOException
{
byte[]signedArray=新字节[unsignedArray.length];
对于(int i=0;i255)
{
抛出新IOException(“位于“+i+”的unsignedArray不在0到255之间。”);
}
signedArray[i]=(字节)(unsignedArray[i]-128);
}
返回签名阵列;
}
静态int[]s2u(字节[]有符号数组)
{
int[]unsignedArray=新int[signedArray.length];
for(int i=0;i

结果bcKey字节数组不同。我做错了什么?我是要正确地处理从未签名到已签名的转换,还是不能像我预期的那样工作?

我没有正确地处理已签名/未签名的转换。下面是一些帮助函数,它们演示整数数组(表示无符号字节数组)和有符号字节数组之间的转换

检查
intsToBytes
中0-255范围之外的整数不是必需的,但可能有助于调试

static byte[] intsToBytes(int[] ints)
{
    byte[] bytes = new byte[ints.length];
    for (int i = 0; i < ints.length; i++)
    {
        if (ints[i] < 0 || ints[i] > 255) System.out.println(String.format("WARNING: ints at index %1$d (%2$d) was not a valid byte value (0-255)", i, ints[i]));

        bytes[i] = (byte)ints[i];
    }

    return bytes;
}

static int[] bytesToInts(byte[] bytes)
{
    int[] ints = new int[bytes.length];
    for (int i = 0; i < bytes.length; i++)
    {
        ints[i] = bytes[i] & 0xff;
    }

    return ints;
}
static byte[]intsToBytes(int[]ints)
{
字节[]字节=新字节[ints.length];
for(int i=0;i255)System.out.println(String.format)(“警告:索引%1$d(%2$d)处的ints不是有效的字节值(0-255)”,则i,ints[i]);
字节[i]=(字节)整数[i];
}
返回字节;
}
静态int[]字节测试点(字节[]字节)
{
int[]ints=新的int[bytes.length];
for(int i=0;i
不要这么做,只需将其转换为字节即可
signedArray[i]=(字节)unsignedArray[i]
它不仅会截断超出范围的数字?是的,但这几乎总是您想要的行为。实际上,它只是将低阶8位从源复制到目标。。。我认为(字节)129==0,而不是-127。另一种方法也可以缩短为&0xff。我修正了我的答案;谢谢你的建议。:)
static byte[] intsToBytes(int[] ints)
{
    byte[] bytes = new byte[ints.length];
    for (int i = 0; i < ints.length; i++)
    {
        if (ints[i] < 0 || ints[i] > 255) System.out.println(String.format("WARNING: ints at index %1$d (%2$d) was not a valid byte value (0-255)", i, ints[i]));

        bytes[i] = (byte)ints[i];
    }

    return bytes;
}

static int[] bytesToInts(byte[] bytes)
{
    int[] ints = new int[bytes.length];
    for (int i = 0; i < bytes.length; i++)
    {
        ints[i] = bytes[i] & 0xff;
    }

    return ints;
}