💻 व्यावहारिक क्रिप्टोग्राफी · इंजीनियरिंग गहन विश्लेषण

TOTP कैसे काम करता है: Python, JavaScript और Go में RFC 6238 एल्गोरिदम का कार्यान्वयन

2F 2FA-Tool सुरक्षा अनुसंधान लैब · अपडेट किया गया: अक्टूबर 2026 · 16 मिनट पढ़ना (2,700+ शब्द)
💡 वास्तुशिल्प सारांश एवं इंजीनियरिंग घोषणापत्र

आधुनिक वेब सुरक्षा में मूलभूत क्रिप्टोग्राफ़िक प्रोटोकॉल के बीच, RFC 6238 (TOTP: Time-Based One-Time Password Algorithm) अपनी गणितीय सादगी के लिए जाना जाता है। इसके लिए किसी इंटरएक्टिव नेटवर्क हैंडशेक, केंद्रीकृत सार्वजनिक कुंजी अवसंरचना (PKI), या क्लाउड राउंड-ट्रिप की आवश्यकता नहीं होती है। केवल एक साझा Base32 गुप्त कुंजी (secret key) और भौतिक Unix समय के निरंतर आगे बढ़ने के साथ, क्लाइंट और सर्वर 100% गणितीय निश्चितता के साथ हर 30 सेकंड में समान, अल्पकालिक 6-अंकीय प्रमाणीकरण टोकन की गणना करते हैं।

इस व्यापक गाइड में, हम आधिकारिक IETF परीक्षण वेक्टर्स के विरुद्ध प्रत्येक कार्यान्वयन को सत्यापित करते हुए, Python, JavaScript, और Go में स्क्रैच से पूर्ण RFC 6238 क्रिप्टोग्राफ़िक पाइपलाइन का निर्माण करने के लिए ब्लैक-बॉक्स तृतीय-पक्ष लाइब्रेरीज़ (जैसे pyotp या otplib) को बायपास करते हैं।

01. समय-आधारित प्रमाणीकरण का लालित्य

TOTP को समझने के लिए, हमें सबसे पहले इसके पूर्ववर्ती: RFC 4226 HOTP (HMAC-Based One-Time Password) को समझना होगा।

HOTP में, क्लाइंट और सर्वर एक इवेंट काउंटर $C$ साझा करते हैं। हर बार जब उपयोगकर्ता टोकन जनरेट करता है, तो काउंटर बढ़ता है ($C = C + 1$), और टोकन $\text{HMAC-SHA-1}(K, C)$ से प्राप्त होता है। हालांकि गणितीय रूप से सुदृढ़, HOTP एक परिचालन कमजोरी से ग्रस्त था: काउंटर डिसिंक्रोनाइज़ेशन। यदि कोई उपयोगकर्ता अपनी जेब में हार्डवेयर डोंगल पर पांच बार अनजाने में बटन दबा देता है, तो क्लाइंट काउंटर $C=6$ तक पहुंच जाता है जबकि प्रमाणीकरण सर्वर $C=1$ पर रहता है, जिसके परिणामस्वरूप लगातार लॉगिन विफलताएं होती हैं।

⏱️ RFC 6238 की सफलता: इवेंट काउंटरों को युग समय (Epoch Time) से बदलना

मई 2011 में N. M'Raihi, S. Machani, M. Pei, और J. Rydell द्वारा प्रकाशित, RFC 6238 ने बढ़ते हुए पूर्णांक को मानकीकृत Unix युग समय से बदलकर काउंटर डिसिंक समस्या का समाधान किया। चूंकि भौतिक समय दुनिया भर में एक समान रूप से आगे बढ़ता है, इसलिए क्लाइंट और सर्वर दोनों एक भी नेटवर्क पैकेट भेजे बिना अपने आंतरिक काउंटरों को एक साथ आगे बढ़ाते हैं।

02. TOTP के 5 क्रिप्टोग्राफ़िक गणितीय चरण

