One Time Passwords (OTPs) are an mechanism to improve security over passwords alone.

Related tags

Security otp
Overview

otp: One Time Password utilities Go / Golang

PkgGoDev Build Status

Why One Time Passwords?

One Time Passwords (OTPs) are an mechanism to improve security over passwords alone. When a Time-based OTP (TOTP) is stored on a user's phone, and combined with something the user knows (Password), you have an easy on-ramp to Multi-factor authentication without adding a dependency on a SMS provider. This Password and TOTP combination is used by many popular websites including Google, Github, Facebook, Salesforce and many others.

The otp library enables you to easily add TOTPs to your own application, increasing your user's security against mass-password breaches and malware.

Because TOTP is standardized and widely deployed, there are many mobile clients and software implementations.

otp Supports:

  • Generating QR Code images for easy user enrollment.
  • Time-based One-time Password Algorithm (TOTP) (RFC 6238): Time based OTP, the most commonly used method.
  • HMAC-based One-time Password Algorithm (HOTP) (RFC 4226): Counter based OTP, which TOTP is based upon.
  • Generation and Validation of codes for either algorithm.

Implementing TOTP in your application:

User Enrollment

For an example of a working enrollment work flow, Github has documented theirs, but the basics are:

  1. Generate new TOTP Key for a User. key,_ := totp.Generate(...).
  2. Display the Key's Secret and QR-Code for the User. key.Secret() and key.Image(...).
  3. Test that the user can successfully use their TOTP. totp.Validate(...).
  4. Store TOTP Secret for the User in your backend. key.Secret()
  5. Provide the user with "recovery codes". (See Recovery Codes bellow)

Code Generation

  • In either TOTP or HOTP cases, use the GenerateCode function and a counter or time.Time struct to generate a valid code compatible with most implementations.
  • For uncommon or custom settings, or to catch unlikely errors, use GenerateCodeCustom in either module.

Validation

  1. Prompt and validate User's password as normal.
  2. If the user has TOTP enabled, prompt for TOTP passcode.
  3. Retrieve the User's TOTP Secret from your backend.
  4. Validate the user's passcode. totp.Validate(...)

Recovery Codes

When a user loses access to their TOTP device, they would no longer have access to their account. Because TOTPs are often configured on mobile devices that can be lost, stolen or damaged, this is a common problem. For this reason many providers give their users "backup codes" or "recovery codes". These are a set of one time use codes that can be used instead of the TOTP. These can simply be randomly generated strings that you store in your backend. Github's documentation provides an overview of the user experience.

Improvements, bugs, adding feature, etc:

Please open issues in Github for ideas, bugs, and general thoughts. Pull requests are of course preferred :)

License

otp is licensed under the Apache License, Version 2.0

