ソースを参照

Fix Security::randomBytes() fallback

randomBytes() should return a binary string always.
Currently, it fallbacks to a hexadecimal string.
Add insecureRandomBytes() for fallback test.
chinpei215 9 年 前
コミット
e4acb35503
2 ファイル変更36 行追加2 行削除
  1. 17 1
      src/Utility/Security.php
  2. 19 1
      tests/TestCase/Utility/SecurityTest.php

+ 17 - 1
src/Utility/Security.php

@@ -121,13 +121,29 @@ class Security
             'Falling back to an insecure random source.',
             E_USER_WARNING
         );
+        return static::insecureRandomBytes($length);
+    }
+
+    /**
+     * Like randomBytes() above, but not cryptographically secure.
+     *
+     * @param int $length The number of bytes you want.
+     * @return string Random bytes in binary.
+     * @see \Cake\Utility\Security::randomBytes()
+     */
+    public static function insecureRandomBytes($length)
+    {
+        $length *= 2;
+
         $bytes = '';
         $byteLength = 0;
         while ($byteLength < $length) {
             $bytes .= static::hash(Text::uuid() . uniqid(mt_rand(), true), 'sha512', true);
             $byteLength = strlen($bytes);
         }
-        return substr($bytes, 0, $length);
+        $bytes = substr($bytes, 0, $length);
+
+        return pack('H*', $bytes);
     }
 
     /**

+ 19 - 1
tests/TestCase/Utility/SecurityTest.php

@@ -294,7 +294,7 @@ class SecurityTest extends TestCase
     }
 
     /**
-     * Test the random method.
+     * Test the randomBytes method.
      *
      * @return void
      */
@@ -305,5 +305,23 @@ class SecurityTest extends TestCase
 
         $value = Security::randomBytes(64);
         $this->assertSame(64, strlen($value));
+
+        $this->assertRegExp('/[^0-9a-f]/', $value, 'should return a binary string');
+    }
+
+    /**
+     * Test the insecureRandomBytes method
+     *
+     * @return void
+     */
+    public function testInsecureRandomBytes()
+    {
+        $value = Security::insecureRandomBytes(16);
+        $this->assertSame(16, strlen($value));
+
+        $value = Security::insecureRandomBytes(64);
+        $this->assertSame(64, strlen($value));
+
+        $this->assertRegExp('/[^0-9a-f]/', $value, 'should return a binary string');
     }
 }