Signer.php 1.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869
  1. <?php
  2. declare(strict_types=1);
  3. /**
  4. * SPDX-FileCopyrightText: 2016 Nextcloud GmbH and Nextcloud contributors
  5. * SPDX-License-Identifier: AGPL-3.0-or-later
  6. */
  7. namespace OC\Security\IdentityProof;
  8. use OCP\AppFramework\Utility\ITimeFactory;
  9. use OCP\IUser;
  10. use OCP\IUserManager;
  11. class Signer {
  12. public function __construct(
  13. private Manager $keyManager,
  14. private ITimeFactory $timeFactory,
  15. private IUserManager $userManager,
  16. ) {
  17. }
  18. /**
  19. * Returns a signed blob for $data
  20. *
  21. * @return array ['message', 'signature']
  22. */
  23. public function sign(string $type, array $data, IUser $user): array {
  24. $privateKey = $this->keyManager->getKey($user)->getPrivate();
  25. $data = [
  26. 'data' => $data,
  27. 'type' => $type,
  28. 'signer' => $user->getCloudId(),
  29. 'timestamp' => $this->timeFactory->getTime(),
  30. ];
  31. openssl_sign(json_encode($data), $signature, $privateKey, OPENSSL_ALGO_SHA512);
  32. return [
  33. 'message' => $data,
  34. 'signature' => base64_encode($signature),
  35. ];
  36. }
  37. /**
  38. * Whether the data is signed properly
  39. *
  40. */
  41. public function verify(array $data): bool {
  42. if (isset($data['message']['signer'])
  43. && isset($data['signature'])
  44. ) {
  45. $location = strrpos($data['message']['signer'], '@');
  46. $userId = substr($data['message']['signer'], 0, $location);
  47. $user = $this->userManager->get($userId);
  48. if ($user !== null) {
  49. $key = $this->keyManager->getKey($user);
  50. return openssl_verify(
  51. json_encode($data['message']),
  52. base64_decode($data['signature']),
  53. $key->getPublic(),
  54. OPENSSL_ALGO_SHA512
  55. ) === 1;
  56. }
  57. }
  58. return false;
  59. }
  60. }