java中的Rfc2898DeriveBytes

rho*_*kha 7 java crypt

我试图在java中实现以下代码:

var keyGenerator = new Rfc2898DeriveBytes(password, salt, 1000);
byte[] key = keyGenerator.GetBytes(32);
byte[] iv = keyGenerator.GetBytes(16);
using (AesManaged aes = new AesManaged())
{
    using (ICryptoTransform encryptor = aes.CreateEncryptor(key, iv)) 
    {
        byte[] result = encryptor.TransformFinalBlock(content, 0, content.Length);
    }
}
Run Code Online (Sandbox Code Playgroud)

使用以下一个:

SecretKeyFactory factory = SecretKeyFactory.getInstance("PBKDF2WithHmacSHA1");
PBEKeySpec keyspec = new PBEKeySpec(password, salt, 1000, 256);
Key key = factory.generateSecret(keyspec);
SecretKeySpec secret = new SecretKeySpec(key.getEncoded(), "AES");
byte[] iv = "how_to_generate_in_java_as_in_c".getBytes();
AlgorithmParameterSpec ivSpec = new IvParameterSpec(iv);
Cipher cipher = Cipher.getInstance("AES/CBC/PKCS5Padding");
cipher.init(Cipher.ENCRYPT_MODE, secret, ivSpec);
byte[] result = cipher.doFinal("asdfasdf".getBytes("UTF-8"));
Run Code Online (Sandbox Code Playgroud)

我查看了很多SO的例子和问题,但没有找到正确生成iv []的方法(与C中的值相同).并且似乎没有办法做到这一点,因为java允许仅将此值创建为随机(不是C中可用的伪随机).这是正确的吗?有人可以帮忙解决这个问题吗?

rho*_*kha 8

得到了crypt专家的提示,找到了正确的解决方案:

SecretKeyFactory factory = SecretKeyFactory.getInstance("PBKDF2WithHmacSHA1");
PBEKeySpec pbeKeySpec = new PBEKeySpec(password, salt, 1000, 384);
Key secretKey = factory.generateSecret(pbeKeySpec);
byte[] key = new byte[32];
byte[] iv = new byte[16];
System.arraycopy(secretKey.getEncoded(), 0, key, 0, 32);
System.arraycopy(secretKey.getEncoded(), 32, iv, 0, 16);
Run Code Online (Sandbox Code Playgroud)


小智 5

我想确保人们明白最终的代码应该是:

SecretKeyFactory factory = SecretKeyFactory.getInstance("PBKDF2WithHmacSHA1");
PBEKeySpec pbeKeySpec = new PBEKeySpec(password, salt, 1000, 384);
Key secretKey = factory.generateSecret(pbeKeySpec);
byte[] key = new byte[32];
byte[] iv = new byte[16];
System.arraycopy(secretKey.getEncoded(), 0, key, 0, 32);
System.arraycopy(secretKey.getEncoded(), 32, iv, 0, 16);

SecretKeySpec secret = new SecretKeySpec(key, "AES");
AlgorithmParameterSpec ivSpec = new IvParameterSpec(iv);
Cipher cipher = Cipher.getInstance("AES/CBC/PKCS5Padding");
cipher.init(Cipher.ENCRYPT_MODE, secret, ivSpec);
byte[] result = cipher.doFinal("asdfasdf".getBytes("UTF-8"));
Run Code Online (Sandbox Code Playgroud)

如果您想使用 new String(result) 将结果转换为字符串,最好使用 new String(result,Charset),否则您可能会得到格式不正确的字符串。