C# 在C中基于字符串生成密码#

C# 在C中基于字符串生成密码#,c#,.net,asp.net-core,cryptography,C#,.net,Asp.net Core,Cryptography,我想根据我们组织中的计算机名生成(安全的)本地管理员密码。通过这种方式,我可以构建一个小UI,它接受计算机名并给出密码。 使用PowerShell,我们将使用相同的DLL生成密码,并在每个工作站上设置密码 我已经搜索过了,但是我在C#中找到的关于加密的所有东西都是散列密码,但我需要散列本身作为密码 密码的长度也应该在8到12个字符之间,以便于输入 我正在使用.NET Core 2.0(如果需要,也可以使用.NET Framework)我不知道这是否是一个好主意-只要每台计算机上的密码保持不变,该

我想根据我们组织中的计算机名生成(安全的)本地管理员密码。通过这种方式,我可以构建一个小UI,它接受计算机名并给出密码。 使用PowerShell,我们将使用相同的DLL生成密码,并在每个工作站上设置密码

我已经搜索过了,但是我在C#中找到的关于加密的所有东西都是散列密码,但我需要散列本身作为密码

密码的长度也应该在8到12个字符之间,以便于输入


我正在使用.NET Core 2.0(如果需要,也可以使用.NET Framework)

我不知道这是否是一个好主意-只要每台计算机上的密码保持不变,该工具就可以工作

无论如何,您可以对计算机名进行哈希运算,并将结果用作密码。大多数(如果不是所有的话)散列生成的散列大于8-12个“很容易输入”字符,但您可以通过以下方法解决此问题:

  • Base64对哈希进行编码(以获取字母、数字和其他几个字符)
  • 从结果中获取所需的字符数
为了更安全一点,在计算散列之前,让UI获取一个密码(单个密码)并将其附加到计算机名。这样,当有人偷走你的工具时,他们仍然无法生成有效的密码


但是,您将永远无法更改该密码。如果您与同事共享密码,他们将知道如何永远复制每个密码。

您肯定希望能够更改计算机上的密码,因此在公式中包含某种日期或计数器

理想情况下,您还希望在工具中包含某种形式的身份验证,无论是主密码、智能卡的复杂功能还是其他功能。这样一来,当你的工具落入坏人手中时,他们不一定能得到你所有的数据

如果你选择主密码路线,你需要一个如何处理泄露的怀疑的计划。(包括知道这件事的人离开公司,因为这是一个漏洞。)

斯特劳曼示例包括:

  • 使用日期
  • 使用主密码
  • 使用HMAC处理由主密码中的密钥键入的机器名
  • 与现代计算机相匹配的PBKDF2的迭代计数

Rfc2898DeriveBytes构造函数重载采用PBKDF2-PRF的HashAlgorithmName,这在netcoreapp20中是新的。如果您试图成为netstandard20,您可以删除最后一个参数,使用基于SHA-1的版本,但危害可能很小(因为HMACSHA-1目前未被视为已损坏)

当要更改机器的密码时,您需要输入上一代密码的日期以获取现有密码。然后输入今天的日期以获取新值,然后在任何文本文件/电子表格/数据库/便笺中记下新日期


另一种选择是生成随机密码并将其保存在加密的结构化文件中。类似于
EnvelopedCms
,加密容器几乎免费为您提供智能卡,并允许您添加/删除读卡器,而无需更改所有机器密码(添加很容易,删除可能需要更改所有密码)


这就是说:构建一个稳定的生成器并部署使用是很容易的。维护它变得很棘手。保持随机性可能更容易,因此提前支付成本可能更好。

真正的问题是什么?将哈希转换为Base64有问题吗?你已经尝试过什么(任何代码)?其他人不可能只使用计算机名和密码。我需要使用某种公钥/私钥生成密码当您需要密码时,请参见:或者(当然是灵感),您可能应该避免使用密码并使用客户端证书。组织中的服务器识别自己,并使用证书而不是密码设置安全通道。要自动注册服务器,请查看。
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);
        }
    }
}