security - recuperar - Google Authenticator disponible como un servicio público?
google authenticator mac (9)
El project es de código abierto. No lo he usado. Pero está usando un algoritmo documentado (anotado en el RFC que figura en la página del proyecto de código abierto), y las implementaciones del autenticador admiten múltiples cuentas.
El proceso real es sencillo. El código de una sola vez es, esencialmente, un generador de números pseudoaleatorios. Un generador de números aleatorios es una fórmula que una vez que se le da una semilla o número inicial, continúa creando una secuencia de números aleatorios. Dada una semilla, mientras que los números pueden ser aleatorios entre sí, la secuencia en sí misma es determinista. Entonces, una vez que tenga su dispositivo y el servidor "sincronizados", los números aleatorios que crea el dispositivo, cada vez que presione el "botón del próximo número", serán los mismos números aleatorios que el servidor espera.
Un sistema seguro de contraseña de una sola vez es más sofisticado que un generador de números aleatorios, pero el concepto es similar. También hay otros detalles para ayudar a mantener el dispositivo y el servidor sincronizados.
Por lo tanto, no es necesario que otra persona aloje la autenticación, como, por ejemplo, OAuth. En su lugar, debe implementar ese algoritmo que sea compatible con las aplicaciones que Google proporciona para los dispositivos móviles. Ese software está (debería estar) disponible en el proyecto de código abierto.
Dependiendo de su sofisticación, debe tener todo lo que necesita para implementar el lado del servidor de este proceso, dar el proyecto OSS y el RFC. No sé si hay una implementación específica para su software de servidor (PHP, Java, .NET, etc.)
Pero, específicamente, no necesita un servicio externo para manejar esto.
¿Existe una API pública para usar Google Authenticator ( autenticación de dos factores) en aplicaciones web autoejecutables (por ejemplo, LAMP stack)?
El algoritmo está documentado en RFC6238 . Se parece un poco a esto:
- su servidor le da al usuario un secreto para instalarlo en Google Authenticator. Google hace esto como un código QR documentado here .
- Google Authenticator genera un código de 6 dígitos de SHA1-HMAC del tiempo Unix y el secreto (hay muchos más detalles al respecto en el RFC)
- El servidor también conoce el tiempo secreto / unix para verificar el código de 6 dígitos.
He tenido una jugada implementando el algoritmo en javascript aquí: http://blog.tinisles.com/2011/10/google-authenticator-one-time-password-algorithm-in-javascript/
Encontré esto: https://github.com/PHPGangsta/GoogleAuthenticator . Lo probé y funciona bien para mí.
Hay una variedad de bibliotecas para PHP (The LAMP Stack)
PHP
https://code.google.com/p/ga4php/
http://www.idontplaydarts.com/2011/07/google-totp-two-factor-authentication-for-php/
Debe tener cuidado al implementar autenticación de dos factores, necesita asegurarse de que sus relojes en el servidor y el cliente estén sincronizados, que haya protección en su lugar contra los ataques de fuerza bruta en el token y que la semilla inicial utilizada sea adecuadamente grande.
No LAMP pero si usas C # este es el código que uso:
Código original de:
https://github.com/kspearrin/Otp.NET
La clase Base32Encoding es de esta respuesta:
https://.com/a/7135008/3850405
Programa de ejemplo:
class Program
{
static void Main(string[] args)
{
var bytes = Base32Encoding.ToBytes("JBSWY3DPEHPK3PXP");
var totp = new Totp(bytes);
var result = totp.ComputeTotp();
var remainingTime = totp.RemainingSeconds();
}
}
Totp:
public class Totp
{
const long unixEpochTicks = 621355968000000000L;
const long ticksToSeconds = 10000000L;
private const int step = 30;
private const int totpSize = 6;
private byte[] key;
public Totp(byte[] secretKey)
{
key = secretKey;
}
public string ComputeTotp()
{
var window = CalculateTimeStepFromTimestamp(DateTime.UtcNow);
var data = GetBigEndianBytes(window);
var hmac = new HMACSHA1();
hmac.Key = key;
var hmacComputedHash = hmac.ComputeHash(data);
int offset = hmacComputedHash[hmacComputedHash.Length - 1] & 0x0F;
var otp = (hmacComputedHash[offset] & 0x7f) << 24
| (hmacComputedHash[offset + 1] & 0xff) << 16
| (hmacComputedHash[offset + 2] & 0xff) << 8
| (hmacComputedHash[offset + 3] & 0xff) % 1000000;
var result = Digits(otp, totpSize);
return result;
}
public int RemainingSeconds()
{
return step - (int)(((DateTime.UtcNow.Ticks - unixEpochTicks) / ticksToSeconds) % step);
}
private byte[] GetBigEndianBytes(long input)
{
// Since .net uses little endian numbers, we need to reverse the byte order to get big endian.
var data = BitConverter.GetBytes(input);
Array.Reverse(data);
return data;
}
private long CalculateTimeStepFromTimestamp(DateTime timestamp)
{
var unixTimestamp = (timestamp.Ticks - unixEpochTicks) / ticksToSeconds;
var window = unixTimestamp / (long)step;
return window;
}
private string Digits(long input, int digitCount)
{
var truncatedValue = ((int)input % (int)Math.Pow(10, digitCount));
return truncatedValue.ToString().PadLeft(digitCount, ''0'');
}
}
Base32Encoding:
public static class Base32Encoding
{
public static byte[] ToBytes(string input)
{
if (string.IsNullOrEmpty(input))
{
throw new ArgumentNullException("input");
}
input = input.TrimEnd(''=''); //remove padding characters
int byteCount = input.Length * 5 / 8; //this must be TRUNCATED
byte[] returnArray = new byte[byteCount];
byte curByte = 0, bitsRemaining = 8;
int mask = 0, arrayIndex = 0;
foreach (char c in input)
{
int cValue = CharToValue(c);
if (bitsRemaining > 5)
{
mask = cValue << (bitsRemaining - 5);
curByte = (byte)(curByte | mask);
bitsRemaining -= 5;
}
else
{
mask = cValue >> (5 - bitsRemaining);
curByte = (byte)(curByte | mask);
returnArray[arrayIndex++] = curByte;
curByte = (byte)(cValue << (3 + bitsRemaining));
bitsRemaining += 3;
}
}
//if we didn''t end with a full byte
if (arrayIndex != byteCount)
{
returnArray[arrayIndex] = curByte;
}
return returnArray;
}
public static string ToString(byte[] input)
{
if (input == null || input.Length == 0)
{
throw new ArgumentNullException("input");
}
int charCount = (int)Math.Ceiling(input.Length / 5d) * 8;
char[] returnArray = new char[charCount];
byte nextChar = 0, bitsRemaining = 5;
int arrayIndex = 0;
foreach (byte b in input)
{
nextChar = (byte)(nextChar | (b >> (8 - bitsRemaining)));
returnArray[arrayIndex++] = ValueToChar(nextChar);
if (bitsRemaining < 4)
{
nextChar = (byte)((b >> (3 - bitsRemaining)) & 31);
returnArray[arrayIndex++] = ValueToChar(nextChar);
bitsRemaining += 5;
}
bitsRemaining -= 3;
nextChar = (byte)((b << bitsRemaining) & 31);
}
//if we didn''t end with a full char
if (arrayIndex != charCount)
{
returnArray[arrayIndex++] = ValueToChar(nextChar);
while (arrayIndex != charCount) returnArray[arrayIndex++] = ''=''; //padding
}
return new string(returnArray);
}
private static int CharToValue(char c)
{
int value = (int)c;
//65-90 == uppercase letters
if (value < 91 && value > 64)
{
return value - 65;
}
//50-55 == numbers 2-7
if (value < 56 && value > 49)
{
return value - 24;
}
//97-122 == lowercase letters
if (value < 123 && value > 96)
{
return value - 97;
}
throw new ArgumentException("Character is not a Base32 character.", "c");
}
private static char ValueToChar(byte b)
{
if (b < 26)
{
return (char)(b + 65);
}
if (b < 32)
{
return (char)(b + 24);
}
throw new ArgumentException("Byte is not a value Base32 value.", "b");
}
}
Para quienes usan Laravel, este https://github.com/sitepoint-editors/google-laravel-2FA es una buena manera de resolver este problema.
Puede usar mi solución , publicada como la respuesta a mi pregunta (hay un código y una explicación completos de Python ):
Implementación de Google Authenticator en Python
Es bastante fácil implementarlo en PHP o Perl, creo. Si tiene algún problema con esto, hágamelo saber.
También publiqué mi código en GitHub como módulo de Python.
Sí, no necesita ningún servicio de red, porque la aplicación Google Authenticator no se comunicará con el servidor de Google, simplemente se sincroniza con el secreto inicial que genera su servidor (entrada en su teléfono a partir del código QR) mientras pasa el tiempo.
Theres: https://www.gauthify.com que lo ofrece como un servicio