@recaptime-dev's working patches + fork for Phorge, a community fork of Phabricator. (Upstream dev and stable branches are at upstream/main and upstream/stable respectively.) hq.recaptime.dev/wiki/Phorge
phorge phabricator
1
fork

Configure Feed

Select the types of activity you want to include in your feed.

Add PhabricatorHash::digestForIndex()

Summary: Does this seem reasonable? It's a bit more compact than digest() (6 bits / byte instead of 4 bits / byte) and 72 bits of entropy @ 12 bytes instead of 128 bits of entropy @ 32 bytes. I feel like it's important to preserve the printability, though, and this seemed like a fairly good balance of concerns.

Test Plan: unit tests

Reviewers: vrana

Reviewed By: vrana

CC: aran, yemao932

Differential Revision: https://secure.phabricator.com/D4253

+85
+2
src/__phutil_library_map__.php
··· 813 813 'PhabricatorGlobalUploadTargetView' => 'applications/files/view/PhabricatorGlobalUploadTargetView.php', 814 814 'PhabricatorHandleObjectSelectorDataView' => 'applications/phid/handle/view/PhabricatorHandleObjectSelectorDataView.php', 815 815 'PhabricatorHash' => 'infrastructure/util/PhabricatorHash.php', 816 + 'PhabricatorHashTestCase' => 'infrastructure/util/__tests__/PhabricatorHashTestCase.php', 816 817 'PhabricatorHeaderView' => 'view/layout/PhabricatorHeaderView.php', 817 818 'PhabricatorHelpController' => 'applications/help/controller/PhabricatorHelpController.php', 818 819 'PhabricatorHelpKeyboardShortcutController' => 'applications/help/controller/PhabricatorHelpKeyboardShortcutController.php', ··· 2098 2099 'PhabricatorGarbageCollectorDaemon' => 'PhabricatorDaemon', 2099 2100 'PhabricatorGlobalLock' => 'PhutilLock', 2100 2101 'PhabricatorGlobalUploadTargetView' => 'AphrontView', 2102 + 'PhabricatorHashTestCase' => 'PhabricatorTestCase', 2101 2103 'PhabricatorHeaderView' => 'AphrontView', 2102 2104 'PhabricatorHelpController' => 'PhabricatorController', 2103 2105 'PhabricatorHelpKeyboardShortcutController' => 'PhabricatorHelpController',
+42
src/infrastructure/util/PhabricatorHash.php
··· 2 2 3 3 final class PhabricatorHash { 4 4 5 + 6 + /** 7 + * Digest a string for general use, including use which relates to security. 8 + * 9 + * @param string Input string. 10 + * @return string 32-byte hexidecimal SHA1+HMAC hash. 11 + */ 5 12 public static function digest($string) { 6 13 $key = PhabricatorEnv::getEnvConfig('security.hmac-key'); 7 14 if (!$key) { ··· 10 17 } 11 18 12 19 return hash_hmac('sha1', $string, $key); 20 + } 21 + 22 + 23 + /** 24 + * Digest a string for use in, e.g., a MySQL index. This produces a short 25 + * (12-byte), case-sensitive alphanumeric string with 72 bits of entropy, 26 + * which is generally safe in most contexts (notably, URLs). 27 + * 28 + * This method emphasizes compactness, and should not be used for security 29 + * related hashing (for general purpose hashing, see @{method:digest}). 30 + * 31 + * @param string Input string. 32 + * @return string 12-byte, case-sensitive alphanumeric hash of the string 33 + * which 34 + */ 35 + public static function digestForIndex($string) { 36 + $hash = sha1($string, $raw_output = true); 37 + 38 + static $map; 39 + if ($map === null) { 40 + $map = "0123456789". 41 + "abcdefghij". 42 + "klmnopqrst". 43 + "uvwxyzABCD". 44 + "EFGHIJKLMN". 45 + "OPQRSTUVWX". 46 + "YZ._"; 47 + } 48 + 49 + $result = ''; 50 + for ($ii = 0; $ii < 12; $ii++) { 51 + $result .= $map[(ord($hash[$ii]) & 0x3F)]; 52 + } 53 + 54 + return $result; 13 55 } 14 56 15 57 }
+41
src/infrastructure/util/__tests__/PhabricatorHashTestCase.php
··· 1 + <?php 2 + 3 + final class PhabricatorHashTestCase extends PhabricatorTestCase { 4 + 5 + public function testHashForIndex() { 6 + $map = array( 7 + 'dog' => 'Aliif7Qjd5ct', 8 + 'cat' => 'toudDsue3Uv8', 9 + 'rat' => 'RswaKgTjqOuj', 10 + 'bat' => 'rAkJKyX4YdYm', 11 + ); 12 + 13 + foreach ($map as $input => $expect) { 14 + $this->assertEqual( 15 + $expect, 16 + PhabricatorHash::digestForIndex($input), 17 + "Input: {$input}"); 18 + } 19 + 20 + // Test that the encoding produces 6 bits of entropy per byte. 21 + $entropy = array( 22 + 'dog', 'cat', 'rat', 'bat', 'dig', 'fig', 'cot', 23 + 'cut', 'fog', 'rig', 'rug', 'dug', 'mat', 'pat', 24 + 'eat', 'tar', 'pot', 25 + ); 26 + 27 + $seen = array(); 28 + foreach ($entropy as $input) { 29 + $chars = preg_split('//', PhabricatorHash::digestForIndex($input)); 30 + foreach ($chars as $char) { 31 + $seen[$char] = true; 32 + } 33 + } 34 + 35 + $this->assertEqual( 36 + (1 << 6), 37 + count($seen), 38 + "Distinct characters in hash of: {$input}"); 39 + } 40 + 41 + }