Well, I don't think you want to even attempt synching, for that very reason, it's too difficult to maintain and there's no reason. Once a user checks out through the custom hash table and is made a bona fide WP user, the old hash for that user is no longer needed. Do something to ensure code does not even try to use it. Either set a flag in a different field or change the hash field to null
or something.
The only other possible user action that could happen requiring the custom hashes besides initial login is a lost password. Use the 'login_form_lostpassword' action for this. This assumes your custom hash table also has the user's email. If that's not available, you'll have to come up with a totally custom way to handle this because the WP method presumes a valid email is available for each user.
Your callback would get $_POST['user_login'] and try to match a username or email from the old site. If found, create a new WP user and continue, WP will now properly handle the lost password. Otherwise just return without doing anything, WP will show an "Invalid username or password" message.
That leaves us with how to know if the original migrated hash should be invalidated or not. There doesn't appear to be a good hook specifically for a successfully restored password. All I can think of is to go back to the 'authenticate' hook.
Add your filter with a priority > 20 so it is called after the WP authenticate callback. If a user object is passed, see if that user has a hash in the custom table, if so, it's no longer needed, the user has been properly transfered to the WP user system. Mark the user as having been transferred. If you get null
(unlikely) or a WP_Error object passed, check if the user has a valid hash in the migrated hashes. If so, create a new user, modify the custom table to indicate the user has been transferred to WP and return the new user object.
If the user does not check out from the migrated hashes (and the callback was not passed a user object), either return the passed WP_Error object (you can add your own error condition here if you like) or create a new one. WP will handle it from there.
In summary, you must hook two places and not try to synch anything. Just alter the custom table as each user is transferred. Once the entire table has all users transferred (or it's just really old), drop the table and remove your hooks.