OpenSSL.php 2.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108
  1. <?php
  2. namespace Lcobucci\JWT\Signer;
  3. use InvalidArgumentException;
  4. use function is_resource;
  5. use function openssl_error_string;
  6. use function openssl_free_key;
  7. use function openssl_pkey_get_details;
  8. use function openssl_pkey_get_private;
  9. use function openssl_pkey_get_public;
  10. use function openssl_sign;
  11. use function openssl_verify;
  12. abstract class OpenSSL extends BaseSigner
  13. {
  14. public function createHash($payload, Key $key)
  15. {
  16. $privateKey = $this->getPrivateKey($key->getContent(), $key->getPassphrase());
  17. try {
  18. $signature = '';
  19. if (! openssl_sign($payload, $signature, $privateKey, $this->getAlgorithm())) {
  20. throw CannotSignPayload::errorHappened(openssl_error_string());
  21. }
  22. return $signature;
  23. } finally {
  24. openssl_free_key($privateKey);
  25. }
  26. }
  27. /**
  28. * @param string $pem
  29. * @param string $passphrase
  30. *
  31. * @return resource
  32. */
  33. private function getPrivateKey($pem, $passphrase)
  34. {
  35. $privateKey = openssl_pkey_get_private($pem, $passphrase);
  36. $this->validateKey($privateKey);
  37. return $privateKey;
  38. }
  39. /**
  40. * @param $expected
  41. * @param $payload
  42. * @param $key
  43. * @return bool
  44. */
  45. public function doVerify($expected, $payload, Key $key)
  46. {
  47. $publicKey = $this->getPublicKey($key->getContent());
  48. $result = openssl_verify($payload, $expected, $publicKey, $this->getAlgorithm());
  49. openssl_free_key($publicKey);
  50. return $result === 1;
  51. }
  52. /**
  53. * @param string $pem
  54. *
  55. * @return resource
  56. */
  57. private function getPublicKey($pem)
  58. {
  59. $publicKey = openssl_pkey_get_public($pem);
  60. $this->validateKey($publicKey);
  61. return $publicKey;
  62. }
  63. /**
  64. * Raises an exception when the key type is not the expected type
  65. *
  66. * @param resource|bool $key
  67. *
  68. * @throws InvalidArgumentException
  69. */
  70. private function validateKey($key)
  71. {
  72. if (! is_resource($key)) {
  73. throw InvalidKeyProvided::cannotBeParsed(openssl_error_string());
  74. }
  75. $details = openssl_pkey_get_details($key);
  76. if (! isset($details['key']) || $details['type'] !== $this->getKeyType()) {
  77. throw InvalidKeyProvided::incompatibleKey();
  78. }
  79. }
  80. /**
  81. * Returns the type of key to be used to create/verify the signature (using OpenSSL constants)
  82. *
  83. * @internal
  84. */
  85. abstract public function getKeyType();
  86. /**
  87. * Returns which algorithm to be used to create/verify the signature (using OpenSSL constants)
  88. *
  89. * @internal
  90. */
  91. abstract public function getAlgorithm();
  92. }