¿Cómo funciona el autenticador de Google?

187

Google Authenticator es una alternativa a SMS para la verificación 2Step, instalando una aplicación en Android donde se enviarán los códigos.

Funciona sin ninguna conectividad; Incluso funciona en modo plano. Esto es lo que no entiendo. ¿Cómo es posible que funcione sin conectividad? ¿Cómo se sincronizan el teléfono móvil y el servidor para saber qué código es válido en ese momento?

    
pregunta yzT 01.05.2013 - 17:24
fuente

5 respuestas

162

Google Authenticator admite tanto HOTP como TOTP algoritmos para generar contraseñas de un solo uso.

Con HOTP, el servidor y el cliente comparten un valor secreto y un contador, que se utilizan para calcular una contraseña de un solo uso de forma independiente en ambos lados. Cada vez que se genera y utiliza una contraseña, el contador se incrementa en ambos lados, lo que permite que el servidor y el cliente permanezcan sincronizados.

TOTP usa esencialmente el mismo algoritmo que HOTP con una diferencia importante. El contador usado en TOTP es reemplazado por la hora actual. El cliente y el servidor permanecen sincronizados mientras los tiempos del sistema permanezcan iguales. Esto se puede hacer utilizando el protocolo de tiempo de red .

La clave secreta (así como el contador en el caso de HOTP) se deben comunicar al servidor y al cliente en algún momento. En el caso de Google Authenticator, esto se realiza en forma de un URI codificado en QRCode. Consulte: KeyUriFormat para obtener más información.

    
respondido por el Ayrx 01.05.2013 - 17:36
fuente
33

Trabajo:

El autenticador implementa el algoritmo de contraseña de una sola vez (TOTP) basada en el tiempo. Tiene los siguientes ingredientes:

• Un secreto compartido (una secuencia de bytes)

• Una entrada derivada de la hora actual

• Una función de firma

Secreto compartido: El secreto compartido es lo que necesita obtener para configurar la cuenta en su teléfono. O toma una foto de un código QR con su teléfono o puede ingresar el secreto manualmente.

Entrada (hora actual): El valor de tiempo de entrada que simplemente obtendrá de su teléfono, no se requiere más interacción con el servidor una vez que haya obtenido el secreto. Sin embargo, es importante que la hora de su teléfono sea precisa, ya que el servidor esencialmente repetirá lo que sucede en su teléfono usando la hora actual conocida por el servidor.

Función de firma: La función de firma utilizada es HMAC-SHA1. HMAC significa código de autenticación de mensaje basado en Hash y es un algoritmo que utiliza una función de hash unidireccional segura (SHA1 en este caso) para firmar un valor. El uso de un HMAC nos permite verificar la autenticidad, solo las personas que saben el secreto pueden generar la misma salida para la misma entrada (la hora actual).

Algoritmo OTP:

Pseudo Código:

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

Referencia: enlace

También puedes ver este proyecto github para la implementación de GO: enlace

    
respondido por el Arjun SK 05.09.2016 - 21:08
fuente
14

Funcionará en una semilla basada en el tiempo, por lo que es similar a la forma en que funcionan los llaveros RSA. es decir, tampoco requieren ninguna conectividad.

Acabo de echar un vistazo y esto se responde aquí: enlace

    
respondido por el AndyMac 01.05.2013 - 17:33
fuente
1

HOTP & Los algoritmos TOTP ahora se han convertido en estándares abiertos en TI. Esto significa que puede usar Google Authenticator no solo para Google, sino también para los sitios web de Facebook, Yahoo, Microsoft o incluso su propio sitio web.

Todo lo que tienes que hacer es usar el siguiente código en la base principal del servidor:

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)

Cortesía: Kyle Kelly-Yahner

    
respondido por el Gaurav Jha 24.07.2013 - 10:00
fuente
-2

Si un strace s el daemon sshd , se puede ver cómo el servidor 'sabe' acerca de la clave secreta, mientras lee el archivo de configuración de los usuarios:

#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]

El teléfono móvil ya lo sabe; lo escaneaste a través de QR o lo escribiste.

    
respondido por el james6125 21.01.2017 - 00:45
fuente

Lea otras preguntas en las etiquetas