otp

package module
v1.1.0 Latest Latest
Warning

This package is not in the latest version of its module.

Go to latest
Published: Feb 1, 2024 License: Apache-2.0 Imports: 13 Imported by: 0

README

(gO)pinionatedTP

CI Go Reference

An opinionated TOTP library for Golang.

background

The goal of this library is basically to work with the standard OTP provider applications (2FAS, Authy, Google Authenticator, etc) without needing to figure out what the correct options to use are. There are a few other Golang libraries that provide HOTP/TOTP functionality but they provide too many other configuration options for the use-case outlined above. Therefore this library is extremely opinionated to only provide what's necessary to work with the standard OTP applications.

That being said, this library takes inspiration from those libraries as well as another blog post on implementing OTP in Go:

usage

Below is an example how to generate a new secret for some user, encrypt it (saving it to the database is left as an exercise for the reader), create a QR code and then generate a token and verify it.

N.B. the secrets need to be stored in the database encrypted not hashed (like for passwords) as it's necessary to access the secret in order to verify a provided token.

package main

import "crypto/rand"
import "encoding/base64"
import "fmt"

import gotp "go.finelli.dev/gopinionatedtp"

func main() {
	// generate an encryption key (you should persist this somewhere
	// secure!)
	r := make([]byte, 32)
	rand.Read(r)
	key := base64.StdEncoding.EncodeToString(r)

	// generate a new secret for a given user
	secret, err := gotp.GenerateNewSecret()
	if err != nil {
		panic(err)
	}

	// encrypt the secret to store it in the database
	crypt, err := gotp.EncryptOtpSecret(secret, key)
	if err != nil {
		panic(err)
	}

	// ...save the result to the user record

	// dump a QR code to the terminal to scan with an authenticator app
	err = gotp.QrCodeToTerminal("user@example.com", "yourapp", secret)
	if err != nil {
		panic(err)
	}

	// ...retrieve the encrypted secret from the database

	// decrypt the secret for use
	secret, err := gotp.DecryptOtpSecret(crypt, key)
	if err != nil {
		panic(err)
	}

	// calculate the current token (for fun!)
	token, err := gotp.GenerateToken(secret, gotp.DefaultInterval())
	if err != nil {
		panic(err)
	}

	// validate a given token
	valid, err := gotp.VerifyToken("123456", secret)
	if err != nil {
		panic(err)
	}

	if valid {
		fmt.Println("Valid token!")
	} else {
		fmt.Println("Invalid token!")
	}
}

license

Copyright 2023-2024 Mario Finelli

Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at

    http://www.apache.org/licenses/LICENSE-2.0

Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.

Documentation

Overview

The otp package provides an opinionated way to generate and verify TOTP tokens as well as providing an easy way to encrypt the secrets for persistent storage (e.g., in the database alongside user records). It also provides a facility to dump QR codes to the terminal so that they can be scanned by an authenticator application.

Index

Constants

This section is empty.

Variables

This section is empty.

Functions

func BuildTotpUri

func BuildTotpUri(username, issuer, secret string) string

BuildTotpUri returns a otpauth:// scheme URI suitable for input into a QR code generator. It requires the username of the user, an issuer and the user's OTP secret (generated with GenerateNewSecret) and reurns the URI:

otpauth://totp/[issuer]:[username]?issuer=[issuer]&secret=[secret]

func DecryptOtpSecret

func DecryptOtpSecret(b64Secret string, key *[32]byte) (string, error)

DecryptOtpSecret will return the original OTP secret after decryption.

func DefaultInterval added in v1.1.0

func DefaultInterval() int

The DefaultInterval calculates the default 30 second interval.

func EncryptOtpSecret

func EncryptOtpSecret(secret string, key *[32]byte) (string, error)

EncryptOtpSecret encrypts the OTP secret using secretbox: https://pkg.go.dev/golang.org/x/crypto/nacl/secretbox

func GenerateNewSecret

func GenerateNewSecret() (string, error)

GenerateNewSecret does what it says on the tin: it generates a new secret that is suitable for use as a TOTP secret.

func GenerateToken

func GenerateToken(secret string, interval int) (string, error)

GenerateToken returns the current time-based token for the given secret and interval.

func QrCodeToTerminal

func QrCodeToTerminal(username, issuer, secret string) error

QrCodeToTerminal constructs a TOTP URI and then outputs a terminal-based (using pterm) QR code that can be scanned by an authentication app.

func RawKeyToBytes

func RawKeyToBytes(rawKey string) (*[32]byte, error)

Given an encryption key as a tring RawKeyToBytes returns it as bytes that can be used by the encryption functions.

func VerifyToken

func VerifyToken(providedToken, secret string) (bool, error)

VerifyToken returns true if the provided token matches the current token (+/- one interval) and false otherwise.

Types

This section is empty.

Jump to

Keyboard shortcuts

? : This menu
/ : Search site
f or F : Jump to
y or Y : Canonical URL