Simple insights into creating GUID (Globally Unique Identifier, Universally Unique Identifier):


// Test code.
// e.g. 3fca05e7-0bd8-47c2-92ac-690cb78f1fc2
string guid = Guid.NewGuid().ToString();

 


// Test code.
private string RandomString(int length)
{
  const string valid = "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789";
  uint validLength = (uint)valid.Length;

  StringBuilder builder = new StringBuilder();
  byte[] uintBuffer = new byte[4];
  using (RNGCryptoServiceProvider rng = new RNGCryptoServiceProvider())
  {
    while (length-- > 0)
    {
      rng.GetBytes(uintBuffer);
      uint num = BitConverter.ToUInt32(uintBuffer, 0);
      builder.Append(valid[(int)(num % validLength)]);
    }
  }

  return builder.ToString();
}

 


// System
// .Guid
// This will create a new guid.  Since we've now decided that constructors should 0-init,
// we need a method that allows users to create a guid.
[System.Security.SecuritySafeCritical]  // auto-generated
public static Guid NewGuid() {
  // CoCreateGuid should never return Guid.Empty, since it attempts to maintain some
  // uniqueness guarantees.  It should also never return a known GUID, but it's unclear
  // how extensively it checks for known values.
  Contract.Ensures(Contract.Result<Guid>() != Guid.Empty);

  Guid guid;
  Marshal.ThrowExceptionForHR(Win32Native.CoCreateGuid(out guid), new IntPtr(-1));
  return guid;
}

 


// Microsoft.Win32
// .Win32Native
[DllImport(OLE32)]
[ResourceExposure(ResourceScope.None)]
internal extern static int CoCreateGuid(out Guid guid);

 


// https://source.winehq.org/WineAPI/CoCreateGuid.html
// Declared in "objbase.h". https://source.winehq.org/source/include/objbase.h
// Implemented in "dlls/ole32/compobj.c". https://source.winehq.org/source/dlls/ole32/compobj.c
// Debug channel "ole".
2094 /******************************************************************************
2095  *      CoCreateGuid [OLE32.@]
2096  *
2097  * Simply forwards to UuidCreate in RPCRT4.
2098  *
2099  * PARAMS
2100  *  pguid [O] Points to the GUID to initialize.
2101  *
2102  * RETURNS
2103  *  Success: S_OK.
2104  *  Failure: HRESULT code.
2105  *
2106  * SEE ALSO
2107  *   UuidCreate
2108  */
2109 HRESULT WINAPI CoCreateGuid(GUID *pguid)
2110 {
2111     DWORD status;
2112
2113     if(!pguid) return E_INVALIDARG;
2114
2115     status = UuidCreate(pguid);
2116     if (status == RPC_S_OK || status == RPC_S_UUID_LOCAL_ONLY) return S_OK;
2117     return HRESULT_FROM_WIN32( status );
2118 }

 


// https://source.winehq.org/source/dlls/rpcrt4/rpcrt4_main.c#0306
0291 /*************************************************************************
0292  *           UuidCreate   [RPCRT4.@]
0293  *
0294  * Creates a 128bit UUID.
0295  *
0296  * RETURNS
0297  *
0298  *  RPC_S_OK if successful.
0299  *  RPC_S_UUID_LOCAL_ONLY if UUID is only locally unique.
0300  *
0301  * NOTES
0302  *
0303  *  Follows RFC 4122, section 4.4 (Algorithms for Creating a UUID from
0304  *  Truly Random or Pseudo-Random Numbers)
0305  */
0306 RPC_STATUS WINAPI UuidCreate(UUID *Uuid)
0307 {
0308     RtlGenRandom(Uuid, sizeof(*Uuid));
0309     /* Clear the version bits and set the version (4) */
0310     Uuid->Data3 &= 0x0fff;
0311     Uuid->Data3 |= (4 << 12);
0312     /* Set the topmost bits of Data4 (clock_seq_hi_and_reserved) as
0313      * specified in RFC 4122, section 4.4.
0314      */
0315     Uuid->Data4[0] &= 0x3f;
0316     Uuid->Data4[0] |= 0x80;
0317 
0318     TRACE("%s\n", debugstr_guid(Uuid));
0319 
0320     return RPC_S_OK;
0321 }

 


// https://source.winehq.org/source/include/ntsecapi.h#0457
0457 #define RtlGenRandom    SystemFunction036

 


