Kendi kendine çalışan (ör. LAMP yığını) web uygulamalarında Google Authenticator'ı (iki faktörlü kimlik doğrulama) kullanmak için herkese açık API var mı ?
Kendi kendine çalışan (ör. LAMP yığını) web uygulamalarında Google Authenticator'ı (iki faktörlü kimlik doğrulama) kullanmak için herkese açık API var mı ?
Yanıtlar:
Proje açık kaynak. Ben kullanmadım. Ancak, belgelenmiş bir algoritma kullanıyor (açık kaynak proje sayfasında listelenen RFC'de belirtilmiştir) ve kimlik doğrulayıcı uygulamaları birden çok hesabı destekler.
Gerçek süreç basittir. Tek seferlik kod esasen sözde rasgele sayı üretecidir. Rastgele sayı üreteci, bir tohum veya başlangıç numarası verildiğinde rastgele sayılar akışı oluşturmaya devam eden bir formüldür. Bir tohum verildiğinde, sayılar birbirine rasgele olabilirken, dizinin kendisi deterministiktir. Dolayısıyla, cihazınızı ve sunucunuzu "senkronize" ettikten sonra, "sonraki sayı düğmesine" her bastığınızda, cihazın oluşturduğu rastgele sayılar, sunucunun beklediği rasgele sayılarla aynı olacaktır.
Tek seferlik güvenli bir şifre sistemi, rastgele sayı üretecinden daha karmaşıktır, ancak konsept benzerdir. Cihazı ve sunucuyu senkronize tutmaya yardımcı olacak başka ayrıntılar da vardır.
Dolayısıyla, OAuth gibi kimlik doğrulamayı başka birinin barındırmasına gerek yoktur. Bunun yerine, Google'ın mobil cihazlar için sağladığı uygulamalarla uyumlu olan bu algoritmayı uygulamanız gerekir. Bu yazılım, açık kaynak projesinde mevcut (olmalıdır).
Kapsamlılığınıza bağlı olarak, bu işlemin sunucu tarafını uygulamak için ihtiyacınız olan her şeye OSS projesini ve RFC'yi vermelisiniz. Sunucu yazılımınız için özel bir uygulama olup olmadığını bilmiyorum (PHP, Java, .NET, vb.)
Ancak, özellikle bununla başa çıkmak için tesis dışında bir hizmete ihtiyacınız yoktur.
Algoritma, RFC6238'de belgelenmiştir . Biraz şuna benzer:
Burada javascript algoritmasını uygulayan bir oyun yaşadım: http://blog.tinisles.com/2011/10/google-authenticator-one-time-password-algorithm-in-javascript/
PHP için çeşitli kitaplıklar vardır (LAMP Yığını)
PHP
https://code.google.com/p/ga4php/
http://www.idontplaydarts.com/2011/07/google-totp-two-factor-authentication-for-php/
İki faktörlü kimlik doğrulamayı uygularken dikkatli olmalısınız, sunucu ve istemcideki saatlerinizi senkronize etmelisiniz, belirteçte kaba kuvvet saldırılarına karşı koruma bulunduğundan ve kullanılan ilk tohumun uygun büyüklükte olduğundan emin olmalısınız.
Sen edebilirsiniz benim çözüm kullanmak , soruma cevap olarak yayınlanmıştır (orada tam Python kodu ve açıklama ):
PHP veya Perl'de uygulamak oldukça kolaydır, bence. Bununla ilgili herhangi bir sorununuz olursa lütfen bize bildirin.
Kodumu GitHub'a Python modülü olarak da gönderdim .
Bunu buldum: https://github.com/PHPGangsta/GoogleAuthenticator . Test ettim ve benim için iyi çalışıyor.
LAMP değil, ancak C # kullanıyorsanız, kullandığım kod budur:
Orijinal kod:
https://github.com/kspearrin/Otp.NET
Base32Encoding sınıfı bu cevaptan geliyor:
https://stackoverflow.com/a/7135008/3850405
Örnek program:
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");
}
}
Var: https://www.gauthify.com onu hizmet olarak sunan
Laravel kullananlar için bu https://github.com/sitepoint-editors/google-laravel-2FA bu sorunu çözmenin güzel bir yoludur.
C # kullanıcısı için, bir defalık jeton kodunun nasıl doğrulanacağını anlamak için bu basit Konsol Uygulamasını çalıştırın. Öncelikle Nuget paketinden kitaplık Otp.Net'i kurmamız gerektiğini unutmayın .
static string secretKey = "JBSWY3DPEHPK3PXP"; //add this key to your Google Authenticator app
private static void Main(string[] args)
{
var bytes = Base32Encoding.ToBytes(secretKey);
var totp = new Totp(bytes);
while (true)
{
Console.Write("Enter your code from Google Authenticator app: ");
string userCode = Console.ReadLine();
//Generate one time token code
string tokenInApp = totp.ComputeTotp();
int remainingSeconds = totp.RemainingSeconds();
if (userCode.Equals(tokenInApp)
&& remainingSeconds > 0)
{
Console.WriteLine("Success!");
}
else
{
Console.WriteLine("Failed. Try again!");
}
}
}