Last active
January 11, 2022 03:04
-
-
Save rwaddin/b20204e372038393db00cb7ac57b34bf to your computer and use it in GitHub Desktop.
this script for generate code to tblclients field authdata. for verify token 2 FA whmcs. This is not clean code just example base on sistem verify whmcs.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
<?php | |
$kd_manual = createBase32Key(); | |
$tokenkey = helperb322hex($kd_manual); | |
$qrcode = helperhex2b32($tokenkey); | |
$backupcode = "123456789012345"; | |
$init = [ | |
"tokenkey" => $tokenkey, | |
"tokentype" => "TOTP", | |
"tokentimer" => 30, | |
"tokencounter" => 1, | |
"tokenalgorithm" => "SHA1", | |
"user" => "" | |
]; | |
$step2 = serialize($init); | |
$step3 = base64_encode($step2); | |
$step4 = [ | |
"tokendata" => $step3, | |
"backupcode" => sha1($backupcode) | |
]; | |
$step5 = serialize($step4); | |
?> | |
<!DOCTYPE html> | |
<html> | |
<head> | |
<meta charset="utf-8"> | |
<meta name="viewport" content="width=device-width, initial-scale=1"> | |
<title>Generate manual 2FA WHMCS</title> | |
<!-- <link rel="stylesheet" href="https://maxcdn.bootstrapcdn.com/bootstrap/3.4.1/css/bootstrap.min.css"> --> | |
<link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/bootstrap@4.6.1/dist/css/bootstrap.min.css"> | |
<style> | |
.card-header{ | |
color: white; | |
font-weight: bold; | |
} | |
</style> | |
</head> | |
<body> | |
<div class="container" style="margin-top: 4%;"> | |
<table class="table table-striped"> | |
<tr> | |
<td>Kode jika tambah manual tidak scan qrcode </td> | |
<td>:</td> | |
<td><?php echo $kd_manual ?></td> | |
</tr> | |
<tr> | |
<td>Token key for the database</td> | |
<td>:</td> | |
<td><?php echo $tokenkey ?></td> | |
</tr> | |
<tr> | |
<td>qrcode</td> | |
<td>:</td> | |
<td>otpauth://totp/companyName:user@mail.com?secret=<?php echo $qrcode ?></td> | |
</tr> | |
<tr> | |
<td>backupcode</td> | |
<td>:</td> | |
<td><?php echo $backupcode ?></td> | |
</tr> | |
</table> | |
<h1 class="text-center alert alert-info">Generate code : </h1> | |
<div class="row"> | |
<div class="col-sm-4"> | |
<div class="card shadow"> | |
<div class="card-header bg-success"> | |
1 : init | |
</div> | |
<div class="card-body"> | |
<?php print_r($init) ?> | |
</div> | |
</div> | |
</div> | |
<div class="col-sm-4"> | |
<div class="card shadow"> | |
<div class="card-header bg-warning">2 : serialize</div> | |
<div class="card-body"> | |
<p style="word-break: break-word;"> | |
<?= $step2 ?> | |
</p> | |
</div> | |
</div> | |
</div> | |
<div class="col-sm-4"> | |
<div class="card shadow"> | |
<div class="card-header bg-info">3 base 64encode</div> | |
<div class="card-body"> | |
<div style="word-break: break-word;"> | |
<?= $step3 ?> | |
</div> | |
</div> | |
</div> | |
</div> | |
<div class="col-sm-4"> | |
<div class="card shadow"> | |
<div class="card-header bg-danger">4 merge</div> | |
<div class="card-body"> | |
<div style="word-break: break-word;"> | |
<?php print_r($step4) ?> | |
</div> | |
</div> | |
</div> | |
</div> | |
<div class="col-sm-4"> | |
<div class="card shadow"> | |
<div class="card-header bg-primary">5 finish</div> | |
<div class="card-body"> | |
<p class="badge badge-info">Copy below to authdata field</p> | |
<div style="word-break: break-word;"> | |
<?= $step5 ?> | |
</div> | |
</div> | |
</div> | |
</div> | |
</div> | |
</div> | |
</body> | |
</html> | |
<?php | |
function createBase32Key() | |
{ | |
$alphabet = "ABCDEFGHIJKLMNOPQRSTUVWXYZ234567"; | |
$key = ""; | |
for ($i = 0; $i < 16; $i++) { | |
$offset = rand(0, strlen($alphabet) - 1); | |
$key .= $alphabet[$offset]; | |
} | |
return $key; | |
} | |
function helperb322hex($b32) | |
{ | |
$alphabet = "ABCDEFGHIJKLMNOPQRSTUVWXYZ234567"; | |
$out = ""; | |
$dous = ""; | |
for ($i = 0; $i < strlen($b32); $i++) { | |
$in = strrpos($alphabet, $b32[$i]); | |
$b = str_pad(base_convert($in, 10, 2), 5, "0", STR_PAD_LEFT); | |
$out .= $b; | |
$dous .= $b . "."; | |
} | |
$ar = str_split($out, 20); | |
$out2 = ""; | |
foreach ($ar as $val) { | |
$rv = str_pad(base_convert($val, 2, 16), 5, "0", STR_PAD_LEFT); | |
$out2 .= $rv; | |
} | |
return $out2; | |
} | |
function helperhex2b32($hex) | |
{ | |
$alphabet = "ABCDEFGHIJKLMNOPQRSTUVWXYZ234567"; | |
$ar = str_split($hex, 5); | |
$out = ""; | |
foreach ($ar as $var) { | |
$bc = base_convert($var, 16, 2); | |
$bin = str_pad($bc, 20, "0", STR_PAD_LEFT); | |
$out .= $bin; | |
} | |
$out2 = ""; | |
$ar2 = str_split($out, 5); | |
foreach ($ar2 as $var2) { | |
$bc = base_convert($var2, 2, 10); | |
$out2 .= $alphabet[$bc]; | |
} | |
return $out2; | |
} | |
?> |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
<?php | |
function backupCode($userid = false) | |
{ | |
$backupCode = sha1("companyname" . $userid . time()); | |
$backupCode = substr($backupCode, 0, 16); | |
$pisah = substr($backupCode, 0, 4) . " " . substr($backupCode, 4, 4) . " " . substr($backupCode, 8, 4) . " " . substr($backupCode, 12, 4); | |
return [ | |
"encrypt" => sha1($backupCode), | |
"plain" => $pisah | |
]; | |
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
<?php | |
$key = "028988"; # key show in google authenticator or other app | |
$username = "companyname"; | |
$username = "WHMCS:" . $username; | |
# in tblconfiguration setting='TOTPUsedOTPs' | |
# for check history code | |
$usedotps = []; | |
$hash = md5($username . $key); | |
if (array_key_exists($hash, $usedotps)) { | |
echo "exist : cannot use this key"; | |
}else{ | |
echo "insert to db"; | |
} | |
echo "<br>"; | |
echo $hash; | |
echo "<br>"; | |
$auth = authenticateUser($username, $key); | |
if ($auth) { | |
echo "verified"; | |
}else{ | |
echo "unverified"; | |
} | |
function authenticateUser($username, $code) | |
{ | |
if (preg_match("/[0-9][0-9][0-9][0-9][0-9][0-9]/", $code) < 1) { | |
return false; | |
} | |
$ttype = "TOTP"; | |
$tlid = 1; | |
$tkey = "a19b90d4e0e19713274e"; | |
$ttimer = 30; | |
$totpSkew = 1; | |
switch ($ttype) { | |
case "TOTP": | |
$t_now = time(); | |
$t_ear = $t_now - $totpSkew * $ttimer; | |
$t_lat = $t_now + $totpSkew * $ttimer; | |
$t_st = (int) ($t_ear / $ttimer); | |
$t_en = (int) ($t_lat / $ttimer); | |
for ($i = $t_st; $i <= $t_en; $i++) { | |
$stest = oath_hotp($tkey, $i); | |
if ($code == $stest) { | |
return true; | |
} | |
} | |
break; | |
default: | |
return false; | |
} | |
return false; | |
} | |
function oath_hotp($key, $counter) | |
{ | |
$key = pack("H*", $key); | |
$cur_counter = array(0, 0, 0, 0, 0, 0, 0, 0); | |
for ($i = 7; 0 <= $i; $i--) { | |
$cur_counter[$i] = pack("C*", $counter); | |
$counter = $counter >> 8; | |
} | |
$bin_counter = implode($cur_counter); | |
if (strlen($bin_counter) < 8) { | |
$bin_counter = str_repeat(chr(0), 8 - strlen($bin_counter)) . $bin_counter; | |
} | |
$hash = hash_hmac("sha1", $bin_counter, $key); | |
return str_pad(oath_truncate($hash), 6, "0", STR_PAD_LEFT); | |
} | |
function oath_truncate($hash, $length = 6) | |
{ | |
foreach (str_split($hash, 2) as $hex) { | |
$hmac_result[] = hexdec($hex); | |
} | |
$offset = $hmac_result[19] & 15; | |
return (($hmac_result[$offset + 0] & 127) << 24 | ($hmac_result[$offset + 1] & 255) << 16 | ($hmac_result[$offset + 2] & 255) << 8 | $hmac_result[$offset + 3] & 255) % pow(10, $length); | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
has been try in whmcs 7.7.1-release.1 and work well