CryptoRndIV

General FreeBASIC programming questions.
Post Reply
deltarho[1859]
Posts: 4292
Joined: Jan 02, 2017 0:34
Location: UK
Contact:

CryptoRndIV

Post by deltarho[1859] »

fxm's recent return to thread pooling got me thinking. :)

The result is CryptoRndIV.

CryptoRndII gives us a choice between using Microsoft's BCryptGenRandom or Intel's RdRand and Microsoft thread pooling. Intel introduced RdRand in 2012 so some of you may not have that on board. RdSeed was introduced in 2014, and I don't have that. CryptoRndIV only uses RdRand and no check is made to test whether you have it or not. If you are not sure, I have some code which will query your PC; just ask. Microsoft's thread pooling has been replaced by fxm's thread pooling (ThreadInitThenMultiStart).

Intel does not guarantee that a RdRand will be returned, but the likelihood of a failure is minimal. We can try again. I allow ten attempts before giving up, and have never seen that. However, it is not impossible, so we must cater for it. CryptoRndII recovers by using RtlGenRandom which is a Microsoft CPRNG function. CryptoRndIV recovers by using FreeBASIC's random number generator #5 available on Win32 and Linux.

So CryptoRndIV is a Microsoft free zone which should work on Linux. It should not be used for cryptographic work.

It is not as fast as PCG32II and MsWs, but is far from being a slouch.

These are the throughputs, in 32-bit mode, that I am getting.

Code: Select all

                   MHz
DW (Ulong)         533
S [0,1)            550
SX [-1, 1]         550
D                  497
DX [-1,1]          467
R (Integral)       528
R (Floating point) 549
Gauss (Single)      39
S and SX have a 32-bit granularity
D and DX have a 53-bit granularity
R a range overloaded as integer or floating point
Gauss is the normal distribution

In 64-bit mode, we use the 64-bit RdRand.

The timings were done using a large buffer greater than the number of random numbers requested to avoid a buffer switch. The CryptoRnd family uses two buffers. When one is purged, we switch buffers and then fill up the purged buffer with fresh data. Two secondary threads of execution are used to fill two half buffers. The switch is too fast for us to perceive it; just over 7 milliseconds on my machine. The buffers default sizes are 5MiB. For numbers requiring 8 bytes, that gives 655,360 random numbers before a buffer switch is executed. Recommendation is to use buffers of at least 1Mib. A 5MiB buffer is filled, in 32-bit mode, in 27 milliseconds, so in practice the unused buffer will be ready for us when the other is purged.

I normally expect one or two insignificant anomalies with PractRand, but I didn't get any up to 1TB. I left it at that – I would rather not insult a class act in RdRand. I have mentioned this before, but when you get to my age you don't push PractRand to 16TiB. Headstone: “He passed away at 8TiB with PractRand.” :)

Unlike other PRNG implementations, we don't have the facility to get snapshots and so on – we are using a CPRNG remember with no state vector. However, we can go back to the beginning of the first buffer by using ResetBufferPointer provided we have not switched buffers. Once we start to refresh the first buffer, we are stuffed.

So, except for D and DX we have a top class half GHz CPRNG; on my beast anyway.

Now I don't have Linux. Would someone be kind enough to test CryptRndIV on Linux for me?

CryptoRndIV.bas

Code: Select all

/'
This is the same as CryptoRndII except we use fxm's FreeBASIC method
as opposed to Microsoft's thread pooling and it only uses Intel RdRand
'/
 
' ****************************** fxm's code
 
Type ThreadInitThenMultiStart
  Public:
  Declare Constructor()
  Declare Sub ThreadInit(Byval pThread As Sub(Byval As Any Ptr), Byval p As Any Ptr = 0)
  Declare Sub ThreadStart()
  Declare Sub ThreadStart(Byval p As Any Ptr)
  Declare Sub ThreadWait()
  Declare Destructor()
  Private:
  Dim As Sub(Byval p As Any Ptr) _pThread
  Dim As Any Ptr _p
  Dim As Any Ptr _mutex1, _mutex2, _mutex3
  Dim As Any Ptr _pt
  Dim As Byte _end
  Declare Static Sub _Thread(Byval p As Any Ptr)
End Type
 
Constructor ThreadInitThenMultiStart()
  This._mutex1 = Mutexcreate()
  Mutexlock(This._mutex1)
  This._mutex2 = Mutexcreate()
  Mutexlock(This._mutex2)
  This._mutex3 = Mutexcreate()
  Mutexlock(This._mutex3)
