KEINOS / go-totp

Simple Go package to implement TOTP authentication functionality to the Go app. It supports ECDH as well.

Geek Repo:Geek Repo

Github PK Tool:Github PK Tool

go-totp

go1.22+ Go Reference

go-totp is a simple Go package to implement Timebased-One-Time-Password authentication functionality, a.k.a. TOTP, to the Go app.

Note: This is a wrapper of the awesome github.com/pquerna/otp package to facilitate the use of TOTP.

As an optional feature, this package supports ECDH (Elliptic-Curve Diffie-Hellman) key agreement protocol, where public keys are exchanged between two parties to obtain a common TOTP passcode.

Usage

// Install package
go get "github.com/KEINOS/go-totp"

Basic Usage

// import "github.com/KEINOS/go-totp/totp"

func Example() {
    Issuer := "Example.com"            // name of the service
    AccountName := "alice@example.com" // name of the user

    // Generate a new secret key with default options.
    // Compatible with most TOTP authenticator apps.
    key, err := totp.GenerateKey(Issuer, AccountName)
    if err != nil {
        log.Fatal(err)
    }

    // Print the default option values.
    fmt.Println("- Algorithm:", key.Options.Algorithm)
    fmt.Println("- Period:", key.Options.Period)
    fmt.Println("- Secret Size:", key.Options.SecretSize)
    fmt.Println("- Skew (time tolerance):", key.Options.Skew)
    fmt.Println("- Digits:", key.Options.Digits)

    // Generate 6 digits passcode (valid for 30 seconds)
    passcode, err := key.PassCode()
    if err != nil {
        log.Fatal(err)
    }

    // Validate the passcode
    if key.Validate(passcode) {
        fmt.Println("* Validation result: Passcode is valid")
    }
    //
    // Output:
    // - Algorithm: SHA1
    // - Period: 30
    // - Secret Size: 128
    // - Skew (time tolerance): 1
    // - Digits: 6
    // * Validation result: Passcode is valid
}
// ----------------------------------------------------------------------------
//  Generate a new secret key with custom options
// ----------------------------------------------------------------------------
key, err := totp.GenerateKey(Issuer, AccountName,
    totp.WithAlgorithm(totp.Algorithm("SHA256")),
    totp.WithPeriod(15),
    totp.WithSecretSize(256),
    totp.WithSkew(5),
    totp.WithDigits(totp.DigitsEight),
)

// ----------------------------------------------------------------------------
//  Major methods of totp.Key object
// ----------------------------------------------------------------------------
//  * You should handle the error in your code.

// Generate the current passcode.
//
// Which is a string of 8 digit numbers and valid for with 5 skews as set in
// the above options (5 skew = time tolerance of ± 15 seconds(period) * 5).
passcode, err := key.PassCode()

// Validate the received passcode.
ok := key.Validate(passcode)

// Get 100x100 px image of QR code as PNG byte data.
//
// FixLevelDefault is the 15% of error correction.
qrCodeObj, err := key.QRCode(totp.FixLevelDefault)
pngBytes, err := qrCodeObj.PNG(100, 100)

// Get the secret key in PEM format text.
pemKey, err := key.PEM()

// Get the secret key in TOTP URI format string.
// This is equivalent to key.String().
uriKey := key.URI()

// Get the secret value in Base32 format string.
// This is equivalent to key.Secret.String().
base32Key := key.Secret.Base32()

// Get the secret value in Base62 format string.
base62Key := key.Secret.Base62()

// Get the secret value in bytes.
rawKey := key.Secret.Bytes()

ECDH Support

This package supports ECDH key agreement protocol for the TOTP secret key generation (deriving TOTP secret from ECDH shared secret).

A shared secret key can be created by exchanging a public ECDH key between two parties. This shared secret key is used to derive the TOTP key. Thus the same TOTP passcode can be shared within the same time period.

This feature is useful when a shared but ephemeral/volatile secret value (a common TOTP passcode) is required to increase security between two parties.

For example, a time-based shared salt for hashing or an additional value to generate a shared secret key for symmetric encryption.

The values expire, but the possibilities are endless.

// Pre-agreement between Alice and Bob.
commonCurve := ecdh.X25519()
commonCtx := "example.com alice@example.com bob@example.com TOTP secret v1"

// Key exchange between Alice and Bob.
alicePriv, alicePub := getECDHKeysSomeHowForAlice(commonCurve)
bobPriv, bobPub := getECDHKeysSomeHowForBob(commonCurve)

// Generate a new TOTP key for Alice
Issuer := "Example.com"
AccountName := "alice@example.com"

key, err := totp.GenerateKey(Issuer, AccountName,
    totp.WithECDH(alicePriv, bobPub, commonCtx),
)
if err != nil {
    log.Fatal(err)
}

// Alice generates 6 digits of TOTP passcode which should be the same as Bob's.
passcode, err := key.PassCode()
if err != nil {
    log.Fatal(err)
}

Contributing

go1.22+ Go Reference Opened Issues PR

Any Pull-Request for improvement is welcome!

Test Statuses

UnitTests PlatformTests

golangci-lint CodeQL-Analysis Vulnerability Scan

codecov Go Report Card

License, copyright and credits

About

Simple Go package to implement TOTP authentication functionality to the Go app. It supports ECDH as well.

License:MIT License


Languages

Language:Go 100.0%