Java Database Authentication generated by Asp.net MVC 5(Generate passwordhash in Java equal Asp.net MVC 5)

Asked

Viewed 124 times

1

I need to authenticate an automatically created user in Asp.net mvc 5 using the java language for example:

user: so-and-so
password: Ab123456

Password recorded in the Database

PasswordHash
ACFCCbS1aKYPrQndKMluPDpLD51m1yh5UDBo49v1m4i44aU9SiCJSnCB16XDXJ5iQQ==

SecurityStamp
905d2faa-ed55-48f0-9d1b-c2d079015329

I need to generate a Java Hash equal to the one generated by the Asp.net MVC 5 Application

  • 1

    What code is recording this in C# (share it with us)? What kind of hash function is this (MD5, SHA, bcrypt, etc)? What are the characteristics of this algorithm (size, salt, etc)?

  • The code that generates this hash is inside the . netFramework 4.5.1 in the Usermanager and Passwordhasher class of the Microsoft.AspNet.Identity namespace the encryption algorithm is encapsulated in these classes

1 answer

1


Assuming you use the PasswordHasher . NET side pattern, as per that SOEN post the whole magic of the algorithm happens in the class Rfc2898DeriveBytes (algorithm implementation PBKDF2 using Hmac based on SHA1).

The result of the hash stored in the database is in Base 64, divided as follows:

  • 16 bytes: Random-generated Salt
  • 32 Bytes: The password hash itself.

That article gives an idea of how to derive the key from Java:

SecretKeyFactory factory = 
    SecretKeyFactory.getInstance("PBKDF2WithHmacSHA1");
KeySpec spec = new PBEKeySpec(passwordChars, 
    saltBytes, iterationCount, 256 + 128);
SecretKey secretKey = factory.generateSecret(spec);

byte[] data = secretKey.getEncoded();
byte[] keyBytes = new byte[256 / 8]; // hash de 32 bytes
byte[] ivBytes = new byte[128 / 8]; // salt de 16 bytes

System.arraycopy(data, 0, keyBytes, 0, 256 / 8);
System.arraycopy(data, 256 / 8, ivBytes, 0, 128 / 8);  

SecretKey secretKey = factory.generateSecret(spec);
byte[] key = secretKey.getEncoded();

Alternatively you can search for a class implementation Rfc2898DeriveBytes (found this one).

Finally once you have an implementation of the above algorithm, simply port the password verification solution from response from the SOEN (class Crypto of Assembly Identity) which consists in breaking the hash persisted in the bank at salt + key, compute password key using the salt persisted and check if the computed key is equal to the persisted key. Follow the steps (I could not test because I am without a compiler).

public boolean verifyPassword(String hashedPassword, String plainPassword) {
    // Se o hash é vazio não autentica
    if (hashedPassword == null) {
        return false;
    }
    if (plainPassword== null) {
        throw new IllegalArgumentException("Password should not be null");
    }
    // Extrai os bytes do hash persistido no banco 
    byte[] src = Base64.getDecoder().decode(hashedPassword);
    // Array de 49 bytes, o primeiro byte é vazio
    if (src.length != 0x31 || array[0] != 0) {
       return false;
    }

    // Extrai o salt
    byte[] salt = new byte[0x10];
    System.arraycopy(src, 1, salt, 0, 0x10);
    // Extrai a chave
    byte[] persistedKey = new byte[0x20];
    System.arraycopy(src, 0x11, persistedKey , 0, 0x20);

    // Computa 1000 iteracoes em cima da senha limpa com o salt do banco
    Rfc2898DeriveBytes rfc2898DeriveBytes = new Rfc2898DeriveBytes(
            plainPassword, salt, 0x3e8); 
    byte[] computedKey = rfc2898DeriveBytes.getBytes(0x20);

    // Se a chave computada for igual a persistida o usuário entrou a senha correta
    return Arrays.equals(persistedKey, computedKey);
} 
  • Thank you so much is exactly what I was looking for!!

Browser other questions tagged

You are not signed in. Login or sign up in order to post.