Beispiel #1
0
        public void Given_AnEmptyIssuer_When_GetAuthenticatorRegistrationDataIsCalled_Then_AnArgumentExceptionIsThrown(
            String issuer)
        {
            ITotpProvider provider = new TotpProvider();

            Assert.Throws <ArgumentException>(() => provider.GetAuthenticatorRegistrationData("ACCOUNTNAME", issuer));
        }
Beispiel #2
0
        public void GenerateSpecificHMacSha1Totp()
        {
            var seed = "werredsxsgfhtdfsde";

            seed = seed.Trim();

            var currentTime = (uint)AuthenticatorApp.Timestamp.UnixTimeStamp.GetCurrentUnixTimestampSeconds();

            long T0 = 0;
            long X  = 30;

            var T     = (currentTime - T0) / X;
            var steps = T.ToString("X").ToUpper();

            while (steps.Length < 16)
            {
                steps = "0" + steps;
            }

            var timeString = steps;

            var data = TotpProvider.GenerateTotp(Base32.Base32ToHex(seed),
                                                 timeString, 6,
                                                 TotpProvider.MacAlgorithmEnum.HmacSha1);

            Assert.AreEqual(GenerateTotpMicrosoft(TotpProvider.StringToByteArray(Base32.Base32ToHex(seed)), timeString, 6), data);
        }
Beispiel #3
0
        public void Given_AnEmptyAccountName_When_GetAuthenticatorRegistrationDataIsCalled_Then_AnArgumentExceptionIsThrown(
            String accountName)
        {
            ITotpProvider provider = new TotpProvider();

            Assert.Throws <ArgumentException>(() => provider.GetAuthenticatorRegistrationData(accountName, "ISSUER"));
        }
Beispiel #4
0
        public void Given_ATimeBeforeUnixEpoch_When_GetCodeAtSpecificTimeIsCalled_Then_AnArgumentExceptionIsThrown(
            String time)
        {
            ITotpProvider provider = new TotpProvider();

            Assert.Throws <ArgumentException>(() => provider.GetCodeAtSpecificTime("SECRETKEY",
                                                                                   DateTimeOffset.Parse(time,
                                                                                                        CultureInfo.InvariantCulture)));
        }
Beispiel #5
0
        public void Given_AnEmptySecretKey_When_GetCodeAtSpecificTimeIsCalled_Then_AnArgumentExceptionIsThrown(
            String secretKey)
        {
            ITotpProvider provider = new TotpProvider();

            Assert.Throws <ArgumentException>(() => provider.GetCodeAtSpecificTime(secretKey,
                                                                                   DateTimeOffset.Parse("2019-09-16",
                                                                                                        CultureInfo.InvariantCulture)));
        }
Beispiel #6
0
        public void CalcHmacSha256Scenario1Desktop()
        {
            var result = TotpProvider.HmacSha(TotpProvider.MacAlgorithmEnum.HmacSha256, _encoding.GetBytes(Key),
                                              _encoding.GetBytes(Text));
            var hexString = String.Join("", result.Select(a => a.ToString("x2")));

            Assert.AreEqual(HMacSha256Expected,
                            hexString);
        }
Beispiel #7
0
        public void Given_AnEmptyCode_When_ValidateCodeIsCalled_Then_AnArgumentExceptionIsThrown(
            String code)
        {
            ITotpProvider provider = new TotpProvider();

            Assert.Throws <ArgumentException>(() => provider.ValidateCode("SECRET",
                                                                          code,
                                                                          DateTimeOffset.Parse("2019-09-16 15:44:09 +02:00",
                                                                                               CultureInfo.InvariantCulture)));
        }
Beispiel #8
0
        private async Task confirmTotpSetup()
        {
            var totpProvider = new TotpProvider(Convert.FromBase64String(totpSetup.secret));

            var resp = await client.PostAsJsonAsync("/a/auth/confirm2fa", new TwoFactorConfirmRequest {
                otpcode = totpProvider.getCode()
            });

            resp.EnsureSuccessStatusCode();
        }
Beispiel #9
0
        public void Given_AnEmptySecretKey_When_GetAuthenticatorRegistrationDataIsCalled_Then_ANewSecretKeyIsGenerated(
            String secretKey)
        {
            ITotpProvider provider = new TotpProvider();

            var result = provider.GetAuthenticatorRegistrationData("ACCOUNT_NAME", "ISSUER", secretKey);

            Assert.NotNull(result);
            Assert.False(String.IsNullOrWhiteSpace(result.SecretKey));
        }