End Constructor
 
Sub ThreadInitThenMultiStart.ThreadInit(Byval pThread As Sub(Byval As Any Ptr), Byval p As Any Ptr = 0)
  This._pThread = pThread
  This._p = p
  If This._pt = 0 Then
    This._pt = Threadcreate(@ThreadInitThenMultiStart._Thread, @This)
    Mutexunlock(This._mutex3)
  End If
End Sub
 
Sub ThreadInitThenMultiStart.ThreadStart()
  Mutexlock(This._mutex3)
  Mutexunlock(This._mutex1)
End Sub
 
Sub ThreadInitThenMultiStart.ThreadStart(Byval p As Any Ptr)
  Mutexlock(This._mutex3)
  This._p = p
  Mutexunlock(This._mutex1)
End Sub
 
Sub ThreadInitThenMultiStart.ThreadWait()
  Mutexlock(This._mutex2)
  Mutexunlock(This._mutex3)
End Sub
 
Sub ThreadInitThenMultiStart._Thread(Byval p As Any Ptr)
  Dim As ThreadInitThenMultiStart Ptr pThis = p
  Do
    Mutexlock(pThis->_mutex1)
    If pThis->_end = 1 Then Exit Sub
    pThis->_pThread(pThis->_p)
    Mutexunlock(pThis->_mutex2)
  Loop
End Sub
 
Destructor ThreadInitThenMultiStart()
  If This._pt > 0 Then
    This._end  = 1
    Mutexunlock(This._mutex1)
    .ThreadWait(This._pt)
  End If
  Mutexdestroy(This._mutex1)
  Mutexdestroy(This._mutex2)
  Mutexdestroy(This._mutex3)
End Destructor
 
' ****************************** End of fxm's code
 
Dim Shared As UByte Buffer0(), Buffer1()
Dim Shared As Integer BufferSize
Dim Shared As Any Ptr ptrBuffer, ptrBaseBuffer0, ptrBaseBuffer1
Dim Shared As Any Ptr ptrBaseBuffer0plus, ptrBaseBuffer1plus
Dim Shared As Integer SwitchBufferCriteria
Dim Shared As ThreadInitThenMultiStart t0, t0plus, t1, t1plus
 
Declare Sub SwitchBuffer
Declare Sub FillBuffer( ByVal As Any Ptr )
Declare Sub ResetBufferPointer
Declare Sub InitializeCryptoBuffers( As Long )
 
BufferSize = 5*1024*1024
 
InitializeCryptoBuffers( BufferSize )
 
Private Function CryptoDW As Ulong
 
  If ptrBuffer >= SwitchBufferCriteria Then
    SwitchBuffer
  End If
 
  Asm
    mov eax, dword Ptr [ptrBuffer]
    mov eax, [eax]
    mov [Function], eax
  End Asm
 
  ptrBuffer += 4
 
End Function
 
Private Function CryptoS As Double ' [0,1)
Dim As Ulong TempVar
 
  If ptrBuffer >= SwitchBufferCriteria Then
    SwitchBuffer
  End If
 
  Asm
     mov eax, dword Ptr [ptrBuffer]
     mov eax, [eax]
     mov dword Ptr [TempVar], eax
  End Asm
  ptrBuffer += 4
  Return TempVar/4294967296.0
 
End Function
 
Private Function CryptoSX As Double ' [-1,1]
Dim As Ulong TempVar
 
  If ptrBuffer >= SwitchBufferCriteria Then
    SwitchBuffer
  End If
 
  Asm
    mov eax, dword Ptr [ptrBuffer]
    mov eax, [eax]
    mov dword Ptr [TempVar], eax
  End Asm
  ptrBuffer += 4
  Return TempVar/2147483648.0 - 1
 
End Function
 
Private Function CryptoD As Double  ' [0,1)
 
  If ptrBuffer >= SwitchBufferCriteria Then
    SwitchBuffer
  End If
 
  ' ASM by Wilbert at PureBasic forums
  Asm
    mov eax, dword Ptr [ptrBuffer]
    movd xmm0, [eax]
    movd xmm1, [eax + 4]
    punpckldq xmm0, xmm1
    psrlq xmm0, 12
    mov eax, 1
    cvtsi2sd xmm1, eax
    por xmm0, xmm1
    subsd xmm0, xmm1
    movq [Function], xmm0
  End Asm
 
  ptrBuffer += 8
 
