Skip to content

Commit ea3c06d

Browse files
authored
fix: complete transport pool and deterministic generation in SimpleFakeCredentialGenerator (#823)
* fix: use all transport types and deterministic generation in SimpleFakeCredentialGenerator Include hybrid, internal and smart-card transports in the fake credential pool so generated credentials are indistinguishable from real ones. Replace random generation with a deterministic HMAC-based seed derived from the username and a server secret, ensuring stable responses across requests without relying on cache. * fix: inject cache service into SimpleFakeCredentialGenerator Use CacheItemPoolInterface with nullOnInvalid() instead of hardcoded null so the cache is actually used when available in the container. * fix: inject cache service into SimpleFakeCredentialGenerator and fix coding standards Use CacheItemPoolInterface with nullOnInvalid() instead of hardcoded null so the cache is actually used when available in the container. Apply coding standards fixes across the codebase. * Refactor: Clean up imports and remove duplicates across denormalizer and service classes - Removed duplicate function imports and organized them in multiple denormalizer classes including CredentialRecordDenormalizer, ExtensionDescriptorDenormalizer, and others. - Ensured consistent use of function imports such as `array_key_exists`, `assert`, `count`, and `in_array`. - Updated import statements in various service classes like DistantResourceMetadataService, FidoAllianceCompliantMetadataService, and others for better clarity and maintainability. - Cleaned up unused imports in test files and ensured proper organization of function imports.
1 parent 7bdf75d commit ea3c06d

File tree

2 files changed

+23
-10
lines changed

2 files changed

+23
-10
lines changed

src/symfony/src/Resources/config/services.php

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@
22

33
declare(strict_types=1);
44

5+
use Psr\Cache\CacheItemPoolInterface;
56
use Psr\Log\NullLogger;
67
use Symfony\Component\Clock\NativeClock;
78
use Symfony\Component\DependencyInjection\Loader\Configurator\ContainerConfigurator;
@@ -82,7 +83,9 @@
8283
->factory([service(CeremonyStepManagerFactory::class), 'conditionalCreateCeremony'])
8384
;
8485

85-
$service->set(SimpleFakeCredentialGenerator::class);
86+
$service->set(SimpleFakeCredentialGenerator::class)
87+
->args([service(CacheItemPoolInterface::class)->nullOnInvalid(), param('kernel.secret')])
88+
;
8689

8790
$service
8891
->set('webauthn.ceremony_step_manager.request')

src/webauthn/src/SimpleFakeCredentialGenerator.php

Lines changed: 19 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -5,14 +5,15 @@
55
namespace Webauthn;
66

77
use function count;
8-
use function is_int;
8+
use function ord;
99
use Psr\Cache\CacheItemPoolInterface;
1010
use Symfony\Component\HttpFoundation\Request;
1111

1212
final readonly class SimpleFakeCredentialGenerator implements FakeCredentialGenerator
1313
{
1414
public function __construct(
15-
private null|CacheItemPoolInterface $cache = null
15+
private null|CacheItemPoolInterface $cache = null,
16+
private string $secret = '',
1617
) {
1718
}
1819

@@ -48,18 +49,27 @@ private function generateCredentials(string $username): array
4849
PublicKeyCredentialDescriptor::AUTHENTICATOR_TRANSPORT_USB,
4950
PublicKeyCredentialDescriptor::AUTHENTICATOR_TRANSPORT_NFC,
5051
PublicKeyCredentialDescriptor::AUTHENTICATOR_TRANSPORT_BLE,
52+
PublicKeyCredentialDescriptor::AUTHENTICATOR_TRANSPORT_HYBRID,
53+
PublicKeyCredentialDescriptor::AUTHENTICATOR_TRANSPORT_INTERNAL,
54+
PublicKeyCredentialDescriptor::AUTHENTICATOR_TRANSPORT_SMART_CARD,
5155
];
56+
$seed = hash('sha256', $username . $this->secret, true);
57+
$count = (ord($seed[0]) % 3) + 1;
58+
5259
$credentials = [];
53-
for ($i = 0; $i < random_int(1, 3); $i++) {
54-
$randomTransportKeys = array_rand($transports, random_int(1, count($transports)));
55-
if (is_int($randomTransportKeys)) {
56-
$randomTransportKeys = [$randomTransportKeys];
60+
for ($i = 0; $i < $count; $i++) {
61+
$credSeed = hash('sha256', $seed . pack('N', $i), true);
62+
$transportCount = (ord($credSeed[0]) % 2) + 1;
63+
$selectedTransports = [];
64+
for ($j = 0; $j < $transportCount; $j++) {
65+
$index = ord($credSeed[$j + 1]) % count($transports);
66+
$selectedTransports[] = $transports[$index];
5767
}
58-
$randomTransports = array_values(array_intersect_key($transports, array_flip($randomTransportKeys)));
68+
$selectedTransports = array_values(array_unique($selectedTransports));
5969
$credentials[] = PublicKeyCredentialDescriptor::create(
6070
PublicKeyCredentialDescriptor::CREDENTIAL_TYPE_PUBLIC_KEY,
61-
hash('sha256', random_bytes(16) . $username),
62-
$randomTransports
71+
hash('sha256', $credSeed . $username),
72+
$selectedTransports
6373
);
6474
}
6575

0 commit comments

Comments
 (0)