આધુનિક વેબ સિક્યુરિટીના પાયાના ક્રિપ્ટોગ્રાફિક પ્રોટોકોલ્સમાં, RFC 6238 (TOTP: Time-Based One-Time Password Algorithm) તેની ગાણિતિક સરળતા માટે અલગ તરી આવે છે. તેને કોઈ ઇન્ટરેક્ટિવ નેટવર્ક હેન્ડશેક, કોઈ સેન્ટ્રલાઇઝ્ડ પબ્લિક કી ઇન્ફ્રાસ્ટ્રક્ચર (PKI) અથવા ક્લાઉડ રાઉન્ડ-ટ્રીપ્સની જરૂર પડતી નથી. માત્ર એક શેર કરેલી Base32 સિક્રેટ કી અને ભૌતિક Unix સમયના સતત આગળ વધવા સાથે, ક્લાયન્ટ અને સર્વર દર 30 સેકન્ડે 100% ગાણિતિક ચોકસાઈ સાથે સમાન, ક્ષણિક 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 ઓપરેશનલ નબળાઈથી પીડાતું હતું: કાઉન્ટર ડિસિંક્રોનાઇઝેશન. જો કોઈ વપરાશકર્તા અજાણતા તેમના ખિસ્સામાં રહેલા હાર્ડવેર ડોંગલ પરનું બટન પાંચ વખત દબાવી દે, તો ક્લાયન્ટ કાઉન્ટર $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$ માં ડીકોડ કરે છે.
વર્તમાન Unix ટાઇમસ્ટેમ્પ (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-અક્ષરની આઉટપુટ સ્ટ્રિંગ સુનિશ્ચિત કરવા માટે પરિણામને ડાબી બાજુ શૂન્ય (zeroes) સાથે પેડ કરો:
03. રનેબલ કોડ 1: Python 3 સ્ટાન્ડર્ડ લાઇબ્રેરી
આ સંપૂર્ણ ઇમ્પ્લીમેન્ટેશન Python ના બિલ્ટ-ઇન base64, struct, hmac અને hashlib મોડ્યુલોનો ઉપયોગ કરે છે, જેમાં કોઈ pip પેકેજની જરૂર નથી:
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 Appendix B ટેસ્ટ વેક્ટર્સ વેરિફિકેશન
સ્ટાન્ડર્ડ પાલન સાબિત કરવા માટે, દરેક ક્રિપ્ટોગ્રાફિક ઇમ્પ્લીમેન્ટેશન IETF RFC 6238 Appendix B માં પ્રકાશિત થયેલા સત્તાવાર ટેસ્ટ વેક્ટર્સ સામે ચકાસવું આવશ્યક છે.
સત્તાવાર ટેસ્ટ સ્યુટ ASCII સિક્રેટ "12345678901234567890" (20 બાઈટ્સ) નો ઉપયોગ કરે છે, જે Base32 માં નીચે પ્રમાણે એન્કોડ થાય છે:
GEZDGNBVGY3TQOJQGEZDGNBVGY3TQOJQ (30-સેકન્ડના સ્ટેપ્સ સાથે 8-અંકના આઉટપુટ માટે મૂલ્યાંકન કરેલ):
| Unix Epoch ટાઇમસ્ટેમ્પ | UTC તારીખ અને સમય | RFC સત્તાવાર અપેક્ષિત કોડ | ઇમ્પ્લીમેન્ટેશન પરિણામ |
|---|---|---|---|
| 59 | 1970-01-01 00:00:59 | 94287082 | ✓ પાસ થયું (ચોક્કસ મેચ / Exact Match) |
| 1111111109 | 2005-03-18 01:58:29 | 07081804 | ✓ પાસ થયું (ચોક્કસ મેચ / Exact Match) |
| 1111111111 | 2005-03-18 01:58:31 | 14050471 | ✓ પાસ થયું (ચોક્કસ મેચ / Exact Match) |
| 1234567890 | 2009-02-13 23:31:30 | 89005924 | ✓ પાસ થયું (ચોક્કસ મેચ / Exact Match) |
| 2000000000 | 2033-05-18 03:33:20 | 69279037 | ✓ પાસ થયું (ચોક્કસ મેચ / Exact Match) |
07. પ્રોડક્શન એન્જિનિયરિંગ: ક્લોક ડ્રિફ્ટ, રીપ્લે અને રેટ લિમિટ્સ
હાઇ-અવેલેબિલિટી એન્ટરપ્રાઇઝ ઓથેન્ટિકેશન સિસ્ટમ્સમાં TOTP વેરિફિકેશન ડિપ્લોય કરતી વખતે, ત્રણ સુરક્ષા આવશ્યકતાઓ લાગુ કરવી આવશ્યક છે:
મોબાઇલ ક્લોકની સામાન્ય અચોક્કસતાઓને કારણે, સર્વર્સે [T - 1, T, T + 1] વિન્ડોનું મૂલ્યાંકન કરવું જોઈએ (અગાઉની 30 સેકન્ડ, વર્તમાન 30 સેકન્ડ અને આગામી 30 સેકન્ડ તપાસવી). વિન્ડોને ક્યારેય $\pm 1$ સ્ટેપથી આગળ વધારશો નહીં, કારણ કે દરેક વધારાનું સ્ટેપ રીપ્લે એટેક સરફેસને 30 સેકન્ડ સુધી વિસ્તૃત કરે છે.
સફળ ઉપયોગ પછી ટોકન તરત જ અમાન્ય (invalid) થવું જોઈએ. Redis અથવા ઇન-મેમરી કેશમાં Last_Verified_Time_Step સ્ટોર કરો. જો કોઈ ક્લાયન્ટ તે જ 30-સેકન્ડની વિન્ડોમાં સમાન ટોકન સબમિટ કરવાનો પ્રયાસ કરે છે, તો મેન-ઇન-ધ-મિડલ રીપ્લે હુમલાઓને નિષ્ક્રિય કરવા માટે વિનંતીને નકારી કાઢો.
કારણ કે 6-અંકના કોડ્સ માત્ર 1,000,000 પરમ્યુટેશન ધરાવે છે, અનથ્રોટલ્ડ એન્ડપોઇન્ટ્સ પર ઝડપથી બ્રુટ-ફોર્સ હુમલો થઈ શકે છે. સતત 3 નિષ્ફળતાઓ પછી પ્રોગ્રેસિવ વિલંબ અને એકાઉન્ટ લોકઆઉટ લાગુ કરો. સાઇડ-ચેનલ ટાઇમિંગ એનાલિસિસને નિષ્ફળ બનાવવા માટે કોડમાં સતત-સમય (constant-time) સમાનતા કાર્યો (દા.ત., Go માં crypto/subtle.ConstantTimeCompare અથવા Node.js માં crypto.timingSafeEqual) નો ઉપયોગ કરીને સરખામણી કરો.
08. વારંવાર પૂછાતા પ્રશ્નો (FAQ)
પ્રશ્ન 1: જો SHA-1 ક્રિપ્ટોગ્રાફિક રીતે નબળું સાબિત થયું છે, તો પછી TOTP હજુ પણ ડિફોલ્ટ રૂપે HMAC-SHA1 નો ઉપયોગ શા માટે કરે છે? ▼
કાચા SHA-1 સામેના સૈદ્ધાંતિક અથડામણ (collision) હુમલાઓ HMAC કન્સ્ટ્રક્શન (RFC 2104) ને તોડતા નથી. HMAC માં, અંતર્ગત હેશ ફંક્શન આંતરિક અને બાહ્ય સિક્રેટ કીની અંદર નેસ્ટેડ હોય છે, જે અથડામણ-આધારિત હુમલાઓને નિષ્ક્રિય કરે છે. આજ સુધી, HMAC-SHA1 2FA માટે સુરક્ષિત રહે છે. વધુમાં, જો ઉચ્ચ સુરક્ષાની જરૂર હોય તો RFC 6238 HMAC-SHA256 અને HMAC-SHA512 ને સંપૂર્ણપણે સપોર્ટ કરે છે.
પ્રશ્ન 2: શું ટાઇમ ઝોન અથવા ડેલાઇટ સેવિંગ ટાઇમ (DST) TOTP સિંક્રોનાઇઝેશનને અસર કરે છે? ▼
ના. Unix epoch સમયને 1970-01-01 00:00:00 UTC થી વીતેલી સેકન્ડ તરીકે વ્યાખ્યાયિત કરવામાં આવે છે. તે ટાઇમ ઝોન, લીપ સેકન્ડ્સ અને ડેલાઇટ સેવિંગ શિફ્ટ્સથી સંપૂર્ણપણે મુક્ત છે. સમયની કોઈપણ ચોક્કસ ક્ષણે, ટોક્યોમાં સર્વર અને કેલિફોર્નિયામાં સ્માર્ટફોન બંને પાસે બરાબર સમાન પૂર્ણાંક ટાઇમસ્ટેમ્પ હોય છે.
પ્રશ્ન 3: Steam Guard 5-અક્ષરનું ઓથેન્ટિકેશન RFC 6238 થી કેવી રીતે અલગ છે? ▼
Steam Guard એ RFC 6238 પર આધારિત માલિકીનું (proprietary) વેરિઅન્ટ છે. તે સમાન 30-સેકન્ડના ટાઇમ-સ્ટેપ અને HMAC-SHA1 ગણતરીનો ઉપયોગ કરે છે, પરંતુ અંતિમ રિડક્શન તબક્કામાં, તે 5-અક્ષરની સ્ટ્રિંગ બનાવવા માટે કસ્ટમ 26-અક્ષર આલ્ફાન્યૂમેરિક કેરેક્ટર એરે (23456789BCDFGHJKMNPQRTVWXY) દ્વારા એક્સટ્રેક્ટ કરેલા પૂર્ણાંકને મેપ કરે છે.
100% ક્લાયન્ટ-સાઇડ TOTP કોડ જનરેશનનો લાઈવ અનુભવ કરો
2FA-Tool W3C Web Crypto API નો ઉપયોગ કરીને સીધા તમારા બ્રાઉઝરની અંદર આ ચોક્કસ ક્રિપ્ટોગ્રાફિક પાઇપલાઇનને અમલમાં મૂકે છે. ઝીરો સર્વર ટ્રાન્સમિશન, ઝીરો ટોકન સ્ટોરેજ, તાત્કાલિક માન્યતા.