2FA-Tool Logo
2FA-Tool.com เครื่องมือ 2FA ออฟไลน์ที่ปลอดภัย
⏱️ วิทยาการรหัสลับและมาตรฐาน RFC ✓ วิเคราะห์มาตรฐาน IETF

เจาะลึกความแตกต่างระหว่าง TOTP กับ HOTP: หลักการทำงานและความปลอดภัย

นักพัฒนาและวิศวกรความปลอดภัยหลายล้านคนมองรหัสยืนยันตัวตน 6 หลักที่หมุนเวียนเปลี่ยนไปทุกวัน แต่น้อยคนนักที่จะเข้าใจกลไกทางคณิตศาสตร์อันชาญฉลาดที่ทำงานอยู่เบื้องหลังหน้าจอ จากตัวนับตามเหตุการณ์ RFC 4226 (HOTP) ในปี 2005 สู่ช่วงเวลาไม่ต่อเนื่อง RFC 6238 (TOTP) ในปี 2011 คู่มือนี้จะพาคุณไปสำรวจอัลกอริทึม Dynamic Truncation ในระดับไบต์, ปัญหาตัวนับไม่ซิงค์, ความคลาดเคลื่อนของเวลา และเหตุผลที่ TOTP ได้รับชัยชนะบนอินเทอร์เน็ตยุคใหม่

2FA
ทีมความปลอดภัย 2FA-Tool
อัปเดตเมื่อ ตุลาคม 2026
เวลาอ่านโดยประมาณ: 14 นาที (2,600+ คำ)
RFC 6238 RFC 4226 Dynamic Truncation
💡 ประเด็นสำคัญทางวิทยาการรหัสลับ (TL;DR)
  • ความแตกต่างพื้นฐานของอินพุต: HOTP คำนวณแฮชจาก ตัวนับที่เพิ่มขึ้นเรื่อยๆ C (Monotonically Increasing Counter) ในขณะที่ TOTP แทนที่ C ด้วย ช่วงเวลา Epoch T (CurrentUnixTime / 30)
  • การสืบทอดโดยตรง: ในทางคณิตศาสตร์ TOTP คือกรณีพิเศษของ HOTP: TOTP(K, Time) = HOTP(K, T) ทั้งสองอัลกอริทึมใช้ฟังก์ชัน Dynamic Truncation เดียวกันทุกประการ
  • ปัจจัยชี้ขาดเชิงสถาปัตยกรรม: HOTP เป็นแบบมีสถานะ (Stateful) เซิร์ฟเวอร์ต้องล็อกและบันทึกค่าตัวนับลงดิสก์ทุกครั้งที่ตรวจสอบสำเร็จ แต่ TOTP เป็นแบบไร้สถานะ (Stateless) ทำให้ไมโครเซอร์วิสบนคลาวด์สามารถตรวจสอบรหัสผ่านโหลดบาลานซ์ได้โดยไม่ต้องแย่งกันเขียนฐานข้อมูล
01

จุดกำเนิด: จากฮาร์ดแวร์โทเค็นเฉพาะสู่มาตรฐานเว็บเปิด

ในช่วงต้นทศวรรษ 2000 การยืนยันตัวตนสองขั้นตอนในระดับองค์กรถูกผูกขาดโดยฮาร์ดแวร์โทเค็นเฉพาะทาง เช่น พวงกุญแจ RSA SecurID อุปกรณ์เหล่านี้มีราคาแพงและมีคริสตัลควอตซ์ภายในที่ซิงค์เวลากับเซิร์ฟเวอร์เฉพาะของบริษัทผู้ผลิต หากองค์กรต้องการแจกโทเค็นความปลอดภัยให้กับพนักงานหลายพันคน ค่าจัดซื้อฮาร์ดแวร์และค่าลิขสิทธิ์จะมีมูลค่ามหาศาล

