Would that be a good practice?
No. The recommended way to protect a password is through a slow hash (PBKDF2, BCrypt, or scrypt). You are correct in saying that a fast hash is ineffective, but do you realize that using an encryption algorithm in a single direction (just encrypting, never deciphering) is almost the same thing as applying a hash?
It would not be honest of me to say that your technique is completely useless, however - if an attacker gets access to the database and only to the database (for example, exploiting an Injection of SQL) it will be unable to recover the passwords. In fact, there is a technique called "pepper" that takes advantage of this fact to give additional protection to a hash (more details in the answer to the linked question). The problem is to base all your security solely on this premise (that the attacker will not have access to your code, even if it is just for reading).
Would AES be the best algorithm?
Neither AES nor any other symmetric encryption algorithm (such as 3DES, etc.). For even if you do not want to decipher the password in no time, an attacker who gets access to your DB and your key will not do the same "out of honor", it will undo the encryption and ready! In other words, your login is slow (because you are encrypting and comparing) and the attacker is still fast ...
Asymmetric cipher would be marginally better (because the attacker could not simply decrypt, he would have to test password by password - because if the private key is off the server, he can only use the public key) risk of being too fast compared to a hash. In the end, a hash is really the best you can reasonably achieve, and using a pepper would help give you the additional security you sought by proposing this method (though I personally do not I tend to worry too much about it - it will depend on how sensitive your particular application is.)
How could AES encryption be done a slow hash using C #? Is there any ready method yet?
Rfc2898DeriveBytes
is a native solution for PBKDF2 (there are also BCrypt and scrypt implementations for .Net, third-party I believe), you just need to adjust the parameters accordingly. An example would be:
string pwd = senha_a_ser_hasheada;
// Cria um sal aleatório de 64 bits
byte[] salt = new byte[8];
using (RNGCryptoServiceProvider rngCsp = new RNGCryptoServiceProvider())
{
// Enche o array com um valor aleatório
rngCsp.GetBytes(salt);
}
// Escolha o valor mais alto que seja "tolerável"
// 100 000 era um valor razoável em 2011, não sei se é suficiente hoje
int myIterations = 100000;
try
{
Rfc2898DeriveBytes k = new Rfc2898DeriveBytes(pwd, salt, myIterations);
byte[] hash = k.getBytes(32);
// Codifica esse hash de alguma forma e salva no BD
// (lembre-se de salvar o salt também! você precisará dele para comparação)
If you want to use a pepper , get the secret value that only exists in your code (or some configuration file) and concatenate it to the password or salt before making the hash the size if needed).