public function deriveKeys($salt)
{
if (Core::ourStrlen($salt) !== Core::SALT_BYTE_SIZE) {
throw new Ex\EnvironmentIsBrokenException('Bad salt.');
}
if ($this->secret_type === self::SECRET_TYPE_KEY) {
$akey = Core::HKDF(Core::HASH_FUNCTION_NAME, $this->secret->getRawBytes(), Core::KEY_BYTE_SIZE, Core::AUTHENTICATION_INFO_STRING, $salt);
$ekey = Core::HKDF(Core::HASH_FUNCTION_NAME, $this->secret->getRawBytes(), Core::KEY_BYTE_SIZE, Core::ENCRYPTION_INFO_STRING, $salt);
return new DerivedKeys($akey, $ekey);
} elseif ($this->secret_type === self::SECRET_TYPE_PASSWORD) {
/* Our PBKDF2 polyfill is vulnerable to a DoS attack documented in
* GitHub issue #230. The fix is to pre-hash the password to ensure
* it is short. We do the prehashing here instead of in pbkdf2() so
* that pbkdf2() still computes the function as defined by the
* standard. */
$prehash = \hash(Core::HASH_FUNCTION_NAME, $this->secret, true);
$prekey = Core::pbkdf2(Core::HASH_FUNCTION_NAME, $prehash, $salt, self::PBKDF2_ITERATIONS, Core::KEY_BYTE_SIZE, true);
$akey = Core::HKDF(Core::HASH_FUNCTION_NAME, $prekey, Core::KEY_BYTE_SIZE, Core::AUTHENTICATION_INFO_STRING, $salt);
/* Note the cryptographic re-use of $salt here. */
$ekey = Core::HKDF(Core::HASH_FUNCTION_NAME, $prekey, Core::KEY_BYTE_SIZE, Core::ENCRYPTION_INFO_STRING, $salt);
return new DerivedKeys($akey, $ekey);
} else {
throw new Ex\EnvironmentIsBrokenException('Bad secret type.');
}
}