पायथन में Google प्रमाणक कार्यान्वयन


104

मैं एक समय के पासवर्ड का उपयोग करने की कोशिश कर रहा हूं जो Google प्रमाणक एप्लिकेशन का उपयोग करके उत्पन्न किया जा सकता है ।

Google प्रमाणक क्या करता है

मूल रूप से, Google प्रमाणक दो प्रकार के पासवर्ड लागू करता है:

  • HOTP - HMAC आधारित एक बार पासवर्ड, जो पासवर्ड का मतलब करने के लिए अनुपालन में प्रत्येक कॉल के साथ बदल गया है, RFC4226 , और
  • TOTP - समय-आधारित वन-टाइम पासवर्ड, जो हर 30-सेकंड की अवधि के लिए बदलता है (जहाँ तक मुझे पता है)।

Google प्रमाणक यहां ओपन सोर्स के रूप में भी उपलब्ध है: code.google.com/p/google-authenticator

वर्तमान कोड

मैं HOTP और TOTP पासवर्ड जनरेट करने के लिए मौजूदा समाधानों की तलाश में था, लेकिन बहुत कुछ नहीं मिला। कोड मेरे पास निम्न स्निपेट है जो HOTP उत्पन्न करने के लिए जिम्मेदार है:

import hmac, base64, struct, hashlib, time

def get_token(secret, digest_mode=hashlib.sha1, intervals_no=None):
    if intervals_no == None:
        intervals_no = int(time.time()) // 30
    key = base64.b32decode(secret)
    msg = struct.pack(">Q", intervals_no)
    h = hmac.new(key, msg, digest_mode).digest()
    o = ord(h[19]) & 15
    h = (struct.unpack(">I", h[o:o+4])[0] & 0x7fffffff) % 1000000
    return h

मैं जिस समस्या का सामना कर रहा हूं वह यह है कि उपरोक्त कोड का उपयोग करके मैंने जो पासवर्ड उत्पन्न किया है, वह एंड्रॉइड के लिए Google प्रमाणक ऐप का उपयोग करके उत्पन्न नहीं है। भले ही मैंने जीए ऐप के भीतर प्रदान की गई कुंजी के बराबर होने के साथ कई intervals_noमूल्यों (बिल्कुल पहले 10000, शुरुआत के साथ intervals_no = 0) की कोशिश की secret

प्रश्न मेरे पास हैं

मेरे प्रश्न हैं:

  1. मैं क्या गलत कर रहा हूं?
  2. मैं पायथन में HOTP और / या TOTP कैसे उत्पन्न कर सकता हूं?
  3. क्या इसके लिए कोई मौजूदा पायथन लाइब्रेरी हैं?

योग करने के लिए: कृपया मुझे कोई भी सुराग दें जो मेरे पायथन कोड के भीतर Google प्रमाणक प्रमाणीकरण को लागू करने में मेरी मदद करेगा।

जवाबों:


152

मैं अपने प्रश्न पर एक इनाम निर्धारित करना चाहता था, लेकिन मैं समाधान बनाने में सफल रहा। मेरी समस्या को secretकुंजी के गलत मान के साथ जोड़ा गया लग रहा था (यह base64.b32decode()फ़ंक्शन के लिए सही पैरामीटर होना चाहिए )।

नीचे मैं इसका उपयोग करने के तरीके के बारे में स्पष्टीकरण के साथ पूर्ण कार्य समाधान पोस्ट करता हूं।

कोड

