This post does not belong here because we are not talking about cryptographic random bytes. On the contrary, we are talking about the same bytes being generated in a similar way to that of 'Randomize number'. If you have no use for 'Randomize number' then you will have no use for the following. The reason why we are here is because the function employed is a derivative of PBCryptRandom called PBCryptFixedSeed. Clearly, Random has been replaced with FixedSeed giving the game away; even though Crypt and FixedSeed is a contradiction in terms.

There is no need for an Inner IV so that has been dropped - the default MS empty array is fine.
The outer IV and password saw a variety of values ranging from hash values of files grabbed at random to all sorts of weird and wonderful values. I finally settled on both being &B10 repeated. Why? Well, I have no particular reason and can only say, why not?
The monotonic counter has been based upon the block index counter with a variety of starting values. The starting value I ended up with was nothing, ie 128 zero bits with the last 32 bits being the counter. As we leave the function the next block, NextBlock, is kept static so that we follow on with a subsequent re-entry - we gotta keep monotonic.

We cannot test the data as previously - 5 x 100MB files will give five identical files - so 10MB was generated with a further nine 10MB following on.
These are the respective chi-squared values:
44.32 71.07 26.95 17.86 68.87 55.53 76.01 39.01 89.62 65.09.
The thing about chi-squared as with any null-hypothesis test is that the null-hypothesis is rejected if results are within the tails of the normal distribution otherwise the test is inconclusive. We cannot say that 55%, for example, is better than 65%; they are both inconclusive and the null-hypothesis holds. So, although that 89.62% is scratching at the "almost suspect" region it is still less than 90%. However, having said that Die-Hard was dusted down and a full test applied to that 9th block. The worst case close to zero and one was 0.0010 and 0.9985 respectively. The p values of the Die-Hard tests should not to be treated in the same way as the chi-squared above. That 9th block is OK. Of course, we don't have to use it. Interestingly, if we jumped straight to the 9th block by using a starting value for NextBlock from nth block as 10*1024*1024 * n \32 then get a chi-squared of 33.32%. We have, of course, bypassed 8 blocks of feedback.
Part Va may use the above principle but I have not examined that.
Using unbiased data is probably more important in a 'Randomize number' scenario so it may be worthwhile to download ent.exe from the Fourmilab link in PART V above if you have specific data sizes differing to those examined above just to make sure that you don't use a bad set. Bad sets are a fact of life but we are not obliged to use them.
Have fun.
Code:
#Compile Exe #Dim All #Tools Off %NOMMIDS = 1 %NOGDI = 1 #Include "win32api.inc" #Include "wincrypt.inc" %Bin = 1 %Hex = 0 '************************************************************************* ' API error macro Macro SysErrMsg( API, Number ) = MessageBox 0, SystemErrorMessage( WinErr, API, FuncName$, Number ), "AES", %MB_ICONERROR + %MB_TOPMOST '************************************************************************* Global hProv As Dword ' Always determine in PBMain and not in a function to be called often - it is time consuming - 6ms on my machine! %Display = %True Function PBMain Local sInterimOutPut, sFinalOutPut As String Local i As Long hProv = crGetDefaultRSAHandle If hProv = 0 Then Exit Function #If %Display sFinalOutPut = "PBCryptoFixedSeed" + $CrLf + $CrLf For i= 1 To 16 sInterimOutPut = PBCryptoFixedSeed( 32, %Hex ) sFinalOutPut = sFinalOutPut + sInterimOutPut + $CrLf Next i MsgBox sFinalOutPut, %MB_TOPMOST #Else For i = 1 To 10 sFinalOutPut = PBCryptoFixedSeed(10*1024*1024, %Bin) Kill "c:\test" + Trim$(Str$(i)) + ".txt" Open "c:\test" + Trim$(Str$(i)) + ".txt" For Binary As #1 Put$ #1, sFinalOutPut Close #1 sFinalOutPut = "" Next MsgBox "Done" #EndIf If hProv Then CryptReleaseContext hProv, 0 End Function '************************************************************************* Function PBCryptoFixedSeed( ByVal ToTalBytes As Long, ByVal Flag As Long ) As String #Register None Local Blocks, Clip, i, j, hKey, hHash, WinErr As Long Local sHex, sPlaintext As String Local ptrPT As Dword Local pbyte As Byte Ptr Dim sTotalPbdata As String ' Dim to avoid potential stack overuse Static sPassword, OuterIV, pbdata As String, NextBlock As Dword If pbdata = "" Then ' this is the 1st pass of PBCryptRandom OuterIV = "AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA" ' &B10 repeated If Len( OuterIV ) Mod 2 <> 0 Then MsgBox "OuterIV is not an even length" GoTo TidyUp End If Hex2Bin( OuterIV ) sPassword = "AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA" ' &B10 repeated If Len( sPassword ) Mod 2 <> 0 Then MsgBox "sPassword is not an even length" GoTo TidyUp End If Hex2Bin( sPassword ) pbdata = OuterIV End If If CryptCreateHash( hProv, %CALG_SHA_256, 0, 0, hHash ) = %False Then WinErr = GetLastError : SysErrMsg( "CryptCreateHash", 10 ) Function = "" GoTo TidyUp Else If CryptHashData( hHash, ByVal StrPtr(sPassword), Len( sPassword ), 0 ) = %False Then WinErr = GetLastError : SysErrMsg( "CryptHasData", 20 ) Function = "" GoTo TidyUp Else If CryptDeriveKey( hProv, %CALG_AES_256, hHash, 0, hKey ) = %False Then WinErr = GetLastError : SysErrMsg( "CryptDeriveKey", 30 ) Function = "" GoTo TidyUp End If End If End If Blocks = TotalBytes\32 If (TotalBytes < 32) Or (TotalBytes Mod 32 <> 0) Then Incr Blocks Clip = %True End If If Flag = %Bin Then sTotalPbdata = Space$( 32*Blocks ) Else sTotalPbdata = Space$( 64*Blocks ) End If For i = 0 To Blocks - 1 sPlaintext = Space$(16) ptrPt = StrPtr( sPlaintext ) ! mov esi, ptrPt ! Xor eax, eax ! mov [esi], eax ! mov [esi+4], eax ! mov [esi+8], eax ! mov eax, NextBlock ! mov ebx, i ! Add eax, ebx ! mov [esi+12], eax ' pbdata = OuterIV when i = 0 and this is the 1st or only application session ' and equals the output of CryptEncrypt for all other events. AXorB(sPlaintext, pbdata) ' sPlainText = sPlainText XOR pbdata ' AES ciphertext = plaintext + 16 bytes pbdata = sPlaintext + Space$(16) If CryptEncrypt( hKey, 0, %True, 0, ByVal StrPtr( pbdata ), 16, 32 ) = %False Then WinErr = GetLastError : SysErrMsg( "CryptEncrypt", 40 ) Function = "" GoTo TidyUp End If If Flag = %Bin Then Mid$( sTotalPbdata, 32*i + 1, 32 ) = pbdata Else pbyte = StrPtr(pbdata) For j = 0 To 31 sHex = sHex + Hex$(@pbyte[j],2) Next j Mid$( sTotalPbdata, 64*i + 1, 64 ) = sHex End If Next If Clip Then sTotalPbdata = Left$(sTotalPbdata, (2-Flag)*TotalBytes) NextBlock = NextBlock + Blocks Function = sTotalPbdata TidyUp: If hHash Then CryptDestroyHash hHash If hKey Then CryptDestroyKey hKey End Function '************************************************************************* Function Hex2Bin( A As String) As Long ' Input: A is upper or lower case hexadecimal ' Output: A is half length of input A #Register None Local ptrA, StringEnd As Dword A = UCase$(A) ptrA = StrPtr( A ) - 1 StringEnd = StrPtr( A ) + Len( A ) ! mov esi, ptrA ! mov edi, ptrA ! mov ecx, StringEnd StartLoop: ! inc esi ' 1st pass is ! inc edi ' start of string ' esi will move in steps of two and edi will move in steps of one ! cmp esi, ecx ' Are we at the end of the string ! je Endloop ! mov al, [esi] ' Get byte in A ! cmp al, 57 ' Is it numeric? ! jg NotNum1 ' No ! Sub al, 48 ' Yes ! jmp IsNo1 NotNum1: ! Sub al, 55 ' Is aphabetic so get numeric value IsNo1: ! shl al, 4 ' Multiply by 16 ! inc esi ' Move on to next character of hex pair ! mov bl, [esi] ' Get byte ! cmp bl, 57 ' Is it numeric? ! jg NotNum2 ' No ! Sub bl, 48 ' Yes ! jmp IsNo2 NotNum2: ! Sub bl, 55 ' Is alphabetic so get numeric value IsNo2: ! Add al, bl ' Add 2nd of pair to 1st of pair ! mov [edi], al ' and put into next edi slot ! jmp StartLoop Endloop: A = Left$(A, Len(A)\2) Function = %True End Function '***************************************************************************** Function AXorB( A As String, B As String ) As Long ' A becomes A Xor B, B remains unchanged ' Computation is limited to the length of the shorter string ' if the strings are not the same length #Register None Local ptrA, ptrB, StringEnd As Dword ptrA = StrPtr( A ) - 1 ptrB = StrPtr( B ) - 1 StringEnd = StrPtr( A ) + Len( A ) If Len( A ) > Len( B ) Then StringEnd = StrPtr( A ) + Len( B ) ! mov esi, ptrA ! mov edi, ptrB ! mov ecx, StringEnd StartLoop: ! inc esi ' 1st pass is ! inc edi ' start of strings ! cmp esi, ecx ' Are we at end of strings? ! je EndLoop ' Yes ! mov al, [esi ] ' Get byte in A ! Xor al, [edi ] ' al becomes byte in A Xor byte in B ! mov [esi ], al ' Put byte in A ' [edi] is unchanged ie B ! jmp StartLoop EndLoop: Function = %True End Function '************************************************************************* Function crGetDefaultRSAHandle As Long Local WinErr As Long If CryptAcquireContext( hProv, ByVal %Null, ByVal %Null, %PROV_RSA_AES, 0 ) = %False Then If CryptAcquireContext( hProv, ByVal %Null, $MS_ENH_RSA_AES_PROV, %PROV_RSA_AES, %CRYPT_NEWKEYSET ) = %False Then WinErr = GetLastError : SysErrMsg( "CryptAcquireContext", 10 ) Function = %False Else Function = hProv End If Else Function = hProv End If End Function '************************************************************************* Function SystemErrorMessage( ByVal WinErr As Long, API As String, sFunction As String, ByVal Number As Long ) As String Local pBuffer As Asciiz Ptr, ncbBuffer As Dword Local sText As String ncbBuffer = FormatMessage( %FORMAT_MESSAGE_ALLOCATE_BUFFER Or %FORMAT_MESSAGE_FROM_SYSTEM Or %FORMAT_MESSAGE_IGNORE_INSERTS, _ ByVal %Null, WinErr, %Null, ByVal VarPtr( pBuffer ), 0, ByVal %Null ) If ncbBuffer Then sText = Peek$( pBuffer, ncbBuffer ) sText = Remove$( sText, Any Chr$( 13 ) + Chr$( 10 ) ) Function = $CrLf + "Error" + Format$( WinErr, " #####" ) + " during " + API + $CrLf + $CrLf + _ Chr$(34) + sText + Chr$(34) + $CrLf + $CrLf + "Location : " + sFunction + IIf$( Number, Format$( Number, " ###" ), "" ) LocalFree pBuffer Else Function = "Unknown error - Code:" + Format$( WinErr, " #####" ) End If End Function '*************************************************************************
Leave a comment: