<?php
// hex2dec_form.php
// Save and open in browser (requires PHP). Uses GMP if available, otherwise BCMath as fallback.

// secp256k1 order n (hex)
$n_hex = "FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFEBAAEDCE6AF48A03BBFD25E8CD0364141";

// Helpers: normalize input hex (remove 0x, whitespace, lowercase)
function normalize_hex(string $s): string {
    $s = trim($s);
    $s = preg_replace('/^0x/i', '', $s);
    $s = preg_replace('/\s+/', '', $s);
    return strtolower($s);
}

// Convert hex -> decimal using GMP
function hexToDecGmp(string $hex): string {
    $g = gmp_init($hex, 16);
    return gmp_strval($g, 10);
}

// Convert hex -> decimal using BCMath (fallback)
function hexToDecBc(string $hex): string {
    $hex = ltrim($hex, "0"); // optional small optimization
    if ($hex === '') return '0';
    $dec = '0';
    $len = strlen($hex);
    for ($i = 0; $i < $len; $i++) {
        $digit = hexdec($hex[$i]); // 0..15
        // dec = dec * 16 + digit
        $dec = bcmul($dec, '16', 0);
        $dec = bcadd($dec, (string)$digit, 0);
    }
    return $dec;
}

// Convert hex -> binary string (bits)
function hexToBinString(string $hex): string {
    $hex = preg_replace('/^0x/i', '', $hex);
    $bin = '';
    $len = strlen($hex);
    // ensure even length
    if ($len % 2 !== 0) $hex = '0' . $hex;
    $len = strlen($hex);
    for ($i = 0; $i < $len; $i += 2) {
        $byteHex = substr($hex, $i, 2);
        $b = hexdec($byteHex);
        $bin .= str_pad(decbin($b), 8, '0', STR_PAD_LEFT);
    }
    return $bin;
}

// Compare using GMP if available, else BCMath
function compareDecStrings(string $a_dec, string $b_dec): int {
    if (extension_loaded('gmp')) {
        $ga = gmp_init($a_dec, 10);
        $gb = gmp_init($b_dec, 10);
        return gmp_cmp($ga, $gb); // <0,0,>0
    } else {
        // bccomp returns -1,0,1
        return bccomp($a_dec, $b_dec, 0);
    }
}

// Convert hex->dec choosing backend
function hexToDecimal(string $hex): array {
    // return ['dec' => '...', 'backend' => 'GMP'|'BCMath']
    if (extension_loaded('gmp')) {
        return ['dec' => hexToDecGmp($hex), 'backend' => 'GMP'];
    } elseif (extension_loaded('bcmath')) {
        return ['dec' => hexToDecBc($hex), 'backend' => 'BCMath'];
    } else {
        throw new Exception("Server missing GMP and BCMath extensions. Enable one of them.");
    }
}

// Process form
$errors = [];
$result = null;
$input_raw = $_POST['priv_hex'] ?? '';

