Giter VIP home page Giter VIP logo

marcoonroad / twostep Goto Github PK

View Code? Open in Web Editor NEW
20.0 2.0 5.0 149 KB

HOTP and TOTP algorithms for 2-step verification (for OCaml). :clock10: :closed_lock_with_key: :1234: :camel:

Home Page: https://twostep.marcoonroad.dev

License: MIT License

Makefile 6.98% OCaml 93.02%
2-step-verification 2-factor-authentication cryptography security security-tools ocaml ocaml-library authentication infosec one-time-password

twostep's Introduction

twostep

HOTP and TOTP algorithms for 2-step verification (for OCaml).

OCaml Minimal Version Ubuntu Workflow Status Windows Workflow Status MacOS Workflow Status Project License Coverage Status

This project implements algorithms for 2-step verification, being the HMAC-based One-Time Password (see RFC 4226) and the Time-based One-Time Password (see RFC 6238).

Installation

If available on OPAM, try:

opam install twostep

Otherwise, you can install the development version of this project with OPAM's pin command.

Usage

The authentication of 2-step verification needs prior known and shared secret between the client and server. If no secret was sent before, you can generate this Base-32 secret with:

let secret: string = Twostep.TOTP.secret();; (* kinda "A222 BBBB 3333 D5D5" *)

As an additional note, the Twostep.TOTP.secret function above uses a cryptographically safe PRNG, that is, a secure source of pseudo randomness. To generate an OTP code, you can use this function:

let code: string = Twostep.TOTP.code ~secret:secret ();; (* kinda "098123" *)

The function above assumes the SHA-1 hash algorithm, 30 seconds as timestep/window before refreshed code, 6 digits for output number code (padded with zeros on left sometimes) and no clock drifts / not-sync time between server and client (i.e, no 30 seconds on the past or on the future).

To verify one-time codes from the client, use the following function below:

let valid: bool = Twostep.TOTP.verify ~secret:secret ~code:code ();;

This function assumes the same configuration of Twostep.TOTP.code, except for the clock drift, where Twostep.TOTP.verify assumes too past and future 30 seconds (ideal on slow connections or latency problems). For the full API reference or coverage status, please refer to:

You can test this library against mobile apps such as Google Authenticator or Microsoft Authenticator without any problems (I have tested on both as well). On any doubts to generate a QR-code for the base-32 secret, please refer to Google Authenticator's Key Uri Format (for the proper data format on QR-code encoding/decoding):

Security Concerns

The generated secret must be sent for the client in a secure channel, such as HTTPS/TLS, and must be stored encrypted in your servers' databases. A good approach is to encrypt with a KDF on the client password, after you checking the client password against the strongly hashed version on database (prefer 256/512-bits hash algorithms whenever possible, and a KDF in front of this with server's salt is ideal too). So, in this approach the front app must send the client password twice, during authentication and during 2-step verification, and after that, erasing the password persisted on front (nice UX for the client to not type twice her own password).

It's recommended for the OTP authentication to be optional on most cases. The end-user can opt-in this feature some time later, and on OTP service setup, she needs to confirm that have configured things properly through the first-time OTP-code verification. For the first-time, which means no OTP-prompt-prior-login until customer confirmation of first-time, you could use a confirmed boolean (initially false) column aside encryptedSecret on your storage -- so this first-time confirmation changes confirmed to true and then all logins would request an OTP code together. Keep in mind that it's just a design sketch of implementation, more like an idea than actual RFC recommendation.

Also, you should track valid OTP codes sent from the end user in a persisted storage (such as databases). This is just to avoid replay attacks once an attacker intercepts a valid OTP code from the end user. Your tracking of the OTP code should be a pair (otpCode, nonce), where nonce is the current interval / period (if using TOTP algorithm, otherwise nonce will be a HOTP counter) and the otpCode is verified / checked as valid. Keep in mind that you should only track valid / verified OTP codes to not waste storage costs with invalid OTP codes (i.e, codes that can't be exploited by replay attacks). After such tracked pairs hit OTP expiration and are not able to be exploited anymore, you can clean them from the underlying tracklist storage without problems.


Important: This is a warning / security advice. Implement such system carefully, and if possible, with audits from external experts and security teams. As a disclaimer, I'm not responsible for any damages.


Tips

For stronger / longer secrets, you can use the ~bytes optional parameter (the default and minimal value is 10, with the invariant that it must be divisible-by / multiple-of 5):

let secret: string = Twostep.TOTP.secret ~bytes:20 ();;
(* kinda "D3D3 F5F5 A2A2 3B3B GGGG 7K7K 5555 Q2Q2" *)

Remarks

Pull requests are welcome! Happy hacking! Hope this project can help you to solve problems.

twostep's People

Contributors

marcoonroad avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar

twostep's Issues

Package on opam requires mirage-crypto-rng < 11.0

The package as it currently exists on opam requires mirage-crypto-rng >= 0.6.1 & < 11.0 but I cannot tell where the < 11.0 requirement is coming from, as there's no such constraint in the .opam file. This makes it impossible to install alongside other packages that require newer versions,

About encrypting OTP secrets with the user's password

Thanks for this library! @andreypopp is building a full 2FA authentication example based on it (work is here).

I'm thinking about some of the issues involved, and I have a question about the secret storage scheme described in the README:

must be stored encrypted in your servers' databases. A good approach is to encrypt with a KDF on the client password, after you checking the client password against the strongly hashed version on database (prefer 256/512-bits hash algorithms whenever possible, and a KDF in front of this with server's salt is ideal too).

What is the advantage of storing the secrets encrypted with the user's password, rather than the server's master password?

I haven't fully thought through all the implications of either scheme. I am wondering if you could comment based on what you know. I didn't find mention of using the user's password for encryption of the secret in either RFC 4226 (which does mention composite secrets based on the password), or RFC 6238. A brief search found this post on Stack Exchange, but it does not have any references or explanation for the choice of scheme.

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    ๐Ÿ–– Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. ๐Ÿ“Š๐Ÿ“ˆ๐ŸŽ‰

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google โค๏ธ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.