Hmac.php 1.4 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071
  1. <?php
  2. namespace Elgg\Security;
  3. /**
  4. * Component for creating HMAC tokens
  5. */
  6. class Hmac {
  7. /**
  8. * @var string
  9. */
  10. private $key;
  11. /**
  12. * @var callable
  13. */
  14. private $comparator;
  15. /**
  16. * @var string
  17. */
  18. private $data;
  19. /**
  20. * @var string
  21. */
  22. private $algo;
  23. /**
  24. * Constructor
  25. *
  26. * @param string $key HMAC key
  27. * @param callable $comparator Function that returns true if given two equal strings, else false
  28. * @param mixed $data HMAC data string or serializable data
  29. * @param string $algo Hash algorithm
  30. */
  31. public function __construct($key, callable $comparator, $data, $algo = 'sha256') {
  32. $this->key = $key;
  33. $this->comparator = $comparator;
  34. if (!$data) {
  35. throw new \InvalidArgumentException('$data cannot be empty');
  36. }
  37. if (!is_string($data)) {
  38. $data = serialize($data);
  39. }
  40. $this->data = $data;
  41. $this->algo = $algo;
  42. }
  43. /**
  44. * Get the HMAC token in Base64URL encoding
  45. *
  46. * @return string
  47. */
  48. public function getToken() {
  49. $bytes = hash_hmac($this->algo, $this->data, $this->key, true);
  50. return strtr(rtrim(base64_encode($bytes), '='), '+/', '-_');
  51. }
  52. /**
  53. * Does the MAC match the given token?
  54. *
  55. * @param string $token HMAC token in Base64URL encoding
  56. * @return bool
  57. */
  58. public function matchesToken($token) {
  59. $expected_token = $this->getToken();
  60. return call_user_func($this->comparator, $expected_token, $token);
  61. }
  62. }