16-वर्ण वाले Base32 सीड (उदा. JBSWY3DPEHPK3PXP) को 6-अंकीय रोलिंग कोड (उदा. 284915) में बदलने में पांच सटीक क्रिप्टोग्राफ़िक चरण शामिल हैं:

1 चरण 1: Base32 गुप्त कुंजी डिकोडिंग

एक्सचेंज नामांकन कुंजियों को वर्णमाला A-Z और 2-7 का उपयोग करके RFC 4648 Base32 में एन्कोड किया जाता है (अस्पष्ट वर्णों जैसे 0, 1, 8, 9 को छोड़कर)। एल्गोरिदम पहले इस स्ट्रिंग को सामान्य करता है, रिक्त स्थान को हटाता है और पैडिंग (=) लागू करता है ताकि इसकी लंबाई 8 का गुणज हो, इससे पहले कि इसे कच्चे बाइनरी कुंजी बाइट्स $K$ में डिकोड किया जाए।

2 चरण 2: टाइम-स्टेप गणना (काउंटर $T$)

वर्तमान Unix टाइमस्टैम्प (1 जनवरी, 1970 UTC से बीते सेकंड) को पूर्णांक काउंटर $T$ पर मैप किया जाता है:

T = floor( (CurrentTime - T0) / X )

मानक पैरामीटर $T_0 = 0$ और स्टेप अवधि $X = 30$ सेकंड के साथ। इस पूर्णांक $T$ को फिर 8-बाइट बिग-एंडियन 64-बिट अहस्ताक्षरित पूर्णांक के रूप में एन्कोड किया जाता है।

3 चरण 3: HMAC-SHA1 हैश गणना

कच्चे कुंजी बाइट्स $K$ को गुप्त कुंजी के रूप में उपयोग करते हुए, हम 8-बाइट बिग-एंडियन समय बफ़र पर HMAC-SHA1 डाइजेस्ट की गणना करते हैं, जिससे 20-बाइट (160-बिट) संदेश प्रमाणीकरण हैश $HS$ प्राप्त होता है:

HS = HMAC-SHA-1(Key, T)
4 चरण 4: डायनामिक ट्रंकेशन (DT)

20 कच्चे बाइट्स को एक पूर्णांक में बदलने के लिए, RFC 4226 डायनामिक ट्रंकेशन निर्दिष्ट करता है:

  • ऑफ़सेट निकालें: अंतिम बाइट $HS[19]$ का निरीक्षण करें और इसके निचले 4 बिट्स निकालने के लिए 0x0F से मास्क करें, जिससे 0 और 15 के बीच एक ऑफ़सेट मान मिलता है: Offset = HS[19] & 0x0F;
  • 4 बाइट्स स्लाइस करें: ऑफ़सेट से शुरू होने वाले 4 लगातार बाइट्स निकालें: $P = HS[Offset \dots Offset+3]$;
  • साइन बिट मास्क करें: हस्ताक्षरित पूर्णांक अतिप्रवाह अस्पष्टता को रोकने के लिए सबसे महत्वपूर्ण बिट (MSB) को 0x7F से मास्क करें:
    BinaryCode = ((P[0] & 0x7F) << 24) | ((P[1] & 0xFF) << 16) | ((P[2] & 0xFF) << 8) | (P[3] & 0xFF)
5 चरण 5: $N$ अंकों में मॉड्यूलो रिडक्शन

अंत में, मानक 6-अंकीय टोकन के लिए BinaryCode का मॉड्यूलो $10^6$ (1,000,000) निकालें। एक सुसंगत 6-वर्ण आउटपुट स्ट्रिंग सुनिश्चित करने के लिए परिणाम को बाईं ओर शून्य के साथ पैड करें:

OTP = BinaryCode mod 10^6

03. निष्पादन योग्य कोड 1: Python 3 मानक लाइब्रेरी

यह संपूर्ण कार्यान्वयन शून्य pip पैकेज की आवश्यकता के साथ Python के अंतर्निहित base64, struct, hmac, और hashlib मॉड्यूल का उपयोग करता है:

