This repository has been archived by the owner on Sep 27, 2024. It is now read-only.
forked from rchouinard/rych-otp
-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathSeed.php
217 lines (190 loc) · 5.45 KB
/
Seed.php
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
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
<?php
/**
* Ryan's OATH-OTP Library
*
* @package Rych\OTP
* @author Ryan Chouinard <[email protected]>
* @copyright Copyright (c) 2013, Ryan Chouinard
* @license MIT License - http://www.opensource.org/licenses/mit-license.php
*/
namespace Rych\OTP;
use Rych\Random\Random;
use Rych\Random\Encoder\EncoderInterface;
use Rych\Random\Encoder\Base32Encoder;
use Rych\Random\Encoder\HexEncoder;
use Rych\Random\Encoder\RawEncoder;
/**
* OTP Seed/Key
*
* @package Rych\OTP
* @author Ryan Chouinard <[email protected]>
* @copyright Copyright (c) 2013, Ryan Chouinard
* @license MIT License - http://www.opensource.org/licenses/mit-license.php
*/
class Seed
{
const FORMAT_BASE32 = 'base32';
const FORMAT_HEX = 'hex';
const FORMAT_RAW = 'raw';
/**
* @var \Rych\Random\Encoder\EncoderInterface
*/
private $encoder;
/**
* @var string
*/
private $value;
/**
* Class constructor.
*
* @param string $value The seed value.
* @return void
*/
public function __construct($value = null)
{
if ($value !== null) {
$this->setValue($value);
}
$this->setFormat(self::FORMAT_HEX);
}
/**
* Output the seed value as a string.
*
* @return string
*/
public function __toString()
{
$value = $this->value;
if ($this->encoder instanceof EncoderInterface) {
$value = $this->encoder->encode($value);
}
return (string) $value;
}
/**
* Get the current format setting.
*
* @return string Returns the current default format.
*/
public function getFormat()
{
switch (true) {
case ($this->encoder instanceof Base32Encoder):
$format = self::FORMAT_BASE32;
break;
case ($this->encoder instanceof HexEncoder):
$format = self::FORMAT_HEX;
break;
case ($this->encoder instanceof RawEncoder):
default:
$format = self::FORMAT_RAW;
break;
}
return $format;
}
/**
* Set the format setting.
*
* @param string $format The format.
* @return self
*/
public function setFormat($format)
{
switch ($format) {
case self::FORMAT_BASE32:
$this->encoder = new Base32Encoder;
break;
case self::FORMAT_HEX:
$this->encoder = new HexEncoder;
break;
case self::FORMAT_RAW:
default:
$this->encoder = new RawEncoder;
break;
}
return $this;
}
/**
* Get the seed value in the optionally specified format.
*
* @param string $format The output format.
* @return string Returns the seed value optionally encoded as $format.
*/
public function getValue($format = null)
{
return $this->encode($this->value, $format);
}
/**
* Set the seed value, optionally specifying an input format.
*
* @param string $value The seed value.
* @param string $format The input format.
* @return self
*/
public function setValue($value, $format = null)
{
$this->value = $this->decode($value, $format);
}
/**
* Generate a new Seed instance with a new random seed value.
*
* @param integer $bytes Number of bytes to use. Default of 20 produces an
* 160-bit seed value as recommended by RFC 4226 Section 4 R6.
* @param \Rych\Random\Random $random Optional pre-configured instance of
* the random generator class.
* @return Seed Returns a preconfigured instance of Seed.
*/
public static function generate($bytes = 20, Random $random = null)
{
if (!$random) {
$random = new Random;
}
$output = $random->getRandomBytes((int) $bytes);
return new Seed($output);
}
/**
* Attempt to decode a seed value with one of the Encoder classes.
*
* @param string $seed The encoded seed value.
* @return string Returns the decoded seed value.
*/
private function decode($seed, $format = null)
{
$encoder = new RawEncoder;
// Auto-detect
if ($format === null) {
if (preg_match('/^[0-9a-f]+$/i', $seed)) {
$encoder = new HexEncoder;
} elseif (preg_match('/^[2-7a-z]+$/i', $seed)) {
$encoder = new Base32Encoder;
}
// User-specified
} else {
if ($format == self::FORMAT_HEX) {
$encoder = new HexEncoder;
} elseif ($format == self::FORMAT_BASE32) {
$encoder = new Base32Encoder;
}
}
$output = $encoder->decode($seed);
return $output;
}
/**
* Attempt to encode a seed value with one of the Encoder classes.
*
* @param string $seed The seed value.
* @return string Returns the encoded seed value.
*/
private function encode($seed, $format = null)
{
$encoder = $this->encoder;
if ($format == self::FORMAT_HEX) {
$encoder = new HexEncoder;
} elseif ($format == self::FORMAT_BASE32) {
$encoder = new Base32Encoder;
} elseif ($format == self::FORMAT_RAW) {
$encoder = new RawEncoder;
}
$output = $encoder->encode($seed);
return $output;
}
}