if ($_SERVER['REQUEST_METHOD'] === 'POST') {
    $hex = normalize_hex($input_raw);

    if ($hex === '') {
        $errors[] = "پرایویت‌کی وارد نشده است.";
    } elseif (!preg_match('/^[0-9a-f]+$/', $hex)) {
        $errors[] = "پرایویت‌کی شامل کاراکترهای غیرمجاز است. فقط 0-9 و a-f مجاز است.";
    } else {
        // pad to even length
        if (strlen($hex) % 2 !== 0) $hex = '0' . $hex;

        try {
            $decData = hexToDecimal($hex);
            $dec = $decData['dec'];
            $backend = $decData['backend'];

            // binary string
            $bin = hexToBinString($hex);

            // sizes
            $hexLen = strlen($hex);
            $bytes = (int)($hexLen / 2);
            $bits = strlen($bin);

            // prepare secp256k1 order n decimal
            if (extension_loaded('gmp')) {
                $n_dec = gmp_strval(gmp_init($GLOBALS['n_hex'], 16), 10);
            } else {
                $n_dec = hexToDecBc($GLOBALS['n_hex']);
            }

            // Check 1 <= d <= n-1
            $one = '1';
            $n_minus_1 = null;
            if (extension_loaded('gmp')) {
                $g_n = gmp_init($GLOBALS['n_hex'], 16);
                $g_nm1 = gmp_sub($g_n, 1);
                $n_minus_1 = gmp_strval($g_nm1, 10);
            } else {
                $n_minus_1 = bcsub($n_dec, '1', 0);
            }

            $ge1 = compareDecStrings($dec, $one) >= 0;
            $leN1 = compareDecStrings($dec, $n_minus_1) <= 0;

            $in_range = ($ge1 && $leN1);

            // Build result array
            $result = [
                'hex' => $hex,
                'dec' => $dec,
                'backend' => $backend,
                'bytes' => $bytes,
                'bits' => $bits,
                'bin' => $bin,
                'n_dec' => $n_dec,
                'n_minus_1' => $n_minus_1,
                'in_range' => $in_range,
            ];
        } catch (Exception $ex) {
            $errors[] = "خطا: " . $ex->getMessage();
        }
    }
}
?>
<!doctype html>
<html lang="fa" dir="rtl">
<head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width,initial-scale=1">
<title>تبدیل Private Key (hex) → عدد (decimal)</title>
<style>
    body{font-family:Tahoma,Arial;background:#f7f9fb;color:#111;padding:20px}
    .container{max-width:900px;margin:12px auto;background:#fff;padding:18px;border-radius:8px;box-shadow:0 6px 18px rgba(0,0,0,0.06)}
    h1{margin-top:0;font-size:20px}
    input[type=text], textarea{width:100%;padding:10px;border:1px solid #ddd;border-radius:6px;font-family:monospace}
    .row{display:flex;gap:12px;flex-wrap:wrap}
    .col{flex:1 1 300px}
    .btn{display:inline-block;padding:10px 14px;background:#0b79d0;color:#fff;border-radius:6px;text-decoration:none;border:none;cursor:pointer}
    .warn{background:#fff4e5;border-left:4px solid #ffb020;padding:10px;margin:10px 0;border-radius:4px}
    pre{background:#0f1724;color:#d7e9ff;padding:12px;border-radius:6px;overflow:auto}
    .ok{color:green;font-weight:bold}
    .bad{color:red;font-weight:bold}
    .small{font-size:13px;color:#666}
</style>
</head>
<body>
<div class="container">
    <h1>تبدیل Private Key (hex) به عدد (decimal)</h1>

    <div class="warn">
        <div class="small">
            ⚠️ هشدار امنیتی: هیچ‌گاه پرایویت‌کی واقعی‌تان را در محیط‌های عمومی یا سرورهای غیرقابل اعتماد قرار ندهید.
            فقط برای تست از کلیدهای نمونه استفاده کنید.
        </div>
    </div>

    <?php if ($errors): ?>
        <div style="background:#ffecec;border-left:4px solid #f44336;padding:10px;border-radius:4px;margin-bottom:12px">
            <strong>خطا:</strong>
            <ul>
                <?php foreach ($errors as $e): ?><li><?php echo htmlspecialchars($e); ?></li><?php endforeach; ?>
            </ul>
        </div>
    <?php endif; ?>

    <form method="post" autocomplete="off">
        <label>پرایویت‌کی (hex) — با یا بدون 0x:</label>
        <input type="text" name="priv_hex" placeholder="مثال: 0x1E99... یا 1e99..." value="<?php echo htmlspecialchars($input_raw); ?>" autofocus>
        <div style="margin-top:10px">
            <button class="btn" type="submit">تبدیل کن</button>
            <button class="btn" type="button" onclick="document.querySelector('input[name=priv_hex]').value='0x1E99423A4ED27608A15A2616F8E1F66C28268C9D6B4E8BDE5A18E73A19D6F5F9';">قرار دادن مثال</button>
        </div>
    </form>

    <?php if ($result): ?>
        <hr>
        <h2>نتیجه</h2>

        <div class="row">
            <div class="col">
                <label>Hex (نرمال‌شده):</label>
                <pre id="outHex"><?php echo htmlspecialchars($result['hex']); ?></pre>
            </div>
            <div class="col">
                <label>طول:</label>
                <pre>هگز: <?php echo strlen($result['hex']); ?> کاراکتر
بایت: <?php echo $result['bytes']; ?> بایت
بیت: <?php echo $result['bits']; ?> بیت
</pre>
            </div>
        </div>

        <div style="margin-top:12px" class="row">
            <div class="col">
                <label>Decimal (base 10) — backend: <?php echo htmlspecialchars($result['backend']); ?></label>
                <pre id="outDec"><?php echo htmlspecialchars($result['dec']); ?></pre>
                <button class="btn" onclick="copyToClipboard('#outDec')">کپی عدد دهدهی</button>
            </div>

            <div class="col">
                <label>مقایسه با order of secp256k1 (n):</label>
                <pre>
n (hex): <?php echo $n_hex; ?>

n (decimal): <?php echo htmlspecialchars($result['n_dec']); ?>

n-1 (decimal): <?php echo htmlspecialchars($result['n_minus_1']); ?>

در بازهٔ معتبر 1 .. n-1 ؟
<?php if ($result['in_range']): ?>
    <span class="ok">بله — مقدار در بازهٔ معتبر است ✅</span>
<?php else: ?>
    <span class="bad">خیر — مقدار خارج از بازهٔ معتبر است ❌</span>
<?php endif; ?>
                </pre>
            </div>
        </div>

        <div style="margin-top:12px">
            <label>Binary (نمایش — فقط برای بررسی؛ طول طولانی است):</label>
            <pre style="max-height:220px;white-space:pre-wrap"><?php
                // show first 128 bits and last 128 bits to avoid huge output
                $bin = $result['bin'];
                $showFirst = 128;
                $showLast = 128;
                if (strlen($bin) <= ($showFirst + $showLast + 32)) {
                    echo $bin;
                } else {
                    echo substr($bin, 0, $showFirst) . "\n...\n" . substr($bin, -$showLast);
                }
            ?></pre>
        </div>

    <?php endif; ?>

    <hr>
    <div class="small">
        توضیحات: این ابزار فقط نمایش عددی را انجام می‌دهد — برای ساخت کلید عمومی یا آدرس نیاز به عملیات منحنی بیضوی (ECDSA/secp256k1) و هش Keccak دارد که این صفحه آنها را انجام نمی‌دهد.
    </div>
</div>

<script>
function copyToClipboard(selector) {
    const el = document.querySelector(selector);
    if (!el) return;
    const text = el.innerText || el.textContent;
    navigator.clipboard.writeText(text).then(() => {
        alert('کپی شد');
    }).catch(()=>{ alert('کپی ناموفق بود — مرورگر شما ممکن است اجازه ندهد'); });
}
</script>
</body>
</html>
