Come funziona Google Authenticator?

191

Google Authenticator è un'alternativa agli SMS per la verifica 2Step, l'installazione di un'app su Android dove verranno inviati i codici.

Funziona senza alcuna connettività; funziona anche in modalità aereo. Questo è quello che non capisco. Com'è possibile che funzioni senza connettività? In che modo il telefono cellulare e il server si sincronizzano per sapere quale codice è valido in quel momento?

    
posta yzT 01.05.2013 - 17:24
fonte

5 risposte

165

Google Authenticator supporta sia il HOTP che TOTP algoritmi per la generazione di password monouso.

Con HOTP, il server e il client condividono un valore segreto e un contatore, che vengono utilizzati per calcolare una singola password indipendentemente su entrambi i lati. Ogni volta che viene generata e utilizzata una password, il contatore viene incrementato su entrambi i lati, consentendo al server e al client di rimanere sincronizzati.

TOTP utilizza essenzialmente lo stesso algoritmo di HOTP con una differenza importante. Il contatore utilizzato in TOTP viene sostituito dall'ora corrente. Il client e il server rimangono sincronizzati fintanto che gli orari di sistema rimangono gli stessi. Questo può essere fatto usando il protocollo dell'ora di rete .

La chiave segreta (così come il contatore nel caso di HOTP) deve essere comunicata sia al server che al client in un determinato momento. Nel caso di Google Authenticator, ciò avviene sotto forma di URI codificato in QRCode. Vedi: KeyUriFormat per ulteriori informazioni.

    
risposta data 01.05.2013 - 17:36
fonte
34

di funzionamento:

Authenticator implementa l'algoritmo TOTP (Time-Based One-Time Password). Ha i seguenti ingredienti:

• Un segreto condiviso (una sequenza di byte)

• Un input derivato dall'ora corrente

• Una funzione di firma

Segreto condiviso: Il segreto condiviso è ciò che devi ottenere per configurare l'account sul tuo telefono. O scatti una foto di un codice QR usando il tuo telefono o puoi inserire il segreto manualmente.

Input (ora corrente): Il valore del tempo di input che riceverai dal tuo telefono non richiede ulteriori interazioni con il server una volta ottenuto il segreto. Tuttavia, è importante che l'ora del tuo telefono sia precisa, in quanto il server ripeterà essenzialmente ciò che accade sul tuo telefono utilizzando l'ora corrente, come è noto al server.