totp_rfc6238.py Python 3.8+ (Zero Dependencies)
import base64
import hashlib
import hmac
import struct
import time

def generate_totp(secret_base32: str, timestamp: int = None, step: int = 30, digits: int = 6) -> str: """ Generate an RFC 6238 compliant TOTP token. :param secret_base32: Base32 प्रारूप में साझा गुप्त कुंजी (उदा. ‘JBSWY3DPEHPK3PXP’) :param timestamp: सेकंड में Unix युग टाइमस्टैम्प। डिफ़ॉल्ट time.time() :param step: सेकंड में टाइम-स्टेप विंडो (डिफ़ॉल्ट: 30) :param digits: आउटपुट अंकों की संख्या (डिफ़ॉल्ट: 6) :return: लेफ्ट-पैडेड OTP स्ट्रिंग (उदा. ‘045812’) """ if timestamp is None: timestamp = int(time.time())

# 1. Base32 स्ट्रिंग को सामान्य करें और '=' पैडिंग वर्ण जोड़ें
normalized_secret = secret_base32.replace(" ", "").upper()
padding_needed = (8 - len(normalized_secret) % 8) % 8
normalized_secret += "=" * padding_needed
key_bytes = base64.b32decode(normalized_secret)

# 2. 64-बिट बिग-एंडियन टाइम-स्टेप काउंटर T की गणना करें
time_counter = timestamp // step
time_bytes = struct.pack(">Q", time_counter)  # 8 बाइट्स बिग-एंडियन अहस्ताक्षरित long long

# 3. HMAC-SHA1 डाइजेस्ट (20 बाइट्स) की गणना करें
hmac_digest = hmac.new(key_bytes, time_bytes, hashlib.sha1).digest()

# 4. डायनामिक ट्रंकेशन निष्पादित करें
offset = hmac_digest[-1] &amp; 0x0F  # 20वें बाइट के निचले 4 बिट्स
# ऑफ़सेट पर 4 बाइट्स अनपैक करें और MSB साइन बिट साफ़ करें
binary_code = struct.unpack(">I", hmac_digest[offset : offset + 4])[0] &amp; 0x7FFFFFFF

# 5. मॉड्यूलो अंकगणित और ज़ीरो-फ़िल स्वरूपण
otp_code = binary_code % (10 ** digits)
return str(otp_code).zfill(digits)

if name == “main”: test_secret = “JBSWY3DPEHPK3PXP” print(f”Generated TOTP Code: {generate_totp(test_secret)}”)

04. निष्पादन योग्य कोड 2: JavaScript और Node.js Crypto

देशी crypto.createHmac का उपयोग करके बैकएंड Node.js रनटाइम के लिए शुद्ध JavaScript कार्यान्वयन:

totp_node.js Node.js Native Crypto
const crypto = require('crypto');

// Pure JavaScript में RFC 4648 Base32 डिकोडर function base32Decode(base32Str) { const alphabet = ‘ABCDEFGHIJKLMNOPQRSTUVWXYZ234567’; const cleaned = base32Str.replace(/=+$/, ”).toUpperCase().replace(/\s+/g, ”); let bits = 0, value = 0, index = 0; const output = new Uint8Array(Math.floor((cleaned.length * 5) / 8));

for (let i = 0; i < cleaned.length; i++) { const val = alphabet.indexOf(cleaned[i]); if (val === -1) continue; value = (value << 5) | val; bits += 5; if (bits >= 8) { output[index++] = (value >>> (bits - 8)) & 255; bits -= 8; } } return Buffer.from(output.buffer, 0, index); }

