Appsum Solutions
Appsum Solutions

Reputation: 1029

Generate password based on string in C#

I'd like to generate (secure) local admin passwords based on computer names in our organisation. This way I can build a small UI that takes the computername and gives the password. With PowerShell we will use the same DLL to generate the password and set it on each workstation.

I've already searched, but all the things I find about cryptography in C# is to hash a password, but I need the hash itself to be the password.

The password should also be of a length between 8 and 12 characters to make it easy enough to type it in.

I'm using .NET Core 2.0 (could use .NET Framework too if needed)

Upvotes: 0

Views: 1518

Answers (2)

bartonjs
bartonjs

Reputation: 33098

You definitely want to be able to change the passwords on your machines, so include some sort of date or counter in the formula.

You ideally also want to include some form of authentication into the tool, whether that be a master password, a complicated thing with smartcards, or something else. That way when your tool gets into the hands of a baddie they don't necessarily get all your data.

If you go the master password route, you need a plan for how to deal with suspecting that got leaked. (Including someone who knew it leaving the organization, since that's a leak.)

A strawman example which includes:

  • Using a date
  • Using a master password
  • Using HMAC to process the machine name, keyed by a key from the master password
  • An iteration count to PBKDF2 which matches modern computers.

.

private static string GeneratePassword(
    string masterPassword,
    string machineName,
    DateTimeOffset lastChangeDate)
{
    // Use the date (ignoring time) of the last password change as a salt.
    byte[] salt = BitConverter.GetBytes(lastChangeDate.ToUniversalTime().Date.Ticks);

    HashAlgorithmName prf = HashAlgorithmName.SHA256;

    using (var pbkdf2 = new Rfc2898DeriveBytes(masterPassword, salt, 123456, prf))
    {
        byte[] key = pbkdf2.GetBytes(256 / 8);

        using (HMAC hmac = new HMACSHA256(key))
        {
            byte[] value = hmac.ComputeHash(
                Encoding.UTF8.GetBytes(machineName.ToUpperInvariant()));

            // Or however long.
            return Convert.ToBase64String(value).Substring(0, 16);
        }
    }
}

The Rfc2898DeriveBytes constructor overload which takes a HashAlgorithmName for the PBKDF2-PRF is new in netcoreapp20. If you are trying to be netstandard20 you can drop the last parameter and use the SHA-1-based version with probably little harm (since HMACSHA-1 isn't currently considered broken).

When going to change a password for a machine you'd enter the date of the last generation to get the existing one. Then enter today's date to get the new value, then write down the new date in whatever text file / spreadsheet / database / sticky note remembers these things.


Another alternative is generating random passwords and saving them in an encrypted structured file. Something like EnvelopedCms as the encryption container gives you smartcard for nearly free, and lets you add/remove readers without changing all the machine passwords (adding is easy, removing might warrant changing them all anyways).

Which is to say: Building a stable generator and deploying the usage is easy. It's maintaining it that gets tricky. Maintaining random might be easier, therefore it's possibly better to pay the cost up front.

Upvotes: 2

C.Evenhuis
C.Evenhuis

Reputation: 26446

I don't know if this is such a good idea - the tool only works as long as the passwords on each and every computer stay unchanged.

Anyway, you could hash the computer name and use the result as a password. Most if not all hashes produce larger hashes than 8-12 "easy enough to type in" characters, but you can solve that by:

  • Base64 encoding the hash (to get letters, numbers and a couple of other characters)
  • Take the desired number of characters from the result.

To make this a bit safer, let your UI take a password (a single one) and append it to the computer name before computing the hash. This way, when someone steals your tool, they still won't be able to generate valid passwords.

You won't ever be able to change that password, though. If you share it with a coworker, they will know how to reproduce every password, forever.

Upvotes: 1

Related Questions