PageRenderTime 48ms CodeModel.GetById 18ms RepoModel.GetById 1ms app.codeStats 0ms

/bitrix/modules/sale/lib/paysystem/asn1.php

https://gitlab.com/neuser/bitrix-core
PHP | 218 lines | 107 code | 30 blank | 81 comment | 30 complexity | 312ec0661ebd025987f580daea5a167d MD5 | raw file
  1. <?php
  2. /*
  3. * SimpleJWT
  4. *
  5. * Copyright (C) Kelvin Mo 2015
  6. *
  7. * Redistribution and use in source and binary forms, with or without
  8. * modification, are permitted provided that the following conditions
  9. * are met:
  10. *
  11. * 1. Redistributions of source code must retain the above copyright
  12. * notice, this list of conditions and the following disclaimer.
  13. *
  14. * 2. Redistributions in binary form must reproduce the above
  15. * copyright notice, this list of conditions and the following
  16. * disclaimer in the documentation and/or other materials provided
  17. * with the distribution.
  18. *
  19. * 3. The name of the author may not be used to endorse or promote
  20. * products derived from this software without specific prior
  21. * written permission.
  22. *
  23. * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS
  24. * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
  25. * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
  26. * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY
  27. * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
  28. * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE
  29. * GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
  30. * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER
  31. * IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
  32. * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN
  33. * IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
  34. */
  35. namespace Bitrix\Sale\PaySystem;
  36. /**
  37. * Functions for interacting with ASN.1 data streams.
  38. *
  39. * Note that this class only implements a small subset of the ASN.1 DER, and should
  40. * not be used as a general-purpose ASN.1 encoder/decoder.
  41. */
  42. class ASN1 {
  43. const UNIVERSAL_CLASS = 0x00;
  44. const APPLICATION_CLASS = 0x40;
  45. const CONTEXT_CLASS = 0x80;
  46. const PRIVATE_CLASS = 0xC0;
  47. const INTEGER_TYPE = 0x02;
  48. const BIT_STRING = 0x03;
  49. const OCTET_STRING = 0x04;
  50. const NULL_TYPE = 0x05;
  51. const OID = 0x06;
  52. const SEQUENCE = 0x10;
  53. /**
  54. * Reads a DER stream and decodes a single object
  55. *
  56. * @param string $der the data stream
  57. * @param int $offset the offset of the data stream containing the object
  58. * to decode
  59. * @param mixed &$data the decoded object
  60. * @param bool $ignore_bit_strings whether to refrain from moving the
  61. * offset when reading a bit string - this allows the caller to read the
  62. * bit string manually
  63. * @return int the number of bytes read, or 0 if there is an error
  64. */
  65. static function readDER($der, $offset, &$data, $ignore_bit_strings = FALSE) {
  66. $pos = $offset;
  67. $size = mb_strlen($der);
  68. if ($size < 2) return 0;
  69. // Tag/Type
  70. $constructed = (ord($der[$pos]) >> 5) & 0x01;
  71. $type = ord($der[$pos++]) & 0x1f;
  72. if ($type == 0x1f) return 0; // Long-form type: not supported
  73. if ($pos >= $size) return 0;
  74. // Length
  75. $len = ord($der[$pos++]);
  76. if ($len & 0x80) {
  77. $n = $len & 0x1f;
  78. $len = 0;
  79. while ($n-- && $pos < $size) {
  80. $len = ($len << 8) | ord($der[$pos++]);
  81. }
  82. }
  83. if ($pos >= $size || $len > $size - $pos) return 0;
  84. // Value
  85. if ($type == self::BIT_STRING) { // BIT STRING
  86. $pos++; // Skip the first contents octet (padding indicator)
  87. $data = mb_substr($der, $pos, $len - 1);
  88. if (!$ignore_bit_strings) $pos += $len - 1;
  89. } elseif (!$constructed /*&& ($type != 0x04)*/) {
  90. $data = mb_substr($der, $pos, $len);
  91. $pos += $len;
  92. }
  93. return $pos - $offset;
  94. }
  95. /**
  96. * Encodes a value into a DER object.
  97. *
  98. * @param int $type the DER tag of the object
  99. * @param string $value the value to encode
  100. * @param bool $primitive whether the object is of a primitive or
  101. * constructed type
  102. * @return string the encoded object
  103. */
  104. static function encodeDER($type, $value = '', $primitive = true, $class = 0) {
  105. $tag_header = $class;
  106. if (!$primitive) $tag_header |= 0x20;
  107. // Type
  108. if ($type < 0x1f) {
  109. $der = chr($tag_header | $type);
  110. } else {
  111. return NULL; // Long form required. not supported.
  112. }
  113. // Length
  114. $len = mb_strlen($value);
  115. if ($len <= 0x7f) {
  116. $der .= chr($len);
  117. } else {
  118. $pack = '';
  119. $n = 0;
  120. while ($len) {
  121. $pack .= chr($len & 0xff);
  122. $len >>= 8;
  123. $n++;
  124. }
  125. $der .= chr($n | 0x80);
  126. if (pack('V', 65534) == pack('L', 65534)) {
  127. $der .= strrev($pack); // Little endian machine - need to convert to big endian
  128. } else {
  129. $der = $pack;
  130. }
  131. }
  132. return $der . $value;
  133. }
  134. /**
  135. * Decodes a DER-encoded object identifier into a string.
  136. *
  137. * @param $string oid the binary DER-encoded object identifier
  138. * @return $string the decoded string
  139. */
  140. static function decodeOID($oid) {
  141. $pos = 0;
  142. $size = mb_strlen($oid);
  143. // First octet
  144. $oct = ord($oid[$pos++]);
  145. $str = floor($oct / 40) . '.' . ($oct % 40);
  146. // Subsequent octets
  147. while ($pos < $size) {
  148. $num = 0;
  149. do {
  150. $oct = ord($oid[$pos++]);
  151. $num = ($num << 7) + ($oct & 0x7F);
  152. } while (($oct & 0x80) && ($pos < $size));
  153. $str .= '.' . $num;
  154. }
  155. return $str;
  156. }
  157. /**
  158. * Encodes a string into a DER-encoded object identifier.
  159. *
  160. * @param $string $str the object identifier string
  161. * @return $string the binary DER-encoded object identifier
  162. */
  163. static function encodeOID($str) {
  164. $numbers = explode('.', $str);
  165. // First octet
  166. $oid = chr(array_shift($numbers) * 40 + array_shift($numbers));
  167. // Subsequent octets
  168. foreach ($numbers as $num) {
  169. if ($num == 0) {
  170. $oid .= chr(0x00);
  171. continue;
  172. }
  173. $pack = '';
  174. while ($num) {
  175. $pack .= chr(0x80 | ($num & 0x7f));
  176. $num >>= 7;
  177. }
  178. $pack[0] = $pack[0] & chr(0x7f);
  179. if (pack('V', 65534) == pack('L', 65534)) {
  180. $oid .= strrev($pack); // Little endian machine - need to convert to big endian
  181. } else {
  182. $oid .= $pack;
  183. }
  184. }
  185. return $oid;
  186. }
  187. }
  188. ?>