Random 加密洗牌和挑选

Random 加密洗牌和挑选,random,Random,我正在实现一个加密安全的洗牌例程,有几个问题: 我使用的方法是加权排序,其中每个权重是一个加密强随机数 我使用列表中的项数(X)计算每个权重所需的位数,并将其插入以下公式=log10(X!)/log10(2)。例如,52卡组需要log10(52!)/log10(2)=225.58100312370276194634244437667位/重量。我总是把它四舍五入,因为一点点的分数是不能表示的。我总是四舍五入是正确的,还是给了我太多的比特 从硬件rng检索位可能不太实际,因此必须检索字节。与前面的示

我正在实现一个加密安全的洗牌例程,有几个问题:

我使用的方法是加权排序,其中每个权重是一个加密强随机数

  • 我使用列表中的项数(X)计算每个权重所需的位数,并将其插入以下公式=
    log10(X!)/log10(2)
    。例如,52卡组需要
    log10(52!)/log10(2)=225.58100312370276194634244437667
    位/重量。我总是把它四舍五入,因为一点点的分数是不能表示的。我总是四舍五入是正确的,还是给了我太多的比特

  • 从硬件rng检索位可能不太实际,因此必须检索字节。与前面的示例一样,我们有28个完整字节,另外还有一个字节来获取剩余的2位。我所做的是丢弃最后一个字节中未使用的上6位,这样数字只追加2位。我简单地丢弃这些比特是正确的还是这样做破坏了熵

  • 我是按(左填充,全大写,ASCII)十六进制字符串对每个数字进行排序的。这似乎产生了正确的排序顺序。我是否应该知道以这种方式对字符串进行排序有什么问题

  • 我应该使用硬件rng来测试它生成的数字的熵,但我一直在使用MS RNGCryptoServiceProvider。是否有更好的加密RNG用于.NET

  • 要从加密加权和排序列表中“选择”一个数字,我只需选择索引0。有没有更好的加密随机方法来选择列表中的项目

  • 让我知道如果我可以帮助澄清,或者如果这是错误的网站,请让我知道什么是更好的网站

    下面是我的代码,如果它有助于说明我所说的VB.NET控制台应用程序:

    Imports System.Security.Cryptography
    
    Module Module1
    
        Public Class Ball
            Public Weight As String
            Public Value As Integer
            Public Sub New(ByVal _Weight As String, ByVal _Value As Integer)
                Weight = _Weight
                Value = _Value
            End Sub
        End Class
    
        Public Class BallComparer_Weight
            Implements IComparer(Of Ball)
            Public Function Compare(x As Ball, y As Ball) As Integer Implements System.Collections.Generic.IComparer(Of Ball).Compare
                If x.Weight > y.Weight Then
                    Return 1
                ElseIf x.Weight < y.Weight Then
                    Return -1
                Else
                    Return 0
                End If
            End Function
        End Class
    
        Public Class BallComparer_Value
            Implements IComparer(Of Ball)
            Public Function Compare(x As Ball, y As Ball) As Integer Implements System.Collections.Generic.IComparer(Of Ball).Compare
                If x.Value > y.Value Then
                    Return 1
                ElseIf x.Value < y.Value Then
                    Return -1
                Else
                    Return 0
                End If
            End Function
        End Class
    
        Public Function Weight(ByVal rng As RNGCryptoServiceProvider, ByVal bits As Integer) As String
            ' generate a "cryptographically" random string of length 'bits' (should be using hardware rng)
            Dim remainder As Integer = bits Mod 8
            Dim quotient As Integer = bits \ 8
            Dim byteCount As Integer = quotient + If(remainder <> 0, 1, 0)
            Dim bytes() As Byte = New Byte(byteCount - 1) {}
            Dim result As String = String.Empty
            rng.GetBytes(bytes)
            For index As Integer = bytes.Length - 1 To 0 Step -1
                If index = bytes.Length - 1 Then
                    ' remove upper `remainder` bits from upper byte
                    Dim value As Byte = (bytes(0) << remainder) >> remainder
                    result &= value.ToString("X2")
                Else
                    result &= bytes(index).ToString("X2")
                End If
            Next
            Return result
        End Function
    
        Public Function ContainsValue(ByVal lst As List(Of Ball), ByVal value As Integer) As Boolean
            For i As Integer = 0 To lst.Count - 1
                If lst(i).Value = value Then
                    Return True
                End If
            Next
            Return False
        End Function
    
        Sub Main()
    
            Dim valueComparer As New BallComparer_Value()
            Dim weightComparer As New BallComparer_Weight()
            Dim picks As New List(Of Ball)
            Dim balls As New List(Of Ball)
            ' number of bits after each "ball" is drawn
            Dim bits() As Integer = New Integer() {364, 358, 351, 345, 339}
    
            Using rng As New RNGCryptoServiceProvider
                While True
    
                    picks.Clear()
    
                    ' simulate random balls
                    'log10(75!) / log10(2) = number of bits required for weighted random shuffle (reduces each time ball is pulled) = 363.40103411549404253061653790169 = 364
                    For i As Integer = 0 To 4
                        balls.Clear()
                        For value As Integer = 1 To 75
                            ' do not add previous picks
                            If Not ContainsValue(picks, value) Then
                                balls.Add(New Ball(Weight(rng, bits(i)), value))
                            End If
                        Next
                        balls.Sort(weightComparer)
    
                        'For Each x As Ball In balls
                        '    Console.WriteLine(x.Weight)
                        'Next
                        'Console.ReadLine()
    
                        ' choose first ball in sorted list
                        picks.Add(balls(0))
                    Next
                    picks.Sort(valueComparer)
    
                    ' simulate random balls
                    'log10(15!) / log10(2) = number of bits required for weighted random shuffle = 40.250140469882621763813506287601 = 41 bits required for megaball
                    balls.Clear()
                    For value As Integer = 1 To 15
                        balls.Add(New Ball(Weight(rng, 41), value))
                    Next
                    balls.Sort(weightComparer)
    
                    ' print to stdout
                    For i As Integer = 0 To 4
                        Console.Write(picks(i).Value.ToString("D2") & " "c)
                    Next
                    Console.WriteLine(balls(0).Value.ToString("D2"))
    
                End While
            End Using
    
        End Sub
    
    End Module
    
    导入System.Security.Cryptography
    模块1
    公共班级舞会
    作为弦的公共重量
    作为整数的公共值
    Public Sub New(ByVal\u权重为字符串,ByVal\u值为整数)
    重量=_重量
    值=\u值
    端接头
    末级
    公共级球形比较器
    机具(球的)比较器
    公共函数Compare(x为Ball,y为Ball)作为整数实现System.Collections.Generic.IComparer(Of Ball).Compare
    如果x.重量>y.重量,则
    返回1
    如果x.重量小于y.重量,则
    返回-1
    其他的
    返回0
    如果结束
    端函数
    末级
    公共类BallComparer_值
    机具(球的)比较器
    公共函数Compare(x为Ball,y为Ball)作为整数实现System.Collections.Generic.IComparer(Of Ball).Compare
    如果x值>y值,则
    返回1
    如果x值小于y值,则
    返回-1
    其他的
    返回0
    如果结束
    端函数
    末级
    作为字符串的公共函数权重(ByVal rng作为RNGCryptoServiceProvider,ByVal位作为整数)
    '生成长度为'位'的“加密”随机字符串(应使用硬件rng)
    将余数调整为整数=位Mod 8
    整数形式的小商=位\8
    作为整数的Dim字节计数=商+If(余数0,1,0)
    Dim bytes()作为Byte=新字节(字节计数-1){
    Dim结果为String=String.Empty
    rng.GetBytes(字节)
    对于作为整数的索引=字节。长度-1到0步骤-1
    如果index=bytes.Length-1,则
    '从高位字节中删除高位`余数'位
    Dim值为字节=(字节(0)>余数
    结果&=value.ToString(“X2”)
    其他的
    结果&=字节(索引).ToString(“X2”)
    如果结束
    下一个
    返回结果
    端函数
    公共函数包含布尔值(ByVal lst作为列表(球),ByVal值作为整数)
    对于i作为整数=0到lst.Count-1
    如果lst(i).Value=Value,则
    返回真值
    如果结束
    下一个
    返回错误
    端函数
    副标题()
    Dim valueComparer作为新的BallComparer_值()
    Dim weightComparer作为新的Ballcomarer_Weight()
    将拾取的球变暗为新列表(球)
    将球调暗为新列表(球)
    '每个“球”绘制后的位数
    Dim bits()作为整数=新整数(){364,358,351,345,339}
    将rng用作新的RNGCryptoServiceProvider
    虽然是真的
    1.Clear()
    '模拟随机球
    'log10(75!)/log10(2)=加权随机洗牌所需的位数(每次拉球时减少)=363.40103411549404253061653790169=364
    对于i,整数=0到4
    球
    对于整数形式的值=1到75
    '不要添加以前的拾取
    如果不包含value(picks,value),则
    球。添加(新球(重量(rng,位(i)),值))
    如果结束
    下一个
    球.分类(重量比较器)
    '对于每个x作为球中的球
    '控制台写入线(x重量)
    ”“接着呢
    'Console.ReadLine()
    '选择排序列表中的第一个球
    拾取。添加(球(0))
    下一个
    picks.Sort(valueComparer)
    '模拟随机球
    'log10(15!)/log10(2)=加权随机洗牌所需的位数=40.250140469882621763813506287601=megaball所需的41位