เพื่อปลดแอกระบบยืนยันตัวตนออกจากผู้ขายเฉพาะราย กลุ่มพันธมิตร OATH (Initiative for Open Authentication) จึงถูกก่อตั้งขึ้นโดยผู้นำในอุตสาหกรรม เพื่อสร้างมาตรฐานเปิดของ IETF ที่ไม่มีค่าลิขสิทธิ์ ซึ่งวิศวกรซอฟต์แวร์ทุกคนสามารถตรวจสอบ พัฒนา และใช้งานได้อย่างเสรี:

📜 ปี 2005: RFC 4226 (HOTP)

อัลกอริทึมรหัสผ่านใช้ครั้งเดียวตาม HMAC ออกแบบมาสำหรับไมโครคอนโทรลเลอร์พลังงานต่ำที่มีปุ่มกด เมื่อกดปุ่ม ตัวนับภายในจะเพิ่มขึ้น และแสดงรหัส 6 หลักบนหน้าจอ LCD

📜 ปี 2011: RFC 6238 (TOTP)

อัลกอริทึมรหัสผ่านใช้ครั้งเดียวตามเวลา ออกแบบขึ้นในยุคที่สมาร์ตโฟนเริ่มแพร่หลาย โดยอาศัยการซิงค์เวลากับเครือข่ายมือถือผ่าน NTP ทำให้ตัดปัญหาตัวนับไม่ตรงกันจากการกดปุ่มออกไปได้อย่างสิ้นเชิง

02

สถาปัตยกรรม HOTP (RFC 4226) & กลไก Dynamic Truncation ในระดับไบต์

คำจำกัดความทางคณิตศาสตร์หลักของ HOTP มีความกระชับและสง่างามอย่างยิ่ง:

HOTP(K, C) = Truncate(HMAC-SHA-1(K, C)) mod 10DigitCount

รายละเอียดของตัวแปร:

  • K: คีย์ลับสมมาตรที่ใช้ร่วมกัน (มักเป็นข้อมูลไบนารี 160 บิต / 20 ไบต์ที่ถอดรหัสมาจาก Base32)
  • C: ตัวนับจำนวนเต็มขนาด 8 ไบต์ (64 บิต) แบบ Big-Endian
  • HMAC-SHA-1: ฟังก์ชัน Keyed-hash message authentication code ที่สร้างไดเจสต์ขนาด 20 ไบต์ (160 บิต)

🔍 กลไก Dynamic Truncation (DT) แปลงข้อมูล 20 ไบต์เป็นตัวเลข 6 หลักได้อย่างไร:

ไดเจสต์ HMAC-SHA1 มีความยาว 20 ไบต์ การดึงเลขฐานสิบ 6 หลักออกมาอย่างสม่ำเสมอและไม่เกิดการชนกัน ต้องใช้กลไกการเลือกแบบกำหนดได้แน่นอนตาม RFC 4226 หัวข้อ 5.3:

// ขั้นตอนที่ 1: คำนวณ Dynamic Offset
Offset = HS[19] & 0x0F
นำไบต์สุดท้าย (ดัชนีที่ 19) ของไดเจสต์มาทำบิตไวส์ AND กับ 0x0F เพื่อแยก 4 บิตล่างออกมา ทำให้ได้ค่าจำนวนเต็มระหว่าง 0 ถึง 15 (0x0 ถึง 0xF) ซึ่งช่วยรับประกันว่าการดึงข้อมูล 4 ไบต์ถัดไปจะไม่ล้นบัฟเฟอร์ 20 ไบต์ (เพราะ 15 + 4 = 19 พอดี)
// ขั้นตอนที่ 2: ดึงข้อมูล 4 ไบต์ติดต่อกันพร้อมมาสก์บิต
P = ( (HS[Offset] & 0x7F) << 24 ) | ( (HS[Offset+1] & 0xFF) << 16 ) | ( (HS[Offset+2] & 0xFF) << 8 ) | ( HS[Offset+3] & 0xFF )
ดึง 4 ไบต์เริ่มจากตำแหน่ง Offset โดยมาสก์ 0x7F ที่ไบต์แรกสุดเพื่อเซ็ตบิตเครื่องหมาย (MSB) ให้เป็น 0 ป้องกันปัญหา Signed integer overflow บนสถาปัตยกรรม CPU ที่ต่างกัน ทำให้ได้จำนวนเต็มบวก 31 บิตที่สะอาด
// ขั้นตอนที่ 3: คำนวณมอดุโลเพื่อให้ได้รหัสสุดท้าย
OTP = P mod 106 = P mod 1000000
การมอดุโลด้วย 1,000,000 จะตัดเอาตัวเลขฐานสิบ 6 หลักสุดท้าย หากตัวเลขไม่ถึง 6 หลัก ให้เติมเลข 0 นำหน้า (เช่น 748 จะกลายเป็น "000748")
🧪 ตัวอย่างจริงจาก Test Vector ใน RFC 4226 ภาคผนวก D:

