Base128.php 1.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263
  1. <?php
  2. namespace FG\ASN1;
  3. use FG\Utility\BigInteger;
  4. use InvalidArgumentException;
  5. /**
  6. * A base-128 decoder.
  7. */
  8. class Base128
  9. {
  10. /**
  11. * @param int $value
  12. *
  13. * @return string
  14. */
  15. public static function encode($value)
  16. {
  17. $value = BigInteger::create($value);
  18. $octets = chr($value->modulus(0x80)->toInteger());
  19. $value = $value->shiftRight(7);
  20. while ($value->compare(0) > 0) {
  21. $octets .= chr(0x80 | $value->modulus(0x80)->toInteger());
  22. $value = $value->shiftRight(7);
  23. }
  24. return strrev($octets);
  25. }
  26. /**
  27. * @param string $octets
  28. *
  29. * @throws InvalidArgumentException if the given octets represent a malformed base-128 value or the decoded value would exceed the the maximum integer length
  30. *
  31. * @return int
  32. */
  33. public static function decode($octets)
  34. {
  35. $bitsPerOctet = 7;
  36. $value = BigInteger::create(0);
  37. $i = 0;
  38. while (true) {
  39. if (!isset($octets[$i])) {
  40. throw new InvalidArgumentException(sprintf('Malformed base-128 encoded value (0x%s).', strtoupper(bin2hex($octets)) ?: '0'));
  41. }
  42. $octet = ord($octets[$i++]);
  43. $l1 = $value->shiftLeft($bitsPerOctet);
  44. $r1 = $octet & 0x7f;
  45. $value = $l1->add($r1);
  46. if (0 === ($octet & 0x80)) {
  47. break;
  48. }
  49. }
  50. return (string)$value;
  51. }
  52. }