Is this a secure way to hash passwords?
Probably, but a lot of your additional complexity isn't really adding much security value.
The idea of a salt is to ensure there is no method more efficient to recover your passwords than to brute force every single one of them from scratch. Therefore your goal is to ensure no two accounts have the same salt (ie. it is globally unique). If they did then an attacker could basically get two for the price of one by constructing a lookup table while brute forcing the first.
To achieve this you need enough entropy in your salt to ensure the probability of two accounts having the same salt is negligible.
Randomly generated salt (using a function designed for generating password salts). This is stored in the MySQL database.
This is the primary source of entropy in your scheme. You could probably discard the rest without significantly compromising security.
However for this salt to be effective you must ensure:
- The random value you're using is generated using a RNG suitable for cryptographic applications.
- There are enough bits in your random value to minimise the probability of a salt collision. OWASP suggests at least 32 bits.
Static salt - hard-coded into the source-code.
This is adding minimal cryptographic value. From a theoretical perspective it's not adding any additional entropy assuming the attacker knows the value, and from a practical perspective DB servers are usually compromised via credentials obtained from a compromised application.
I'm using sha512, by the way.
While this is a cryptographically secure hashing algorithm, it's also a "fast" one which is a problem given that users typically use weak passwords. You should consider using either a slow hashing algorithm (eg. bcrypt) or iterate your hashing process 10k or so times. If it takes a second or so to calculate every hash then even a dictionary attack will take a very long time.
When checking the hash, I generate 100 different hashes with the static salt, the salt stored in the database, and one of the possible random numbers, if one of them matches the password is correct.
The value of this is minimal, you're basically just adding one or two extra characters to the password then brute forcing them every time. This will slow your hashing scheme down which is good, but you'd be better off using the technique above to achieve this.