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