Base32.php 3.2 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485
  1. <?php
  2. namespace OTPHP;
  3. /**
  4. * Encode in Base32 based on RFC 4648.
  5. * Requires 20% more space than base64
  6. * Great for case-insensitive filesystems like Windows and URL's (except for = char which can be excluded using the pad option for urls)
  7. *
  8. * @package default
  9. * @author Bryan Ruiz
  10. **/
  11. class Base32 {
  12. private static $map = array(
  13. 'A', 'B', 'C', 'D', 'E', 'F', 'G', 'H', // 7
  14. 'I', 'J', 'K', 'L', 'M', 'N', 'O', 'P', // 15
  15. 'Q', 'R', 'S', 'T', 'U', 'V', 'W', 'X', // 23
  16. 'Y', 'Z', '2', '3', '4', '5', '6', '7', // 31
  17. '=' // padding char
  18. );
  19. private static $flippedMap = array(
  20. 'A'=>'0', 'B'=>'1', 'C'=>'2', 'D'=>'3', 'E'=>'4', 'F'=>'5', 'G'=>'6', 'H'=>'7',
  21. 'I'=>'8', 'J'=>'9', 'K'=>'10', 'L'=>'11', 'M'=>'12', 'N'=>'13', 'O'=>'14', 'P'=>'15',
  22. 'Q'=>'16', 'R'=>'17', 'S'=>'18', 'T'=>'19', 'U'=>'20', 'V'=>'21', 'W'=>'22', 'X'=>'23',
  23. 'Y'=>'24', 'Z'=>'25', '2'=>'26', '3'=>'27', '4'=>'28', '5'=>'29', '6'=>'30', '7'=>'31'
  24. );
  25. /**
  26. * Use padding false when encoding for urls
  27. *
  28. * @return base32 encoded string
  29. * @author Bryan Ruiz
  30. **/
  31. public static function encode($input, $padding = true) {
  32. if(empty($input)) return "";
  33. $input = str_split($input);
  34. $binaryString = "";
  35. for($i = 0; $i < count($input); $i++) {
  36. $binaryString .= str_pad(base_convert(ord($input[$i]), 10, 2), 8, '0', STR_PAD_LEFT);
  37. }
  38. $fiveBitBinaryArray = str_split($binaryString, 5);
  39. $base32 = "";
  40. $i=0;
  41. while($i < count($fiveBitBinaryArray)) {
  42. $base32 .= self::$map[base_convert(str_pad($fiveBitBinaryArray[$i], 5,'0'), 2, 10)];
  43. $i++;
  44. }
  45. if($padding && ($x = strlen($binaryString) % 40) != 0) {
  46. if($x == 8) $base32 .= str_repeat(self::$map[32], 6);
  47. else if($x == 16) $base32 .= str_repeat(self::$map[32], 4);
  48. else if($x == 24) $base32 .= str_repeat(self::$map[32], 3);
  49. else if($x == 32) $base32 .= self::$map[32];
  50. }
  51. return $base32;
  52. }
  53. public static function decode($input) {
  54. if(empty($input)) return;
  55. $paddingCharCount = substr_count($input, self::$map[32]);
  56. $allowedValues = array(6,4,3,1,0);
  57. if(!in_array($paddingCharCount, $allowedValues)) return false;
  58. for($i=0; $i<4; $i++){
  59. if($paddingCharCount == $allowedValues[$i] &&
  60. substr($input, -($allowedValues[$i])) != str_repeat(self::$map[32], $allowedValues[$i])) return false;
  61. }
  62. $input = str_replace('=','', $input);
  63. $input = str_split($input);
  64. $binaryString = "";
  65. for($i=0; $i < count($input); $i = $i+8) {
  66. $x = "";
  67. if(!in_array($input[$i], self::$map)) return false;
  68. for($j=0; $j < 8; $j++) {
  69. $x .= str_pad(base_convert(@self::$flippedMap[@$input[$i + $j]], 10, 2), 5, '0', STR_PAD_LEFT);
  70. }
  71. $eightBits = str_split($x, 8);
  72. for($z = 0; $z < count($eightBits); $z++) {
  73. $binaryString .= ( ($y = chr(base_convert($eightBits[$z], 2, 10))) || ord($y) == 48 ) ? $y:"";
  74. }
  75. }
  76. return $binaryString;
  77. }
  78. }