Changeset View
Changeset View
Standalone View
Standalone View
src/infrastructure/util/PhabricatorHash.php
Show First 20 Lines • Show All 133 Lines • ▼ Show 20 Lines | public static function digestToLength($string, $length) { | ||||
$hash = self::digestForIndex($string); | $hash = self::digestForIndex($string); | ||||
$prefix = substr($string, 0, ($length - ($min_length - 1))); | $prefix = substr($string, 0, ($length - ($min_length - 1))); | ||||
return $prefix.'-'.$hash; | return $prefix.'-'.$hash; | ||||
} | } | ||||
public static function digestWithNamedKey($message, $key_name) { | |||||
$key_bytes = self::getNamedHMACKey($key_name); | |||||
return self::digestHMACSHA256($message, $key_bytes); | |||||
} | |||||
public static function digestHMACSHA256($message, $key) { | |||||
if (!strlen($key)) { | |||||
throw new Exception( | |||||
pht('HMAC-SHA256 requires a nonempty key.')); | |||||
} | |||||
$result = hash_hmac('sha256', $message, $key, $raw_output = false); | |||||
if ($result === false) { | |||||
throw new Exception( | |||||
pht('Unable to compute HMAC-SHA256 digest of message.')); | |||||
} | |||||
return $result; | |||||
} | |||||
/* -( HMAC Key Management )------------------------------------------------ */ | |||||
private static function getNamedHMACKey($hmac_name) { | |||||
$cache = PhabricatorCaches::getImmutableCache(); | |||||
$cache_key = "hmac.key({$hmac_name})"; | |||||
$hmac_key = $cache->getKey($cache_key); | |||||
if (!strlen($hmac_key)) { | |||||
$hmac_key = self::readHMACKey($hmac_name); | |||||
if ($hmac_key === null) { | |||||
$hmac_key = self::newHMACKey($hmac_name); | |||||
self::writeHMACKey($hmac_name, $hmac_key); | |||||
} | |||||
$cache->setKey($cache_key, $hmac_key); | |||||
} | |||||
// The "hex2bin()" function doesn't exist until PHP 5.4.0 so just | |||||
// implement it inline. | |||||
$result = ''; | |||||
for ($ii = 0; $ii < strlen($hmac_key); $ii += 2) { | |||||
$result .= pack('H*', substr($hmac_key, $ii, 2)); | |||||
} | |||||
return $result; | |||||
} | |||||
private static function newHMACKey($hmac_name) { | |||||
$hmac_key = Filesystem::readRandomBytes(64); | |||||
return bin2hex($hmac_key); | |||||
} | |||||
private static function writeHMACKey($hmac_name, $hmac_key) { | |||||
$unguarded = AphrontWriteGuard::beginScopedUnguardedWrites(); | |||||
id(new PhabricatorAuthHMACKey()) | |||||
->setKeyName($hmac_name) | |||||
->setKeyValue($hmac_key) | |||||
->save(); | |||||
unset($unguarded); | |||||
} | |||||
private static function readHMACKey($hmac_name) { | |||||
$table = new PhabricatorAuthHMACKey(); | |||||
$conn = $table->establishConnection('r'); | |||||
$row = queryfx_one( | |||||
$conn, | |||||
'SELECT keyValue FROM %T WHERE keyName = %s', | |||||
$table->getTableName(), | |||||
$hmac_name); | |||||
if (!$row) { | |||||
return null; | |||||
} | |||||
return $row['keyValue']; | |||||
} | |||||
} | } |