// https://source.winehq.org/source/dlls/advapi32/crypt.c#2374
2360 /******************************************************************************
2361  * SystemFunction036   (ADVAPI32.@)
2362  *
2363  * MSDN documents this function as RtlGenRandom and declares it in ntsecapi.h
2364  *
2365  * PARAMS
2366  *  pbBuffer [O] Pointer to memory to receive random bytes.
2367  *  dwLen   [I] Number of random bytes to fetch.
2368  *
2369  * RETURNS
2370  *  Success: TRUE
2371  *  Failure: FALSE
2372  */
2374 BOOLEAN WINAPI SystemFunction036(PVOID pbBuffer, ULONG dwLen)
2375 {
2376     int dev_random;
2377
2378     dev_random = open("/dev/urandom", O_RDONLY);
2379     if (dev_random != -1)
2380     {
2381         if (read(dev_random, pbBuffer, dwLen) == (ssize_t)dwLen)
2382         {
2383             close(dev_random);
2384             return TRUE;
2385         }
2386         close(dev_random);
2387     }
2388     else
2389         FIXME("couldn't open /dev/urandom\n");
2390     SetLastError(NTE_FAIL);
2391     return FALSE;
2392 }  

 

Theory of random number generator ( http://lxr.linux.no/linux/drivers/char/random.c ):

Computers are very predictable devices. Hence it is extremely hard to produce truly random numbers on a computer — as opposed to pseudo-random numbers, which can easily generated by using a algorithm. Unfortunately, it is very easy for attackers to guess the sequence of pseudo-random number generators, and for some applications this is not acceptable. So instead, we must try to gather “environmental noise" from the computer’s environment, which must be hard for outside attackers to observe, and use that to generate random numbers.

add_device_randomness():
This would be things like MAC addresses or serial numbers, or the read-out of the RTC (Real-time clock).

add_input_randomness():
uses the input layer interrupt timing, as well as the event type information from the hardware.

add_interrupt_randomness():
uses the interrupt timing as random inputs to the entropy pool. Using the cycle counters and the irq (Interrupt Request) source as inputs, it feeds the randomness roughly once a second.

add_disk_randomness():
uses what amounts to the seek time of block layer request events, on a per-disk_devt basis, as input to the entropy pool.

 

Reference:

(1) mscorlib https://referencesource.microsoft.com/#mscorlib/system/guid.cs,1152
(2) 好問題:GUID 真的不會重複嗎? https://blog.darkthread.net/blog/is-guid-really-unique
(3) using RNGCryptoServiceProvider to generate random string https://stackoverflow.com/questions/32932679/using-rngcryptoserviceprovider-to-generate-random-string
(4) Random vs. Pseudorandom Number Generators https://www.youtube.com/watch?v=itaMNuWLzJo
(5) win32pal.c https://github.com/fixdpt/shared-source-cli-2.0/blob/master/pal/win32/win32pal.c
(6) What entropy sources are available on Windows? https://stackoverflow.com/questions/4955527/what-entropy-sources-are-available-on-windows
(7) What is the most secure seed for random number generation? https://stackoverflow.com/questions/3436376/what-is-the-most-secure-seed-for-random-number-generation
(8) RtlGenRandom/CryptGenRandom or other WinAPI to generate cryptographically secure random numbers (first quarter of 2018) https://stackoverflow.com/questions/48875929/rtlgenrandom-cryptgenrandom-or-other-winapi-to-generate-cryptographically-secure
(9) linux/drivers/char/random.c http://lxr.linux.no/linux/drivers/char/random.c
(10) Pseudo Random Number Generators in Programming Languages http://portal.idc.ac.il/en/schools/cs/research/documents/sinai_2011.pdf
(11) Interrupt Request (IRQ) https://bcc16.ncu.edu.tw/pool/1.14.shtml

 

發表迴響

在下方填入你的資料或按右方圖示以社群網站登入:

WordPress.com 標誌

您的留言將使用 WordPress.com 帳號。 登出 /  變更 )

Google photo

您的留言將使用 Google 帳號。 登出 /  變更 )

Twitter picture

您的留言將使用 Twitter 帳號。 登出 /  變更 )

Facebook照片

您的留言將使用 Facebook 帳號。 登出 /  變更 )

連結到 %s