function generateTOTP(secretBase32, timestamp = Math.floor(Date.now() / 1000), step = 30, digits = 6) { const key = base32Decode(secretBase32); const counter = Math.floor(timestamp / step);

// बिग-एंडियन प्रारूप में 8-बाइट बफ़र आवंटित करें const buffer = Buffer.alloc(8); buffer.writeBigUInt64BE(BigInt(counter), 0);

// HMAC-SHA1 की गणना करें const hmac = crypto.createHmac(‘sha1’, key).update(buffer).digest();

// डायनामिक ट्रंकेशन const offset = hmac[hmac.length - 1] & 0x0f; const binary = ((hmac[offset] & 0x7f) << 24) | ((hmac[offset + 1] & 0xff) << 16) | ((hmac[offset + 2] & 0xff) << 8) | (hmac[offset + 3] & 0xff);

const otp = binary % (10 ** digits); return otp.toString().padStart(digits, ‘0’); }

console.log(“Calculated TOTP:”, generateTOTP(“JBSWY3DPEHPK3PXP”));

W3C Web Crypto API के माध्यम से क्लाइंट-साइड ब्राउज़र निष्पादन:

100% ऑफ़लाइन सुरक्षा चाहने वाले आधुनिक वेब अनुप्रयोगों के लिए (वही आर्किटेक्चर जो 2FA-Tool को संचालित करता है), W3C Web Crypto API तृतीय-पक्ष npm बंडलों के बिना सीधे ब्राउज़र सैंडबॉक्स में अतुल्यकालिक, हार्डवेयर-त्वरित क्रिप्टोग्राफ़िक प्रिमिटिव प्रदान करता है:

webcrypto_totp.js Browser W3C Web Crypto API
async function generateBrowserTOTP(secretBase32, timestamp = Math.floor(Date.now() / 1000)) {
  const keyBytes = base32Decode(secretBase32);
  const counter = Math.floor(timestamp / 30);

// 1. SubtleCrypto में कच्ची गुप्त कुंजी आयात करें const cryptoKey = await window.crypto.subtle.importKey( “raw”, keyBytes, { name: “HMAC”, hash: { name: “SHA-1” } }, false, [“sign”] );

// 2. 8-बाइट बिग-एंडियन काउंटर बफ़र एन्कोड करें const buffer = new ArrayBuffer(8); const view = new DataView(buffer); view.setBigUint64(0, BigInt(counter), false); // false = Big-Endian

// 3. क्रिप्टोग्राफ़िक HMAC हस्ताक्षर निष्पादित करें const signature = await window.crypto.subtle.sign(“HMAC”, cryptoKey, buffer); const hmacResult = new Uint8Array(signature);

// 4. डायनामिक ट्रंकेशन const offset = hmacResult[hmacResult.length - 1] & 0x0f; const binary = ((hmacResult[offset] & 0x7f) << 24) | ((hmacResult[offset + 1] & 0xff) << 16) | ((hmacResult[offset + 2] & 0xff) << 8) | (hmacResult[offset + 3] & 0xff);

const otp = binary % 1000000; return otp.toString().padStart(6, ‘0’); }

05. निष्पादन योग्य कोड 3: प्रोडक्शन Golang (Go)

उच्च-थ्रूपुट माइक्रोसर्विसेज को Go की युद्ध-परीक्षित मानक लाइब्रेरी से लाभ होता है:

totp.go Go 1.20+ Standard Library
package main

import ( “crypto/hmac” “crypto/sha1” “encoding/base32” “encoding/binary” “fmt” “math” “strings” “time” )

// GenerateTOTP मानक RFC 6238 समय-आधारित टोकन की गणना करता है func GenerateTOTP(secretBase32 string, timestamp int64, step int64, digits int) (string, error) { // 1. Base32 सीड को सैनिटाइज़ और डिकोड करें cleaned := strings.ToUpper(strings.ReplaceAll(secretBase32, ” ”, "")) key, err := base32.StdEncoding.WithPadding(base32.NoPadding).DecodeString(cleaned) if err != nil { key, err = base32.StdEncoding.DecodeString(cleaned) if err != nil { return "", err } }

