Replace VB6's Rnd function with cryptographically secure alternative-VBForums
Results 1 to 17 of 17

Thread: Replace VB6's Rnd function with cryptographically secure alternative

  1. #1

    Thread Starter
    Junior Member
    Join Date
    Aug 2016
    Posts
    16

    Replace VB6's Rnd function with cryptographically secure alternative

    I'm using the Rnd function to generate passwords. However, it's susceptible to brute-force attacks, regardless of the strength of the password itself which becomes (sort of) trivial when the aim of the attacker is not the password but the Rnd seed which generates it.

    I use Rnd in many places in my code, and I know it's possible to replace native VB6 functions with our own, so I would like a fully operational replacement for Rnd which requires no code modification elsewhere, and is cryptographically secure. Like the standard Rnd function, it must return a Single value type. Like the standard Rnd function, the replacement can be used with parameter number or without it... the latter returns a value equal or greater than 0 and less than 1 (i.e. >= 0 and < 1).

    APIs, as long as they are supported by default from Windows XP/Server 2003 to Windows 10, are welcome.

    Why a Rnd replacement instead of a fit-my-mold function? Because there are thousands of Rnd-dependent functions on the net, for n different purposes, many of which have shortcomings due to the inherent weakness in the standard Rnd function.
    Last edited by veloz; Mar 19th, 2017 at 03:07 PM.

  2. #2
    Hyperactive Member
    Join Date
    Jan 2013
    Posts
    285

    Re: Replace VB6's Rnd function with cryptographically secure alternative

    Quote Originally Posted by veloz View Post
    I'm using the Rnd function to generate passwords. However, it's susceptible to brute-force attacks, regardless of the strength of the password itself which becomes (sort of) trivial when the aim of the attacker is not the password but the Rnd seed which generates it.

    I use Rnd in many places in my code, and I know it's possible to replace native VB6 functions with our own, so I would like a fully operational replacement for Rnd which requires no code modification elsewhere, and is cryptographically secure. Like the standard Rnd function, it must return a Single value type. Like the standard Rnd function, the replacement can be used with parameter number or without it... the latter returns a value equal or greater than 0 and less than 1 (i.e. >= 0 and < 1).

    APIs, as long as they are supported by default from Windows XP/Server 2003 to Windows 10, are welcome.

    Why a Rnd replacement instead of a fit-my-mold function? Because there are thousands of Rnd-dependent functions on the net, for n different purposes, many of which have shortcomings due to the inherent weakness in the standard Rnd function.
    you are using cryptography for communication?.

  3. #3

    Thread Starter
    Junior Member
    Join Date
    Aug 2016
    Posts
    16

    Re: Replace VB6's Rnd function with cryptographically secure alternative

    @flyguille

    It's not for communication, no.

    * * *

    Here's a function by Bonnie West that I believe can be edited to replace Rnd:

    Code:
    Option Explicit
    
    Private Declare Function CryptAcquireContextW Lib "advapi32.dll" (ByRef phProv As Long, ByVal pszContainer As Long, ByVal pszProvider As Long, ByVal dwProvType As Long, ByVal dwFlags As Long) As Long
    Private Declare Function CryptGenRandom Lib "advapi32.dll" (ByVal hProv As Long, ByVal dwLen As Long, ByRef pbBuffer As Any) As Long
    Private Declare Function CryptReleaseContext Lib "advapi32.dll" (ByVal hProv As Long, Optional ByVal dwFlags As Long) As Long
    
    Public Function GenRnd() As Long
        Const PROV_RSA_FULL = 1&, CRYPT_VERIFYCONTEXT = &HF0000000
        Dim hProvider As Long
    
        If CryptAcquireContextW(hProvider, 0&, 0&, PROV_RSA_FULL, CRYPT_VERIFYCONTEXT) Then
            If CryptGenRandom(hProvider, 4&, GenRnd) = 0& Then GenRnd = 0&
            hProvider = CryptReleaseContext(hProvider): Debug.Assert hProvider
        End If
    End Function

  4. #4
    Hyperactive Member
    Join Date
    Jan 2013
    Posts
    285

    Re: Replace VB6's Rnd function with cryptographically secure alternative

    so, it is for storage, right?

  5. #5
    Member
    Join Date
    Feb 2017
    Posts
    60

    Re: Replace VB6's Rnd function with cryptographically secure alternative

    Perhaps something like this (first attempt to Rnd replacement):
    It uses the previous code that you posted.

    Code:
    Public Function Rnd(Optional ByVal Number) As Single
        Dim Dbl As Double
        Static sLast As Single
        
        If IsMissing(Number) Then
            Number = 1
        End If
        Select Case Number
            Case Is < 0 ' The same number every time, using Number as the seed.
                Rnd = VBA.Rnd
            Case Is > 0 ' The next random number in the sequence.
                Dbl = CDbl(GenRnd)
                Dbl = Dbl + 2147483648#
                Dbl = Dbl / 4294967296#
                Rnd = CSng(Dbl)
            Case Else ' 0: The most recently generated number.
                If sLast <> 0 Then
                    Rnd = sLast
                Else
                    Rnd = Rnd(1)
                End If
        End Select
        sLast = Rnd
    End Function
    Last edited by Eduardo-; Mar 19th, 2017 at 05:01 PM.

  6. #6
    Member
    Join Date
    Feb 2017
    Posts
    60

    Re: Replace VB6's Rnd function with cryptographically secure alternative

    But I don't see a way to repeat the sequence replacing also Randomize, because CryptGenRandom API doesn't seem to have a way to set the seed.

  7. #7
    Hyperactive Member
    Join Date
    Jan 2013
    Posts
    285

    Re: Replace VB6's Rnd function with cryptographically secure alternative

    being it for communication or storage is more or less the same thing but with particular differences...., if someone want to decrypt your file, is not only how to get the seed, if brute force or from some file containing it, it is also knowing how you use the RND function and how you apply the numbers in data record.

    So, the hacker already dissasemble or traced your EXE, for knowing how to read your records. If it is a DB like access is far more easy thing, than custom binary file format.

    Concern about the speed of the code, can make you to do a weaker or harder cryptography.

    If for comunication, can be included universal things like "UTC time" in the cryptography, so the message a given day isn't the same as next day.

    if for storage, your APP must konw how to decrypt it to use, if not inputed by user on every instance, so in some place you needs to save the seed. And there is a place of interest for the guy trying to do inverse engineering.

    But there is a basic rule, the software will deserve the man-hours needed to hack it or not?. Do it a bit harder than what the hacker is willing to invest and your software or files never will be cracked.

  8. #8

    Thread Starter
    Junior Member
    Join Date
    Aug 2016
    Posts
    16

    Re: Replace VB6's Rnd function with cryptographically secure alternative

    Quote Originally Posted by Eduardo- View Post
    But I don't see a way to repeat the sequence replacing also Randomize, because CryptGenRandom API doesn't seem to have a way to set the seed.
    There's no need to set the seed in most cases (like, >99%) if all you want is true randomization.

    Can you incorporate GenRnd() into Rnd() to make it a single function?

  9. #9
    Hyperactive Member
    Join Date
    Jan 2013
    Posts
    285

    Re: Replace VB6's Rnd function with cryptographically secure alternative

    Quote Originally Posted by veloz View Post
    There's no need to set the seed in most cases (like, >99%) if all you want is true randomization.

    Can you incorporate GenRnd() into Rnd() to make it a single function?
    but if you can't repeat the rnd serie (setting the seed), ┐how do you build up the same kripto password again and again?. The only other way I see, is to save the krypto password already builded in some place, and that is a weakness because if found saved in a file it is already done!, ofcourse you can save the krypto pass in another encrypted file, but that is a vicious circle.
    Last edited by flyguille; Mar 19th, 2017 at 06:11 PM.

  10. #10
    Member
    Join Date
    Feb 2017
    Posts
    60

    Re: Replace VB6's Rnd function with cryptographically secure alternative

    Quote Originally Posted by veloz View Post
    There's no need to set the seed in most cases (like, >99%) if all you want is true randomization.

    Can you incorporate GenRnd() into Rnd() to make it a single function?
    Code:
    Private Declare Function CryptAcquireContextW Lib "advapi32.dll" (ByRef phProv As Long, ByVal pszContainer As Long, ByVal pszProvider As Long, ByVal dwProvType As Long, ByVal dwFlags As Long) As Long
    Private Declare Function CryptGenRandom Lib "advapi32.dll" (ByVal hProv As Long, ByVal dwLen As Long, ByRef pbBuffer As Any) As Long
    Private Declare Function CryptReleaseContext Lib "advapi32.dll" (ByVal hProv As Long, Optional ByVal dwFlags As Long) As Long
    
    Public Function Rnd(Optional ByVal Number) As Single
        Dim Dbl As Double
        Static sLast As Single
        Const PROV_RSA_FULL = 1&, CRYPT_VERIFYCONTEXT = &HF0000000
        Dim hProvider As Long
        Dim Lng As Long
        
        If IsMissing(Number) Then
            Number = 1
        End If
        Select Case Number
            Case Is < 0 ' The same number every time, using Number as the seed.
                Rnd = VBA.Rnd
            Case Is > 0 ' The next random number in the sequence.
                If CryptAcquireContextW(hProvider, 0&, 0&, PROV_RSA_FULL, CRYPT_VERIFYCONTEXT) Then
                    If CryptGenRandom(hProvider, 4&, Lng) = 0& Then Lng = 0&
                    hProvider = CryptReleaseContext(hProvider)
                End If
                If Lng <> 0 Then
                    Dbl = CDbl(Lng)
                    Dbl = Dbl + 2147483648#
                    Dbl = Dbl / 4294967296#
                    Rnd = CSng(Dbl)
                Else
                    Rnd = VBA.Rnd
                End If
            Case Else ' 0: The most recently generated number.
                If sLast <> 0 Then
                    Rnd = sLast
                Else
                    Rnd = Rnd(1)
                End If
        End Select
        sLast = Rnd
    End Function

  11. #11
    Member
    Join Date
    Feb 2017
    Posts
    60

    Re: Replace VB6's Rnd function with cryptographically secure alternative

    Quote Originally Posted by flyguille View Post
    but if you can't repeat the rnd serie (setting the seed), ┐how do you build up the same kripto password again and again?. The only other way I see, is to save the krypto password already builded in some place, and that is a weakness because if found saved in a file it is already done!, ofcourse you can save the krypto pass in another encrypted file, but that is a vicious circle.
    In that case then there is the need to find another function to generate the random numbers that can accept a seed.

    You can try with this.

    You'll need to add this API declaration:
    Code:
    Private Declare Function timeGetTime Lib "winmm.dll" () As Long
    And remove the last procedure: Private Sub ErrRaise

    It is supposed to be better (or more random) than the VB Rnd function, and it accepts seeds.
    Use the RandomReal property to get the numbers.

    That's not a direct replacement of the Rnd function, but it could be done if neccesary.

  12. #12

    Thread Starter
    Junior Member
    Join Date
    Aug 2016
    Posts
    16

    Re: Replace VB6's Rnd function with cryptographically secure alternative

    Quote Originally Posted by flyguille View Post
    but if you can't repeat the rnd serie (setting the seed), ┐how do you build up the same kripto password again and again?
    I don't need to. The whole point is to avoid a pattern, i.e. to make it truly random.

    * * *

    Thanks, Eduardo.

    What is VBA.Rnd? My guess is that you need to call the VB6's Rnd() inside a function with the same name, and VBA.Rnd is some kind of workaround, though I have never heard of it.

    As for the code, I'm using it, but I would like to hear what other experts have to say regarding its safety and reliability.

    EDIT: See the attached image. The vast majority of outputs are 0,decimals, but shouldn't ALL outputs be 0,decimals? Why is this one 3,decimals?
    Attached Images Attached Images  
    Last edited by veloz; Mar 19th, 2017 at 11:11 PM.

  13. #13
    Hyperactive Member
    Join Date
    Jan 2013
    Posts
    285

    Re: Replace VB6's Rnd function with cryptographically secure alternative

    Quote Originally Posted by veloz View Post
    I don't need to. The whole point is to avoid a pattern, i.e. to make it truly random.

    * * *

    Thanks, Eduardo.

    What is VBA.Rnd? My guess is that you need to call the VB6's Rnd() inside a function with the same name, and VBA.Rnd is some kind of workaround, though I have never heard of it.

    As for the code, I'm using it, but I would like to hear what other experts have to say regarding its safety and reliability.

    EDIT: See the attached image. The vast majority of outputs are 0,decimals, but shouldn't ALL outputs be 0,decimals? Why is this one 3,decimals?
    for make it truly random just set up the seed with the system TIMER. is an old trick from very old computers.

    As the app never start from the same micro-second than any other instance, you can read system tick count, and with it set up the seed.

    RND() also has a function to do that, iirc, if parameter positive is a seed, repeatable, if negative the seed is initialize in the mentioned way (IIRC), so, no pattern repeated.

  14. #14

    Thread Starter
    Junior Member
    Join Date
    Aug 2016
    Posts
    16

    Re: Replace VB6's Rnd function with cryptographically secure alternative

    Randomize uses the timer, meaning the range of the seed can be guessed. The standard Rnd function is just not recommended for implementations where security is important.

    See:

    Historically, we always told developers not to use functions such as rand to generate keys, nonces and passwords, rather they should use functions like CryptGenRandom, which creates cryptographically secure random numbers.
    https://blogs.msdn.microsoft.com/mic...ing-cryptoapi/

    Creating a replacement for Rnd with CryptGenRandom will solve this 'flaw' while being compatible with thousands of Rnd-dependent functions readily available on the internet, and this is my intent.

    I'm using Eduardo's code from post #10 but I need other experts in the community to vouch for its security and reliability. For instance: can it generate any number between 0 and 1000000 (one million) using it like e.g.:

    Code:
    CLng((1000000 * Rnd) + 0)
    ... or would any number(s) be never reproduced in this manner?
    Last edited by veloz; Mar 20th, 2017 at 12:03 AM.

  15. #15
    Hyperactive Member
    Join Date
    Jan 2013
    Posts
    285

    Re: Replace VB6's Rnd function with cryptographically secure alternative

    Quote Originally Posted by veloz View Post
    Randomize uses the timer, meaning the range of the seed can be guessed. The standard Rnd function is just not recommended for implementations where security is important.

    See:



    https://blogs.msdn.microsoft.com/mic...ing-cryptoapi/

    Creating a replacement for Rnd with CryptGenRandom will solve this 'flaw' while being compatible with thousands of Rnd-dependent functions readily available on the internet, and this is my intent.
    oh!, you means that the range of possibles seeds are too small, so susceptible to brute force (IF hacker knows how looks the uncrypted data).

    Well, when I secured my software communications I didn't use RND(), I uses XOR , AND , NOT , POWERs and DIVISIONS manually, strings, ambient universal values, plus multiple layers of packaging with CRCs, universal factors taken from SSL methods, etc.,, and by example, for most the trafic one cryptographic a single layer is enough, for more sensitive information, like DRM, nestling another crypto/packing protocolo as parameter of the main protocol, three times, is the best..., just too much headache for the cracker, and nobody will want to crack it.

    Now in storage as the best think, don't use standard file formats like DB access, etc. Unless massive data handling, and fast, is a must have, ofcourse you can do your own DB engine in plain BASIC, and make it work unrecognizable for the human eye.

    About paswords, the rule is NEVER NEVER store a password, store a hash or MD5 of it, and store it in the unrecognizable most twisted format your pick.

    Needs to read it again, so hold the seed or string key somewhere?, ok an idea, krypto it with the MAIN admin password hash, and lets the app asks for it before it can ever read the DB. If the admin introduce wrong password, it generate incorrect hash which lead to incorrect CRC attempting to read the DB. The only bad thing, if the admin account change its password is require to recrypt all the database before forgetting the old password.

    is there so many ways to protect information.


    But the weaker point of it all, is the VB compiled CODE, it is not like you doing nasty things abusing of hard to known ASM opcodes behaviour to build up twisted routines in ASM, in VB as C, all compiled code is easy to understand, boring, just easy, traceable , easy easy....

    So then it all relies on how many seeds, keys, are possible. and how many time the hacker wants to invest.
    Last edited by flyguille; Mar 20th, 2017 at 12:24 AM.

  16. #16
    Member
    Join Date
    Feb 2017
    Posts
    60

    Re: Replace VB6's Rnd function with cryptographically secure alternative

    Quote Originally Posted by veloz View Post
    Thanks, Eduardo.
    You're welcome.

    Quote Originally Posted by veloz View Post
    What is VBA.Rnd? My guess is that you need to call the VB6's Rnd() inside a function with the same name, and VBA.Rnd is some kind of workaround, though I have never heard of it.
    Yes, since the function's name is Rnd, now to call the VB6's Rnd we cannot just write Rnd, we need to qualify with VBA.Rnd (that means Rnd from the VBA library, not this one that would be Module1.Rnd -or ModuleName.Rnd-)

    Quote Originally Posted by veloz View Post
    As for the code, I'm using it, but I would like to hear what other experts have to say regarding its safety and reliability.
    Yes, that would be nice, because I'm not an expert in security.

    Quote Originally Posted by veloz View Post
    EDIT: See the attached image. The vast majority of outputs are 0,decimals, but shouldn't ALL outputs be 0,decimals? Why is this one 3,decimals?
    They are all values between 0 and 1, like the VB6's Rnd (and that's what I get).
    Some of them are small values, yes, but not "the majority".

  17. #17
    PowerPoster techgnome's Avatar
    Join Date
    May 2002
    Posts
    30,319

    Re: Replace VB6's Rnd function with cryptographically secure alternative

    IF you haven't found it yet, take a look at this thread:
    http://www.vbforums.com/showthread.p...usly-described

    -tg
    * I don't respond to private (PM) requests for help. It's not conducive to the general learning of others.*
    * I also don't respond to friend requests. Save a few bits and don't bother. I'll just end up rejecting anyways.*
    * How to get EFFECTIVE help: The Hitchhiker's Guide to Getting Help at VBF - Removing eels from your hovercraft *
    * How to Use Parameters * Create Disconnected ADO Recordset Clones * Set your VB6 ActiveX Compatibility * Get rid of those pesky VB Line Numbers * I swear I saved my data, where'd it run off to??? *

Posting Permissions

  • You may not post new threads
  • You may not post replies
  • You may not post attachments
  • You may not edit your posts
  •  



Featured


Click Here to Expand Forum to Full Width

Survey posted by VBForums.