สมมุติว่าคีย์ลับคือสตริง ASCII "12345678901234567890" และตัวนับ C = 0 จะได้ผลลัพธ์ HMAC-SHA1 ในเลขฐานสิบหกดังนี้:

cc 93 cf 18 50 8d 94 93 4c 64 b6 6d 8b fb 87 fb 23 cb 4b 71

1. ไบต์สุดท้ายคือ 0x71 โดย 0x71 & 0x0F = 0x01 ดังนั้น Offset = 1
2. ไบต์ตำแหน่งที่ 1 ถึง 4 คือ: 93 cf 18 50 เมื่อเซ็ต MSB เป็น 0 จะได้ 0x13cf1850 ซึ่งแปลงเป็นฐานสิบได้ 332,339,280
3. 332339280 mod 1000000 = 339280 ดังนั้น รหัส OTP 6 หลักที่ได้คือ 339280!

03

วิวัฒนาการสู่ TOTP (RFC 6238): พลังของคาบเวลา (Time-Step Magic)

HOTP จำเป็นต้องซิงค์ตัวนับระหว่างเครื่องผู้ใช้กับเซิร์ฟเวอร์ แต่การนับจำนวนการกดปุ่มบนอุปกรณ์ซอฟต์แวร์มักเกิดความผิดพลาดจากการกระทำของมนุษย์ได้ง่าย

RFC 6238 จึงได้แทนที่ตัวนับ C ด้วย ช่วงเวลาไม่ต่อเนื่อง T ที่คำนวณจากนาฬิกา Unix Epoch โดยตรง:

T = ⌊ (CurrentUnixTime - T0) / X ⌋
  • CurrentUnixTime: วินาทีที่ผ่านไปนับตั้งแต่วันที่ 1 มกราคม 1970 00:00:00 UTC
  • T0: จุดอ้างอิงเริ่มต้นของเวลา (ในระบบปัจจุบันกำหนดให้เป็น 0 เสมอ)
  • X (หน้าต่างคาบเวลา): ระยะเวลามาตรฐานที่แนะนำคือ 30 วินาที
  • ฟังก์ชันปัดเศษลง ⌊ ⌋: ตลอดระยะเวลา 30 วินาทีใดๆ ค่า T จะมีค่าคงที่เสมอ เช่น ระหว่างวินาทีที่ 1728211200 ถึง 1728211229 ค่า T จะได้จำนวนเต็ม 64 บิตเดิมทุกประการ

การจัดเก็บในรูปแบบไบนารี: เมื่อคำนวณค่า T ได้แล้ว ระบบจะแปลง T เป็นไบต์บัฟเฟอร์ขนาด 8 ไบต์แบบ Big-Endian (โครงสร้างเดียวกับตัวนับ C ใน HOTP) ทำให้สูตรสรุปของ TOTP คือ:
TOTP(K, Time) = HOTP(K, T) ความเรียบง่ายทางคณิตศาสตร์นี้เองที่ทำให้แอปยืนยันตัวตนสามารถหมุนเวียนรหัสได้พร้อมกับเซิร์ฟเวอร์ทุก 30 วินาที โดยไม่ต้องมีการส่งข้อมูลอัปเดตสถานะตัวนับหากันเลย

