SodiumMixer.php 2.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105
  1. <?php
  2. namespace RandomLib\Mixer;
  3. use RandomLib\AbstractMixer;
  4. use SecurityLib\Strength;
  5. use SecurityLib\Util;
  6. /**
  7. * Class SodiumMixer
  8. *
  9. * @package RandomLib\Mixer
  10. *
  11. * @category PHPCryptLib
  12. * @package Random
  13. * @subpackage Mixer
  14. *
  15. * @author Paragon Initiative Enterprises <security@paragonie.com>
  16. * @copyright 2017 The Authors
  17. * @license http://www.opensource.org/licenses/mit-license.html MIT License
  18. *
  19. * @version Build @@version@@
  20. */
  21. class SodiumMixer extends AbstractMixer
  22. {
  23. const SALSA20_BLOCK_SIZE = 64;
  24. /**
  25. * Return an instance of Strength indicating the strength of the source
  26. *
  27. * @return \SecurityLib\Strength An instance of one of the strength classes
  28. */
  29. public static function getStrength()
  30. {
  31. return new Strength(Strength::HIGH);
  32. }
  33. /**
  34. * Test to see if the mixer is available
  35. *
  36. * @return bool If the mixer is available on the system
  37. */
  38. public static function test()
  39. {
  40. return is_callable('sodium_crypto_stream') && is_callable('sodium_crypto_generichash');
  41. }
  42. /**
  43. * @return bool
  44. */
  45. public static function advisable()
  46. {
  47. return static::test() && !defined('HHVM_VERSION');
  48. }
  49. /**
  50. * Get the block size (the size of the individual blocks used for the mixing)
  51. *
  52. * @return int The block size
  53. */
  54. protected function getPartSize()
  55. {
  56. return self::SALSA20_BLOCK_SIZE;
  57. }
  58. /**
  59. * Mix 2 parts together using one method
  60. *
  61. * This method is jut a simple BLAKE2b hash of the two strings
  62. * concatenated together
  63. *
  64. * @param string $part1 The first part to mix
  65. * @param string $part2 The second part to mix
  66. *
  67. * @return string The mixed data
  68. */
  69. protected function mixParts1($part1, $part2)
  70. {
  71. return (string) \sodium_crypto_generichash($part1 . $part2, '', $this->getPartSize());
  72. }
  73. /**
  74. * Mix 2 parts together using another different method
  75. *
  76. * This method is a salsa20 stream based on a hash of the two inputs
  77. *
  78. * @param string $part1 The first part to mix
  79. * @param string $part2 The second part to mix
  80. *
  81. * @return string The mixed data
  82. */
  83. protected function mixParts2($part1, $part2)
  84. {
  85. // Pre-hash the two inputs into a 448-bit output
  86. /** @var string $hash */
  87. $hash = \sodium_crypto_generichash($part1 . $part2, '', 56);
  88. // Use salsa20 to expand into a pseudorandom string
  89. return (string) \sodium_crypto_stream(
  90. $this->getPartSize(),
  91. Util::safeSubstr($hash, 0, 24),
  92. Util::safeSubstr($hash, 0, 32)
  93. );
  94. }
  95. }