OTPHelper::setAccount()   A
last analyzed

Complexity

Conditions 2
Paths 2

Size

Total Lines 9

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 5
CRAP Score 2

Importance

Changes 0
Metric Value
dl 0
loc 9
ccs 5
cts 5
cp 1
rs 9.9666
c 0
b 0
f 0
cc 2
nc 2
nop 1
crap 2
1
<?php
2
3
/**
4
 * OTPHelper
5
 * @package OTPAuthenticate
6
 * @copyright (c) Marc Alexander <[email protected]>
7
 *
8
 * For the full copyright and license information, please view the LICENSE
9
 * file that was distributed with this source code.
10
 */
11
12
namespace OTPAuthenticate;
13
14
class OTPHelper
15
{
16
	/** @var array Allowed types of OTP */
17
	protected $allowedType = array(
18
		'hotp',
19
		'totp',
20
	);
21
22
	/** @var array Allowed algorithms */
23
	protected $allowedAlgorithm = array(
24
		'sha1',
25
		'sha256',
26
		'sha512',
27
	);
28
29
	/** @var string Label string for URI */
30
	protected $label;
31
32
	/** @var string Issuer string for URI */
33
	protected $issuer;
34
35
	/** @var string Additional parameters for URI */
36
	protected $parameters = '';
37
38
	/**
39
	 * Generate OTP key URI
40
	 *
41
	 * @param string $type OTP type
42
	 * @param string $secret Base32 encoded secret
43
	 * @param string $account Account name
44
	 * @param string $issuer Issuer name (optional)
45
	 * @param int $counter Counter for HOTP (optional)
46
	 * @param string $algorithm Algorithm name (optional)
47
	 * @param string $digits Number of digits for code (optional)
48
	 * @param string $period Period for TOTP codes (optional)
49
	 *
50
	 * @return string OTP key URI
51
	 */
52 12
	public function generateKeyURI($type, $secret, $account, $issuer = '', $counter = 0, $algorithm = '', $digits = '', $period = '')
53
	{
54
		// Check if type is supported
55 12
		$this->validateType($type);
56 11
		$this->validateAlgorithm($algorithm);
57
58
		// Format label string
59 10
		$this->formatLabel($issuer, 'issuer');
60 10
		$this->formatLabel($account, 'account');
61
62
		// Set additional parameters
63 8
		$this->setCounter($type, $counter);
64 7
		$this->setParameter($algorithm, 'algorithm');
65 7
		$this->setParameter($digits, 'digits');
66 7
		$this->setParameter($period, 'period');
67
68 7
		return 'otpauth://' . $type . '/' . $this->label . '?secret=' . $secret . $this->issuer . $this->parameters;
69
	}
70
71
	/**
72
	 * Check if OTP type is supported
73
	 *
74
	 * @param string $type OTP type
75
	 *
76
	 * @throws \InvalidArgumentException When type is not supported
77
	 */
78 12
	protected function validateType($type)
79
	{
80 12
		if (empty($type) || !in_array($type, $this->allowedType))
81
		{
82 1
			throw new \InvalidArgumentException("The OTP type $type is not supported");
83
		}
84 11
	}
85
86
	/**
87
	 * Check if algorithm is supported
88
	 *
89
	 * @param string $algorithm Algorithm to use
90
	 *
91
	 * @throws \InvalidArgumentException When algorithm is not supported
92
	 */
93 11
	protected function validateAlgorithm($algorithm)
94
	{
95 11
		if (!empty($algorithm) && !in_array($algorithm, $this->allowedAlgorithm))
96
		{
97 1
			throw new \InvalidArgumentException("The algorithm $algorithm is not supported");
98
		}
99 10
	}
100
101
	/**
102
	 * Format label string according to expected urlencoded standards.
103
	 *
104
	 * @param string $string The label string
105
	 * @param string $part Part of label
106
	 */
107 10
	protected function formatLabel($string, $part)
108
	{
109 10
		$string = trim($string);
110
111 10
		if ($part === 'account')
112
		{
113 10
			$this->setAccount($string);
114
		}
115 10
		else if ($part === 'issuer')
116
		{
117 10
			$this->setIssuer($string);
118
		}
119 10
	}
120
121
	/**
122
	 * Format and and set account name
123
	 *
124
	 * @param string $account Account name
125
	 *
126
	 * @throws \InvalidArgumentException When given account name is an empty string
127
	 */
128 10
	protected function setAccount($account)
129
	{
130 10
		if (empty($account))
131
		{
132 2
			throw new \InvalidArgumentException("Label can't contain empty strings");
133
		}
134
135 8
		$this->label .= str_replace('%40', '@', rawurlencode($account));
136 8
	}
137
138
	/**
139
	 * Format and set issuer
140
	 *
141
	 * @param string $issuer Issuer name
142
	 */
143 10
	protected function setIssuer($issuer)
144
	{
145 10
		if (!empty($issuer))
146
		{
147 2
			$this->label = rawurlencode($issuer) . ':';
148 2
			$this->issuer = '&issuer=' . rawurlencode($issuer);
149
		}
150 10
	}
151
152
	/**
153
	 * Set parameter if it is defined
154
	 *
155
	 * @param string $data Data to set
156
	 * @param string $name Name of data
157
	 */
158 7
	protected function setParameter($data, $name)
159
	{
160 7
		if (!empty($data))
161
		{
162 2
			$this->parameters .= "&$name=" . rawurlencode($data);
163
		}
164 7
	}
165
166
	/**
167
	 * Set counter value if hotp is being used
168
	 *
169
	 * @param string $type Type of OTP auth, either HOTP or TOTP
170
	 * @param int $counter Counter value
171
	 *
172
	 * @throws \InvalidArgumentException If counter is empty while using HOTP
173
	 */
174 8
	protected function setCounter($type, $counter)
175
	{
176 8
		if ($type === 'hotp')
177
		{
178 5
			if ($counter !== 0 && empty($counter))
179
			{
180 1
				throw new \InvalidArgumentException("Counter can't be empty if HOTP is being used");
181
			}
182
183 4
			$this->parameters .= "&counter=$counter";
184
		}
185 7
	}
186
}
187