การรองรับ SHA-256 และ SHA-512 ใน RFC 6238: แม้ว่า RFC 4226 จะกำหนดเฉพาะ HMAC-SHA-1 แต่ RFC 6238 ได้ขยายให้รองรับ HMAC-SHA-256 และ HMAC-SHA-512 ด้วย โดยใน SHA-256 (ไดเจสต์ 32 ไบต์) ออฟเซ็ตจะดึงจากไบต์ที่ 31 (HS[31] & 0x0F) และใน SHA-512 (ไดเจสต์ 64 ไบต์) จะดึงจากไบต์ที่ 63 (HS[63] & 0x0F) อย่างไรก็ตาม ในเว็บไซต์เชิงพาณิชย์กว่า 99.9% (Google, Microsoft, GitHub, AWS) SHA-1 ยังคงเป็นมาตรฐานหลักเพื่อความเข้ากันได้กับแอปมือถือรุ่นเก่า
04

ตารางเปรียบเทียบเชิงลึกแบบเคียงข้างกัน (HOTP vs. TOTP)

มิติการเปรียบเทียบ HOTP (RFC 4226) TOTP (RFC 6238)
ตัวแปรอินพุต ตัวนับเหตุการณ์ C (เพิ่มขึ้นเรื่อยๆ) ช่วงเวลา T (หน้าต่าง 30 วินาที Unix Epoch)
อายุขัยของรหัสผ่าน ไม่จำกัดเวลา (ใช้ได้จนกว่าจะล็อกอินสำเร็จ) 30 วินาทีเท่านั้น (หมดอายุโดยอัตโนมัติ)
สถาปัตยกรรมเซิร์ฟเวอร์ Stateful (ต้องเขียนฐานข้อมูลล็อกตัวนับทุกครั้ง) Stateless (ตรวจสอบได้อิสระผ่านเวลา NTP)
ความเสี่ยงจากการโจมตีแบบ Replay ปานกลาง (รหัสที่ดักจับได้ใช้ได้จนกว่าเจ้าของจะล็อกอิน) ต่ำมาก (รหัสใช้งานได้เฉพาะในวินาทีที่เหลือของรอบ)
ปัญหาหลักที่พบบ่อย ตัวนับไม่ตรงกัน (จากการเผลอกดปุ่มเล่น) นาฬิกาคลาดเคลื่อน (เวลาของโทรศัพท์ไม่ตรง)
ฟังก์ชันแฮชที่รองรับ HMAC-SHA-1 เท่านั้น HMAC-SHA-1, HMAC-SHA-256, HMAC-SHA-512
การนำไปใช้ในปัจจุบัน โทเค็นฮาร์ดแวร์ธนาคารรุ่นเก่า, ประตูดิจิทัล 99.9% ของระบบยืนยันตัวตนบนเว็บสมัยใหม่
05

การแก้ปัญหา Desynchronization และ Time Drift เชิงวิศวกรรม

ในสภาพแวดล้อมโปรดักชันจริง ความล่าช้าของเครือข่ายและนาฬิกาที่ไม่ตรงกันย่อมเกิดขึ้นได้ นักวิทยาการรหัสลับจึงได้ออกแบบหน้าต่างชดเชยเพื่อรักษาความเสถียรของระบบ:

⚙️ การแก้ปัญหาของ HOTP: หน้าต่างค้นหาล่วงหน้า (Look-Ahead Window: s)

หากผู้ใช้กดปุ่มโทเค็นเล่นไป 5 ครั้งโดยไม่ได้ล็อกอิน ตัวนับฝั่งไคลเอนต์จะกลายเป็น C+5 ในขณะที่เซิร์ฟเวอร์ยังอยู่ที่ C
RFC 4226 จึงกำหนดให้เซิร์ฟเวอร์คำนวณรหัสล่วงหน้าครอบคลุมช่วง [C+1, C+s] (โดยทั่วไป s=20) หากพบรหัสที่ตรงกัน เซิร์ฟเวอร์จะกระโดดตัวนับไปที่จุดนั้นและซิงค์ข้อมูลให้ทันที

⏱️ การแก้ปัญหาของ TOTP: หน้าต่างยอมรับความคลาดเคลื่อน (±1 Window)