Beispiel #10
0
        public void Given_AValidSecretKey_When_GetAuthenticatorRegistrationDataIsCalled_Then_ResultContainsTheEncodedSecretKey(
            String secretKey,
            String expected)
        {
            ITotpProvider provider = new TotpProvider();

            var result = provider.GetAuthenticatorRegistrationData("ACCOUNT_NAME", "ISSUER", secretKey);

            Assert.NotNull(result);
            Assert.Equal(expected, result.ManualRegistrationKey);
        }
Beispiel #11
0
        public void Given_AnIncorrectCode_When_ValidateCodeIsCalled_Then_InvalidResultIsReturned(
            String secret,
            String time,
            String code)
        {
            ITotpProvider provider = new TotpProvider();

            var result = provider.ValidateCode(secret, code, DateTimeOffset.Parse(time, CultureInfo.InvariantCulture));

            Assert.False(result);
        }
Beispiel #12
0
        public void Given_AValidCodeAndValidTime_When_GetCodeAtSpecificTimeIsCalled_Then_TheCorrectCodeAndReminderIsReturned(
            String secret,
            String time,
            String expectedCode,
            int expectedRemainingSeconds)
        {
            ITotpProvider provider = new TotpProvider();

            var result =
                provider.GetCodeAtSpecificTime(secret, DateTimeOffset.Parse(time, CultureInfo.InvariantCulture), out var remaining);

            Assert.Equal(expectedCode, result);
            Assert.Equal(TimeSpan.FromSeconds(expectedRemainingSeconds), remaining);
        }
Beispiel #13
0
        public void Given_ACodeThatWouldBeCorrectXSecondsInTheFuture_When_ValidateCodeIsCalledWithoutTolerance_Then_InvalidResultIsReturned(
            String secret,
            String time,
            String code)
        {
            ITotpProvider provider = new TotpProvider();

            var result = provider.ValidateCode(secret,
                                               code,
                                               DateTimeOffset.Parse(time, CultureInfo.InvariantCulture),
                                               TimeSpan.Zero);

            Assert.False(result);
        }
Beispiel #14
0
        public async Task canLoginTwoFactor()
        {
            await confirmTotpSetup();

            var totpProvider = new TotpProvider(Convert.FromBase64String(totpSetup.secret));
            // attempt a 2fa login
            var resp = await client.PostAsJsonAsync("/a/auth/login2fa", new LoginRequestTwoFactor {
                username = username,
                password = AccountRegistrar.TEST_PASSWORD,
                otpcode  = totpProvider.getCode()
            });

            resp.EnsureSuccessStatusCode();
        }
Beispiel #15
0
        public static string GenerateTotpMicrosoft(byte[] keyBytes, string time, int returnDigits)
        {
            var array  = TotpProvider.StringToByteArray(time);
            var array2 = TotpProvider.HmacSha(TotpProvider.MacAlgorithmEnum.HmacSha1, keyBytes, array);

            var num  = (int)(array2[array2.Length - 1] & 15);
            var num2 = (int)(array2[num] & 127) << 24 | (int)(array2[num + 1] & 255) << 16 | (int)(array2[num + 2] & 255) << 8 | (int)(array2[num + 3] & 255);
            var text = (num2 % DigitsPower[returnDigits]).ToString();

            while (text.Length < returnDigits)
            {
                text = "0" + text;
            }
            return(text);
        }
Beispiel #16
0
        public void Given_ACodeThatWasCorrectXSecondsAgo_When_ValidateCodeIsCalledWithToleranceX_Then_ValidResultIsReturned(
            String secret,
            String time,
            String code,
            int toleranceInSeconds)
        {
            ITotpProvider provider = new TotpProvider();

            var result = provider.ValidateCode(secret,
                                               code,
                                               DateTimeOffset.Parse(time, CultureInfo.InvariantCulture),
                                               TimeSpan.FromSeconds(toleranceInSeconds));

            Assert.True(result);
        }