End Function
 
Private Function CryptoDX As Double  ' [-1,1]
 
  If ptrBuffer >= SwitchBufferCriteria Then
    SwitchBuffer
  End If
 
  ' ASM adapted from CryptoD by author
  Asm
    mov eax, dword Ptr [ptrBuffer]
    movd xmm0, [eax]
    movd xmm1, [eax + 4]
    punpckldq xmm0, xmm1
    psrlq xmm0, 12
    mov eax, 2
    cvtsi2sd xmm1, eax
    por xmm0, xmm1
    subsd xmm0, xmm1
    mov eax, 1
    cvtsi2sd xmm1, eax
    subsd xmm0, xmm1
    movq [Function], xmm0
  End Asm
 
  ptrBuffer += 8
 
End Function
 
Private Function CryptoR Overload( Byval One As Long, Byval Two As Long ) As Long
Dim As Ulong TempVar
 
  If ptrBuffer >= SwitchBufferCriteria Then
    SwitchBuffer
  End If
 
  Asm
    mov eax, dword Ptr [ptrBuffer]
    mov eax, [eax]
    mov dword Ptr [TempVar], eax
  End Asm
  ptrBuffer += 4
  return clng(TempVar Mod (Two-One+1)) + One ' By dodicat
 
End Function
 
Private Function CryptoR Overload( Byval One As Double, Byval Two As Double ) As Double
Dim As Ulong TempVar
 
  If ptrBuffer >= SwitchBufferCriteria Then
    SwitchBuffer
  End If
 
  Asm
    mov eax, dword Ptr [ptrBuffer]
    mov eax, [eax]
    mov dword Ptr [TempVar], eax
  End Asm
  ptrBuffer += 4
  Return TempVar/2^32*( Two - One ) + One
End Function
 
Private Function Gauss As Single
Static As Long u2_cached
Static As Single u1, u2, x1, x2, w
 
  If u2_cached = -1 Then
    u2_cached = 0
    Function = u2
  Else
    Do
      x1 = CryptoS
      x2 = CryptoS
      w = x1 * x1 + x2 * x2
    Loop While w >= 1
    w = Sqr( -2 * Log(w)/w )
    u1 = x1 * w
    u2 = x2 * w
    u2_cached = -1
    Function = u1
  End If
 
End Function
 
Private Sub InitializeCryptoBuffers( Byval Buffer As Long )
  If Buffer < 1024 Then
    BufferSize = 1024
  Else
    BufferSize = Buffer - Buffer Mod 8
  End If
  Redim Buffer0( 1 To BufferSize) As UByte
  ptrBaseBuffer0 = Varptr( Buffer0(1) )
  ptrBuffer = ptrBaseBuffer0
  SwitchBufferCriteria = Cast( Integer, ptrBuffer ) + BufferSize
  t0.ThreadInit( @FillBuffer )
  ptrBaseBuffer0plus = ptrBaseBuffer0 + BufferSize\2
  t0plus.ThreadInit( @FillBuffer )
  t0.ThreadStart( ptrBaseBuffer0 )
  t0plus.ThreadStart( ptrBaseBuffer0plus )
  Redim Buffer1( 1 To BufferSize) As UByte
  ptrBaseBuffer1 = Varptr( Buffer1(1) )
  t1.ThreadInit( @FillBuffer )
  ptrBaseBuffer1plus = ptrBaseBuffer1 + BufferSize\2
  t1plus.ThreadInit( @FillBuffer )
  t1.ThreadStart( ptrBaseBuffer1 )
  t1plus.ThreadStart( ptrBaseBuffer1plus )
  t0.ThreadWait()
  t0plus.ThreadWait()
End Sub
 
