Skip to content

sentryco/TwoFa

Repository files navigation

Tests codebeat badge

TwoFa ⏳

2FA framework (One-time-password) (TOTP / HOTP)

Description:

  • It helps keep your online accounts secure by generating unique one-time passwords, which you use in combination with your other passwords to log into supporting websites.
  • TOTP stands for Time-Based One-Time Password. This is a standardized method for generating a regularly-changing password that is based on a shared secret, ensuring that each code is unique.
  • HOTP stands for HMAC-Based One-Time Password. Unlike TOTP, HOTP passwords are based on a counter mechanism and do not expire after a short period of time, making them suitable for situations where time-sync might not be possible.

Table of Contents

Features:

  • Easy setup via QR code, "otpauth://" URL, or manual entry
  • Secure storage of all data in encrypted form on the iOS keychain
  • Full support for time-based and counter-based one-time passwords as standardized in RFC 4226 and 6238
  • Offline functionality with no internet connection required, ensuring that your secret keys never leave your device

Installation

To integrate TwoFa into your Xcode project using Swift Package Manager, add it as a dependency to your Package.swift:

.package(url: "https://github.com/sentryco/TwoFa", branch: "main")

Example:

From "OTP url" to "one time password"

let account = try? Account(url: URL(string: "otpauth://totp/test?secret=GEZDGNBV")!)
print(account?.currentPassword) // 123321

This code snippet uses a predefined secret key and generates a TOTP that changes every 30 seconds.

let totpGenerator = TOTPGenerator(secret: "GEZDGNBVGY3TQOJQGEZDGNBVGY3TQOJQ", digits: 6, timeInterval: 30)
let totp = totpGenerator.generateOTP()
print("Generated TOTP: \(totp)")

The HOTP is generated using a counter, which should be incremented for each new OTP generation.

let hotpGenerator = HOTPGenerator(secret: "GEZDGNBVGY3TQOJQGEZDGNBVGY3TQOJQ", counter: 1)
let hotp = hotpGenerator.generateOTP()
print("Generated HOTP: \(hotp)")

Validating an OTP: This example demonstrates how to validate an OTP that a user might enter. This snippet checks if the provided OTP is valid for the given secret key.

let isValid = OTPValidator.validate(otp: "123456", secret: "GEZDGNBVGY3TQOJQGEZDGNBVGY3TQOJQ")
if isValid {
    print("OTP is valid.")
} else {
    print("OTP is invalid.")
}

Resources:

Inspiration:

Library:

Notes:

HOTP: Event-based One-Time Password

Event-based OTP (also called HOTP meaning HMAC-based One-Time Password) is the original One-Time Password algorithm and relies on two pieces of information. The first is the secret key, called the "seed", which is known only by the token and the server that validates submitted OTP codes. The second piece of information is the moving factor which, in event-based OTP, is a counter. The counter is stored in the token and on the server. The counter in the token increments when the button on the token is pressed, while the counter on the server is incremented only when an OTP is successfully validated.

To calculate an OTP the token feeds the counter into the HMAC algorithm using the token seed as the key. HOTP uses the SHA-1 hash function in the HMAC. This produces a 160-bit value which is then reduced down to the 6 (or 8) decimal digits displayed by the token.

TOTP: Time-based One-Time Password

Time-based OTP (TOTP for short), is based on HOTP but where the moving factor is time instead of the counter. TOTP uses time in increments called the timestep, which is usually 30 or 60 seconds. This means that each OTP is valid for the duration of the timestep.

Comparison

Both OTP schemes offer single-use codes but the key difference is that in HOTP a given OTP is valid until it is used, or until a subsequent OTP is used. In HOTP there are a number of valid "next OTP" codes. This is because the button on the token can be pressed, thus incrementing the counter on the token, without the resulting OTP being submitted to the validating server. For this reason, HOTP validating servers accept a range of OTPs. Specifically, they will accept an OTP that is generated by a counter that is within a set number of increments from the previous counter value stored on the server. This is range is referred to as the validation window. If the token counter is outside of the range allowed by the server, the validation fails and the token must be re-synchronised.

So clearly in HOTP there is a trade-off to make. The larger the validation window the less likely the chance of needing to re-sync the token with the server, which is inconvenient for the user. Importantly though, the larger the window the greater the chance of an adversary guessing one of the accepted OTPs through a brute-force attack.

Choosing between HOTP and TOTP purely from a security perspective clearly favours TOTP. Importantly, the validating server must be able to cope with potential for time-drift with TOTP tokens in order to minimise any impact on users.

There is also more choice of form-factor with TOTP tokens. Traditional key fob OTP tokens are getting smaller and Microcosm has now introduced the OTP Card - a credit card sized OTP token with EPD display. Cards can be a more convenient option as they can be stored with other cards in a wallet or purse, or in the back of a mobile phone case. In contrast, in TOTP there is only one valid OTP at any given time - the one generated from the current UNIX time.

Todo:

About

2FA framework (TOTP / HOTP)

Resources

License

Stars

Watchers

Forks

Releases

No releases published

Packages

No packages published

Languages