เบราว์เซอร์ของคุณดึงกุญแจสาธารณะจาก key directory ของเรา แล้วตรวจสอบว่าเซิร์ฟเวอร์นี้ผลิตลายเซ็นที่ตรงกันได้จริง เฉพาะผู้ที่มีกุญแจส่วนตัวที่ตรงกันเท่านั้นที่ทำได้
Your browser fetches our public key from our key directory and verifies that this server produced a matching signature. Only the holder of the matching private key could do that.
เบราว์เซอร์ใช้ crypto.subtle.verify('Ed25519', ...) กับกุญแจที่ดึงมาจาก directory โดยตรง — ไม่ใช่กุญแจที่ endpoint ส่งมา นั่นคือส่วนที่เป็นหลักฐาน
The browser calls crypto.subtle.verify('Ed25519', …) using the key fetched from the directory — never a key returned by the endpoint. That's the part that constitutes proof.
/.well-known/http-message-signatures-directory → แยก JWKS → ดึง public JWK ที่ตรงกับ keyid ของเรา → crypto.subtle.importKey('jwk', …, 'Ed25519', …)
Browser fetches /.well-known/http-message-signatures-directory → parses JWKS → takes the public JWK matching our keyid → crypto.subtle.importKey('jwk', …, 'Ed25519', …)
/api/verify-self → ได้รับ { message, signature_b64, keyid } (เซิร์ฟเวอร์เซ็นสตริงรูปแบบตายตัว aibotauth-verify:<timestamp> ด้วยกุญแจส่วนตัว)
Browser fetches /api/verify-self → receives { message, signature_b64, keyid } (server signs fixed-format string aibotauth-verify:<timestamp> with its private key)
crypto.subtle.verify('Ed25519', publicKey, signature, message) — กุญแจสาธารณะมาจาก directory เท่านั้น ไม่ใช่จาก endpoint
Confirm verify-self keyid === directory keyid, then crypto.subtle.verify('Ed25519', publicKey, signature, message) — the public key comes from the directory only, never from the endpoint
verify() คืนค่า true แสดงว่าเซิร์ฟเวอร์นี้ถือกุญแจส่วนตัวที่ตรงกับ identity ที่เผยแพร่ต่อสาธารณะ
If verify() returns true, this server holds the private key matching our publicly published identity
// Fetch the published public key from the key directory
const dir = await fetch('/.well-known/http-message-signatures-directory');
const { keys } = await dir.json();
const jwk = keys.find(k => k.kid === TARGET_KID);
// Import the public key (browser SubtleCrypto — no library needed)
const publicKey = await crypto.subtle.importKey(
'jwk', jwk, { name: 'Ed25519' }, true, ['verify']
);
// Ask the server for a fresh signed challenge
const res = await fetch('/api/verify-self');
const { message, signature_b64, keyid } = await res.json();
// Guard: the keyid must match what we fetched from the directory
if (keyid !== TARGET_KID) throw new Error('keyid mismatch');
// Base64 → bytes helpers
const b64ToBytes = s => Uint8Array.from(atob(s), c => c.charCodeAt(0));
const utf8 = s => new TextEncoder().encode(s);
// PROOF: verify the signature using the PUBLIC key from the DIRECTORY
const ok = await crypto.subtle.verify(
'Ed25519', publicKey,
b64ToBytes(signature_b64),
utf8(message)
);
การเซ็นลายเซ็นด้วย Ed25519 นั้นเป็นเรื่องของคณิตศาสตร์: มีเพียงกุญแจส่วนตัวเท่านั้นที่สามารถผลิตลายเซ็นที่กุญแจสาธารณะตรวจสอบผ่าน เบราว์เซอร์ของคุณเพิ่งทำสิ่งที่ยากมากที่จะปลอมแปลง — มันดึงกุญแจสาธารณะจาก directory อิสระ แล้วพิสูจน์ว่าเซิร์ฟเวอร์นี้มีกุญแจที่ตรงกัน
Ed25519 signing is mathematics: only the private key can produce a signature that the public key verifies. Your browser just did something very hard to fake — it fetched our public key from an independent directory and proved this server holds the matching private key.
นั่นหมายความว่าเมื่อ AIBotAuth เยี่ยมชมเว็บไซต์ของคุณพร้อมลายเซ็น — คุณสามารถตรวจสอบกับ directory เดียวกันนี้ได้ และรู้ว่าเป็นเราจริงๆ ไม่ใช่ใครก็ตามที่พิมพ์ชื่อของเราลงใน User-Agent
That means when AIBotAuth visits your site with a signature — you can verify against this same directory and know it's actually us, not anyone who typed our name into a User-Agent string.
keyid ที่ใช้ในหน้านี้: 5xf8JFMLpUyZNxMO0BKDIirQ-K03npBxuOhXRa3nQNI · ดู key directory · หน้า bot identity
keyid used on this page: 5xf8JFMLpUyZNxMO0BKDIirQ-K03npBxuOhXRa3nQNI · View key directory · Bot identity page