public void authenticateUser(String username, char[] password)
			throws IOException, FailedLoginException {
		if (username == null || password == null) {
			throw new FailedLoginException("Invalid authentication data");
		}
		synchronized (repositoryMgr) {
			clearExpiredPasswords();
			UserEntry entry = userList.get(username);
			if (entry == null) {
				throw new FailedLoginException("Unknown user: " + username);
			}

			if (entry.passwordHash == null ||
				entry.passwordHash.length < HashUtilities.MD5_UNSALTED_HASH_LENGTH) {
				throw new FailedLoginException("User password not set, must be reset");
			}

			// Support deprecated unsalted hash
			if (entry.passwordHash.length == HashUtilities.MD5_UNSALTED_HASH_LENGTH &&
				Arrays.equals(
					HashUtilities.getHash(HashUtilities.MD5_ALGORITHM, password),
					entry.passwordHash)) {
				return;
			}

			char[] salt = new char[HashUtilities.SALT_LENGTH];
			System.arraycopy(entry.passwordHash, 0, salt, 0, HashUtilities.SALT_LENGTH);

			if (entry.passwordHash.length == HashUtilities.MD5_SALTED_HASH_LENGTH) {
				if (!Arrays.equals(
					HashUtilities.getSaltedHash(HashUtilities.MD5_ALGORITHM, salt, password),
					entry.passwordHash)) {
					throw new FailedLoginException("Incorrect password");
				}
			}
			else if (entry.passwordHash.length == HashUtilities.SHA256_SALTED_HASH_LENGTH) {
				if (!Arrays.equals(
					HashUtilities.getSaltedHash(HashUtilities.SHA256_ALGORITHM, salt, password),
					entry.passwordHash)) {
					throw new FailedLoginException("Incorrect password");
				}
			}
			else {
				throw new FailedLoginException("User password not set, must be reset");
			}
		}
	}
Verify that the specified password corresponds to the local
password set for the specified user.
@param username user name/SID
@param password password data
@throws IOException if error occurs while updating user file
@throws FailedLoginException if authentication fails
Ghidra/Features/GhidraServer/src/main/java/ghidra/server/UserManager.java