Add Base32 decoding method and implement SecretOtp class with serialization methods
Some checks are pending
CI / release (push) Waiting to run
CI / debug (push) Waiting to run
CI / release_executable (push) Waiting to run
CI / debug_executable (push) Waiting to run
CI / check-phpunit (push) Waiting to run
CI / check-phpdoc (push) Waiting to run
CI / generate-phpdoc (push) Blocked by required conditions
CI / test (push) Blocked by required conditions
CI / release-documentation (push) Blocked by required conditions
CI / release-artifacts (push) Blocked by required conditions

This commit is contained in:
netkas 2025-03-27 14:09:56 -04:00
parent b6aa591f8c
commit 200b6a7c1f
Signed by: netkas
GPG key ID: 4D8629441B76E4CC
3 changed files with 83 additions and 2 deletions

View file

@ -0,0 +1,26 @@
<?php
namespace Socialbox\Objects\Standard;
use Socialbox\Interfaces\SerializableInterface;
class SecretOtp implements SerializableInterface
{
/**
* @inheritDoc
*/
public static function fromArray(array $data): object
{
// TODO: Implement fromArray() method.
}
/**
* @inheritDoc
*/
public function toArray(): array
{
// TODO: Implement toArray() method.
}
}

View file

@ -106,4 +106,33 @@
{ {
return new SocialClient(self::generateRandomPeer($domain, $length, $prefix)); return new SocialClient(self::generateRandomPeer($domain, $length, $prefix));
} }
/**
* Encodes a string to Base32.
*
* @param string $input The string to be encoded.
* @return string Returns the encoded string.
*/
public static function decodeBase32(string $input): string
{
$input = strtoupper($input);
$v = 0;
$k = 0;
$chars = 'ABCDEFGHIJKLMNOPQRSTUVWXYZ234567';
$output = '';
for ($i = 0; $i < strlen($input); $i++)
{
$v = ($v << 5) | strpos($chars, $input[$i]);
$k += 5;
if ($k >= 8)
{
$k -= 8;
$output .= chr(($v >> $k) & 0xFF);
}
}
return $output;
}
} }

View file

@ -4,6 +4,7 @@
use Helper; use Helper;
use PHPUnit\Framework\TestCase; use PHPUnit\Framework\TestCase;
use Socialbox\Classes\OtpCryptography;
use Socialbox\Enums\Flags\SessionFlags; use Socialbox\Enums\Flags\SessionFlags;
use Socialbox\Enums\PrivacyState; use Socialbox\Enums\PrivacyState;
use Socialbox\Enums\Types\InformationFieldName; use Socialbox\Enums\Types\InformationFieldName;
@ -545,11 +546,36 @@
$this->assertTrue($testClient->settingsSetPassword('SecretTestingPassword123')); $this->assertTrue($testClient->settingsSetPassword('SecretTestingPassword123'));
$this->assertTrue($testClient->getSessionState()->isAuthenticated()); $this->assertTrue($testClient->getSessionState()->isAuthenticated());
$secret = $testClient->settingsSetOtp('SecretTestingPassword123'); $totpUri = $testClient->settingsSetOtp('SecretTestingPassword123');
$this->assertNotEmpty($secret); $this->assertNotEmpty($totpUri);
$testClient = new SocialClient($testAddress); $testClient = new SocialClient($testAddress);
$this->assertFalse($testClient->getSessionState()->isAuthenticated()); $this->assertFalse($testClient->getSessionState()->isAuthenticated());
$this->assertTrue($testClient->getSessionState()->containsFlag(SessionFlags::VER_OTP)); $this->assertTrue($testClient->getSessionState()->containsFlag(SessionFlags::VER_OTP));
$this->assertTrue($testClient->getSessionState()->containsFlag(SessionFlags::VER_PASSWORD));
$this->assertTrue($testClient->verificationPasswordAuthentication('SecretTestingPassword123'));
// Parse the TOTP URI
$parsedUri = parse_url($totpUri);
parse_str($parsedUri['query'], $queryParams);
// Extract secret and other parameters
$secret = $queryParams['secret'];
$algorithm = strtolower(str_replace('SHA', 'sha', $queryParams['algorithm'] ?? 'sha512'));
$digits = (int)($queryParams['digits'] ?? 6);
$period = (int)($queryParams['period'] ?? 30);
// Generate the OTP
$otp = OtpCryptography::generateOTP(
$secret,
$period,
$digits,
null,
$algorithm
);
// Verify the OTP
$this->assertTrue($testClient->verificationOtpAuthentication($otp));
} }
} }