sketchucation logo sketchucation
    • Login
    ℹ️ Licensed Extensions | FredoBatch, ElevationProfile, FredoSketch, LayOps, MatSim and Pic2Shape will require license from Sept 1st More Info

    SecureRandom slow

    Scheduled Pinned Locked Moved Developers' Forum
    10 Posts 4 Posters 630 Views 4 Watching
    Loading More Posts
    • Oldest to Newest
    • Newest to Oldest
    • Most Votes
    Reply
    • Reply as topic
    Log in to reply
    This topic has been deleted. Only users with topic management privileges can see it.
    • jiminy-billy-bobJ Offline
      jiminy-billy-bob
      last edited by

      Hi guys,

      On SU 2014, I require 'securerandom.rb', then use SecureRandom.uuid.
      But for whatever reason, the first uuid takes several seconds to be generated. After that, it's instantaneous.

      Any idea why?

      25% off Skatter for SketchUcation Premium Members

      1 Reply Last reply Reply Quote 0
      • Dan RathbunD Offline
        Dan Rathbun
        last edited by

        IF you have the CHM Ruby dictionary (comes in the "doc" folder of a system Ruby install,) you can click on the methods, and a code box will appear. Often this code is in C, but in this case, they are pure Ruby.

        SecureRandom::uuid calls SecureRandom::random_bytes

        # File lib/securerandom.rb, line 247
        def self.uuid
          ary = self.random_bytes(16).unpack("NnnnnN")
          ary[2] = (ary[2] & 0x0fff) | 0x4000
          ary[3] = (ary[3] & 0x3fff) | 0x8000
          "%08x-%04x-%04x-%04x-%04x%08x" % ary
        end
        
        

        SecureRandom::random_bytes has several platform dependent conditional statements (I'll call them parts,) that execute one time setup code, then the else clause thereafter.
        The part that executes on Windows, you see must load "Win32API.rb" which conditionally loads other libraries.
        THEN, it sets up the Win API call object referenced by a instance var in SecureRandom, that is then used thereafter.
        The first part is used IF OpenSSL is loaded, the second part used by Mac/UNIX-like OSes.)
        The third partof SecureRandom::random_bytes that is used by Windows:

          if !defined?(@has_win32)
            begin
              require 'Win32API'
        
              crypt_acquire_context = Win32API.new("advapi32", "CryptAcquireContext", 'PPPII', 'L')
              @crypt_gen_random = Win32API.new("advapi32", "CryptGenRandom", 'VIP', 'L')
        
              hProvStr = " " * DL;;SIZEOF_VOIDP
              prov_rsa_full = 1
              crypt_verifycontext = 0xF0000000
        
              if crypt_acquire_context.call(hProvStr, nil, nil, prov_rsa_full, crypt_verifycontext) == 0
                raise SystemCallError, "CryptAcquireContext failed; #{lastWin32ErrorMessage}"
              end
              type = DL;;SIZEOF_VOIDP == DL;;SIZEOF_LONG_LONG ? 'q' ; 'l'
              @hProv, = hProvStr.unpack(type)
        
              @has_win32 = true
            rescue LoadError
              @has_win32 = false
            end
          end
          if @has_win32
            bytes = " ".force_encoding("ASCII-8BIT") * n
            if @crypt_gen_random.call(@hProv, bytes.size, bytes) == 0
              raise SystemCallError, "CryptGenRandom failed; #{lastWin32ErrorMessage}"
            end
            return bytes
          end
        

        So once @has_win32 is defined, only the last small if statement is executed thereafter.

        I'm not here much anymore.

        1 Reply Last reply Reply Quote 0
        • A Offline
          Aerilius
          last edited by

          Could it be initialization?
          Click the source: http://ruby-doc.org/stdlib-2.0.0/libdoc/securerandom/rdoc/SecureRandom.html#method-c-random_bytes

          If you run it on Windows, it runs the first time also the if !defined?(@has_win32) block, later only the if @has_win32 block.

          1 Reply Last reply Reply Quote 0
          • jiminy-billy-bobJ Offline
            jiminy-billy-bob
            last edited by

            Thanks guys.

            Ok so this is normal, my only option is to generate an uuid when the script loads and be done with it? (But it slows down SU's startup)

            25% off Skatter for SketchUcation Premium Members

            1 Reply Last reply Reply Quote 0
            • tt_suT Offline
              tt_su
              last edited by

              What do you need the UID for? Do you need this particular implementation?

              1 Reply Last reply Reply Quote 0
              • jiminy-billy-bobJ Offline
                jiminy-billy-bob
                last edited by

                I need it for keeping track of component definitions throughout sessions.
                It would be easier if definitions had a persistent GUID (Why does the current one change when the definition changes? It's useless).

                In fact, all entities should have persistent GUIDs like groups and instances in 2014.

                25% off Skatter for SketchUcation Premium Members

                1 Reply Last reply Reply Quote 0
                • Dan RathbunD Offline
                  Dan Rathbun
                  last edited by

                  Why can't you save the defintion's guid into an attribute dictionary when it is first loaded (or created,) and thereafter let the API's change as it wants.

                  You simply use the original saved in the attribute.

                  I'm not here much anymore.

                  1 Reply Last reply Reply Quote 0
                  • tt_suT Offline
                    tt_su
                    last edited by

                    @jiminy-billy-bob said:

                    I need it for keeping track of component definitions throughout sessions.
                    It would be easier if definitions had a persistent GUID

                    Then if I was you I would find a different GUID generator that doesn't have the overhead. This one seems to be aimed at security, not just a GUID. Often hash generator (which this looks like) make a point out of being slow to make cracking harder and more expensive.
                    You just need something random enough. Using the hash of the component name might be good enough for your use. Current definition name and time should give you a different hash per component name per object.

                    id = "#{definition.name}#{Time.now}".hash

                    1 Reply Last reply Reply Quote 0
                    • tt_suT Offline
                      tt_su
                      last edited by

                      @dan rathbun said:

                      Why can't you save the defintion's guid into an attribute dictionary when it is first loaded (or created,) and thereafter let the API's change as it wants.

                      That can also work. πŸ‘

                      1 Reply Last reply Reply Quote 0
                      • jiminy-billy-bobJ Offline
                        jiminy-billy-bob
                        last edited by

                        @tt_su said:

                        You just need something random enough. Using the hash of the component name might be good enough for your use. Current definition name and time should give you a different hash per component name per object.

                        Yeah I was looking at something like that. But Dan's solution is simpler and seems so obvious! πŸ˜„
                        smack on the forehead

                        25% off Skatter for SketchUcation Premium Members

                        1 Reply Last reply Reply Quote 0
                        • 1 / 1
                        • First post
                          Last post
                        Buy SketchPlus
                        Buy SUbD
                        Buy WrapR
                        Buy eBook
                        Buy Modelur
                        Buy Vertex Tools
                        Buy SketchCuisine
                        Buy FormFonts

                        Advertisement