38 protected $cache =
null;
43 protected $cacheKey =
null;
48 protected $algorithm =
null;
80 protected $context = [];
88 public static $hashLength = [
110 if ( strlen( $secretKeyMaterial ) < 16 ) {
111 throw new InvalidArgumentException(
"secret was too short." );
113 $this->skm = $secretKeyMaterial;
114 $this->algorithm = $algorithm;
115 $this->cache = $cache;
116 $this->context = is_array( $context ) ? $context : [ $context ];
121 $this->cacheKey = $cache->
makeKey(
'HKDF', mt_rand( 0, 16 ) );
130 if ( $this->lastK ) {
131 $this->cache->set( $this->cacheKey, $this->lastK );
140 if ( $this->salt ==
'' ) {
141 $lastSalt = $this->cache->get( $this->cacheKey );
142 if ( $lastSalt ===
false ) {
149 $lastSalt = random_bytes( 16 );
152 $this->salt = hash( $this->algorithm, $lastSalt,
true );
165 public function generate( $bytes, $context =
'' ) {
166 if ( $this->prk ===
'' ) {
168 $this->prk = self::HKDFExtract(
175 $CTXinfo = implode(
':', array_merge( $this->context, [ $context ] ) );
177 return self::HKDFExpand(
215 public static function HKDF( $hash, $ikm, $salt, $info, $L ) {
216 $prk = self::HKDFExtract( $hash, $salt, $ikm );
217 $okm = self::HKDFExpand( $hash, $prk, $info, $L );
231 private static function HKDFExtract( $hash, $salt, $ikm ) {
232 return hash_hmac( $hash, $ikm, $salt,
true );
250 private static function HKDFExpand( $hash, $prk, $info, $bytes, &$lastK =
'' ) {
251 $hashLen = self::$hashLength[$hash];
252 $rounds = ceil( $bytes / $hashLen );
255 if ( $bytes > 255 * $hashLen ) {
256 throw new InvalidArgumentException(
'Too many bytes requested from HDKFExpand' );
261 for ( $counter = 1; $counter <= $rounds; ++$counter ) {
264 $lastK . $info . chr( $counter ),
271 return substr( $output, 0, $bytes );
Class representing a cache/ephemeral data store.
makeKey( $collection,... $components)
Make a cache key for the global keyspace and given components.
generate( $bytes, $context='')
Produce $bytes of secure random data.
getSaltUsingCache()
MW specific salt, cached from last run.
string $lastK
The last block (K(i)) of the most recent expanded key.
__destruct()
Save the last block generated, so the next user will compute a different PRK from the same SKM.
static HKDF( $hash, $ikm, $salt, $info, $L)
RFC5869 defines HKDF in 2 steps, extraction and expansion.
static int[] $hashLength
Round count is computed based on the hash'es output length, which neither php nor openssl seem to pro...
string $algorithm
The hash algorithm being used.
string $salt
binary string, the salt for the HKDF
BagOStuff $cache
The persistent cache.
__construct( $secretKeyMaterial, $algorithm, BagOStuff $cache, $context)
string $cacheKey
Cache key we'll use for our salt.
array $context
a "context information" string CTXinfo (which may be null) See http://eprint.iacr....