file Crypt.php

Namespace

Drupal\bootstrap\Utility
  1. <?php
  2. namespace Drupal\bootstrap\Utility;
  3. use Drupal\bootstrap\Bootstrap;
  4. use Drupal\Component\Utility\Crypt as CoreCrypt;
  5. /**
  6. * Extends \Drupal\Component\Utility\Crypt.
  7. *
  8. * @ingroup utility
  9. */
  10. class Crypt extends CoreCrypt {
  11. /**
  12. * The regular expression used to match an SRI integrity value.
  13. *
  14. * @var string
  15. */
  16. const SRI_INTEGRITY_REGEXP = '/^(sha(?:256|384|512))-(.*)$/';
  17. /**
  18. * The length of each algorithm's digest, keyed by algorithm name.
  19. *
  20. * @var int[]
  21. *
  22. * @todo Move to a constant once PHP 5.5 is no longer supported.
  23. */
  24. protected static $algorithmDigestLengths = [
  25. 'md5' => 32,
  26. 'sha1' => 40,
  27. 'sha224' => 56,
  28. 'sha256' => 64,
  29. 'sha384' => 96,
  30. 'sha512' => 128,
  31. ];
  32. /**
  33. * The valid SRI Integrity algorithms supported by current browsers.
  34. *
  35. * @var string[]
  36. *
  37. * @todo Move to a constant once PHP 5.5 is no longer supported.
  38. */
  39. protected static $validSriIntegrityAlgorithms = [
  40. 'sha256',
  41. 'sha384',
  42. 'sha512',
  43. ];
  44. /**
  45. * Ensures the base64 encoded hash matches the algorithm's digest length.
  46. *
  47. * @param string $algorithm
  48. * The algorithm output length to check.
  49. * @param string $hash
  50. * The base64 encoded hash to check.
  51. * @param bool $sriIntegrity
  52. * Flag indicating whether this is a hash intended for use as an SRI
  53. * integrity value.
  54. *
  55. * @return bool
  56. * TRUE if the digest length from decoding the base64 hash matches what
  57. * the algorithm length is supposed to be; FALSE otherwise.
  58. */
  59. public static function checkBase64HashAlgorithm($algorithm, $hash, $sriIntegrity = FALSE) {
  60. // Immediately return if values aren't provided or an unsupported algorithm.
  61. if (!$algorithm || !$hash || !isset(static::$algorithmDigestLengths[$algorithm])) {
  62. return FALSE;
  63. }
  64. // Check if this is an SRI algorithm supported by a browser.
  65. if ($sriIntegrity && !in_array($algorithm, static::$validSriIntegrityAlgorithms)) {
  66. return FALSE;
  67. }
  68. // Ensure the provided hash matches the length of the algorithm provided.
  69. return !!preg_match('/^([a-f0-9]{' . static::$algorithmDigestLengths[$algorithm] . '})$/', static::decodeHashBase64($hash));
  70. }
  71. /**
  72. * Decodes a base64 encoded hash back into its raw digest value.
  73. *
  74. * Note: this will also decode binary digests into a proper hexadecimal value.
  75. *
  76. * @param string $hash
  77. * The base64 encoded hash to decode.
  78. *
  79. * @return string|false
  80. * The decoded digest value or FALSE if unable to decode it.
  81. */
  82. public static function decodeHashBase64($hash) {
  83. $digest = base64_decode($hash);
  84. // Check if digest is binary and convert to hex, if needed.
  85. if ($digest && preg_match('/[^a-f0-9]*/', $digest) && (!extension_loaded('ctype') || !ctype_print($digest))) {
  86. $digest = bin2hex($digest);
  87. }
  88. return $digest;
  89. }
  90. /**
  91. * Determines the algorithm used for a base64 encoded hash.
  92. *
  93. * @param string $hash
  94. * The base64 encoded hash to check.
  95. *
  96. * @return string|false
  97. * The algorithm used or FALSE if unable to determine it.
  98. */
  99. public static function determineHashBase64Algorithm($hash) {
  100. $digest = static::decodeHashBase64($hash);
  101. $length = strlen($digest);
  102. return array_search($length, static::$algorithmDigestLengths, TRUE);
  103. }
  104. /**
  105. * Generates a unique identifier by serializing and hashing an array of data.
  106. *
  107. * @param array $data
  108. * The data to serialize and hash.
  109. * @param string|string[] $prefix
  110. * The value(s) to use to prefix the identifier, separated by colons (:).
  111. * @param string $delimiter
  112. * The delimiter to use when joining the prefix and hash.
  113. *
  114. * @return string
  115. * The uniquely generated identifier.
  116. */
  117. public static function generateBase64HashIdentifier(array $data, $prefix = NULL, $delimiter = ':') {
  118. $prefix = Unicode::castToString($prefix, $delimiter);
  119. $hash = self::hashBase64(serialize(array_merge([$prefix], $data)));
  120. return $prefix ? $prefix . $delimiter . $hash : $hash;
  121. }
  122. /**
  123. * Parses a SRI integrity value to separate the algorithm from the hash.
  124. *
  125. * @param string $integrity
  126. * An integrity value beginning with a prefix indicating a particular hash
  127. * algorithm (currently the allowed prefixes are sha256, sha384, and
  128. * sha512), followed by a dash, and ending with the actual base64 encoded
  129. * hash.
  130. *
  131. * @return array
  132. * An indexed array containing intended for use with list():
  133. * - algorithm - (string) The provided or matched algorithm.
  134. * - hash - (string) The base64 encoded hash.
  135. *
  136. * @see https://developer.mozilla.org/en-US/docs/Web/Security/Subresource_Integrity
  137. */
  138. public static function parseSriIntegrity($integrity) {
  139. // Extract the algorithm and base64 encoded hash.
  140. preg_match(Crypt::SRI_INTEGRITY_REGEXP, $integrity, $matches);
  141. $algorithm = !empty($matches[1]) ? $matches[1] : FALSE;
  142. $hash = !empty($matches[2]) ? $matches[2] : $integrity;
  143. // Attempt to determine the algorithm used if one wasn't prepended.
  144. if (!$algorithm) {
  145. $algorithm = static::determineHashBase64Algorithm($hash);
  146. }
  147. return [$algorithm, $hash];
  148. }
  149. /****************************************************************************
  150. *
  151. * Deprecated methods
  152. *
  153. ***************************************************************************/
  154. /**
  155. * Generates a unique hash name.
  156. *
  157. * @param ...
  158. * All arguments passed will be serialized and used to generate the hash.
  159. *
  160. * @return string
  161. * The generated hash identifier.
  162. *
  163. * @deprecated since 8.x-3.18. Will be removed in a future release.
  164. *
  165. * @see \Drupal\bootstrap\Utility\Crypt::generateBase64HashIdentifier()
  166. */
  167. public static function generateHash() {
  168. Bootstrap::deprecated();
  169. $args = func_get_args();
  170. return static::generateBase64HashIdentifier($args, $args[0]);
  171. }
  172. }

Classes

Name Description
Crypt Extends \Drupal\Component\Utility\Crypt.