0

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)

jww
  • 97,681
  • 90
  • 411
  • 885
Appsum Solutions
  • 999
  • 2
  • 10
  • 30
  • 2
    And what's the real problem? Is there any problem converting hash to Base64? What have you already tried *(any code)*? – Julo May 14 '18 at 07:40
  • It should not be possible for other people to just use the computer name and base64 it. I need to generate the password using a public key/private key of some sort – Appsum Solutions May 14 '18 at 07:44
  • When you need a password, then see: https://stackoverflow.com/a/273499/2826535 or https://stackoverflow.com/a/18486225/2826535 or https://stackoverflow.com/a/18850104/2826535 *(as inspiration of course)* – Julo May 14 '18 at 07:51
  • You should probably avoid passwords and use client certificates. The servers in the organization identify themselves and setup a secure channel using the cert rather than a password. To automatically enroll the servers take a look at the [Simple Certificate Enrollment Protocol](https://en.wikipedia.org/wiki/Simple_Certificate_Enrollment_Protocol). – jww May 15 '18 at 09:40

2 Answers2

2

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.

bartonjs
  • 30,352
  • 2
  • 71
  • 111
1

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.

C.Evenhuis
  • 25,996
  • 2
  • 58
  • 72