आधुनिक वेब सुरक्षेमधील मूलभूत क्रिप्टोग्राफिक प्रोटोकॉलमध्ये, RFC 6238 (TOTP: Time-Based One-Time Password Algorithm) त्याच्या गणितीय साधेपणासाठी उठून दिसतो. यासाठी कोणत्याही परस्परसंवादी नेटवर्क हँडशेकची, केंद्रीकृत सार्वजनिक की पायाभूत सुविधांची (PKI) आणि क्लाउड राउंड-ट्रिपची आवश्यकता नसते. केवळ एका सामायिक Base32 सिक्रेट की आणि भौतिक युनिक्स वेळेच्या निरंतर प्रवाहासह, क्लायंट आणि सर्व्हर 100% गणितीय निश्चिततेसह दर 30 सेकंदांनी एकसारखे, अल्पायुषी 6-अंकी प्रमाणीकरण टोकन मोजतात.
या सर्वसमावेशक मार्गदर्शकामध्ये, आम्ही ब्लॅक-बॉक्स तृतीय-पक्ष लायब्ररी (जसे की pyotp किंवा otplib) बाजूला ठेवून Python, JavaScript आणि Go मध्ये सुरवातीपासून संपूर्ण RFC 6238 क्रिप्टोग्राफिक पाइपलाइन तयार करतो, आणि अधिकृत IETF टेस्ट वेक्टर्स विरुद्ध प्रत्येक अंमलबजावणीची पडताळणी करतो.
01. काळावर आधारित प्रमाणीकरणाचे सौंदर्य
TOTP समजून घेण्यासाठी, आपण प्रथम त्याचा पूर्ववर्ती समजून घेतला पाहिजे: RFC 4226 HOTP (HMAC-Based One-Time Password).
HOTP मध्ये, क्लायंट आणि सर्व्हर एक इव्हेंट काउंटर $C$ सामायिक करतात. जेव्हा जेव्हा वापरकर्ता टोकन व्युत्पन्न करतो, तेव्हा काउंटर वाढतो ($C = C + 1$), आणि टोकन $\text{HMAC-SHA-1}(K, C)$ मधून काढले जाते. गणितीयदृष्ट्या योग्य असले तरी, HOTP मध्ये एक ऑपरेशनल कमकुवतपणा होता: काउंटर डिंक्रोनाइझेशन (counter desynchronization). जर वापरकर्त्याने अजाणतेपणे त्यांच्या खिशात असलेल्या हार्डवेअर डोंगलवरील बटण पाच वेळा दाबले, तर क्लायंट काउंटर $C=6$ वर पोहोचतो तर प्रमाणीकरण सर्व्हर $C=1$ वरच राहतो, ज्यामुळे लॉगिन सतत नाकारले जाते.
मे 2011 मध्ये N. M'Raihi, S. Machani, M. Pei, आणि J. Rydell यांनी प्रकाशित केलेल्या RFC 6238 ने वाढत्या पूर्णांकाच्या जागी प्रमाणित युनिक्स युगाची वेळ (Unix epoch time) वापरून काउंटर डिंक समस्येचे निराकरण केले. भौतिक वेळ जगभरात एकसमान रीतीने पुढे जात असल्याने, क्लायंट आणि सर्व्हर दोन्ही एकही नेटवर्क पॅकेट न पाठवता एकाच वेळी त्यांचे अंतर्गत काउंटर पुढे नेतात.
02. TOTP च्या 5 क्रिप्टोग्राफिक गणितीय पायऱ्या
16-वर्णांच्या Base32 सीडला (उदा. JBSWY3DPEHPK3PXP) 6-अंकी रोलिंग कोडमध्ये (उदा. 284915) रूपांतरित करण्यात पाच अचूक क्रिप्टोग्राफिक टप्पे समाविष्ट आहेत:
एक्सचेंज नोंदणी की RFC 4648 Base32 मध्ये A-Z आणि 2-7 वर्णमाला वापरून एन्कोड केल्या जातात (अस्पष्ट वर्ण जसे की 0, 1, 8, 9 वगळून). अल्गोरिदम प्रथम ही स्ट्रिंग सामान्यीकृत करतो, पांढरी जागा काढून टाकतो आणि पॅडिंग (=) लागू करतो जेणेकरून त्याची लांबी 8 च्या पटीत असेल, त्यानंतर त्याला कच्च्या बायनरी की बाइट्स $K$ मध्ये डिकोड करतो.
सध्याचा युनिक्स टाइमस्टॅम्प (1 जानेवारी 1970 UTC पासून उलटलेले सेकंद) पूर्णांक काउंटर $T$ वर मॅप केला जातो:
मानक पॅरामीटर्स $T_0 = 0$ आणि स्टेप कालावधी $X = 30$ सेकंद. हा पूर्णांक $T$ नंतर 8-बाइट बिग-एंडियन 64-बिट अनसाइंड इंटिजर म्हणून एन्कोड केला जातो.
कच्च्या की बाइट्स $K$ चा सिक्रेट की म्हणून वापर करून, आम्ही 8-बाइट बिग-एंडियन टाइम बफरवर HMAC-SHA1 डायजेस्ट मोजतो, ज्यामुळे 20-बाइट (160-बिट) संदेश प्रमाणीकरण हॅश $HS$ प्राप्त होतो:
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)
शेवटी, मानक 6-अंकी टोकन्ससाठी BinaryCode मॉड्युलो $10^6$ (1,000,000) कमी करा. सुसंगत 6-वर्णांची आउटपुट स्ट्रिंग सुनिश्चित करण्यासाठी परिणामाच्या डाव्या बाजूला शून्यांनी पॅड करा:
03. रन करण्यायोग्य कोड 1: Python 3 स्टँडर्ड लायब्ररी
ही संपूर्ण अंमलबजावणी कोणत्याही बाह्य pip पॅकेजशिवाय Python च्या अंगभूत base64, struct, hmac, आणि hashlib मॉड्यूल्सचा वापर करते:
import base64 import hashlib import hmac import struct import timedef 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: Shared secret key in Base32 format (e.g., ‘JBSWY3DPEHPK3PXP’) :param timestamp: Unix epoch timestamp in seconds. Defaults to time.time() :param step: Time-step window in seconds (default: 30) :param digits: Number of output digits (default: 6) :return: Left-padded OTP string (e.g., ‘045812’) """ if timestamp is None: timestamp = int(time.time())
# 1. Normalize Base32 string and append '=' padding characters 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. Compute 64-bit big-endian time-step counter T time_counter = timestamp // step time_bytes = struct.pack(">Q", time_counter) # 8 bytes big-endian unsigned long long # 3. Calculate HMAC-SHA1 digest (20 bytes) hmac_digest = hmac.new(key_bytes, time_bytes, hashlib.sha1).digest() # 4. Perform Dynamic Truncation offset = hmac_digest[-1] & 0x0F # Lower 4 bits of the 20th byte # Unpack 4 bytes at offset and clear MSB sign bit binary_code = struct.unpack(">I", hmac_digest[offset : offset + 4])[0] & 0x7FFFFFFF # 5. Modulo arithmetic and zero-fill formatting 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 अंमलबजावणी:
const crypto = require('crypto');// RFC 4648 Base32 Decoder in Pure JavaScript 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);
// Allocate 8-byte buffer in Big-Endian format const buffer = Buffer.alloc(8); buffer.writeBigUInt64BE(BigInt(counter), 0); // Compute HMAC-SHA1 const hmac = crypto.createHmac('sha1', key).update(buffer).digest(); // Dynamic Truncation 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 बंडल्सशिवाय थेट ब्राउझर सँडबॉक्समध्ये असिंक्रोनस, हार्डवेअर-प्रवेगक क्रिप्टोग्राफिक प्रिमिटिव्ह प्रदान करते:
async function generateBrowserTOTP(secretBase32, timestamp = Math.floor(Date.now() / 1000)) { const keyBytes = base32Decode(secretBase32); const counter = Math.floor(timestamp / 30);// 1. Import raw secret key into SubtleCrypto const cryptoKey = await window.crypto.subtle.importKey( "raw", keyBytes, { name: "HMAC", hash: { name: "SHA-1" } }, false, ["sign"] ); // 2. Encode 8-byte Big-Endian counter buffer const buffer = new ArrayBuffer(8); const view = new DataView(buffer); view.setBigUint64(0, BigInt(counter), false); // false = Big-Endian // 3. Perform cryptographic HMAC sign const signature = await window.crypto.subtle.sign("HMAC", cryptoKey, buffer); const hmacResult = new Uint8Array(signature); // 4. Dynamic Truncation 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 च्या चाचणी केलेल्या मानक लायब्ररीचा मोठा फायदा होतो:
package mainimport ( “crypto/hmac” “crypto/sha1” “encoding/base32” “encoding/binary” “fmt” “math” “strings” “time” )
// GenerateTOTP computes standard RFC 6238 time-based tokens func GenerateTOTP(secretBase32 string, timestamp int64, step int64, digits int) (string, error) { // 1. Sanitize Base32 seed and decode 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. Encode 64-bit Big-Endian time-step counter counter := uint64(timestamp / step) buf := make([]byte, 8) binary.BigEndian.PutUint64(buf, counter) // 3. Compute HMAC-SHA1 mac := hmac.New(sha1.New, key) mac.Write(buf) hash := mac.Sum(nil) // 4. Dynamic Truncation offset := hash[len(hash)-1] & 0x0f binaryCode := binary.BigEndian.Uint32(hash[offset:offset+4]) & 0x7fffffff // 5. Modulo arithmetic 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 Appendix B मध्ये प्रकाशित अधिकृत चाचणी वेक्टर्सविरुद्ध सत्यापित केली पाहिजे.
अधिकृत चाचणी संच ASCII सिक्रेट "12345678901234567890" (20 बाइट्स) चा वापर करतो, जो Base32 मध्ये एन्कोड केला जातो:
GEZDGNBVGY3TQOJQGEZDGNBVGY3TQOJQ (30-सेकंदांच्या पायऱ्यांसह 8-अंकी आउटपुटसाठी मूल्यांकित):
| युनिक्स युगाचा टाइमस्टॅम्प | UTC तारीख आणि वेळ | RFC अधिकृत अपेक्षित कोड | अंमलबजावणी निकाल |
|---|---|---|---|
| 59 | 1970-01-01 00:00:59 | 94287082 | ✓ उत्तीर्ण (अचूक जुळणी) |
| 1111111109 | 2005-03-18 01:58:29 | 07081804 | ✓ उत्तीर्ण (अचूक जुळणी) |
| 1111111111 | 2005-03-18 01:58:31 | 14050471 | ✓ उत्तीर्ण (अचूक जुळणी) |
| 1234567890 | 2009-02-13 23:31:30 | 89005924 | ✓ उत्तीर्ण (अचूक जुळणी) |
| 2000000000 | 2033-05-18 03:33:20 | 69279037 | ✓ उत्तीर्ण (अचूक जुळणी) |
07. प्रॉडक्शन अभियांत्रिकी: क्लॉक ड्रिफ्ट, रीप्ले आणि मर्यादा
उच्च-उपलब्धता एंटरप्राइझ प्रमाणीकरण प्रणालींमध्ये TOTP पडताळणी तैनात करताना, तीन सुरक्षा आवश्यकता लागू केल्या पाहिजेत:
मोबाईलच्या किरकोळ वेळेच्या चुकीमुळे, सर्व्हरने [T - 1, T, T + 1] विंडोचे मूल्यांकन केले पाहिजे (मागील 30 सेकंद, चालू 30 सेकंद आणि पुढील 30 सेकंद तपासणे). विंडो कधीही $\pm 1$ पायरीच्या पुढे वाढवू नका, कारण प्रत्येक अतिरिक्त पायरी रीप्ले हल्ल्याची पृष्ठभूमी 30 सेकंदांनी वाढवते.
यशस्वी वापरानंतर टोकन तात्काळ अवैध केले पाहिजे. Redis किंवा इन-मेमरी कॅशेमध्ये Last_Verified_Time_Step साठवा. क्लायंटने त्याच 30-सेकंदांच्या विंडोमध्ये तेच टोकन सबमिट करण्याचा प्रयत्न केल्यास, मॅन-इन-द-मिडल रीप्ले हल्ले निष्फळ करण्यासाठी विनंती नाकारा.
6-अंकी कोड केवळ 1,000,000 शक्यतांचे असल्याने, अनियंत्रित एंडपॉइंट्सवर वेगाने ब्रूट-फोर्स हल्ला केला जाऊ शकतो. लागोपाठ 3 अयशस्वी प्रयत्नांनंतर खात्यावर मर्यादा आणि लॉकआउट लागू करा. कोडमध्ये, साइड-चॅनेल टाइमिंग विश्लेषण निष्फळ करण्यासाठी कॉन्स्टंट-टाइम समानता फंक्शन्सचा (उदा. Go मध्ये crypto/subtle.ConstantTimeCompare किंवा Node.js मध्ये crypto.timingSafeEqual) वापर करून तुलना करा.
08. वारंवार विचारले जाणारे प्रश्न (FAQ)
Q1: SHA-1 क्रिप्टोग्राफिकदृष्ट्या कमकुवत मानले जात असल्याने, TOTP अजूनही HMAC-SHA1 का वापरते? ▼
कच्च्या SHA-1 विरुद्ध सैद्धांतिक टक्कर हल्ले (collision attacks) HMAC रचनेला (RFC 2104) खंडित करत नाहीत. HMAC मध्ये, अंतर्निहित हॅश फंक्शन अंतर्गत आणि बाह्य सिक्रेट कीमध्ये नेस्ट केलेले असते, जे टक्कर-आधारित हल्ल्यांना निष्फळ करते. आजपर्यंत, HMAC-SHA1 हे 2FA साठी पूर्णपणे सुरक्षित आहे. याव्यतिरिक्त, उच्च सुरक्षेची आवश्यकता असल्यास RFC 6238 हे HMAC-SHA256 आणि HMAC-SHA512 चे पूर्ण समर्थन करते.
Q2: टाइम झोन किंवा डेलाइट सेव्हिंग टाइम (DST) मुळे TOTP सिंक्रोनाइझेशनवर परिणाम होतो का? ▼
नाही. युनिक्स वेळ 1970-01-01 00:00:00 UTC पासून उलटलेले सेकंद म्हणून परिभाषित केली आहे. हे टाइम झोन, लीप सेकंद आणि डेलाइट सेव्हिंग बदलांपासून पूर्णपणे स्वतंत्र आहे. कोणत्याही अचूक क्षणी, टोकियोमधील सर्व्हर आणि कॅलिफोर्नियामधील स्मार्टफोनचा पूर्णांक टाइमस्टॅम्प तंतोतंत सारखाच असतो.
Q3: Steam Guard 5-अक्षरी प्रमाणीकरण RFC 6238 पेक्षा कसे वेगळे आहे? ▼
Steam Guard हा RFC 6238 वर आधारित प्रोप्रायटरी प्रकार आहे. तो तंतोतंत 30-सेकंदांची वेळ-पायरी आणि HMAC-SHA1 गणना वापरतो, परंतु अंतिम रिडक्शन टप्प्यात, तो 5-वर्णांची स्ट्रिंग तयार करण्यासाठी कस्टम 26-अक्षरी अल्फान्यूमेरिक कॅरेक्टर ॲरे (23456789BCDFGHJKMNPQRTVWXY) द्वारे काढलेला पूर्णांक मॅप करतो.
थेट 100% क्लायंट-साइड TOTP कोड जनरेशनचा अनुभव घ्या
2FA-Tool हीच तंतोतंत क्रिप्टोग्राफिक पाइपलाइन W3C Web Crypto API वापरून थेट तुमच्या ब्राउझरमध्ये लागू करते. शून्य सर्व्हर ट्रान्समिशन, शून्य टोकन स्टोरेज, त्वरित प्रमाणीकरण.