C#: подтвердите пароль ha sh (SHA512) с солью для пользователя linux из / etc / shadow - PullRequest
0 голосов
/ 24 марта 2020

Я хочу проверить учетные данные пользователя ( имя и пароль ) для Linux пользователей с собственным кодом C# (. NET Core). Учетные данные пользователя в Linux системах обычно хранятся в файле: / etc / shadow .

Например, пользователь с именем " csharp " с паролем " 1337"имеет следующую запись внутри файла / etc / shadow :

string entry = "csharp:$6$qVnvjWpk$DOUTmbC9ROZ6s1h0hCZTYWLFfVeUWDbz8f0EUFPEJEC2UKQV0gRiIfoGpnaA.8i4RCcrGpOEHEd9xrAUDpo3Y/:18337:0:99999:7:::"
  • Строка перед первым": "имеет вид имя пользователя => entry.Split (":") [0] (csharp)

  • Символ после первого "$" - это га sh method => entry.Split ("$") [1] (6 = SHA256). Возможные методы: MD5 => 1; SHA256 => 5; SHA512 => 6

  • Строка после второго "$" - это соль (или ха sh?) => entry.Split ("$") [2 ] (qVnvjWpk)

При использовании программы openssl в системе Linux с " openssl passwd -6 -salt qVnvjWpk 1337 ", тогда он выдаст мне следующий вывод: $6$qVnvjWpk$DOUTmbC9ROZ6s1h0hCZTYWLFfVeUWDbz8f0EUFPEJEC2UKQV0gRiIfoGpnaA.8i4RCcrGpOEHEd9xrAUDpo3Y/

Как видите, вывод openssl является частью / etc / shadow запись:

entry.Split(":")[1] == openssl_output

Но как это можно сделать с помощью собственного кода csharp и без использования программы openssl?

У меня есть следующий подход для этого:

CheckCredentials("csharp", "1337");
public static bool CheckCredentials(string username, string password) {

    string[] shadow = File.ReadAllLines("/etc/shadow");

    foreach(string entry in shadow) {
        // entry = csharp:$6$qVnvjWpk$DOUTmbC9ROZ6s1h0hCZTYWLFfVeUWDbz8f0EUFPEJEC2UKQV0gRiIfoGpnaA.8i4RCcrGpOEHEd9xrAUDpo3Y/:18337:0:99999:7:::
        if(entry.Split(":")[0] == username) {

            // hash = 6f0ac65fe01188660aad900bfe16c566ebf0e56c0a7d4a15bd831049108de80bd3a2fbf1a8b91662433a40458ec208a207cab073f190bd65b889e95e4fca8e09
            // $6 => SHA512 
            string hash = HashSHA512(password);

            // salt = qVnvjWpk
            string salt = entry.Split("$")[2];

            // >>> how to check now the given password "1337"? <<< 

            break; 
        }

        throw new Exception($"User '{username}' was not found");

    }

    return false;

}
public static string HashSHA512(string input)
{
    SHA512Managed crypt = new SHA512Managed();
    StringBuilder hash = new StringBuilder();
    byte[] crypto = crypt.ComputeHash(Encoding.UTF8.GetBytes(input));

    foreach (byte append in crypto)
    {
        hash.Append(append.ToString("x2"));
    }
    return hash.ToString();
}
...