Private Sub FillBuffer( ByVal BaseBuffer As Any Ptr )
Dim As ULong HalfBuffer
Dim As Ulongint RecoverBuffer
Dim As Ulong Ptr ptrRecoverBuffer
Dim AS Ulong Ptr Dummy = BaseBuffer
 
  ptrRecoverBuffer = cast( Ulong Ptr, @RecoverBuffer)
 
  HalfBuffer = BufferSize\2
  Asm
    mov edi, dword Ptr [HalfBuffer]
    mov esi, 0
    mov ebx, dword Ptr [Dummy]
  rptRdRand:
    mov ecx, 10 ' Max number Of tries before going into a recovery
  queryAgain:
  #ifdef __FB_64BIT__
    RdRand rax
  #Else
    RdRand eax
  #endif
    jc OK ' A Random value was available
    dec ecx
    jnz queryAgain
    Call Recover ' Use RtlGenRandom For This ULong
  OK:
    #ifdef __FB_64BIT__
      mov qword Ptr [ebx + esi], rax ' Store RdRand
      Add esi, 8
    #Else
      mov dword Ptr [ebx + esi], eax ' Store RdRand
      Add esi, 4
    #endif
      cmp edi, esi
      jne rptRdRand
      jmp Done
  Recover:
  #ifndef __FB_64BIT__
    pushad ' I am playing it safe here
  #endif
  End Asm
  Randomize , 5
  #ifdef __FB_64BIT__
    *ptrRecoverBuffer = Int(Rnd*2^32)
    *(ptrRecoverBuffer + 1) = Int(Rnd*2^32)
  #Else
    *ptrRecoverBuffer = Int(Rnd*2^32)
  #endif
  Asm
  #ifndef __FB_64BIT__
    popad
  #endif
  #ifdef __FB_64BIT__
    mov rax, qword Ptr [ptrRecoverBuffer]
  #Else
    mov eax, dword Ptr [ptrRecoverBuffer]
  #endif
    ret
  Done:
  End Asm
End Sub
 
Private Sub SwitchBuffer
  t1.ThreadWait()
  t1plus.ThreadWait()
  Swap ptrBaseBuffer0, ptrBaseBuffer1
  Swap ptrBaseBuffer0plus, ptrBaseBuffer1plus
  ptrBuffer = ptrBaseBuffer0
  SwitchBufferCriteria = Cast( Integer, ptrBuffer ) + BufferSize
  t1.ThreadStart( ptrBaseBuffer1 )
  t1plus.ThreadStart( ptrBaseBuffer1plus )
End Sub
 
Private Sub ResetBufferPointer
  ptrBuffer = ptrBaseBuffer0
End Sub
Try this:

Code: Select all

#Include Once "CryptoRndIV.bas"
Print CryptoDW
Print CryptoS
Print CryptoSX
Print CryptoD
Print CryptoDX
Print CryptoR(10, 20)
Print CryptoR(10.,20.)
deltarho[1859]
Posts: 4292
Joined: Jan 02, 2017 0:34
Location: UK
Contact:

Re: CryptoRndIV

Post by deltarho[1859] »

How about this for distribution uniformity – average of five 10^8 CryptoS?

Code: Select all

 0.5000155490314405
 0.5000133829293141
 0.5000261462290128
 0.4999809064912515
 0.5000354147181636
That plus its speed is ideal for Monte Carlo work.
deltarho[1859]
Posts: 4292
Joined: Jan 02, 2017 0:34
Location: UK
Contact:

Re: CryptoRndIV

Post by deltarho[1859] »

Actually, I couldn't remember where it was. :)

AMD added support for the instruction in June 2015.

IsRdRand.bas

Code: Select all

#include once "windows.bi"

Function IsRdRand() As Long

Dim CPUManID As String * 12
Dim CPUManIDPtr As Ulong Ptr

' Get Manufactures Id String
CPUManIDPtr = Cptr(Ulong Ptr, StrPtr( CPUManID ))
Asm
  mov eax, 0 ' Get Vendor Id
  cpuid
  mov eax, [CPUManIDPtr]
  mov [eax], ebx
  mov [eax + 4], edx
  mov [eax + 8], ecx
End Asm
If CPUManID = "GenuineIntel" or CPUManID = "AuthenticAMD" Then
  ' Is RdRand supported?
  Asm
    mov eax, 1 ' Get features
    cpuid
    test ecx, &h40000000 ' Bit 30
    jz NoRdRand
    mov [Function], -1
NoRdRand:
  End Asm
End If
End Function

If IsRdRand = True then
  Messagebox( Null, "Yes, it is.", "Is RdRand supported?", MB_OK )
Else
  Messagebox( Null, "No, it is not.", "Is RdRand supported?", MB_OK )
End If
dodicat
Posts: 7976
Joined: Jan 10, 2006 20:30
Location: Scotland

Re: CryptoRndIV

Post by dodicat »

Hi deltarho[]
using your try this code I cannot get past InitializeCryptoBuffers sub
32 bits stops at t0.ThreadWait()
64 bits stops at t0plus.ThreadStart( ptrBaseBuffer0plus ), sometimes it gets past it but stops at the next line.
Win 10, official builds.
(-exx does not capture the runtime crash)
srvaldez
Posts: 3373
Joined: Sep 25, 2005 21:54

Re: CryptoRndIV

Post by srvaldez »

for me it works in 32-bit but in 64-bit I get exit-code 3
[edit]
it works in 64-bit if you use FB with older binutils
deltarho[1859], the following doesn't look right to me

Code: Select all

    mov edi, dword Ptr [HalfBuffer]
    mov esi, 0
and later

Code: Select all

    mov qword Ptr [ebx + esi], rax
and there are other places where you use a 32-bit pointer which is not guaranteed to work in 64-bit
I think that would be better to have the 32-bit and 64-bit asm blocks separated, it would be less confusing
deltarho[1859]
Posts: 4292
Joined: Jan 02, 2017 0:34
Location: UK
Contact:

Re: CryptoRndIV

Post by deltarho[1859] »

Ok dear!

With Windows 10, latest build, it works with gas, gas64, gcc 32-bit -O2, and gcc 64-bit -O2. I am using the official fbc builds.

OK, I took the forum code and put it into a file. I then took the WiKi code and put that into a file. I then loaded both into TextPad and compared files.

The forum code is the last posted by fxm on 'Type ThreadInitThenMultiStart' that I was using when I was testing for fxm. It is not the same as the WiKi version. The WiKi version has three small additonal blocks of code. fxm has done further work since his last forum posting. This repeats my cock up a few weeks back with MacroTimersQPC.inc.

The WiKi version uses ThreadState flags and a few other things besides. This may have nothing whatsoever to do with the above issues.

dodicat's issues are worrisome.

srvaldez's issues appear fixable, but why is my setup behaving so well?

Why are your issues so very different?

srvaldez's code issues have been used for years for getting 32-bit RdRand over at PowerBASIC which is only a 32-bit compiler. Getting the 64-bit RdRand was added when the original CryotoRnd was ported from PowerBASIC. However, I am getting 0 Errors and 0 Warnings, so the compilers seem happy. Let's face it, it doesn't take much to get a failed compilation with ASM.

64-bit mode uses rdi and rsi but I am only interested in the lower 32 bits. Perhaps my logic is wrong, but we keep coming back to my having no issues.

Houston, we have a problem. :?

Oh, thanks for testing, guys. What a bummer. I was looking forward to: “Yep, it works on Linux.”

To eliminate from our enquiries, would you try your Windows kit?
deltarho[1859]
Posts: 4292
Joined: Jan 02, 2017 0:34
Location: UK
Contact:

Re: CryptoRndIV

Post by deltarho[1859] »

With Windows only 48 bits of a 64 bit pointer is used. With a 4GiB address space for processes, we only need 32 bits to navigate within that. Apparently, in 64-bit mode, Linux uses bit 63, so perhaps we should be using rdi and rsi.

I will do that and post a new 'Sub FillBuffer',
That may solve srvaldez's issue with getting the RdRand code.

dodicat's issues seem different.
deltarho[1859]
Posts: 4292
Joined: Jan 02, 2017 0:34
Location: UK
Contact:

Re: CryptoRndIV

Post by deltarho[1859] »

Code: Select all

Dim Buffer As Any Ptr
Print SizeOf(Buffer)
Sleep
Gives 4 in 32-bit mode and 8 in 64-bit mode.

Obvious really but I have never needed to know that – but I do now. :)
srvaldez
Posts: 3373
Joined: Sep 25, 2005 21:54

Re: CryptoRndIV

Post by srvaldez »

deltarho[1859], just a comment if you want your code to run on linux
windows x64 uses the following registers for integer/pointer parameters
rcx, rdx, r8 and r9 see https://andreaspk.github.io/posts/2019- ... ntion.html and https://learn.microsoft.com/en-us/cpp/b ... w=msvc-170
linux uses
rdi, rsi, rdx and rcx see https://cmcenroe.me/2017/06/29/sysv-abi-reference.html
note that in linux rbx is Callee-saved
deltarho[1859]
Posts: 4292
Joined: Jan 02, 2017 0:34
Location: UK
Contact:

Re: CryptoRndIV

Post by deltarho[1859] »

Thanks srvaldez

In 64-bit mode I'll be using rdi and rsi for both Windows and Linux. Testing for 64-bit mode is one thing, but I would rather not test for Windows as well. Windows won't mind if I use rdi and rsi. I have been using edi and esi in 32-bit mode on Windows for some time.
fxm
Moderator
Posts: 12081
Joined: Apr 22, 2009 12:46
Location: Paris suburbs, FRANCE

Re: CryptoRndIV

Post by fxm »

@deltarho[1859],

I have not fixed any bugs between your version and my latest version of ThreadInitThenMultiStart.
Only new features have been introduced:
- the user thread procedure must be now of the form of a function like:
Declare Function ThreadProc (Byref p As Any Ptr) As String
and ThreadWait is also now a function.
- a property 'ThreadState' which returns (in a Ubyte) the current state of the thread is added.
deltarho[1859]
Posts: 4292
Joined: Jan 02, 2017 0:34
Location: UK
Contact:

Re: CryptoRndIV

Post by deltarho[1859] »

fxm wrote:Only new features have been introduced:
I figured that when I wrote: “This may have nothing whatsoever to do with the above issues.”
deltarho[1859]
Posts: 4292
Joined: Jan 02, 2017 0:34
Location: UK
Contact:

Re: CryptoRndIV

Post by deltarho[1859] »

srvaldez wrote:I think that would be better to have the 32-bit and 64-bit asm blocks separated, it would be less confusing
Agreed and done.

Replace 'Private Sub FillBuffer' with the following:

Code: Select all

Private Sub FillBuffer( ByVal BaseBuffer As Any Ptr )
Dim As ULong HalfBuffer
Dim As Ulongint RecoverBuffer
Dim As Any Ptr ptrRecoverBuffer
Dim AS Any Ptr Dummy = BaseBuffer

ptrRecoverBuffer = cast( Any Ptr, @RecoverBuffer)

HalfBuffer = BufferSize\2

Randomize , 5

#ifndef __FB_64BIT__ ' 32_bit
Asm
  mov edi, dword Ptr [HalfBuffer]
  mov esi, 0
  mov ebx, dword Ptr [Dummy]
rptRdRand32:
  mov ecx, 10 ' Max number Of tries before going into a recovery
queryAgain32:
  RdRand eax
  jc OK32 ' A random value was available
  dec ecx
  jnz queryAgain32
  Call Recover32
OK32:
  mov dword Ptr [ebx + esi], eax ' Store RdRand
  Add esi, 4
  cmp edi, esi
  jne rptRdRand32
  jmp Done32
Recover32:
  pushad ' I am playing it safe here
End Asm
  *(Cast( Ulong Ptr, ptrRecoverBuffer )) = Int(Rnd*2^32)
  Asm
    popad
    mov eax, dword Ptr [ptrRecoverBuffer]
    ret
  Done32:
  End Asm
#Else '64-bt
  Asm
    mov rdi, qword Ptr [HalfBuffer]
    mov rsi, 0
    mov rbx, qword Ptr [Dummy]
  rptRdRand64:
    mov ecx, 10 ' Max number Of tries before going into a recovery
  queryAgain64:
    RdRand rax
    jc OK64 ' A random value was available
    dec ecx
    jnz queryAgain64
    Call Recover64
  OK64:
    mov qword Ptr [rbx + rsi], rax ' Store RdRand
    Add rsi, 8
    cmp rdi, rsi
    jne rptRdRand64
    jmp Done64
  Recover64:
  End Asm
  *(Cast( Ulongint Ptr, ptrRecoverBuffer )) = Int(Rnd*2^32)
  *(Cast( UlongInt Ptr, ptrRecoverBuffer + 1 )) = Int(Rnd*2^32)
  Asm
    mov rax, qword Ptr [ptrRecoverBuffer]
    ret
  Done64:
  End Asm
#EndIf
End Sub
srvaldez
Posts: 3373
Joined: Sep 25, 2005 21:54

Re: CryptoRndIV

Post by srvaldez »

deltarho[1859] :)
you still need to make the following functions 64-bit clean
CryptoDW, CryptoS, CryptoSX, CryptoD, CryptoDX, CryptoR and CryptoR overload
as is it will crash in 64-bit
deltarho[1859]
Posts: 4292
Joined: Jan 02, 2017 0:34
Location: UK
Contact:

Re: CryptoRndIV

Post by deltarho[1859] »

@srvaldez

Whatever I do, I cannot test because I don't have Linux.

Show me how to clean CryptoDW, for example, and I will do the rest.
Post Reply