ObjectIdentifier.php 3.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138
  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\Base128;
  13. use FG\ASN1\OID;
  14. use FG\ASN1\ASNObject;
  15. use FG\ASN1\Parsable;
  16. use FG\ASN1\Identifier;
  17. use FG\ASN1\Exception\ParserException;
  18. class ObjectIdentifier extends ASNObject implements Parsable
  19. {
  20. protected $subIdentifiers;
  21. protected $value;
  22. public function __construct($value)
  23. {
  24. $this->subIdentifiers = explode('.', $value);
  25. $nrOfSubIdentifiers = count($this->subIdentifiers);
  26. for ($i = 0; $i < $nrOfSubIdentifiers; $i++) {
  27. if (is_numeric($this->subIdentifiers[$i])) {
  28. // enforce the integer type
  29. $this->subIdentifiers[$i] = intval($this->subIdentifiers[$i]);
  30. } else {
  31. throw new Exception("[{$value}] is no valid object identifier (sub identifier ".($i + 1).' is not numeric)!');
  32. }
  33. }
  34. // Merge the first to arcs of the OID registration tree (per ASN definition!)
  35. if ($nrOfSubIdentifiers >= 2) {
  36. $this->subIdentifiers[1] = ($this->subIdentifiers[0] * 40) + $this->subIdentifiers[1];
  37. unset($this->subIdentifiers[0]);
  38. }
  39. $this->value = $value;
  40. }
  41. public function getContent()
  42. {
  43. return $this->value;
  44. }
  45. public function getType()
  46. {
  47. return Identifier::OBJECT_IDENTIFIER;
  48. }
  49. protected function calculateContentLength()
  50. {
  51. $length = 0;
  52. foreach ($this->subIdentifiers as $subIdentifier) {
  53. do {
  54. $subIdentifier = $subIdentifier >> 7;
  55. $length++;
  56. } while ($subIdentifier > 0);
  57. }
  58. return $length;
  59. }
  60. protected function getEncodedValue()
  61. {
  62. $encodedValue = '';
  63. foreach ($this->subIdentifiers as $subIdentifier) {
  64. $encodedValue .= Base128::encode($subIdentifier);
  65. }
  66. return $encodedValue;
  67. }
  68. public function __toString()
  69. {
  70. return OID::getName($this->value);
  71. }
  72. public static function fromBinary(&$binaryData, &$offsetIndex = 0)
  73. {
  74. self::parseIdentifier($binaryData[$offsetIndex], Identifier::OBJECT_IDENTIFIER, $offsetIndex++);
  75. $contentLength = self::parseContentLength($binaryData, $offsetIndex, 1);
  76. $firstOctet = ord($binaryData[$offsetIndex++]);
  77. $oidString = floor($firstOctet / 40).'.'.($firstOctet % 40);
  78. $oidString .= '.'.self::parseOid($binaryData, $offsetIndex, $contentLength - 1);
  79. $parsedObject = new self($oidString);
  80. $parsedObject->setContentLength($contentLength);
  81. return $parsedObject;
  82. }
  83. /**
  84. * Parses an object identifier except for the first octet, which is parsed
  85. * differently. This way relative object identifiers can also be parsed
  86. * using this.
  87. *
  88. * @param $binaryData
  89. * @param $offsetIndex
  90. * @param $octetsToRead
  91. *
  92. * @throws ParserException
  93. *
  94. * @return string
  95. */
  96. protected static function parseOid(&$binaryData, &$offsetIndex, $octetsToRead)
  97. {
  98. $oid = '';
  99. while ($octetsToRead > 0) {
  100. $octets = '';
  101. do {
  102. if (0 === $octetsToRead) {
  103. throw new ParserException('Malformed ASN.1 Object Identifier', $offsetIndex - 1);
  104. }
  105. $octetsToRead--;
  106. $octet = $binaryData[$offsetIndex++];
  107. $octets .= $octet;
  108. } while (ord($octet) & 0x80);
  109. $oid .= sprintf('%d.', Base128::decode($octets));
  110. }
  111. // Remove trailing '.'
  112. return substr($oid, 0, -1) ?: '';
  113. }
  114. }