Skip to content

Instantly share code, notes, and snippets.

@DeepSnowNeeL
Last active March 20, 2024 22:37
Show Gist options
  • Star 1 You must be signed in to star a gist
  • Fork 2 You must be signed in to fork a gist
  • Save DeepSnowNeeL/b97214c6410d83b0cbb8f998a53e75d5 to your computer and use it in GitHub Desktop.
Save DeepSnowNeeL/b97214c6410d83b0cbb8f998a53e75d5 to your computer and use it in GitHub Desktop.
java version of C# identity hashing method (password version 3)
package com.degineo.server.tools;
import java.security.NoSuchAlgorithmException;
import java.security.spec.InvalidKeySpecException;
import java.util.Arrays;
import java.util.Base64;
import javax.crypto.SecretKey;
import javax.crypto.SecretKeyFactory;
import javax.crypto.spec.PBEKeySpec;
public class TestAuth {
public static void main(String[] args) throws NoSuchAlgorithmException, InvalidKeySpecException {
String dbPassword = "BASE64PWD";
String password = "test";
//https://github.com/aspnet/Identity/blob/master/src/Core/PasswordHasher.cs
System.out.println(u.getPasswordHash());
byte[] dbPass = Base64.getDecoder().decode(dbPassword);
System.out.println(dbPass.length == 0x31);
System.out.println(Arrays.toString(dbPass));
int prf = ReadNetworkByteOrder(dbPass, 1);
System.out.println(prf);
int iterCount = ReadNetworkByteOrder(dbPass, 5);
System.out.println(iterCount);
int saltLength = ReadNetworkByteOrder(dbPass, 9);
System.out.println(saltLength);
byte[] salt = new byte[saltLength];
System.arraycopy(dbPass, 13, salt, 0, salt.length);
//Buffer.BlockCopy(hashedPassword, 13, salt, 0, salt.Length);
System.out.println(Arrays.toString(salt));
int subKeyLength = dbPass.length - 13 - salt.length;
byte[] expectedSubkey = new byte[subKeyLength];
System.arraycopy(dbPass, 13 + salt.length, expectedSubkey, 0, expectedSubkey.length);
System.out.println("expected " + Arrays.toString(expectedSubkey));
//Buffer.BlockCopy(hashedPassword, 13 + salt.Length, expectedSubkey, 0, expectedSubkey.Length);
SecretKeyFactory factory = SecretKeyFactory.getInstance("PBKDF2WithHMACSHA256");
PBEKeySpec spec = new PBEKeySpec(password.toCharArray(), salt, iterCount, expectedSubkey.length * 8);
SecretKey secretKey = factory.generateSecret(spec);
byte[] actualSubKey = secretKey.getEncoded();
System.out.println("actual " + Arrays.toString(actualSubKey));
//byte[] actualSubkey = KeyDerivation.Pbkdf2(password, salt, prf, iterCount, subkeyLength);
//return ByteArraysEqual(actualSubkey, expectedSubkey);
System.out.println("Password is ok : " + Arrays.equals(expectedSubkey, actualSubKey));
//Create a new hashed password
System.out.println("New hash " + hash(password));
}
private static String hash(String password) throws NoSuchAlgorithmException, InvalidKeySpecException {
int saltSize = 128 / 8;
int numBytesRequested = 256;
int prf = 1;
int iterCount = 10000;
byte[] salt = new byte[saltSize];
SecureRandom random = new SecureRandom();
random.nextBytes(salt);
//rng.GetBytes(salt);
SecretKeyFactory factory = SecretKeyFactory.getInstance("PBKDF2WithHMACSHA256");
PBEKeySpec spec = new PBEKeySpec(password.toCharArray(), salt, iterCount, numBytesRequested);
SecretKey secretKey = factory.generateSecret(spec);
byte[] subkey = secretKey.getEncoded();
//byte[] subkey = KeyDerivation.Pbkdf2(password, salt, prf, iterCount, numBytesRequested);
var outputBytes = new byte[13 + salt.length + subkey.length];
outputBytes[0] = 0x01; // format marker
WriteNetworkByteOrder(outputBytes, 1, prf);
WriteNetworkByteOrder(outputBytes, 5, iterCount);
WriteNetworkByteOrder(outputBytes, 9, saltSize);
System.arraycopy(salt, 0, outputBytes, 13, salt.length);
//Buffer.BlockCopy(salt, 0, outputBytes, 13, salt.length);
System.arraycopy(subkey, 0, outputBytes, 13 + saltSize, subkey.length);
//Buffer.BlockCopy(subkey, 0, outputBytes, 13 + saltSize, subkey.Length);
System.out.println(outputBytes.length + " " + Arrays.toString(outputBytes));
return Base64.getEncoder().encodeToString(outputBytes);
}
private static void WriteNetworkByteOrder(byte[] buffer, int offset, int value) {
buffer[offset + 0] = (byte) (value >> 24);
buffer[offset + 1] = (byte) (value >> 16);
buffer[offset + 2] = (byte) (value >> 8);
buffer[offset + 3] = (byte) (value >> 0);
}
private static int ReadNetworkByteOrder(byte[] buffer, int offset) {
return ((buffer[offset + 0]) << 24) | ((buffer[offset + 1]) << 16) | ((buffer[offset + 2]) << 8) | ((buffer[offset + 3]));
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment