CRM_Core_Key - Improve entropy of "privateKey"
authorTim Otten <totten@civicrm.org>
Mon, 6 Apr 2020 06:33:55 +0000 (23:33 -0700)
committerSeamus Lee <seamuslee001@gmail.com>
Wed, 19 Aug 2020 06:16:57 +0000 (16:16 +1000)
In PHP 4/5, there was no good, universal source of entropy.  The old code
mitigated this by aggregating mediocre sources.  On my system, it appears
to be roughly:

* 2^31 for each `mt_rand()`
* 10^8 =~ 2^26 for each `uniqid(...TRUE)` (after discounting the non-random right half of the uniqid).

So that's ~114 bits (albeit low-quality bits).

In PHP 7, the docs describe `random_bytes()` as "generat[ing] cryptographically secure pseudo-random bytes."

CRM/Core/Key.php

index 83317ac14946e180f0fa8f5d0c9420b7a5f3b4c8..2bbaf593e58985cec17a812369424126bacdaaed 100644 (file)
  *
  */
 class CRM_Core_Key {
+
+  /**
+   * The length of the randomly-generated, per-session signing key.
+   *
+   * Expressed as number of bytes. (Ex: 128 bits = 16 bytes)
+   *
+   * @var int
+   */
+  const PRIVATE_KEY_LENGTH = 16;
+
   public static $_key = NULL;
 
   public static $_sessionID = NULL;
@@ -32,7 +42,7 @@ class CRM_Core_Key {
       $session = CRM_Core_Session::singleton();
       self::$_key = $session->get('qfPrivateKey');
       if (!self::$_key) {
-        self::$_key = md5(uniqid(mt_rand(), TRUE)) . md5(uniqid(mt_rand(), TRUE));
+        self::$_key = base64_encode(random_bytes(self::PRIVATE_KEY_LENGTH));
         $session->set('qfPrivateKey', self::$_key);
       }
     }