// 2. 64-बिट बिग-एंडियन टाइम-स्टेप काउंटर एन्कोड करें
counter := uint64(timestamp / step)
buf := make([]byte, 8)
binary.BigEndian.PutUint64(buf, counter)

// 3. HMAC-SHA1 की गणना करें
mac := hmac.New(sha1.New, key)
mac.Write(buf)
hash := mac.Sum(nil)

// 4. डायनामिक ट्रंकेशन
offset := hash[len(hash)-1] &amp; 0x0f
binaryCode := binary.BigEndian.Uint32(hash[offset:offset+4]) &amp; 0x7fffffff

// 5. मॉड्यूलो अंकगणित
mod := uint32(math.Pow10(digits))
otp := binaryCode % mod

format := fmt.Sprintf("%%0%dd", digits)
return fmt.Sprintf(format, otp), nil

}

func main() { code, err := GenerateTOTP(“JBSWY3DPEHPK3PXP”, time.Now().Unix(), 30, 6) if err != nil { panic(err) } fmt.Printf(“Golang Computed TOTP: %s\n”, code) }

06. RFC 6238 परिशिष्ट B टेस्ट वेक्टर्स सत्यापन

मानक अनुपालन साबित करने के लिए, IETF RFC 6238 परिशिष्ट B में प्रकाशित आधिकारिक परीक्षण वेक्टर्स के विरुद्ध प्रत्येक क्रिप्टोग्राफ़िक कार्यान्वयन का सत्यापन किया जाना चाहिए।

आधिकारिक परीक्षण सुइट ASCII सीक्रेट "12345678901234567890" (20 बाइट्स) का उपयोग करता है, जो Base32 में एन्कोड होता है:
GEZDGNBVGY3TQOJQGEZDGNBVGY3TQOJQ (30-सेकंड के चरणों के साथ 8-अंकीय आउटपुट के लिए मूल्यांकित):

Unix युग टाइमस्टैम्प UTC दिनांक एवं समय RFC आधिकारिक अपेक्षित कोड कार्यान्वयन परिणाम
59 1970-01-01 00:00:59 94287082 ✓ PASSED (सटीक मेल)
1111111109 2005-03-18 01:58:29 07081804 ✓ PASSED (सटीक मेल)
1111111111 2005-03-18 01:58:31 14050471 ✓ PASSED (सटीक मेल)
1234567890 2009-02-13 23:31:30 89005924 ✓ PASSED (सटीक मेल)
2000000000 2033-05-18 03:33:20 69279037 ✓ PASSED (सटीक मेल)

07. प्रोडक्शन इंजीनियरिंग: विचलन, रीप्ले और दर सीमाएं

उच्च-उपलब्धता एंटरप्राइज़ प्रमाणीकरण प्रणालियों में TOTP सत्यापन तैनात करते समय, तीन सुरक्षा आवश्यकताओं को लागू किया जाना चाहिए:

नियम 1 क्लॉक ड्रिफ्ट सहनशीलता विंडो

मामूली मोबाइल घड़ी की अशुद्धियों के कारण, सर्वरों को विंडो [T - 1, T, T + 1] का मूल्यांकन करना चाहिए (पिछले 30 सेकंड, वर्तमान 30 सेकंड और अगले 30 सेकंड की जांच करना)। विंडो को कभी भी $\pm 1$ चरण से आगे न बढ़ाएं, क्योंकि प्रत्येक अतिरिक्त चरण रीप्ले हमले की सतह को 30 सेकंड बढ़ा देता है।

नियम 2 एकल-उपयोग टोकन प्रवर्तन (एंटी-रीप्ले)

सफल उपभोग पर एक टोकन को तुरंत अमान्य किया जाना चाहिए। Redis या इन-मेमोरी कैश में Last_Verified_Time_Step संग्रहीत करें। यदि कोई क्लाइंट उसी 30-सेकंड की विंडो के भीतर समान टोकन सबमिट करने का प्रयास करता है, तो मैन-इन-द-मिडिल रीप्ले हमलों को निष्प्रभावी करने के लिए अनुरोध को अस्वीकार करें।

