source: vendor/paragonie/constant_time_encoding/src/Hex.php@ f9c482b

Last change on this file since f9c482b was f9c482b, checked in by Vlado 222039 <vlado.popovski@…>, 7 days ago

Upload new project files

  • Property mode set to 100644
File size: 4.7 KB
Line 
1<?php
2declare(strict_types=1);
3namespace ParagonIE\ConstantTime;
4
5use RangeException;
6use TypeError;
7
8/**
9 * Copyright (c) 2016 - 2022 Paragon Initiative Enterprises.
10 * Copyright (c) 2014 Steve "Sc00bz" Thomas (steve at tobtu dot com)
11 *
12 * Permission is hereby granted, free of charge, to any person obtaining a copy
13 * of this software and associated documentation files (the "Software"), to deal
14 * in the Software without restriction, including without limitation the rights
15 * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
16 * copies of the Software, and to permit persons to whom the Software is
17 * furnished to do so, subject to the following conditions:
18 *
19 * The above copyright notice and this permission notice shall be included in all
20 * copies or substantial portions of the Software.
21 *
22 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
23 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
24 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
25 * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
26 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
27 * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
28 * SOFTWARE.
29 */
30
31/**
32 * Class Hex
33 * @package ParagonIE\ConstantTime
34 */
35abstract class Hex implements EncoderInterface
36{
37 /**
38 * Convert a binary string into a hexadecimal string without cache-timing
39 * leaks
40 *
41 * @param string $binString (raw binary)
42 * @return string
43 * @throws TypeError
44 */
45 public static function encode(
46 #[\SensitiveParameter]
47 string $binString
48 ): string {
49 $hex = '';
50 $len = Binary::safeStrlen($binString);
51 for ($i = 0; $i < $len; ++$i) {
52 /** @var array<int, int> $chunk */
53 $chunk = \unpack('C', $binString[$i]);
54 $c = $chunk[1] & 0xf;
55 $b = $chunk[1] >> 4;
56
57 $hex .= \pack(
58 'CC',
59 (87 + $b + ((($b - 10) >> 8) & ~38)),
60 (87 + $c + ((($c - 10) >> 8) & ~38))
61 );
62 }
63 return $hex;
64 }
65
66 /**
67 * Convert a binary string into a hexadecimal string without cache-timing
68 * leaks, returning uppercase letters (as per RFC 4648)
69 *
70 * @param string $binString (raw binary)
71 * @return string
72 * @throws TypeError
73 */
74 public static function encodeUpper(
75 #[\SensitiveParameter]
76 string $binString
77 ): string {
78 $hex = '';
79 $len = Binary::safeStrlen($binString);
80
81 for ($i = 0; $i < $len; ++$i) {
82 /** @var array<int, int> $chunk */
83 $chunk = \unpack('C', $binString[$i]);
84 $c = $chunk[1] & 0xf;
85 $b = $chunk[1] >> 4;
86
87 $hex .= \pack(
88 'CC',
89 (55 + $b + ((($b - 10) >> 8) & ~6)),
90 (55 + $c + ((($c - 10) >> 8) & ~6))
91 );
92 }
93 return $hex;
94 }
95
96 /**
97 * Convert a hexadecimal string into a binary string without cache-timing
98 * leaks
99 *
100 * @param string $encodedString
101 * @param bool $strictPadding
102 * @return string (raw binary)
103 * @throws RangeException
104 */
105 public static function decode(
106 #[\SensitiveParameter]
107 string $encodedString,
108 bool $strictPadding = false
109 ): string {
110 $hex_pos = 0;
111 $bin = '';
112 $c_acc = 0;
113 $hex_len = Binary::safeStrlen($encodedString);
114 $state = 0;
115 if (($hex_len & 1) !== 0) {
116 if ($strictPadding) {
117 throw new RangeException(
118 'Expected an even number of hexadecimal characters'
119 );
120 } else {
121 $encodedString = '0' . $encodedString;
122 ++$hex_len;
123 }
124 }
125
126 /** @var array<int, int> $chunk */
127 $chunk = \unpack('C*', $encodedString);
128 while ($hex_pos < $hex_len) {
129 ++$hex_pos;
130 $c = $chunk[$hex_pos];
131 $c_num = $c ^ 48;
132 $c_num0 = ($c_num - 10) >> 8;
133 $c_alpha = ($c & ~32) - 55;
134 $c_alpha0 = (($c_alpha - 10) ^ ($c_alpha - 16)) >> 8;
135
136 if (($c_num0 | $c_alpha0) === 0) {
137 throw new RangeException(
138 'Expected hexadecimal character'
139 );
140 }
141 $c_val = ($c_num0 & $c_num) | ($c_alpha & $c_alpha0);
142 if ($state === 0) {
143 $c_acc = $c_val * 16;
144 } else {
145 $bin .= \pack('C', $c_acc | $c_val);
146 }
147 $state ^= 1;
148 }
149 return $bin;
150 }
151}
Note: See TracBrowser for help on using the repository browser.