C# 应否";谷歌双因素认证器“;accountSecretKey是否存储到我的数据库中?

C# 应否";谷歌双因素认证器“;accountSecretKey是否存储到我的数据库中?,c#,two-factor-authentication,google-authenticator,authenticator,google-2fa,C#,Two Factor Authentication,Google Authenticator,Authenticator,Google 2fa,我试图了解Google双因素认证程序是如何工作的,以便将其整合到我的网站中。我的理解是,这个过程有两个不同的部分 我的网站上的用户启用了2FA,它在我的用户和应用程序之间创建了链接。这是一个一次性步骤,并非每次登录尝试都会发生 每次用户登录时,他都需要从Google Authenticator应用程序中提供一个六位数的代码 现在,使用下面的代码,生成QR图像和设置代码以启用2FA并将帐户链接到Google Authenticate TwoFactorAuthenticator tfa = new

我试图了解Google双因素认证程序是如何工作的,以便将其整合到我的网站中。我的理解是,这个过程有两个不同的部分

  • 我的网站上的用户启用了2FA,它在我的用户和应用程序之间创建了链接。这是一个一次性步骤,并非每次登录尝试都会发生
  • 每次用户登录时,他都需要从Google Authenticator应用程序中提供一个六位数的代码
  • 现在,使用下面的代码,生成QR图像和设置代码以启用2FA并将帐户链接到Google Authenticate

    TwoFactorAuthenticator tfa = new TwoFactorAuthenticator();
    string accountSecretKey = Guid.NewGuid();
    var setupInfo = tfa.GenerateSetupCode("Dotnet Awesome", login.Username, accountSecretKey, 300, 300);
    ViewBag.BarcodeImageUrl = setupInfo.QrCodeSetupImageUrl;
    ViewBag.SetupCode = setupInfo.ManualEntryKey;
    
    现在,对于每个请求,我都会使用以下代码对用户进行身份验证

    TwoFactorAuthenticator tfa = new TwoFactorAuthenticator();
    tfa.ValidateTwoFactorPIN(accountSecretKey, "Six Digit Code");
    
    问题


    在上面的代码中,
    accountSecretKey
    是否会将我必须保存到数据库中的某个代码编码,以便每次需要验证时都可以传递它?或者,
    accountSecretKey
    在每次登录尝试时都必须重新创建的东西?如果这段代码是我要存储到数据库中的东西,那么它是否也应该像密码一样加密?

    当我设置它时,我倾向于:

    在数据库中有一个G2FAEnabled列,一个用于用户的SecretKey

    生成一个唯一的密钥并使用它为用户正在使用设置G2FA的页面生成条形码,在服务器端记住它(将其放入数据库),但不要设置启用列

    在用户将您的站点添加到authenticator后,要求用户扫描或键入其设备显示的代码。这证明他们的设备设置正确,设备时钟正确等等

    如果他们键入的数字正确,则将enabled列设置为true并锁定内容,以便secretkey现在不可更改(更改它将杀死他们的2FA)

    从那时起,用户必须为当前服务器时间和存储在服务器上的密钥提供正确的基于时间的pin。他们的设备时钟必须与服务器保持同步。您可以通过检查当前时间的任意一侧来获得时钟漂移的容差,例如6次尝试查找匹配(这意味着设备时钟可以相对于服务器时间加3分钟,并且仍然匹配)

    任何停用2FA的尝试(将启用列设置为false)也需要有效的2FA代码,但客户服务部门的替代流程(如查看用户护照)应允许在不知情的情况下重置

    你不必在数据库中加密secretkey,你必须解密它才能使用它,这不像是一个失礼的行为,比如存储明文密码(如果你的数据库被盗,这是一个问题,因为用户一直在重复使用密码,所以数据库被盗可能意味着你泄露了用户在其他所有服务中的密码)因为它应该是随机数据,在你的组织之外没有任何意义,所以它不会帮助黑客侵入另一个使用相同2FA设备的用户站点

    通常,如果有人能够窃取您的数据库,他们已经达到了可以窃取必要位来解密您加密存储的任何内容的程度,但是如果您确定您的数据库可能会被盗,但您的web服务器将保持安全,那么请务必加密数据库数据