BitString.php 2.8 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788
  1. <?php
  2. /*
  3. * This file is part of the PHPASN1 library.
  4. *
  5. * Copyright © Friedrich Große <friedrich.grosse@gmail.com>
  6. *
  7. * For the full copyright and license information, please view the LICENSE
  8. * file that was distributed with this source code.
  9. */
  10. namespace FG\ASN1\Universal;
  11. use Exception;
  12. use FG\ASN1\Exception\ParserException;
  13. use FG\ASN1\Parsable;
  14. use FG\ASN1\Identifier;
  15. class BitString extends OctetString implements Parsable
  16. {
  17. private $nrOfUnusedBits;
  18. /**
  19. * Creates a new ASN.1 BitString object.
  20. *
  21. * @param string|int $value Either the hexadecimal value as a string (spaces are allowed - leading 0x is optional) or a numeric value
  22. * @param int $nrOfUnusedBits the number of unused bits in the last octet [optional].
  23. *
  24. * @throws Exception if the second parameter is no positive numeric value
  25. */
  26. public function __construct($value, $nrOfUnusedBits = 0)
  27. {
  28. parent::__construct($value);
  29. if (!is_numeric($nrOfUnusedBits) || $nrOfUnusedBits < 0) {
  30. throw new Exception('BitString: second parameter needs to be a positive number (or zero)!');
  31. }
  32. $this->nrOfUnusedBits = $nrOfUnusedBits;
  33. }
  34. public function getType()
  35. {
  36. return Identifier::BITSTRING;
  37. }
  38. protected function calculateContentLength()
  39. {
  40. // add one to the length for the first octet which encodes the number of unused bits in the last octet
  41. return parent::calculateContentLength() + 1;
  42. }
  43. protected function getEncodedValue()
  44. {
  45. // the first octet determines the number of unused bits
  46. $nrOfUnusedBitsOctet = chr($this->nrOfUnusedBits);
  47. $actualContent = parent::getEncodedValue();
  48. return $nrOfUnusedBitsOctet.$actualContent;
  49. }
  50. public function getNumberOfUnusedBits()
  51. {
  52. return $this->nrOfUnusedBits;
  53. }
  54. public static function fromBinary(&$binaryData, &$offsetIndex = 0)
  55. {
  56. self::parseIdentifier($binaryData[$offsetIndex], Identifier::BITSTRING, $offsetIndex++);
  57. $contentLength = self::parseContentLength($binaryData, $offsetIndex, 2);
  58. $nrOfUnusedBits = ord($binaryData[$offsetIndex]);
  59. $value = substr($binaryData, $offsetIndex + 1, $contentLength - 1);
  60. if ($nrOfUnusedBits > 7 || // no less than 1 used, otherwise non-minimal
  61. ($contentLength - 1) == 1 && $nrOfUnusedBits > 0 || // content length only 1, no
  62. (ord($value[strlen($value)-1])&((1<<$nrOfUnusedBits)-1)) != 0 // unused bits set
  63. ) {
  64. throw new ParserException("Can not parse bit string with invalid padding", $offsetIndex);
  65. }
  66. $offsetIndex += $contentLength;
  67. $parsedObject = new self(bin2hex($value), $nrOfUnusedBits);
  68. $parsedObject->setContentLength($contentLength);
  69. return $parsedObject;
  70. }
  71. }