Issues
  • validate six digits one time password

    validate six digits one time password

    First of all thank you for this great library!

    I'm using otp for my web service and I'm currently trying to write some tests against my login process. Since otp uses six digits by default (same as google authenticator app) I have to create a valid otp with six digits.

    I looked at your tests for otp but they all use eight digits. How can I generate a valid six digit one time password?

    Thank you!

    opened by zemirco 5
  • Cannot reuse the secret

    Cannot reuse the secret

    in https://github.com/pquerna/otp/blob/master/totp/totp.go#L183 the secret should not be re-encoded since that is the final seed we will store in the DB. To be able to reuse the seed to generate a new key we need to add it as a final secret.

    opened by gadelkareem 4
  • use options keeps users from choosing between Validate/ValidateCustom and Generate/GenerateCustom

    use options keeps users from choosing between Validate/ValidateCustom and Generate/GenerateCustom

    I've been using this package for quite a while and it has helped me thousands of times. However, sometimes I get confused in using custom validators/generators. I think we can make it better if you agree on using options in main functions, say, Validate and Generate funcs.

    opened by d-fal 3
  • can I use a secret string containg specail characters?

    can I use a secret string containg specail characters?

    I want to generate a password so I used the function in totp package GenerateCodeCustom() as

       func getPassword(token_shared_secret string) string{
    	opts := totp.ValidateOpts{}
    	opts.Period = 30
    	opts.Skew = 1
    	opts.Digits = 10
    	opts.Algorithm = otp.AlgorithmSHA512
    	
    	var password string
    	t := time.Now()
    	password, err := totp.GenerateCodeCustom(token_shared_secret,t,opts)
    	if err != nil {
    		panic(err)
    	}
    	return password
    }
    
    var password string = getPassword(myID+subfix)
    

    I needed to change some options like that cuz the main purpose is to make a HTTP POST to some URL and they directed me to make the password as an 10-digit time-based one, time step X is 30secs ,T0 is 0 and use HMAC-SHA-512 for the hash function.

    the parameter I put as myID+subfix is a concatenated string with an email address and an English string.

    The problem is that email address contains special charters @ and . (at and dot). And I failed to get the password with the error sign

    panic: Decoding of secret as base32 failed.

    So I tried modifying the GenerateCodeCustom() function in hotp package I changed the line (line no.84)

    secretBytes, err := base32.StdEncoding.DecodeString(secret)

    as

    secretBytes := []byte(secret)

    At least I succeeded to get a ten-digit time-based password but I don't think it is correct one because the server keep sending me http 401 response. I think it's not a proper way, I may need to do something.

    Can you let me know how can I solve this ?

    opened by Nogawan 3
  • Problems with TOTP SHA512

    Problems with TOTP SHA512

    Hi, I use the following code (which is very similar to this example, if not for line 19 (which I added), line 38 (which I added), and the cycle (lines 56 and 64) which I added to simplify testing with multiple clients:

    package main
    
    import (
    	"github.com/pquerna/otp"
    	"github.com/pquerna/otp/totp"
    
    	"bufio"
    	"bytes"
    	"fmt"
    	"image/png"
    	"io/ioutil"
    	"os"
    )
    
    func display(key *otp.Key, data []byte) {
    	fmt.Printf("Issuer:       %s\n", key.Issuer())
    	fmt.Printf("Account Name: %s\n", key.AccountName())
    	fmt.Printf("Secret:       %s\n", key.Secret())
    	fmt.Printf("URL:          %s\n", key.URL())
    	fmt.Println("Writing PNG to qr-code.png....")
    	ioutil.WriteFile("qr-code.png", data, 0644)
    	fmt.Println("")
    	fmt.Println("Please add your TOTP to your OTP Application now!")
    	fmt.Println("")
    }
    
    func promptForPasscode() string {
    	reader := bufio.NewReader(os.Stdin)
    	fmt.Print("Enter Passcode: ")
    	text, _ := reader.ReadString('\n')
    	return text
    }
    
    func main() {
    	key, err := totp.Generate(totp.GenerateOpts{
    		Issuer:      "Example.com",
    		AccountName: "[email protected]",
    		Algorithm:   otp.AlgorithmSHA512,
    	})
    	if err != nil {
    		panic(err)
    	}
    	// Convert TOTP key into a PNG
    	var buf bytes.Buffer
    	img, err := key.Image(200, 200)
    	if err != nil {
    		panic(err)
    	}
    	png.Encode(&buf, img)
    
    	// display the QR code to the user.
    	display(key, buf.Bytes())
    
    	// Now Validate that the user's successfully added the passcode.
    	fmt.Println("Validating TOTP...")
    	for {
    		passcode := promptForPasscode()
    		valid := totp.Validate(passcode, key.Secret())
    		if valid {
    			println("Valid passcode!")
    		} else {
    			println("Invalid passocde!")
    		}
    	}
    }
    

    In a test run, this is what it outputs:

    Issuer:       Example.com
    Account Name: [email protected]
    Secret:       N3K5NHE26HHXP2CL
    URL:          otpauth://totp/Example.com:[email protected]?algorithm=SHA512&digits=6&issuer=Example.com&period=30&secret=N3K5NHE26HHXP2CL
    

    qr-code

    I tried to add the QRCode to Google Authenticator (on Android), FreeOTP (on Android), Google Authenticator (on iOS), FreeOTP (on iOS), gopass (on Linux).

    On multiple tests, FreeOTP (on both Android and iOS), Google Authenticator on iOS and gopass agree on the generated OTPs, while Google Authenticator on Android does not. Only the code from Google Authenticator on Android is recognised as right.

    Now, I'm not sure if this is a problem on the server side or on the client side, so I'm opening the ticket on both the clients (FreeOTP Android, gopass) and the server (github.com/pquerna/otp)

    opened by Fale 3
  • Google changed provisioning of totp-URLs to lowercase-base32 now, which fails to parse

    Google changed provisioning of totp-URLs to lowercase-base32 now, which fails to parse

    Google gave me a QR code with this content: otpauth://totp/Google%3Afoo%40example.com?secret=qlt6vmy6svfx4bt4rpmisaiyol6hihca&issuer=Google (don't worry, I haven't taken this secret into use).

    It yields this error: Decoding of secret as base32 failed

    If I uppercase the secret myself (=> otpauth://totp/Google%3Afoo%40example.com?secret=QLT6VMY6SVFX4BT4RPMISAIYOL6HIHCA&issuer=Google), it succeeds.

    opened by joonas-fi 3
  • Must use AlgorithmSHA1 with iOS version of Google Authenticator

    Must use AlgorithmSHA1 with iOS version of Google Authenticator

            key,_ := totp.Generate(totp.GenerateOpts{ 
                  AccountName: "XYZ Test", 
                  Issuer: "some.domain.com", 
                  Algorithm: otp.AlgorithmSHA512, 
            })
            
            var buff bytes.Buffer
    	img, _ := key.Image(256,256)
    	f, _ := os.Create("test.html")
    	png.Encode(&buff, img)
    	encodedString := base64.StdEncoding.EncodeToString(buff.Bytes())
    	htmlImage := "<img src=\"data:image/png;base64," + encodedString + "\" />"
    	l, err := f.WriteString(htmlImage)
    	if err != nil {
    		log.Println(err)
    	}
    

    The resultant test.html shows a QR code that provides correct codes when scanned with Google Authenticator on Android, but not on iPhone.

    opened by yghazi 2
  • Prevent Conflicting Accounts

    Prevent Conflicting Accounts

    Google proposes actions mentioned on Conflicting Accounts to prevent conflicting accounts with same username on different websites.

    I come accross it using Gitea in production and in my local machine for development. While testing TOTP on my local machine I unfortunately have overwritten my key from production server, thus locking me out of the production system.

    Must admit that I am new to TOTP protocol. Is it something you can implement in your library or is it the reponsibility of the library's user?

    opened by daviian 2
  • fix missing padding in secrets

    fix missing padding in secrets

    This is a PR for the fix made by @Luzifer in issue #10

    I ran into this issue today as well and patched it locally for my app, however I also believe it makes sense to have this in the library.

    opened by maxvw 2
  • Hiding Code Generation Makes Testing Hard

    Hiding Code Generation Makes Testing Hard

    Hey @pquerna, thanks for this library! I'm currently reimplementing a security system from Python in Go that uses TOTP to control access to a physical location, and it's great to have a sane interface for validating codes.

    The problem though, is that this library is only for server-side authentication and not for client-side authcode generation. This seems like a missed opportunity generally, but specifically it makes testing very awkward. I'd like to be able to generate a few keys for testing, then run my system through its paces using these keys, but the interface expects that external code will do the code generation.

    Any way you could add a pair of generator methods to totp.Key, such as CodeFromCounter(i int) string and CodeFromTime(t time.Time) string, for testing and client generation uses?

    Thanks!

    opened by cathalgarvey 2
  • Invalid codes (example)

    Invalid codes (example)

    Hello,

    I am encountering a issue which was first flagged by another user last year. The example file runs fine, but the codes generated by the apps are all invalid when verified. However, this does not happen on every system I tested - three of our laptops have this issue, while a fourth runs the example and the codes are validated correctly. This is a really weird issue, and we are seeing it with some of the other Golang OTP, so it might be related to the OTP generation / validation process itself or to the system date/time.

    opened by Andudududu 1
  • URL Encoding bug

    URL Encoding bug

    Hello

    if the issuer contains a space, the URL encoder will mix up the URL.

    key, err := totp.Generate(totp.GenerateOpts{
    	Issuer:      "Test Issuer",
    	AccountName: "[email protected]",
    })
    

    Actual result: otpauth://totp/Test%20Issuer:[email protected]?algorithm=SHA1&digits=6&issuer=Test+Issuer&period=30&secret=QE2C7JXZB3TY3FBKL6PB7PZXP7UCRPOA

    otp_issue

    Expected result: otpauth://totp/Test%20Issuer:[email protected]?algorithm=SHA1&digits=6&issuer=Test%20Issuer&period=30&secret=QE2C7JXZB3TY3FBKL6PB7PZXP7UCRPOA

    otp_issue_expected

    opened by arigon 3
  • Problems with example code and google authenticator (android)

    Problems with example code and google authenticator (android)

    Hello, So I was trying out the library and using google authenticator to scan the QR codes. This is the code I'm using to do so.

    import (
    	"github.com/pquerna/otp"
    	"github.com/pquerna/otp/totp"
    
    	"bufio"
    	"bytes"
    	"fmt"
    	"image/png"
    	"io/ioutil"
    	"os"
    )
    
    func display(key *otp.Key, data []byte) {
    	fmt.Printf("Issuer:       %s\n", key.Issuer())
    	fmt.Printf("Account Name: %s\n", key.AccountName())
    	fmt.Printf("Secret:       %s\n", key.Secret())
    	fmt.Printf("URL:          %s\n", key.URL())
    	fmt.Println("Writing PNG to qr-code.png....")
    	ioutil.WriteFile("qr-code.png", data, 0644)
    	fmt.Println("")
    	fmt.Println("Please add your TOTP to your OTP Application now!")
    	fmt.Println("")
    }
    
    func promptForPasscode() string {
    	reader := bufio.NewReader(os.Stdin)
    	fmt.Print("Enter Passcode: ")
    	text, _ := reader.ReadString('\n')
    	return text
    }
    
    func main() {
    	key, err := totp.Generate(totp.GenerateOpts{
    		Issuer:      "Example.com",
    		AccountName: "[email protected]",
    		Algorithm:   otp.AlgorithmSHA1,
    	})
    	if err != nil {
    		panic(err)
    	}
    	// Convert TOTP key into a PNG
    	var buf bytes.Buffer
    	img, err := key.Image(200, 200)
    	if err != nil {
    		panic(err)
    	}
    	png.Encode(&buf, img)
    
    	// display the QR code to the user.
    	display(key, buf.Bytes())
    
    	// Now Validate that the user's successfully added the passcode.
    	fmt.Println("Validating TOTP...")
    	for {
    		passcode := promptForPasscode()
    		valid := totp.Validate(passcode, key.Secret())
    		if valid {
    			println("Valid passcode!")
    		} else {
    			println("Invalid passocde!")
    		}
    	}
    }
    

    This generates a QR code which I am able to scan with goole authenticator, but everytime i try the passcode it is invalid. Wanted to know if theres some issue with my code.

    opened by Pranav-B23 1
  • Feature/docker

    Feature/docker

    First of all, thank you for keeping things simple. It was very easy going over your code, great job!

    Motivation - I wanted to see how it works out-of-the-box, without installing/compiling anything.

    So I wrote a Dockerfile to build the application and test it easily, allowing users to test the app immediately.

    Build a Docker image

    DOCKER_ORG=unfor19
    $ docker build -t ${DOCKER_ORG}/totp -f Dockerfile.example .
    

    Run a container

    DOCKER_ORG=unfor19
    $ docker run --rm -it -e GENERATE_TEMP_PASSCODE="true" ${DOCKER_ORG}/totp:latest
    

    Example

    Issuer:       Example.com
    Account Name: [email protected]
    Secret:       PZLTOL3RPGS67EYXPYFLIBYEY5QMSJB5
    Writing PNG to qr-code.png....
    
    Please add your TOTP to your OTP Application now!
    
    Generating temporary passcode, valid for 30 seconds...
    Temp Passcode: 375146
    Validating TOTP...
    Enter Passcode: 375146
    Valid passcode!
    

    TODO

    • I've already pushed this image to my DockerHub repository unfor19/totp, so I recommend that you do the same, and then replace unfor19 in README.md

    Let me know if you want to migrate from Travis to GitHub Actions, your builds/tests will run much faster and it's free ๐Ÿ˜„

    opened by unfor19 0
  • Example on how to handle recovery codes?

    Example on how to handle recovery codes?

    Forgive me if this is a stupid question, how exactly can I handle recovery codes for users?

    In README, you said "These can simply be randomly generated strings that you store in your backend" but I could not find the code that do this.

    Does that mean I need to handle recovery codes myself? I was thinking along the lines of

    1. Generate recovery codes in backend
    2. Give users recovery codes
    3. Compare passcode with recovery codes (pulled from backend storage). If not matched, then compare passcode with TOTP / HOTP as usual? If matched, remove recovery codes (one time use like Github)

    Let me know if you have plan to support this behavior natively in this package, or if you are interested in a Pull Request that does this (backend storage via an interface, of course)?

    opened by binhnguyenduc 3
Releases(v1.3.0)
  • v1.3.0(Nov 11, 2020)

    v1.3.0 contains minor changes and enhancements. All users should be safe to upgrade.

    Functional changes

    • Added GenerateOpts.Rand to control the random source for generating secrets https://github.com/pquerna/otp/pull/45
    • Parse the Period of an OTP URL https://github.com/pquerna/otp/pull/49

    Documentation changes

    • Note that SHA1 should be used for compatibility with Google Authenticator https://github.com/pquerna/otp/pull/57
    • Expanded Example https://github.com/pquerna/otp/pull/53
    Source code(tar.gz)
    Source code(zip)
  • v1.2.0(Jun 1, 2019)

    v1.2.0 of otp contains no breaking changes, and is safe for all users to upgrade.

    Changes since v1.1.0:

    • Add Go modules related files https://github.com/pquerna/otp/pull/40
    • Expose a new .Secret field on the {hotp,totp}.GenerateOpts structs. This lets you import an existing secret instead of generating a new one. https://github.com/pquerna/otp/pull/42
    • Internal change to use base32.NoPadding as an encoding rather than trimming the standard padding https://github.com/pquerna/otp/pull/41

    Non-functional changes since v1.1.0:

    • Upgrade Go versions tested in Travis CI https://github.com/pquerna/otp/pull/39
    Source code(tar.gz)
    Source code(zip)
  • v1.1.0(Dec 25, 2018)

    Most users of otp should be able to upgrade safely. I'm happy to say otp is a stable library and is being used by many groups successfully.

    Changes since v1.0.0:

    • #30: Increases default secret size from 10 bytes to 20 bytes. This may effect storage of newly generated secrets, eg in a SQL database backend.
    • #25: Improved interoperability with broken base32 encoders.
    • #31: Bugfix: Check for a zero default Digits in hotp.Generate.
    • #21: Adds otp.key.URL() method.

    Non-functional changes since v1.0.0:

    • #27: Add additional test cases.
    • #28 and #23: Update Travis CI Settings.
    • #23: gofmt repo.

    Thank you to all of the contributors for this release:

    • @champkeh
    • @clarcharr
    • @pquerna
    • @rohitshriwas
    • @shawnps
    Source code(tar.gz)
    Source code(zip)
  • v1.0.0(Aug 7, 2017)

Owner
Paul Querna
CTO at ConductorOne
Paul Querna
QR secrets is a cryptographically secure mechanism to store secret data with the highest levels of security and store it on physical paper.

QR Secrets QR secrets is a cryptographically secure mechanism to store secret data with the highest levels of security. Incorporating; AES256-GCM-HKDF

Go Compile 0 Jan 12, 2022
Web-Security-Academy - Web Security Academy, developed in GO

Web-Security-Academy - Web Security Academy, developed in GO

Xavier Llauca 1 Feb 23, 2022
Create strong passwords using words that are easy for you to remember

Grasp Create strong passwords using words that are easy for you to remember A way to circumvent password complexity rules and restrictions while only

Luca Sepe 17 Apr 5, 2021
Find secrets and passwords in container images and file systems

Find secrets and passwords in container images and file systems

null 1.3k Jun 28, 2022
A Go Library For Generating Random, Rule Based Passwords. Many Random, Much Secure.

Can Haz Password? A Go library for generating random, rule based passwords. Many random, much secure. Features Randomized password length (bounded). T

null 7 Dec 6, 2021
linenoise is a library that generates strings of random characters that can be used as reasonably secure passwords.

linenoise linenoise is a library that generates strings of random characters (herein called a "noise") that can be used as reasonably secure passwords

Mark Cornick 0 Nov 29, 2021
Simple CLI to generate passwords

pwdrng Simple CLI to generate passwords $ pwdrng Copied password to clipboard: bfx861[X<26-b^UT Installation and Usage With Homebrew $ brew tap docto

Perry 2 Apr 8, 2022
Cossack Labs 1k Jul 4, 2022
HTTP middleware for Go that facilitates some quick security wins.

Secure Secure is an HTTP middleware for Go that facilitates some quick security wins. It's a standard net/http Handler, and can be used with many fram

Cory Jacobsen 2k Jun 28, 2022
Gryffin is a large scale web security scanning platform.

Gryffin (beta) Gryffin is a large scale web security scanning platform. It is not yet another scanner. It was written to solve two specific problems w

Yahoo 2.1k Jun 29, 2022
set of web security test cases and a toolkit to construct new ones

Webseclab Webseclab contains a sample set of web security test cases and a toolkit to construct new ones. It can be used for testing security scanners

Yahoo 917 Jun 14, 2022
PHP security vulnerabilities checker

Local PHP Security Checker The Local PHP Security Checker is a command line tool that checks if your PHP application depends on PHP packages with know

Fabien Potencier 913 Jun 30, 2022
Tracee: Linux Runtime Security and Forensics using eBPF

Tracee is a Runtime Security and forensics tool for Linux. It is using Linux eBPF technology to trace your system and applications at runtime, and analyze collected events to detect suspicious behavioral patterns.

Aqua Security 1.9k Jun 27, 2022
Sqreen's Application Security Management for the Go language

Sqreen's Application Security Management for Go After performance monitoring (APM), error and log monitoring itโ€™s time to add a security component int

Sqreen 160 Jun 18, 2022
A scalable overlay networking tool with a focus on performance, simplicity and security

What is Nebula? Nebula is a scalable overlay networking tool with a focus on performance, simplicity and security. It lets you seamlessly connect comp

Slack 10k Jul 1, 2022
How to systematically secure anything: a repository about security engineering

How to Secure Anything Security engineering is the discipline of building secure systems. Its lessons are not just applicable to computer security. In

Veeral Patel 9.3k Jun 27, 2022
Convenience of containers, security of virtual machines

Convenience of containers, security of virtual machines With firebuild, you can build and deploy secure VMs directly from Dockerfiles and Docker image

null 47 May 15, 2022
MQTTๅฎ‰ๅ…จๆต‹่ฏ•ๅทฅๅ…ท (MQTT Security Tools)

โ–ˆโ–ˆโ–ˆโ•— โ–ˆโ–ˆโ–ˆโ•— โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•— โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•—โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•—โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•— โ–ˆโ–ˆโ–ˆโ–ˆโ•— โ–ˆโ–ˆโ–ˆโ–ˆโ•‘โ–ˆโ–ˆโ•”โ•โ•โ•โ–ˆโ–ˆโ•—โ•šโ•โ•โ–ˆโ–ˆโ•”โ•โ•โ•โ•šโ•โ•โ–ˆโ–ˆโ•”โ•โ•โ•โ–ˆโ–ˆโ•”โ•โ•โ•โ•โ• โ–ˆโ–ˆโ•”โ–ˆโ–ˆโ–ˆโ–ˆโ•”โ–ˆโ–ˆโ•‘โ–ˆโ–ˆโ•‘ โ–ˆโ–ˆโ•‘ โ–ˆโ–ˆโ•‘ โ–ˆโ–ˆโ•‘ โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•‘โ•šโ–ˆโ–ˆโ•”โ•โ–ˆ

null 25 Jun 17, 2022