Beispiel #17
0
        public void Given_CorrectRegistrationData_When_GetAuthenticatorRegistrationDataIsCalledWithoutAccountNamePrefixing_Then_TheCorrectUriIsReturned(
            String secretKey,
            String issuer,
            String accountName,
            String expectedQrCode)
        {
            ITotpProvider provider = new TotpProvider();

            var result = provider.GetAuthenticatorRegistrationData(accountName, issuer, secretKey, false);

            Assert.NotNull(result);
            Assert.Equal(secretKey, result.SecretKey);
            Assert.Equal(accountName, result.AccountName);
            Assert.Equal(issuer, result.Issuer);
            Assert.Equal(expectedQrCode, result.QrCodeUri);
        }
Beispiel #18
0
        public TwoFactorSetupModule(SContext serverContext) : base("/auth", serverContext)
        {
            Get <SetupTwoFactor>("/setup2fa", async(req, res) => {
                // check if two-factor ALREADY enabled
                if (currentUser.totpEnabled)
                {
                    // otp is already enabled
                    res.StatusCode = (int)HttpStatusCode.Conflict;
                    return;
                }

                // we generate a new TOTP secret
                var seed         = StringUtils.secureRandomString(TotpProvider.TOTP_SECRET_LENGTH);
                var seedBytes    = Hasher.sha256(seed);
                currentUser.totp = seedBytes;
                serverContext.userManager.updateUser(currentUser);

                // return the seed
                await res.respondSerialized(new TotpSetupResponse {
                    secret = Convert.ToBase64String(seedBytes)
                });
                return;
            });

            Post <ConfirmTwoFactor>("/confirm2fa", async(req, res) => {
                var validatedReq = await this.validateRequest <TwoFactorConfirmRequest>(req, res);
                if (!validatedReq.isValid)
                {
                    return;
                }
                var confirmReq = validatedReq.request;

                // use TOTP provider to check code
                var provider = new TotpProvider(currentUser.totp);
                if (provider.verify(confirmReq.otpcode))
                {
                    // totp confirmed, enable totp and lock
                    serverContext.userManager.setupTotpLock(currentUser, credential.token);

                    res.StatusCode = (int)HttpStatusCode.OK;
                    return;
                }

                res.StatusCode = (int)HttpStatusCode.Unauthorized;
                return;
            });
        }
Beispiel #19
0
        public void CalcHmacSha1Scenario1Desktop()
        {
            // Please refer to wikipedia for the test data:
            // http://en.wikipedia.org/wiki/Hash-based_message_authentication_code#Examples_of_HMAC_.28MD5.2C_SHA1.2C_SHA256.29
            const string key  = "";
            const string text = "";

            try
            {
                TotpProvider.HmacSha(TotpProvider.MacAlgorithmEnum.HmacSha1, _encoding.GetBytes(key),
                                     _encoding.GetBytes(text));
            }
            catch (InvalidOperationException)
            {
                Assert.IsTrue(true);
            }
        }
Beispiel #20
0
        /// <summary>
        /// Generate TOTP(HMacSha1) from test time
        /// </summary>
        /// <param name="time">Time</param>
        /// <returns>TOTP</returns>
        public string GenerateTotpHMacSha1FromTime(long time)
        {
            // Seed for HMAC-SHA1 - 20 bytes
            const string seed = "3132333435363738393031323334353637383930";

            long T0 = 0;
            long X  = 30;

            var T     = (time - T0) / X;
            var steps = T.ToString("X").ToUpper();

            while (steps.Length < 16)
            {
                steps = "0" + steps;
            }

            return(TotpProvider.GenerateTotp(seed, steps, "8", TotpProvider.MacAlgorithmEnum.HmacSha1));
        }
Beispiel #21
0
        /// <summary>
        /// Generate TOTP(HMacSha256) from test time
        /// </summary>
        /// <param name="time">Time</param>
        /// <returns>TOTP</returns>
        private static string GenerateTotpHMacSha256FromTime(long time)
        {
            // Seed for HMAC-SHA256 - 32 bytes
            const string seed32 = "3132333435363738393031323334353637383930" +
                                  "313233343536373839303132";

            const long t0 = 0;
            const long x  = 30;

            var T     = (time - t0) / x;
            var steps = T.ToString("X").ToUpper();

            while (steps.Length < 16)
            {
                steps = "0" + steps;
            }

            return(TotpProvider.GenerateTotp(seed32, steps, "8", TotpProvider.MacAlgorithmEnum.HmacSha256));
        }
