获取随机种子以生成唯一密码

时间:2014-07-22 11:49:40

标签: .net vb.net random passwords cryptography

我编写了一个简单的模块,可以生成满足我复杂性要求的密码。

Module PasswordGenerator
   Private ReadOnly _alphaChars As Char() = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz".ToArray()
   Private ReadOnly _digitChars As Char() = "0123456789".ToArray()
   Private ReadOnly _nonAlphaNumChars As Char() = "_-.,:;!$%&/()[]=+#".ToArray()
   Private ReadOnly _allPswChars As Char() = _alphaChars.Concat(_digitChars).Concat(_nonAlphaNumChars).ToArray()

   Public Function GeneratePassword(length As Integer, minNonAlphaNum As Integer, minDigits As Integer) As String
      Return GeneratePassword(length, minNonAlphaNum, minDigits, New Random(GetSeed()))
   End Function

   Public Function GeneratePassword(length As Integer, minNonAlphaNum As Integer, minDigits As Integer, rnd As Random) As String
      Dim selectedChars As List(Of Char),
          psw As String,
          rndSelectedChar As Integer
      If length < (minNonAlphaNum + minDigits) Then Throw New ArgumentException
      selectedChars = New List(Of Char)(length)
      selectedChars.AddRange(GetRandomChars(_nonAlphaNumChars, minNonAlphaNum, rnd))
      selectedChars.AddRange(GetRandomChars(_digitChars, minDigits, rnd))
      selectedChars.AddRange(GetRandomChars(_allPswChars, (length - minNonAlphaNum - minDigits), rnd))
      psw = ""
      For i As Integer = 1 To selectedChars.Count
         rndSelectedChar = rnd.Next(0, selectedChars.Count)
         psw &= selectedChars(rndSelectedChar)
         selectedChars.RemoveAt(rndSelectedChar)
      Next
      Return psw
   End Function

   Private Function GetSeed() As Integer
      Dim guidString As String
      guidString = Guid.NewGuid().ToString("N").Substring(0, 5)
      Return Int32.Parse(guidString, Globalization.NumberStyles.HexNumber)
   End Function

   Private Function GetRandomChars(charRange As Char(), count As Integer, rnd As Random) As List(Of Char)
      Dim retVal As New List(Of Char),
          selectedPos As Integer

      If count < 1 Then Return retVal
      For i As Integer = 1 To count
         selectedPos = rnd.Next(0, charRange.Length)
         retVal.Add(charRange(selectedPos))
      Next

      Return retVal
   End Function
End Module

如果我在没有GetSeed()功能的情况下使用此代码,如果我在循环中生成密码,我将多次获得相同的密码。通过使用guid作为随机种子,我可以确保不会获得相同的密码,因为NewGuid函数确保不生成相同的guid。系统提供了生成guid的函数,确保不会获得相同的guid,但不能用于在加密环境中生成随机值,因为它是某种可预测的(或者比其他函数更可预测 - 不可预测)。

  • 您会建议以任何方式更改我的代码吗?
  • 有没有更好的选择来解决我的问题?
  • 单个随机对象是否比使用guid作为种子更难预测(这样可以确保不会获得相同的密码,我相信)?

1 个答案:

答案 0 :(得分:3)

根本不要使用Random这样敏感的东西。请改用RNGCryptoServiceProvider,这样可以提供合理安全的播种。

使用Random并不是一个简单的API - 你基本上只是获取字节,可能保证不为零 - 但它是一个更合适的API。