11<?php
22
33/**
4- * PHP Class for handling Google Authenticator 2-factor authentication
4+ * PHP Class for handling Google Authenticator 2-factor authentication.
55 *
66 * @author Michael Kliewe
77 * @copyright 2012 Michael Kliewe
88 * @license http://www.opensource.org/licenses/bsd-license.php BSD License
9+ *
910 * @link http://www.phpgangsta.de/
1011 */
11-
1212class PHPGangsta_GoogleAuthenticator
1313{
1414 protected $ _codeLength = 6 ;
@@ -18,6 +18,7 @@ class PHPGangsta_GoogleAuthenticator
1818 * 16 characters, randomly chosen from the allowed base32 characters.
1919 *
2020 * @param int $secretLength
21+ *
2122 * @return string
2223 */
2324 public function createSecret ($ secretLength = 16 )
@@ -41,20 +42,22 @@ public function createSecret($secretLength = 16)
4142 }
4243 }
4344 if ($ rnd !== false ) {
44- for ($ i = 0 ; $ i < $ secretLength ; $ i ++ ) {
45+ for ($ i = 0 ; $ i < $ secretLength ; ++ $ i ) {
4546 $ secret .= $ validChars [ord ($ rnd [$ i ]) & 31 ];
4647 }
4748 } else {
4849 throw new Exception ('No source of secure random ' );
4950 }
51+
5052 return $ secret ;
5153 }
5254
5355 /**
54- * Calculate the code, with given secret and point in time
56+ * Calculate the code, with given secret and point in time.
5557 *
56- * @param string $secret
58+ * @param string $secret
5759 * @param int|null $timeSlice
60+ *
5861 * @return string
5962 */
6063 public function getCode ($ secret , $ timeSlice = null )
@@ -81,37 +84,42 @@ public function getCode($secret, $timeSlice = null)
8184 $ value = $ value & 0x7FFFFFFF ;
8285
8386 $ modulo = pow (10 , $ this ->_codeLength );
87+
8488 return str_pad ($ value % $ modulo , $ this ->_codeLength , '0 ' , STR_PAD_LEFT );
8589 }
8690
8791 /**
88- * Get QR-Code URL for image, from google charts
92+ * Get QR-Code URL for image, from google charts.
8993 *
9094 * @param string $name
9195 * @param string $secret
9296 * @param string $title
93- * @param array $params
97+ * @param array $params
98+ *
9499 * @return string
95100 */
96- public function getQRCodeGoogleUrl ($ name , $ secret , $ title = null , $ params = array ()) {
97- $ width = !empty ($ params ['width ' ]) && (int )$ params ['width ' ] > 0 ? (int )$ params ['width ' ] : 200 ;
98- $ height = !empty ($ params ['height ' ]) && (int )$ params ['height ' ] > 0 ? (int )$ params ['height ' ] : 200 ;
101+ public function getQRCodeGoogleUrl ($ name , $ secret , $ title = null , $ params = array ())
102+ {
103+ $ width = !empty ($ params ['width ' ]) && (int ) $ params ['width ' ] > 0 ? (int ) $ params ['width ' ] : 200 ;
104+ $ height = !empty ($ params ['height ' ]) && (int ) $ params ['height ' ] > 0 ? (int ) $ params ['height ' ] : 200 ;
99105 $ level = !empty ($ params ['level ' ]) && array_search ($ params ['level ' ], array ('L ' , 'M ' , 'Q ' , 'H ' )) !== false ? $ params ['level ' ] : 'M ' ;
100106
101107 $ urlencoded = urlencode ('otpauth://totp/ ' .$ name .'?secret= ' .$ secret .'' );
102- if (isset ($ title )) {
103- $ urlencoded .= urlencode ('&issuer= ' .urlencode ($ title ));
108+ if (isset ($ title )) {
109+ $ urlencoded .= urlencode ('&issuer= ' .urlencode ($ title ));
104110 }
111+
105112 return 'https://chart.googleapis.com/chart?chs= ' .$ width .'x ' .$ height .'&chld= ' .$ level .'|0&cht=qr&chl= ' .$ urlencoded .'' ;
106113 }
107114
108115 /**
109- * Check if the code is correct. This will accept codes starting from $discrepancy*30sec ago to $discrepancy*30sec from now
116+ * Check if the code is correct. This will accept codes starting from $discrepancy*30sec ago to $discrepancy*30sec from now.
110117 *
111- * @param string $secret
112- * @param string $code
113- * @param int $discrepancy This is the allowed time drift in 30 second units (8 means 4 minutes before or after)
118+ * @param string $secret
119+ * @param string $code
120+ * @param int $discrepancy This is the allowed time drift in 30 second units (8 means 4 minutes before or after)
114121 * @param int|null $currentTimeSlice time slice if we want use other that time()
122+ *
115123 * @return bool
116124 */
117125 public function verifyCode ($ secret , $ code , $ discrepancy = 1 , $ currentTimeSlice = null )
@@ -124,7 +132,7 @@ public function verifyCode($secret, $code, $discrepancy = 1, $currentTimeSlice =
124132 return false ;
125133 }
126134
127- for ($ i = -$ discrepancy ; $ i <= $ discrepancy ; $ i ++ ) {
135+ for ($ i = -$ discrepancy ; $ i <= $ discrepancy ; ++ $ i ) {
128136 $ calculatedCode = $ this ->getCode ($ secret , $ currentTimeSlice + $ i );
129137 if ($ this ->timingSafeEquals ($ calculatedCode , $ code )) {
130138 return true ;
@@ -135,56 +143,68 @@ public function verifyCode($secret, $code, $discrepancy = 1, $currentTimeSlice =
135143 }
136144
137145 /**
138- * Set the code length, should be >=6
146+ * Set the code length, should be >=6.
139147 *
140148 * @param int $length
149+ *
141150 * @return PHPGangsta_GoogleAuthenticator
142151 */
143152 public function setCodeLength ($ length )
144153 {
145154 $ this ->_codeLength = $ length ;
155+
146156 return $ this ;
147157 }
148158
149159 /**
150- * Helper class to decode base32
160+ * Helper class to decode base32.
151161 *
152162 * @param $secret
163+ *
153164 * @return bool|string
154165 */
155166 protected function _base32Decode ($ secret )
156167 {
157- if (empty ($ secret )) return '' ;
168+ if (empty ($ secret )) {
169+ return '' ;
170+ }
158171
159172 $ base32chars = $ this ->_getBase32LookupTable ();
160173 $ base32charsFlipped = array_flip ($ base32chars );
161174
162175 $ paddingCharCount = substr_count ($ secret , $ base32chars [32 ]);
163176 $ allowedValues = array (6 , 4 , 3 , 1 , 0 );
164- if (!in_array ($ paddingCharCount , $ allowedValues )) return false ;
165- for ($ i = 0 ; $ i < 4 ; $ i ++){
177+ if (!in_array ($ paddingCharCount , $ allowedValues )) {
178+ return false ;
179+ }
180+ for ($ i = 0 ; $ i < 4 ; ++$ i ) {
166181 if ($ paddingCharCount == $ allowedValues [$ i ] &&
167- substr ($ secret , -($ allowedValues [$ i ])) != str_repeat ($ base32chars [32 ], $ allowedValues [$ i ])) return false ;
182+ substr ($ secret , -($ allowedValues [$ i ])) != str_repeat ($ base32chars [32 ], $ allowedValues [$ i ])) {
183+ return false ;
184+ }
168185 }
169- $ secret = str_replace ('= ' ,'' , $ secret );
186+ $ secret = str_replace ('= ' , '' , $ secret );
170187 $ secret = str_split ($ secret );
171- $ binaryString = "" ;
172- for ($ i = 0 ; $ i < count ($ secret ); $ i = $ i +8 ) {
173- $ x = "" ;
174- if (!in_array ($ secret [$ i ], $ base32chars )) return false ;
175- for ($ j = 0 ; $ j < 8 ; $ j ++) {
188+ $ binaryString = '' ;
189+ for ($ i = 0 ; $ i < count ($ secret ); $ i = $ i + 8 ) {
190+ $ x = '' ;
191+ if (!in_array ($ secret [$ i ], $ base32chars )) {
192+ return false ;
193+ }
194+ for ($ j = 0 ; $ j < 8 ; ++$ j ) {
176195 $ x .= str_pad (base_convert (@$ base32charsFlipped [@$ secret [$ i + $ j ]], 10 , 2 ), 5 , '0 ' , STR_PAD_LEFT );
177196 }
178197 $ eightBits = str_split ($ x , 8 );
179- for ($ z = 0 ; $ z < count ($ eightBits ); $ z ++ ) {
180- $ binaryString .= ( ($ y = chr (base_convert ($ eightBits [$ z ], 2 , 10 ))) || ord ($ y ) == 48 ) ? $ y: "" ;
198+ for ($ z = 0 ; $ z < count ($ eightBits ); ++ $ z ) {
199+ $ binaryString .= (($ y = chr (base_convert ($ eightBits [$ z ], 2 , 10 ))) || ord ($ y ) == 48 ) ? $ y : '' ;
181200 }
182201 }
202+
183203 return $ binaryString ;
184204 }
185205
186206 /**
187- * Get array with all 32 characters for decoding from/encoding to base32
207+ * Get array with all 32 characters for decoding from/encoding to base32.
188208 *
189209 * @return array
190210 */
@@ -195,18 +215,18 @@ protected function _getBase32LookupTable()
195215 'I ' , 'J ' , 'K ' , 'L ' , 'M ' , 'N ' , 'O ' , 'P ' , // 15
196216 'Q ' , 'R ' , 'S ' , 'T ' , 'U ' , 'V ' , 'W ' , 'X ' , // 23
197217 'Y ' , 'Z ' , '2 ' , '3 ' , '4 ' , '5 ' , '6 ' , '7 ' , // 31
198- '= ' // padding char
218+ '= ' , // padding char
199219 );
200220 }
201221
202222 /**
203223 * A timing safe equals comparison
204- * more info here: http://blog.ircmaxell.com/2014/11/its-all-about-time.html
224+ * more info here: http://blog.ircmaxell.com/2014/11/its-all-about-time.html.
205225 *
206226 * @param string $safeString The internal (safe) value to be checked
207227 * @param string $userString The user submitted (unsafe) value
208228 *
209- * @return boolean True if the two strings are identical.
229+ * @return bool True if the two strings are identical
210230 */
211231 private function timingSafeEquals ($ safeString , $ userString )
212232 {
@@ -222,7 +242,7 @@ private function timingSafeEquals($safeString, $userString)
222242
223243 $ result = 0 ;
224244
225- for ($ i = 0 ; $ i < $ userLen ; $ i ++ ) {
245+ for ($ i = 0 ; $ i < $ userLen ; ++ $ i ) {
226246 $ result |= (ord ($ safeString [$ i ]) ^ ord ($ userString [$ i ]));
227247 }
228248
0 commit comments