PageRenderTime 37ms CodeModel.GetById 14ms RepoModel.GetById 0ms app.codeStats 0ms

/core/src/main/php/security/crypto/MD5CryptImpl.class.php

http://github.com/xp-framework/xp-framework
PHP | 109 lines | 49 code | 13 blank | 47 comment | 7 complexity | 1a5b0631cc6442ea5a0809d09ab5d1e1 MD5 | raw file
Possible License(s): BSD-3-Clause
  1. <?php
  2. /* This class is part of the XP framework
  3. *
  4. * $Id$
  5. */
  6. uses('security.crypto.CryptImpl');
  7. /**
  8. * MD5 Crypt implementation
  9. *
  10. * Based on the implementation found in FreeBSD 2.2.[56]-RELEASE, which
  11. * contains the following license:
  12. * <pre>
  13. * "THE BEER-WARE LICENSE" (Revision 42):
  14. * <phk@login.dknet.dk> wrote this file. As long as you retain this notice you
  15. * can do whatever you want with this stuff. If we meet some day, and you think
  16. * this stuff is worth it, you can buy me a beer in return. Poul-Henning Kamp
  17. * </pre>
  18. *
  19. * @see php://md5
  20. * @see php://pack
  21. * @see xp://security.crypto.UnixCrypt
  22. * @see https://bugs.php.net/bug.php?id=55439
  23. */
  24. class MD5CryptImpl extends security·crypto·CryptImpl {
  25. const MAGIC = '$1$';
  26. /**
  27. * Converts an integer to a base64 string
  28. *
  29. * @param int value
  30. * @param int length
  31. * @return string
  32. */
  33. protected function to64($value, $length) {
  34. static $itoa= './0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz';
  35. $r= '';
  36. while ($length--) {
  37. $r.= $itoa{$value & 0x3F};
  38. $value >>= 6;
  39. }
  40. return $r;
  41. }
  42. /**
  43. * Crypt a given plain-text string
  44. *
  45. * @param string plain
  46. * @param string salt salt, optionally including magic '$1$'
  47. * @return string
  48. */
  49. public function crypt($plain, $salt) {
  50. // Take care of situation when magic is present in string
  51. if (0 === strpos($salt, self::MAGIC)) {
  52. $salt= substr($salt, strlen(self::MAGIC));
  53. }
  54. // Salt can have up to 8 characters, and goes max. until '$'
  55. $salt= substr($salt, 0, min(8, strpos($salt.'$', '$')));
  56. // Initial
  57. $ctx= $plain.self::MAGIC.$salt;
  58. $final= pack('H*', md5($plain.$salt.$plain));
  59. $l= strlen($plain);
  60. // Initial transformation
  61. for ($i= $l; $i > 0; $i-= 16) {
  62. $ctx.= substr($final, 0, $i > 16 ? 16 : $i);
  63. }
  64. // Memset
  65. for ($i= $l; $i; $i >>= 1) {
  66. $ctx.= $i & 1 ? "\0" : $plain{0};
  67. }
  68. // Slow down
  69. for ($final= pack('H*', md5($ctx)), $i= 0; $i < 1000; $i++) {
  70. $ctx1= $i & 1 ? $plain : substr($final, 0, 16);
  71. $i % 3 && $ctx1.= $salt;
  72. $i % 7 && $ctx1.= $plain;
  73. $ctx1.= $i & 1 ? substr($final, 0, 16) : $plain;
  74. $final= pack('H*', md5($ctx1));
  75. }
  76. // Final transformation
  77. return (
  78. self::MAGIC.$salt.'$'.
  79. $this->to64((ord($final{0}) << 16) | (ord($final{6}) << 8) | ord($final{12}), 4).
  80. $this->to64((ord($final{1}) << 16) | (ord($final{7}) << 8) | ord($final{13}), 4).
  81. $this->to64((ord($final{2}) << 16) | (ord($final{8}) << 8) | ord($final{14}), 4).
  82. $this->to64((ord($final{3}) << 16) | (ord($final{9}) << 8) | ord($final{15}), 4).
  83. $this->to64((ord($final{4}) << 16) | (ord($final{10}) << 8) | ord($final{5}), 4).
  84. $this->to64(ord($final{11}), 2)
  85. );
  86. }
  87. /**
  88. * Creates a string representation of this crypt implementation
  89. *
  90. * @return string
  91. */
  92. public function toString() {
  93. return $this->getClassName();
  94. }
  95. }
  96. ?>