नियम 3 ब्रूट-फ़ोर्स दर सीमा एवं कॉन्स्टेंट-टाइम तुलना

चूंकि 6-अंकीय कोड केवल 1,000,000 क्रमचय (permutations) तक फैले हैं, इसलिए अनियंत्रित एंडपॉइंट्स को तेजी से ब्रूट-फ़ोर्स किया जा सकता है। लगातार 3 विफलताओं के बाद प्रगतिशील विलंब और खाता लॉकआउट लागू करें। कोड में, साइड-चैनल टाइमिंग विश्लेषण को विफल करने के लिए कॉन्स्टेंट-टाइम समानता फ़ंक्शन (उदा. Go में crypto/subtle.ConstantTimeCompare या Node.js में crypto.timingSafeEqual) का उपयोग करके तुलना करें।

08. अक्सर पूछे जाने वाले प्रश्न (FAQ)

प्रश्न 1: चूंकि SHA-1 क्रिप्टोग्राफ़िक रूप से टूटा हुआ माना जाता है, तो TOTP अभी भी HMAC-SHA1 को डिफ़ॉल्ट क्यों रखता है? ▼

कच्चे SHA-1 के विरुद्ध सैद्धांतिक टकराव हमले HMAC निर्माण (RFC 2104) को नहीं तोड़ते हैं। HMAC में, अंतर्निहित हैश फ़ंक्शन आंतरिक और बाहरी गुप्त कुंजियों के भीतर नेस्टेड होता है, जो टकराव-आधारित हमलों को निष्प्रभावी करता है। आज तक, HMAC-SHA1 2FA के लिए पूरी तरह से सुरक्षित बना हुआ है। इसके अलावा, यदि उच्च आश्वासन की आवश्यकता होती है तो RFC 6238 HMAC-SHA256 और HMAC-SHA512 का पूरी तरह से समर्थन करता है।

प्रश्न 2: क्या समय क्षेत्र (Time Zones) या डेलाइट सेविंग टाइम (DST) TOTP सिंक्रोनाइज़ेशन को प्रभावित करते हैं? ▼

नहीं। Unix युग समय को 1970-01-01 00:00:00 UTC से बीते सेकंड के रूप में परिभाषित किया गया है। यह समय क्षेत्रों, लीप सेकंड और डेलाइट सेविंग बदलावों से पूरी तरह स्वतंत्र (agnostic) है। समय के किसी भी सटीक क्षण में, टोक्यो में एक सर्वर और कैलिफोर्निया में एक स्मार्टफोन का पूर्णांक टाइमस्टैम्प बिल्कुल समान होता है।

प्रश्न 3: Steam Guard 5-अक्षर प्रमाणीकरण RFC 6238 से कैसे भिन्न है? ▼

Steam Guard RFC 6238 पर आधारित एक मालिकाना संस्करण है। यह बिल्कुल समान 30-सेकंड के टाइम-स्टेप और HMAC-SHA1 गणना का उपयोग करता है, लेकिन अंतिम रिडक्शन चरण में, यह 5-वर्ण की स्ट्रिंग उत्पन्न करने के लिए एक कस्टम 26-वर्ण अल्फ़ान्यूमेरिक वर्ण सरणी (23456789BCDFGHJKMNPQRTVWXY) के माध्यम से निकाले गए पूर्णांक को मैप करता है।

RFC 6238 अनुपालन · W3C Web Crypto API क्लाइंट-साइड कंप्यूटिंग

100% क्लाइंट-साइड TOTP कोड जनरेशन का लाइव अनुभव लें

2FA-Tool W3C Web Crypto API का उपयोग करके सीधे आपके ब्राउज़र के भीतर इस सटीक क्रिप्टोग्राफ़िक पाइपलाइन को लागू करता है। शून्य सर्वर ट्रांसमिशन, शून्य टोकन भंडारण, त्वरित सत्यापन।