เนื่องจากความล่าช้าในการส่งผ่านเครือข่ายหรือเวลาของโทรศัพท์เดินช้าไปเล็กน้อย รหัสอาจมาถึงในช่วงเวลาถัดไป
เซิร์ฟเวอร์ในระบบจริงจะตรวจสอบรหัสล่วงหน้าและย้อนหลังครอบคลุม 3 หน้าต่างเวลา: [T-1, T, T+1] ซึ่งเทียบเท่ากับช่วงเวลายอมรับ 90 วินาที

กฎเหล็กป้องกัน Replay Attack: เพื่อป้องกันไม่ให้ผู้ไม่หวังดีนำรหัสในหน้าต่าง 90 วินาทีมาใช้ซ้ำ เซิร์ฟเวอร์ต้องแคชรหัสที่ใช้แล้วลงหน่วยความจำชั่วคราว (เช่น Redis) เป็นเวลา 90 วินาที และปฏิเสธการส่งรหัสซ้ำ
🛡️ การเปรียบเทียบสตริงแบบเวลาคงที่ (Constant-Time String Comparison):

เมื่อเซิร์ฟเวอร์ตรวจสอบว่ารหัสที่ผู้ใช้กรอกตรงกับรหัสที่คำนวณได้หรือไม่ การเปรียบเทียบสตริงแบบทั่วไป (เช่น userOtp === serverOtp) จะหยุดการทำงานทันทีที่เจอตัวอักษรตัวแรกที่ไม่ตรงกัน ผู้โจมตีที่จับเวลาการตอบสนองของเครือข่ายในระดับไมโครวินาทีอาจสามารถเดารหัสทีละหลักได้ (Timing Attack) แบ็กเอนด์ระดับองค์กรจึงต้องบังคับใช้ฟังก์ชันเปรียบเทียบแบบเวลาคงที่เสมอ (เช่น crypto.timingSafeEqual ใน Node.js)

06

ทำไม TOTP ถึงชนะใจนักพัฒนาและครองโลกอินเทอร์เน็ต

ชัยชนะอย่างเด็ดขาดของ TOTP เหนือ HOTP บนเว็บสมัยใหม่ขับเคลื่อนด้วยปัจจัยสำคัญ 3 ประการ:

☁️ การขยายระบบบนคลาวด์แบบไร้สถานะ

ในระบบไมโครเซอร์วิสแบบหลาย Region เซิร์ฟเวอร์ทุกเครื่องที่ซิงค์เวลาผ่าน NTP สามารถตรวจสอบรหัส TOTP ได้ทันทีโดยไม่ต้องเชื่อมต่อหรือแย่งกันเขียนฐานข้อมูลส่วนกลาง

📱 ระบบนิเวศของสมาร์ตโฟน

สมาร์ตโฟนจะปรับเวลาให้ตรงกับเสาสัญญาณมือถือและดาวเทียม GPS อยู่เสมอ ตัดปัญหาเรื่องเวลาคลาดเคลื่อนโดยไม่ต้องมีทีมช่างคอยดูแลฮาร์ดแวร์

🛡️ หน้าต่างการถูกโจมตีสั้นเพียง 30 วินาที

รหัส HOTP ใช้ได้ตลอดไปจนกว่าจะล็อกอิน แต่รหัส TOTP หมดอายุใน 30 วินาที ช่วยลดความเสี่ยงจากการที่รหัสรั่วไหลหรือถูกดักจับผ่านเครือข่ายลงได้อย่างมาก

🧮 เอนจินคำนวณ RFC 6238 ฝั่งไคลเอนต์แท้ 100%

สัมผัสการคำนวณรหัส TOTP แบบเรียลไทม์ใน 2FA-Tool

ดูว่าคีย์ลับ Base32 ของคุณถูกแปลงเป็นรหัส 6 หลักได้อย่างไรผ่านการคำนวณ HMAC-SHA1 Dynamic Truncation ทำงานแบบออฟไลน์บนเบราว์เซอร์ของคุณ 100%

เปิดเครื่องมือสร้างรหัสออนไลน์