signWith($this->algos[0], $isProcedure, $action, $paramString); } private function signWith(string $algo, bool $isProcedure, string $action, string $paramString): string { $time = time(); $hash = $this->createHash($algo, $time, $isProcedure, $action, $paramString); return UriBase64::encode(AiwassMsgPack::encode([ 'a' => $algo, 't' => $time, 'h' => $hash, ])); } private function createHash( string $algo, int $timeStamp, bool $isProcedure, string $action, string $paramString ): string { $data = sprintf( '^<=>%d<=>%s<=>%s<=>%s<=>$', $timeStamp, $isProcedure ? 'p' : 'q', $action, $paramString ); return hash_hmac($algo, $data, ($this->getSecretKey)(), true); } /** * Checks if a given hashing algorithm is allowed by this verification provider. * * @param string $algo Algorithm name. * @return bool true if it is supported. */ public function isValidAlgo(string $algo): bool { return in_array($algo, $this->algos); } public function verify(string $userToken, bool $isProcedure, string $action, string $paramString): bool { $userToken = UriBase64::decode($userToken); if($userToken === false) return false; $userTokenInfo = AiwassMsgPack::decode($userToken); if(!is_array($userTokenInfo)) return false; $userAlgo = $userTokenInfo['a'] ?? null; if(!is_string($userAlgo) || !$this->isValidAlgo($userAlgo)) return false; $userTime = $userTokenInfo['t'] ?? null; $currentTime = time(); if(!is_int($userTime) || $userTime < ($currentTime - $this->timeValidPlusMinusSeconds) || $userTime > ($currentTime + $this->timeValidPlusMinusSeconds)) return false; $userHash = $userTokenInfo['h'] ?? null; if(!is_string($userHash)) return false; $realHash = $this->createHash($userAlgo, $userTime, $isProcedure, $action, $paramString); return hash_equals($realHash, $userHash); } }