Beispiel #22
0
        public void Given_ASecretKeyAndValidTime_When_GetValidCodesForPeriodIsCalled_Then_AValidCodeRangeIsReturned(
            String secret,
            String time,
            int pastToleranceSeconds,
            int futureToleranceSeconds,
            params String[] expectedCodes)
        {
            var provider = new TotpProvider();

            var result = provider.GetValidCodesForPeriod(secret,
                                                         DateTimeOffset.Parse(time, CultureInfo.InvariantCulture),
                                                         TimeSpan.FromSeconds(pastToleranceSeconds),
                                                         TimeSpan.FromSeconds(futureToleranceSeconds))
                         .ToArray();

            Assert.Collection(result,
                              expectedCodes
                              .Select <String, Action <String> >(expected => code => Assert.Equal(expected, code))
                              .ToArray());
        }
Beispiel #23
0
        public AuthModule(SContext context) : base("/auth", context)
        {
            Post <CreateUser>("/create", async(req, res) => {
                var validatedCreateReq = await this.validateRequest <RegisterRequest>(req, res);
                if (!validatedCreateReq.isValid)
                {
                    return;
                }
                var createReq = validatedCreateReq.request;

                // attempt to register user
                try {
                    // register the user
                    var user = serverContext.userManager.registerUser(createReq);
                    serverContext.log.writeLine($"registered user {user.username}",
                                                Logger.Verbosity.Information);
                    var token = serverContext.userManager.issueRootToken(user.id);

                    // Return user details
                    res.StatusCode = (int)HttpStatusCode.Created;
                    await res.respondSerialized(new AuthedUserResponse {
                        user  = new AuthenticatedUser(user),
                        token = token
                    });
                }
                catch (UserManagerService.UserAlreadyExistsException) {
                    res.StatusCode = (int)HttpStatusCode.Conflict;
                    return;
                }
            });

            Post <LoginUser>("/login", async(req, res) => {
                var login = await validateAndCheckPassword <LoginRequest>(req, res);
                if (login.isValid)
                {
                    // check two-factor
                    if (login.user.totpEnabled)
                    {
                        // require login with otp code, but creds were good
                        res.StatusCode = (int)HttpStatusCode.FailedDependency;
                        return;
                    }

                    // issue a new token
                    var token = serverContext.userManager.issueRootToken(login.user.id);

                    // return user details
                    res.StatusCode = (int)HttpStatusCode.OK;
                    await res.respondSerialized(new AuthedUserResponse {
                        user  = new AuthenticatedUser(login.user),
                        token = token
                    });
                }
            });

            Post <LoginTwoFactor>("/login2fa", async(req, res) => {
                var login = await validateAndCheckPassword <LoginRequestTwoFactor>(req, res);
                if (login.isValid)
                {
                    // this route is not to be used unless two factor is enabled
                    if (!login.user.totpEnabled)
                    {
                        res.StatusCode = (int)HttpStatusCode.PreconditionFailed;
                        return;
                    }

                    // use TOTP provider to check code
                    var provider = new TotpProvider(login.user.totp);
                    if (!provider.verify(login.request.otpcode))
                    {
                        res.StatusCode = (int)HttpStatusCode.Unauthorized;
                        return;
                    }

                    // issue a new token
                    var token = serverContext.userManager.issueRootToken(login.user.id);

                    // return user details
                    res.StatusCode = (int)HttpStatusCode.OK;
                    await res.respondSerialized(new AuthedUserResponse {
                        user  = new AuthenticatedUser(login.user),
                        token = token
                    });
                }
            });

            Post <DeleteUser>("/delete", async(req, res) => {
                var login = await validateAndCheckPassword <LoginRequest>(req, res);
                if (login.isValid)
                {
                    // delete the account
                    serverContext.userManager.deleteUser(login.user.id);
                    // return success indication
                    res.StatusCode = (int)HttpStatusCode.NoContent;
                    return;
                }
            });
        }
Beispiel #24
0
        public void Given_AnIssuerWithColon_When_GetAuthenticatorRegistrationDataIsCalled_Then_AnArgumentExceptionIsThrown()
        {
            ITotpProvider provider = new TotpProvider();

            Assert.Throws <ArgumentException>(() => provider.GetAuthenticatorRegistrationData("ACCOUNTNAME", "ISS:UER"));
        }