Cryptographer.php 3.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140
  1. <?php
  2. /**
  3. * Copyright © Magento, Inc. All rights reserved.
  4. * See COPYING.txt for license details.
  5. */
  6. namespace Magento\Analytics\Model;
  7. use Magento\Framework\Exception\LocalizedException;
  8. /**
  9. * Class for encrypting data.
  10. */
  11. class Cryptographer
  12. {
  13. /**
  14. * Resource for handling MBI token value.
  15. *
  16. * @var AnalyticsToken
  17. */
  18. private $analyticsToken;
  19. /**
  20. * Cipher method for encryption.
  21. *
  22. * @var string
  23. */
  24. private $cipherMethod = 'AES-256-CBC';
  25. /**
  26. * @var EncodedContextFactory
  27. */
  28. private $encodedContextFactory;
  29. /**
  30. * @param AnalyticsToken $analyticsToken
  31. * @param EncodedContextFactory $encodedContextFactory
  32. */
  33. public function __construct(
  34. AnalyticsToken $analyticsToken,
  35. EncodedContextFactory $encodedContextFactory
  36. ) {
  37. $this->analyticsToken = $analyticsToken;
  38. $this->encodedContextFactory = $encodedContextFactory;
  39. }
  40. /**
  41. * Encrypt input data.
  42. *
  43. * @param string $source
  44. * @return EncodedContext
  45. * @throws LocalizedException
  46. */
  47. public function encode($source)
  48. {
  49. if (!is_string($source)) {
  50. try {
  51. $source = (string)$source;
  52. } catch (\Exception $e) {
  53. throw new LocalizedException(
  54. __(
  55. 'The data is invalid. '
  56. . 'Enter the data as a string or data that can be converted into a string and try again.'
  57. )
  58. );
  59. }
  60. } elseif (!$source) {
  61. throw new LocalizedException(__('The data is invalid. Enter the data as a string and try again.'));
  62. }
  63. if (!$this->validateCipherMethod($this->cipherMethod)) {
  64. throw new LocalizedException(__('The data is invalid. Use a valid cipher method and try again.'));
  65. }
  66. $initializationVector = $this->getInitializationVector();
  67. $encodedContext = $this->encodedContextFactory->create([
  68. 'content' => openssl_encrypt(
  69. $source,
  70. $this->cipherMethod,
  71. $this->getKey(),
  72. OPENSSL_RAW_DATA,
  73. $initializationVector
  74. ),
  75. 'initializationVector' => $initializationVector,
  76. ]);
  77. return $encodedContext;
  78. }
  79. /**
  80. * Return key for encryption.
  81. *
  82. * @return string
  83. * @throws LocalizedException
  84. */
  85. private function getKey()
  86. {
  87. $token = $this->analyticsToken->getToken();
  88. if (!$token) {
  89. throw new LocalizedException(__('Enter the encryption key and try again.'));
  90. }
  91. return hash('sha256', $token);
  92. }
  93. /**
  94. * Return established cipher method.
  95. *
  96. * @return string
  97. */
  98. private function getCipherMethod()
  99. {
  100. return $this->cipherMethod;
  101. }
  102. /**
  103. * Return each time generated random initialization vector which depends on the cipher method.
  104. *
  105. * @return string
  106. */
  107. private function getInitializationVector()
  108. {
  109. $ivSize = openssl_cipher_iv_length($this->getCipherMethod());
  110. return openssl_random_pseudo_bytes($ivSize);
  111. }
  112. /**
  113. * Check that cipher method is allowed for encryption.
  114. *
  115. * @param string $cipherMethod
  116. * @return bool
  117. */
  118. private function validateCipherMethod($cipherMethod)
  119. {
  120. $methods = array_map(
  121. 'strtolower',
  122. openssl_get_cipher_methods()
  123. );
  124. $cipherMethod = strtolower($cipherMethod);
  125. return (false !== array_search($cipherMethod, $methods));
  126. }
  127. }