Funzione di firma: La funzione di firma utilizzata è HMAC-SHA1. HMAC sta per codice di autenticazione dei messaggi basato su hash ed è un algoritmo che utilizza una funzione di hash unidirezionale (SHA1 in questo caso) per firmare un valore. L'utilizzo di un HMAC ci consente di verificare l'autenticità: solo le persone che conoscono il segreto possono generare lo stesso output per lo stesso input (l'ora corrente).

Algoritmo OTP:

Pseudo codice:

original_secret = xxxx xxxx xxxx xxxx xxxx xxxx xxxx xxxx

secret = BASE32_DECODE(TO_UPPERCASE(REMOVE_SPACES(original_secret)))

input = CURRENT_UNIX_TIME() / 30  // sets a constant value for 30 seconds

hmac = SHA1(secret + SHA1(secret + input)) //apply hashing

offset = hmac[len(hmac)-1] & 0x0F //Last nibble

four_bytes = hmac[offset : offset+4] //takes a subset of 4 bytes from 20 bytes

large_integer = INT(four_bytes) //Covert four bytes to integer

small_integer = large_integer % 1,000,00 //gives 6 digit code

Riferimento: link

Controlla anche questo progetto github per l'implementazione GO: link

    
risposta data 05.09.2016 - 21:08
fonte
14

Funzionerà su un seme in base al tempo, quindi è simile al modo in cui funzionano i telecomandi RSA. anche essi non richiedono alcuna connettività.

Ho appena dato un'occhiata e qui viene fornita una risposta qui: link

    
risposta data 01.05.2013 - 17:33
fonte
1

HOTP & Gli algoritmi TOTP sono ora diventati standard aperti nell'IT. Ciò significa che puoi utilizzare Google Authenticator non solo per Google, ma anche per Facebook, Yahoo, siti Web Microsoft o persino per il tuo sito web.

Tutto quello che devi fare è usare il seguente codice nella base principale del server:

import os

import bcrypt
from twilio.rest import TwilioRestClient
from flask.ext.login import LoginManager
from flask import Flask
from flask import request
from flask import redirect
from flask import url_for
from flask import render_template
from flask.ext.login import login_user
from flask.ext.login import logout_user
from flask.ext.login import current_user
from flask.ext.login import login_required
from pymongo import Connection

from konfig import Konfig

app = Flask(__name__)
konf = Konfig()
app.secret_key = konf.secret_key

connection = Connection(konf.mongo_url)

login_manager = LoginManager()
login_manager.setup_app(app)

twilio = TwilioRestClient()

@login_manager.user_loader
def load_user(user_id):
    return User(user_id)

class User:
    def __init__(self, user_id):
        self.id = user_id.lower()
        self.db = connection.tfa.users
        self.account = self.db.find_one({'uid': self.id})

    def create(self):
        self.db.insert({'uid': self.id})
        self.account = self.db.find_one({'uid': self.id})

    def save(self):
        self.db.save(self.account)

    def password_valid(self, pwd):
        pwd_hash = self.account['password_hash']
        return bcrypt.hashpw(pwd, pwd_hash) == pwd_hash

    # The methods below are required by flask-login
    def is_authenticated(self):
        """Always return true - we don't do any account verification"""
        return True

    def is_active(self):
        return True

    def is_anonymous(self):
        return False

    def get_id(self):
        return self.id

@app.route("/", methods=['GET', 'POST'])
def main_page():
    opts = {}
    if request.method == 'GET':
        return render_template('main_page.html', opts=opts)
    user = User(request.form['username'])
    if not user.account or not user.password_valid(request.form['password']):
        opts['invalid_username_or_password'] = True
        return render_template('main_page.html', opts=opts)
    login_user(user)
    return redirect(url_for('user'))

@app.route("/sign-up", methods=['GET', 'POST'])
def sign_up():
    opts = {}
    if request.method == 'GET':
        return render_template('sign_up.html', opts=opts)
    user = User(request.form['username'])
    if user.account:
        opts['username_exists'] = True
        return render_template('sign_up.html', opts=opts)
    if request.form['password1'] != request.form['password2']:
        opts['passwords_do_not_match'] = True
        return render_template('sign_up.html', opts=opts)
    user.create()
    pwd_hash = bcrypt.hashpw(request.form['password1'], bcrypt.gensalt())
    user.account['password_hash'] = pwd_hash
    user.save()
    login_user(user)
    return redirect(url_for('user'))

@app.route("/user")
@login_required
def user():
    opts = {'user': current_user,
            'logged_in': True}
    return render_template('user.html', opts=opts)

@app.route("/logout")
def logout():
    logout_user()
    return redirect(url_for('main_page'))

if __name__ == "__main__":
    # Bind to PORT if defined, otherwise default to 5000.
    port = int(os.environ.get('PORT', 5000))
    if port == 5000:
        app.debug = True
    app.run(host='0.0.0.0', port=port)

Cortesia: Kyle Kelly-Yahner

    
risposta data 24.07.2013 - 10:00
fonte
-2

Se un strace s è il daemon sshd , si può vedere come il server 'conosce' la chiave segreta, mentre legge il file di configurazione degli utenti:

#strace -f -v -e open /usr/sbin/sshd -p 2222 -dddd -f /etc/ssh/sshd_config 2>&1 | grep -i goog


> > [pid  2105] open("/home/myuser/.google_authenticator", O_RDONLY) = 4
> > [pid  2105] open("/home/myuser/.google_authenticator~",
> > O_WRONLY|O_CREAT|O_EXCL|O_TRUNC|O_NOFOLLOW, 0400debug3:
> > mm_sshpam_respond: pam_respond returned 1 [preauth]

Il telefono cellulare lo conosce già; l'hai scannerizzato tramite QR o l'hai digitato.

    
risposta data 21.01.2017 - 00:45
fonte