Files
michaelschiemer/tests/debug/test-syndrome-deep-dive.php
Michael Schiemer 95147ff23e refactor(deployment): Remove WireGuard VPN dependency and restore public service access
Remove WireGuard integration from production deployment to simplify infrastructure:
- Remove docker-compose-direct-access.yml (VPN-bound services)
- Remove VPN-only middlewares from Grafana, Prometheus, Portainer
- Remove WireGuard middleware definitions from Traefik
- Remove WireGuard IPs (10.8.0.0/24) from Traefik forwarded headers

All monitoring services now publicly accessible via subdomains:
- grafana.michaelschiemer.de (with Grafana native auth)
- prometheus.michaelschiemer.de (with Basic Auth)
- portainer.michaelschiemer.de (with Portainer native auth)

All services use Let's Encrypt SSL certificates via Traefik.
2025-11-05 12:48:25 +01:00

153 lines
5.4 KiB
PHP
Raw Permalink Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
<?php
declare(strict_types=1);
require_once __DIR__ . '/../../vendor/autoload.php';
use App\Framework\QrCode\ErrorCorrection\ReedSolomonEncoder;
echo "=== Deep Dive: Syndrome Calculation ===\n\n";
// We know the RS encoding is correct, so let's understand why syndromes aren't zero
// Reference data and EC codewords
$data = [64, 180, 132, 84, 196, 196, 242, 5, 116, 245, 174, 59, 64, 109, 236, 233];
$ec = [0, 245, 228, 127, 21, 207, 194, 102, 66, 52];
echo "Reference data codewords: " . implode(', ', $data) . "\n";
echo "Reference EC codewords: " . implode(', ', $ec) . "\n\n";
// Initialize GF(256)
$gfLog = array_fill(0, 256, 0);
$gfExp = array_fill(0, 512, 0);
$x = 1;
for ($i = 0; $i < 255; $i++) {
$gfExp[$i] = $x;
$gfLog[$x] = $i;
$x <<= 1;
if ($x & 0x100) {
$x ^= 0x11d;
}
}
for ($i = 255; $i < 512; $i++) {
$gfExp[$i] = $gfExp[$i - 255];
}
function gfMult(array $gfExp, array $gfLog, int $a, int $b): int
{
if ($a === 0 || $b === 0) return 0;
return $gfExp[$gfLog[$a] + $gfLog[$b]];
}
// Get generator polynomial
$rs = new ReedSolomonEncoder();
$reflection = new \ReflectionClass($rs);
$getGeneratorMethod = $reflection->getMethod('getGeneratorPolynomial');
$getGeneratorMethod->setAccessible(true);
$generator = $getGeneratorMethod->invoke($rs, 10);
echo "Generator polynomial: " . implode(', ', $generator) . "\n";
echo "This represents: g(x) = (x - α^0)(x - α^1)...(x - α^9)\n";
echo "The roots are: α^0, α^1, ..., α^9\n\n";
// For a valid RS codeword, when we evaluate the codeword polynomial at the generator roots,
// we should get zero. But the question is: what is the codeword polynomial representation?
// In QR codes, codewords are placed in a specific order. Let's check if the order matters.
$fullCodeword = array_merge($data, $ec);
echo "Full codeword (26 bytes): " . implode(', ', $fullCodeword) . "\n\n";
// Test 1: Standard RS polynomial representation
// c(x) = c[0] + c[1]*x + c[2]*x^2 + ... + c[n-1]*x^(n-1)
// where c[0] is the first codeword (data[0])
echo "=== Test 1: Standard RS Polynomial (c[0] is lowest power) ===\n";
$syndromes1 = [];
for ($i = 0; $i < 10; $i++) {
$alphaPower = $gfExp[$i];
$syndrome = 0;
$power = 1; // x^0 = 1
for ($j = 0; $j < count($fullCodeword); $j++) {
$syndrome ^= gfMult($gfExp, $gfLog, $fullCodeword[$j], $power);
$power = gfMult($gfExp, $gfLog, $power, $alphaPower);
}
$syndromes1[$i] = $syndrome;
}
echo "Syndromes: " . implode(', ', $syndromes1) . "\n";
echo "All zero: " . (array_sum($syndromes1) === 0 ? "" : "") . "\n\n";
// Test 2: Reversed polynomial (MSB-first)
// c(x) = c[0]*x^(n-1) + c[1]*x^(n-2) + ... + c[n-1]
// This is how QR codes typically represent polynomials
$n = count($fullCodeword);
echo "=== Test 2: Reversed Polynomial (c[0] is highest power) ===\n";
$syndromes2 = [];
for ($i = 0; $i < 10; $i++) {
$alphaPower = $gfExp[$i];
$syndrome = 0;
// Start with x^(n-1) evaluated at α^i
$power = $gfExp[($i * ($n - 1)) % 255];
for ($j = 0; $j < $n; $j++) {
$syndrome ^= gfMult($gfExp, $gfLog, $fullCodeword[$j], $power);
// Divide by α^i (multiply by α^(255-i))
$power = gfMult($gfExp, $gfLog, $power, $gfExp[255 - $i]);
}
$syndromes2[$i] = $syndrome;
}
echo "Syndromes: " . implode(', ', $syndromes2) . "\n";
echo "All zero: " . (array_sum($syndromes2) === 0 ? "" : "") . "\n\n";
// Test 3: Maybe the generator polynomial roots are different?
// In some RS implementations, the generator is g(x) = (x - α^1)(x - α^2)...(x - α^t)
// instead of (x - α^0)(x - α^1)...(x - α^(t-1))
echo "=== Test 3: Shifted Generator Roots (α^1 to α^10) ===\n";
$syndromes3 = [];
for ($i = 1; $i <= 10; $i++) {
$alphaPower = $gfExp[$i];
$syndrome = 0;
$power = 1;
for ($j = 0; $j < count($fullCodeword); $j++) {
$syndrome ^= gfMult($gfExp, $gfLog, $fullCodeword[$j], $power);
$power = gfMult($gfExp, $gfLog, $power, $alphaPower);
}
$syndromes3[$i - 1] = $syndrome;
}
echo "Syndromes: " . implode(', ', $syndromes3) . "\n";
echo "All zero: " . (array_sum($syndromes3) === 0 ? "" : "") . "\n\n";
// Test 4: Maybe we need to reverse the codeword array?
echo "=== Test 4: Reversed Codeword Array ===\n";
$reversedCodeword = array_reverse($fullCodeword);
$syndromes4 = [];
for ($i = 0; $i < 10; $i++) {
$alphaPower = $gfExp[$i];
$syndrome = 0;
$power = 1;
for ($j = 0; $j < count($reversedCodeword); $j++) {
$syndrome ^= gfMult($gfExp, $gfLog, $reversedCodeword[$j], $power);
$power = gfMult($gfExp, $gfLog, $power, $alphaPower);
}
$syndromes4[$i] = $syndrome;
}
echo "Syndromes: " . implode(', ', $syndromes4) . "\n";
echo "All zero: " . (array_sum($syndromes4) === 0 ? "" : "") . "\n\n";
// Test 5: Verify our encoding produces valid codewords
echo "=== Test 5: Verify Our Encoding ===\n";
$ourEC = $rs->encode($data, 10);
if ($ourEC === $ec) {
echo "✅ Our encoding matches reference EC codewords!\n";
echo "This confirms Reed-Solomon encoding is CORRECT.\n\n";
echo "Conclusion:\n";
echo "The syndrome calculation might use a different polynomial representation\n";
echo "or evaluation method than standard RS. However, since the EC codewords\n";
echo "are correct and match the reference, the QR code should work correctly.\n";
echo "The syndrome calculation is primarily for debugging/validation purposes.\n";
} else {
echo "❌ Our encoding doesn't match!\n";
}