निम्नलिखित कोड पर्याप्त है। मैंने इसे GitHub पर अलग-अलग मॉड्यूल के रूप में अपलोड किया है जिसे ऑनटाइमपास (यहाँ उपलब्ध: https://github.com/tadeck/onetimepass ) कहा जाता है ।

import hmac, base64, struct, hashlib, time

def get_hotp_token(secret, intervals_no):
    key = base64.b32decode(secret, True)
    msg = struct.pack(">Q", intervals_no)
    h = hmac.new(key, msg, hashlib.sha1).digest()
    o = ord(h[19]) & 15
    h = (struct.unpack(">I", h[o:o+4])[0] & 0x7fffffff) % 1000000
    return h

def get_totp_token(secret):
    return get_hotp_token(secret, intervals_no=int(time.time())//30)

इसके दो कार्य हैं:

  • get_hotp_token() एक बार टोकन उत्पन्न करता है (जो एकल उपयोग के बाद अमान्य होना चाहिए),
  • get_totp_token() समय के आधार पर टोकन उत्पन्न करता है (30 सेकंड के अंतराल में परिवर्तित),

पैरामीटर

जब मापदंडों की बात आती है:

  • secret सर्वर (उपरोक्त स्क्रिप्ट) और क्लाइंट के लिए जाना जाने वाला एक गुप्त मान है (Google प्रमाणक, आवेदन के भीतर पासवर्ड के रूप में प्रदान करके),
  • intervals_no टोकन की प्रत्येक पीढ़ी के बाद संख्या में वृद्धि हुई है (यह संभवतया सर्वर पर हल किया जाना चाहिए पूर्णांक की कुछ परिमित संख्या की जांच करने के बाद पिछले सफल जाँच के बाद)

इसे कैसे उपयोग करे

  1. उत्पन्न करें secret(इसके लिए सही पैरामीटर होना चाहिए base64.b32decode()) - अधिमानतः 16-चार (कोई =संकेत नहीं ), क्योंकि यह निश्चित रूप से स्क्रिप्ट और Google प्रमाणक दोनों के लिए काम करता है।
  2. का प्रयोग करें get_hotp_token()आप एक बार पासवर्ड प्रत्येक उपयोग के बाद अवैध चाहते हैं। Google प्रमाणक में इस प्रकार के पासवर्ड का उल्लेख किया गया है जो काउंटर पर आधारित हैं। सर्वर पर इसे जाँचने के लिए आपको कई मानों की जाँच करने की आवश्यकता होगी intervals_no(जैसा कि आपके पास कोई संगरोध नहीं है कि उपयोगकर्ता ने किसी कारण से अनुरोधों के बीच पास उत्पन्न नहीं किया है), लेकिन पिछले काम के intervals_noमूल्य से कम नहीं है (इस प्रकार आपको शायद इसे स्टोर करना चाहिए कहीं)।
  3. उपयोग करें get_totp_token(), यदि आप 30 सेकंड के अंतराल में एक टोकन काम करना चाहते हैं। आपको यह सुनिश्चित करना होगा कि दोनों प्रणालियों का सही समय निर्धारित है (इसका अर्थ है कि वे दोनों किसी भी समय एक ही यूनिक्स टाइमस्टैम्प उत्पन्न करते हैं)।
  4. अपने आप को ब्रूट-फोर्स हमले से बचाने के लिए सुनिश्चित करें। यदि समय-आधारित पासवर्ड का उपयोग किया जाता है, तो 30 सेकंड से कम समय में 1000000 मानों की कोशिश करने से पासवर्ड का अनुमान लगाने का 100% मौका मिलता है। HMAC- आधारित पैसोड्र्स (HOTPs) के मामले में यह और भी बुरा लगता है।

उदाहरण

एक बार एचएमएसी-आधारित पासवर्ड के लिए निम्नलिखित कोड का उपयोग करते समय:

secret = 'MZXW633PN5XW6MZX'
for i in xrange(1, 10):
    print i, get_hotp_token(secret, intervals_no=i)

आपको निम्न परिणाम मिलेगा:

1 448400
2 656122
3 457125
4 35022
5 401553
6 581333
7 16329
8 529359
9 171710

जो Google ऑथेंटिकेटर ऐप द्वारा उत्पन्न टोकन के अनुरूप है (यदि 6 संकेतों से छोटा है, तो ऐप 6 शून्य की लंबाई तक पहुंचने के लिए शुरुआत में शून्य जोड़ता है)।


3
@ बर्धन: यदि आपको कोड की आवश्यकता है, तो मैंने इसे GitHub (यहां: https://github.com/tadeck/onetimepass ) पर भी अपलोड कर दिया है , इसलिए इसे अलग मॉड्यूल के रूप में परियोजनाओं के भीतर उपयोग करना काफी आसान होना चाहिए। का आनंद लें!
ताडेक

1
मुझे इस कोड के साथ एक समस्या थी क्योंकि मैं जिस 'गुप्त' सेवा के द्वारा प्रदान किया गया था, मैं लॉग इन करने की कोशिश कर रहा था, अपरकेस नहीं था। "कुंजी = base64.b32decode (गुप्त, सत्य)" पढ़ने के लिए पंक्ति 4 को बदलना मेरे लिए समस्या को निर्धारित करता है।
क्रिस मूर

1
@ क्रिसमोर: मैंने कोड को अपडेट किया है casefold=Trueताकि लोगों को अब ऐसी ही समस्या न हो। आपके सहयोग के लिए धन्यवाद।
टाडेक

3
मुझे एक साइट द्वारा सिर्फ 23 चरित्र का रहस्य दिया गया था। जब मैं यह रहस्य देता हूं तो आपका कोड "टाइपर्रर: गलत पैडिंग" से विफल हो जाता है। गुप्त को इस तरह से जोड़ना, समस्या को ठीक करता है: key = base64.b32decode (गुप्त + '====' [: 3 - (((गुप्त) -1)% 4)], सत्य)
क्रिस मूर

3
अजगर 3 के लिए: परिवर्तन: ord(h[19]) & 15में: o = h[19] & 15 धन्यवाद बीटीडब्लू
ऑरविल

6

मैं TOTP पासवर्ड उत्पन्न करने के लिए एक अजगर स्क्रिप्ट चाहता था। इसलिए, मैंने अजगर की पटकथा लिखी। यह मेरा कार्यान्वयन है। मेरे पास विकिपीडिया पर यह जानकारी है और इस स्क्रिप्ट को लिखने के लिए HOTP और TOTP के बारे में कुछ ज्ञान है।

import hmac, base64, struct, hashlib, time, array

def Truncate(hmac_sha1):
    """
    Truncate represents the function that converts an HMAC-SHA-1
    value into an HOTP value as defined in Section 5.3.

    http://tools.ietf.org/html/rfc4226#section-5.3

    """
    offset = int(hmac_sha1[-1], 16)
    binary = int(hmac_sha1[(offset * 2):((offset * 2) + 8)], 16) & 0x7fffffff
    return str(binary)

def _long_to_byte_array(long_num):
    """
    helper function to convert a long number into a byte array
    """
    byte_array = array.array('B')
    for i in reversed(range(0, 8)):
        byte_array.insert(0, long_num & 0xff)
        long_num >>= 8
    return byte_array

def HOTP(K, C, digits=6):
    """
    HOTP accepts key K and counter C
    optional digits parameter can control the response length

    returns the OATH integer code with {digits} length
    """
    C_bytes = _long_to_byte_array(C)
    hmac_sha1 = hmac.new(key=K, msg=C_bytes, digestmod=hashlib.sha1).hexdigest()
    return Truncate(hmac_sha1)[-digits:]

def TOTP(K, digits=6, window=30):
    """
    TOTP is a time-based variant of HOTP.
    It accepts only key K, since the counter is derived from the current time
    optional digits parameter can control the response length
    optional window parameter controls the time window in seconds

    returns the OATH integer code with {digits} length
    """
    C = long(time.time() / window)
    return HOTP(K, C, digits=digits)

दिलचस्प है, लेकिन आप इसे पाठक के लिए और अधिक समझने की इच्छा कर सकते हैं। कृपया चर नामों को अधिक सार्थक बनाएं, या डोकस्ट्रिंग्स जोड़ें। इसके अलावा, PEP8 का अनुसरण करने से आपको अधिक समर्थन मिल सकता है। क्या आपने इन दो समाधानों के बीच प्रदर्शन की तुलना की? अंतिम प्रश्न: क्या आपका समाधान Google प्रमाणक के साथ संगत है (जैसा कि प्रश्न इस विशिष्ट समाधान के बारे में था)?
ताडेक

@ टैडेक मैंने कुछ टिप्पणियां जोड़ी हैं। और मुझे इस स्क्रिप्ट का उपयोग करके अपनी चीजें मिल गईं। तो हाँ, यह पूरी तरह से काम करना चाहिए।
अनिश शाह
हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.