twofa
Simple 2FA QR CodeGen based on otp & openparser packages
Summary
| Latest Version | 0.1.0 |
|---|---|
| License | MIT |
| CI Status | Failing |
| Downloads | 0 |
| Last Indexed | 2026-09-04 07:26 |
Tags
Authors
- George Lemon
Installation
nimble install twofa
choosenim install twofa
git clone https://github.com/openpeeps/twofa
OS Compatibility
| Platform | Linux | macOS | Windows | FreeBSD | OpenBSD | NetBSD | Android | iOS | WASM | Embedded |
|---|---|---|---|---|---|---|---|---|---|---|
| twofa | ✓ | ✓ | ✓ | - | - | - | - | - | - | - |
Dependencies
| Package | Version | Optional |
|---|---|---|
| nim >= | 2.0.0 | No |
| openparser | - | No |
Source
| Repository | https://github.com/openpeeps/twofa |
|---|---|
| Homepage | https://github.com/openpeeps/twofa |
| Registry Source | nimble_official |
README
A tiny package for generating 2FA QR codes and TOTP/HOTP codes in Nim
nimble install twofa
😍 Key Features
- 🔐 TOTP (RFC 6238) and HOTP (RFC 4226) code generation and verification
- 🔑 SHA1 and SHA512 HMAC algorithms, configurable digits (6–8) and period/counter
- 🛡️ Verification with clock-drift window and constant-time secret handling
- 📱 QR code generation via
openparser/qr- Model 2 (versions 1-40), all EC levels (L/M/Q/H) - 🎨 Customizable SVG rendering:
scale,border,dark/lightcolors, andQrEncodeOptions - 🧩 Raw matrix support via
saveMatrixfor pre-encodedQrMatrixvalues - 🔗
otpauth://provisioning URIs withprovisioningUri,genTotpUriandgenHotpUrihelpers
[!NOTE] This library is built on top of
openparser/qrfor QR code generation.
Examples
Check out the tests/*.nim folder for more examples.
TOTP and HOTP
import twofa
# TOTP with SHA1 (compatible with Google Authenticator)
let totp = initTotp("JBSWY3DPEHPK3PXP",
issuer = "MyApp", accountName = "alice@example.com")
echo totp.now() # code for current time
echo totp.at(1234567890) # code for specific timestamp
echo totp.verify(123456, timestamp = 1234567890) # verification with window
# TOTP with SHA512 and custom period/digits
let totp512 = initTotp("JBSWY3DPEHPK3PXP",
interval = 60, digits = 8, algorithm = algSHA512)
# HOTP (counter-based)
var hotp = initHotp("JBSWY3DPEHPK3PXP",
issuer = "MyApp", accountName = "bob@example.com", counter = 0)
echo hotp.at(0) # code for counter 0
echo hotp.next() # next code and auto-increment counter
echo hotp.verify(755224, counter = 0)
Provisioning URIs
import twofa
let totp = initTotp("JBSWY3DPEHPK3PXP",
issuer = "OpenPeeps", accountName = "alice@example.com")
# From TOTP/HOTP instances (follows Google Authenticator Key Uri Format)
let totpUri = totp.provisioningUri()
let hotpUri = initHotp("JBSWY3DPEHPK3PXP",
issuer = "OpenPeeps", accountName = "bob@example.com").provisioningUri(initialCount = 1)
# Standalone helpers without creating an instance
let uri1 = genTotpUri(secret = "JBSWY3DPEHPK3PXP",
label = "alice@example.com", issuer = "MyApp", interval = 30)
let uri2 = genHotpUri(secret = "JBSWY3DPEHPK3PXP",
label = "bob@example.com", issuer = "MyApp", counter = 42)
QR Code Generation
import twofa
let totp = initTotp("JBSWY3DPEHPK3PXP",
issuer = "MyApp", accountName = "alice@example.com")
let uri = totp.provisioningUri()
# Save to file (default rendering)
uri.saveQr("totp.svg")
# Get SVG as string
let svg = uri.getQr()
writeFile("totp.svg", svg)
# Custom rendering settings
uri.saveQr("totp-custom.svg",
scale = 10, # pixel size per module
border = 2, # quiet zone in modules
dark = "#000000",
light = "#ffffff")
# Custom error correction / version
import openparser/qr # for QrEncodeOptions / ecHigh
uri.saveQr("totp-high-ec.svg",
options = QrEncodeOptions(ecLevel: ecHigh))
let svgHigh = uri.getQr(
scale = 8, border = 4,
options = QrEncodeOptions(ecLevel: ecHigh))
Raw Matrix with saveMatrix
Useful when you already have a QrMatrix from openparser/qr:
import twofa
import openparser/qr
let uri = genTotpUri(
secret = "JBSWY3DPEHPK3PXP",
label = "alice@example.com",
issuer = "MyApp")
# Encode once, render multiple ways
let m = encodeQr(uri) # or encodeQrBytes, etc.
m.saveMatrix("matrix-default.svg")
m.saveMatrix("matrix-red.svg", scale = 6, dark = "#ff0000", light = "#ffffff")
# High error correction matrix
let m2 = encodeQr(uri, QrEncodeOptions(ecLevel: ecQuartile))
m2.saveMatrix("matrix-quartile.svg", scale = 8, border = 4)
❤ Contributions & Support
- 🐛 Found a bug? Create a new Issue
- 👋 Wanna help? Fork it!
🎩 License
MIT license. Made by Humans from OpenPeeps.
Copyright OpenPeeps & Contributors - All rights reserved.