<!DOCTYPE html>
<html lang="en">
<head>
  <meta charset="UTF-8">
  <title>Bitcoin Address Verifier</title>
  <style>
    body { font-family: Arial, sans-serif; padding: 20px; }
    input, button { padding: 8px; margin: 5px 0; width: 100%; }
    pre { background: #f4f4f4; padding: 10px; }
  </style>
</head>
<body>
  <h2>🔑 Bitcoin Address Verifier</h2>
  <label>Private Key (hex):</label>
  <input id="privKey" value="00000000000000000000000000000000000000000000000000000000000000e0">
  <label>Expected hash160:</label>
  <input id="expHash160" value="dce76b2613052ea012204404a97b3c25eac31715">
  <label>Expected Address:</label>
  <input id="expAddr" value="1M92tSqNmQLYw33fuBvjmeadirh1ysMBxK">
  <button onclick="runVerification()">Verify</button>
  <h3>Result:</h3>
  <pre id="output"></pre>

  <script>
    // --- Base58, ECC, and Hash functions from before ---

    function hexToBytes(hex) {
      return new Uint8Array(hex.match(/.{1,2}/g).map(byte => parseInt(byte, 16)));
    }
    function bytesToHex(bytes) {
      return Array.from(bytes).map(b => b.toString(16).padStart(2, '0')).join('');
    }
    const BASE58_ALPHABET = '123456789ABCDEFGHJKLMNPQRSTUVWXYZabcdefghijkmnopqrstuvwxyz';
    function base58Encode(buffer) {
      let x = BigInt('0x' + bytesToHex(buffer));
      let result = '';
      while (x > 0) {
        const mod = x % 58n;
        result = BASE58_ALPHABET[Number(mod)] + result;
        x = x / 58n;
      }
      for (let byte of buffer) {
        if (byte === 0x00) result = '1' + result;
        else break;
      }
      return result;
    }
    function getPublicKeyCompressed(privKeyHex) {
      const secp256k1 = {
        p: BigInt('0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFEFFFFFC2F'),
        a: 0n,
        b: 7n,
        Gx: BigInt('0x79BE667EF9DCBBAC55A06295CE870B07029BFCDB2DCE28D959F2815B16F81798'),
        Gy: BigInt('0x483ADA7726A3C4655DA4FBFC0E1108A8FD17B448A68554199C47D08FFB10D4B8'),
      };
      function mod(n, p) { return ((n % p) + p) % p; }
      function inv(n, p) {
        let [a, b] = [n, p], [x, y] = [1n, 0n];
        while (b) [a, b, x, y] = [b, a % b, y, x - y * (a / b)];
        return mod(x, p);
      }
      function add(P, Q) {
        if (!P) return Q;
        if (!Q) return P;
        let [x1, y1] = P, [x2, y2] = Q;
        if (x1 === x2 && y1 !== y2) return null;
        let m = x1 === x2 ? mod(3n * x1 * x1, secp256k1.p) * inv(2n * y1, secp256k1.p) : mod(y2 - y1, secp256k1.p) * inv(x2 - x1, secp256k1.p);
        let x3 = mod(m * m - x1 - x2, secp256k1.p);
        let y3 = mod(m * (x1 - x3) - y1, secp256k1.p);
        return [x3, y3];
      }
      function multiply(k, P) {
        let R = null;
        for (let i = 0; i < 256; i++) {
          if (k & (1n << BigInt(i))) R = add(R, P);
          P = add(P, P);
        }
        return R;
      }
      let privKey = BigInt('0x' + privKeyHex);
      let pubKey = multiply(privKey, [secp256k1.Gx, secp256k1.Gy]);
      let prefix = pubKey[1] % 2n === 0n ? '02' : '03';
      return prefix + pubKey[0].toString(16).padStart(64, '0');
    }

    async function hash160(hex) {
      let sha = await crypto.subtle.digest('SHA-256', hexToBytes(hex));
      let shaBytes = new Uint8Array(sha);
      let ripemd = await crypto.subtle.digest('RIPEMD-160', shaBytes);
      return bytesToHex(new Uint8Array(ripemd));
    }

    async function runVerification() {
      let privKeyHex = document.getElementById('privKey').value.trim();
      let expectedHash160 = document.getElementById('expHash160').value.trim();
      let expectedAddr = document.getElementById('expAddr').value.trim();
      let output = '';

      output += '🔑 Private Key: ' + privKeyHex + '\\n';
      let pubKeyHex = getPublicKeyCompressed(privKeyHex);
      output += '🔓 Public Key (Compressed): ' + pubKeyHex + '\\n';

      let shaHash = await crypto.subtle.digest('SHA-256', hexToBytes(pubKeyHex));
      let shaHex = bytesToHex(new Uint8Array(shaHash));
      output += '🌀 SHA256(pubkey): ' + shaHex + '\\n';

      let hash160Hex = await hash160(pubKeyHex);
      output += '🌪️ RIPEMD160(SHA256(pubkey)): ' + hash160Hex + '\\n';

      output += '✅ Expected hash160: ' + expectedHash160 + ' | Match: ' + (expectedHash160 === hash160Hex) + '\\n';

      let versioned = '00' + hash160Hex;
      let verBuf = hexToBytes(versioned);
      let chk1 = await crypto.subtle.digest('SHA-256', verBuf);
      let chk2 = await crypto.subtle.digest('SHA-256', chk1);
      let checksum = bytesToHex(new Uint8Array(chk2)).slice(0, 8);
      output += '🔗 Version + hash160: ' + versioned + '\\n';
      output += '🔐 Checksum: ' + checksum + '\\n';

      let fullHex = versioned + checksum;
      let address = base58Encode(hexToBytes(fullHex));
      output += '🏁 Bitcoin Address: ' + address + '\\n';
      output += '✅ Expected Address: ' + expectedAddr + ' | Match: ' + (expectedAddr === address) + '\\n';

      document.getElementById('output').innerText = output;
    }
  </script>
</body>
</html>