I have a task to rewrite some python crypto code to java. I'm new in python. Python code:
from cryptography.hazmat.primitives.kdf.pbkdf2 import PBKDF2HMAC
from cryptography.hazmat.backends import default_backend
backend = default_backend()
PASSWORD = bytes((1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16))
key = PBKDF2HMAC(hashes.SHA256(), 32, salt, iterations, backend).derive(PASSWORD)
My java implementation:
import javax.crypto.SecretKeyFactory;
import javax.crypto.spec.PBEKeySpec;
byte[] PASSWORD = new byte[]{1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16};
SecretKeyFactory factory = SecretKeyFactory.getInstance("PBKDF2WithHmacSHA256");
SecretKey tmp = factory.generateSecret(new PBEKeySpec(new String(PASSWORD).toCharArray(), salt, iterations, 256));
byte[] key = tmp.getEncoded();
As you can see PASSWORD is a byte array which I get from a hex string, i.e 010203....0F10, I can't change it (i.e. can't specify it as a string in python realization, as I understand server transforms PASSWORD to byte array also). All worked fine with this dummy PASSWORD i.e. keys generated by python and java code were equal. But I'm faced with a problem when the password changed to arbitrary, i.e. for example AFFFFFFFFDBGEHTH.... As I understand the problem with java byte array representation as signed integers. I.e. when I convert hex "FFFAAABBBCCCDDDDFFAAAAAAAAAAAABB" for example to byte array it will be byte array [-1, -6, -86, -69, -68, -52, -35, -35, -1, -86, -86, -86, -86, -86, -86, -69], but in python it will [255, 250, 170, 187, 188, 204, 221, 221, 255, 170, 170, 170, 170, 170, 170, 187]. Then when I convert java byte array to charArray for PBEKeySpec constructor - new PBEKeySpec(new String(new byte[]{-1, -6, -86, -69, -68, -52, -35, -35, -1, -86, -86, -86, -86, -86, -86, -69}).toCharArray()... it works as unexpected.
How I have to change my java code to receive the same key as in python? As I understand I have to encode java byte array string to the same value as in python .derive(...) method. Thanks in advance.
UPDATE:
salt = b'salt'
PASSWORD = = bytes((255, 250, 170, 187, 188, 204, 221, 221, 255, 170, 170, 170, 170, 170, 170, 187))
key = PBKDF2HMAC(hashes.SHA256(), 32, salt, 512, backend).derive(PASSWORD)
and
SecretKeyFactory factory = SecretKeyFactory.getInstance("PBKDF2WithHmacSHA256");
password = new String(new byte[]{-1, -6, -86, -69, -68, -52, -35, -35, -1, -86, -86, -86, -86, -86, -86, -69});
var key = secretKeyFactory
.generateSecret(new PBEKeySpec(password.toCharArray(),
"salt".getBytes(), 512, 256))
.getEncoded();
should give the same result. It works for new byte[]{1,2,3,4,....16} password.
UPDATE2: I changed password to unsigned int[] but it not works anyway:
char[] password = new char[PASSWORD.length];
for (int i = 0; i<PASSWORD.length; password[i] = (char)(PASSWORD[i++] & 0xFF));
var key = secretKeyFactory
.generateSecret(new PBEKeySpec(password, "salt".getBytes(), 512, 256))
.getEncoded();