public function verify($message) { $parts = explode('|', $message); if (count($parts) != 2) { throw new SecurityException(sprintf('Given message does not contain an HMAC signature')); } if (!SecurityUtil::timingSafeEquals($this->sign($parts[1]), (string) $message)) { throw new SecurityException(sprintf('HMAC verification failed')); } return (string) $parts[1]; }
/** * Decrypts a message with auhtenticity check. * * @param string $message Encoded message. * @return mixed Plaintext message. * * @throws IntegrityCheckFailedException */ public function decryptMessage($message) { $calgo = $this->config->getCipherAlgorithm(); $cmode = $this->config->getCipherMode(); $malgo = $this->config->getHmacAlgorithm(); $size = mcrypt_get_iv_size($calgo, $cmode); $keySize = mcrypt_get_key_size($calgo, $cmode); $hmacSize = strlen(hash_hmac($malgo, '', 'foo-key', true)); $cmac = substr($message, -1 * $hmacSize); $iv = substr($message, 0, $size); $cipherText = substr($message, $size, -1 * $hmacSize); $hmac = hash_hmac($malgo, $iv . $cipherText, $this->computeCipherKey($this->config->getHmacKey(), $hmacSize, $iv), true); if (!SecurityUtil::timingSafeEquals($hmac, $cmac)) { throw new IntegrityCheckFailedException('Invalid encrypted input message detected'); } $key = $this->computeCipherKey($this->config->getCipherKey(), $keySize, $iv); $data = mcrypt_decrypt($calgo, $key, $cipherText, $cmode, $iv); // PKCS7 Padding $pad = ord($data[strlen($data) - 1]); $data = substr($data, 0, -1 * $pad); // Remove zero-byte padding from the string. return $data; }
/** * Needs the MD4 hash of the UTF-16LE encoded password of the user in hex- or binary format. * * @param string $username * @param string $hash * @param unknown $challenge */ public function isValidResponse($username, $hash, $challenge) { if (self::NTLM_BLOB_HEADER != substr($this->clientBlob, 0, 8)) { return false; } // Timstamp, seconds since january 1, 1601, used in replay-attack prevention. // $str = (float)vsprintf('%u%04u%04u%04u', array_reverse(unpack('vt1/vt2/vt3/vt4', substr($this->clientBlob, 8, 8)))); // $seconds = floor($str / 1000000); // Client nonce, useful in replay-attack prevention. // $cnonce = substr($this->clientBlob, 16, 8); if (!SecurityUtil::timingSafeEquals($username, $this->username)) { return false; } if (!SecurityUtil::timingSafeEquals($this->provider->getDomain(), $this->domain)) { return false; } $ntlmhash = $this->computeHmacMd5($hash, $this->encodeUtf16(strtoupper($this->username) . $this->domain)); $hash = (string) $this->computeHmacMd5($ntlmhash, $challenge . $this->clientBlob); if (!SecurityUtil::timingSafeEquals($hash, $this->clientHash)) { return false; } return true; }
/** * Check if the response is valid using the given HA1 value. * * @param string $ha1 * @return boolean */ public function isValidResponse($ha1) { if ($this->opaque === NULL) { return false; } if (!SecurityUtil::timingSafeEquals($this->auth->getOpaque(), $this->opaque)) { return false; } $args = [$ha1, $this->nonce, $this->nc, $this->cnonce, $this->auth->getQualityOfProtection(), $this->ha2]; return SecurityUtil::timingSafeEquals(md5(vsprintf('%s:%s:%s:%s:%s:%s', $args)), $this->response); }