Skip to content
 
 

Folders and files

NameName
Last commit message
Last commit date

Latest commit

 

History

23 Commits
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 

Repository files navigation

V OTP 0.3

votp enables you to add TOTP or HOTP functionaltiies in your code the V programming language.

Twitter URL

Installation

v up
v install OdaiGH.votp

Usage

import odaigh.votp { HOTP, TOTP }
import readline { read_line }

// You can use a key length of 6 or 8. Anything more or less or in-between might not work correctly on some apps.
const keylen := 6;

// TOTP is time-based, so this serves as our token expiration which is usually 30 or 60 seconds after generating.
// You can add a few seconds of buffer room for network latency, but this code does not implement a buffer (yet).
const interval_in_seconds := 30;

// You can now set a string as your secret key, you must not re-use this key for multiple users because otherwise
// there will be duplicate tokens generated which defeats the security aspect of HOTP and TOTP.
const secret_key := "YOUR_SECRET";

// If we're using HOTP, then we have a counter variable that increments upon each *successful* token entry.
mut counter := 0;

// Initialize the HOTP or TOTP structure, I opted to change from SHA512 to SHA1 to match the RFCs for HOTP and TOTP.
totp := votp.new[TOTP](secret_key, keylen, interval_in_seconds);
hotp := votp.new[HOTP](secret_key, keylen, interval_in_seconds);

// Generate the HOTP or TOTP token string.
totp_token := votp.generate[TOTP](totp, counter);
hotp_token := votp.generate[HOTP](hotp, counter);

// Verify that the HOTP or TOTP token is valid.
totp_input := read_line("Enter ${totp_token}: ") or { exit(1) };
hotp_input := read_line("Enter ${hotp_token}: ") or { exit(1) };

if votp.verify[TOTP](totp, totp_input, counter) {
	println("TOTP token successfully verified!");
} else {
	println("TOTP token failed to verify!");
}

if votp.verify[HOTP](hotp, hotp_input, counter) {
	println("HOTP token successfully verified!");
	counter++; // Increment upon success
} else {
	println("HOTP token failed to verify!");
}

Using this with authenticator apps.

Authenticator apps will require a URI that follows the following format:

TOTP:

otpauth://totp/{app name}?secret={URL safe base32 secret key}&issuer={app name}&algorithm=SHA512&digits={keylen}&period={interval_in_seconds}

HOTP:

otpauth://hotp/{app name}?secret={URL safe base32 secret key}&issuer={app name}&algorithm=SHA512&digits={keylen}&counter={counter}

You can generate a QR Code with this URI and that can be scanned in by most authenticator applications to test out your HOTP and TOTP implementation in real-time on real hardware with real-world latencies. It is recommended to experiment with artificial network throttling to determine how the authorization behaves in various network conditions.

You can use this to generate the URI:

pub fn makeurl[T](otp T, counter u64) string {
	urlsafe_base32 := otp.secret.bytestr().replace('=', '%3D');

	$if T is TOTP {
		return "otpauth://totp/votp?secret=${urlsafe_base32}&issuer=votp&algorithm=SHA1&digits=${otp.digits}&period=${otp.expiry}"
	}
	$else $if T is HOTP {
		return "otpauth://hotp/votp?secret=${urlsafe_base32}&issuer=votp&algorithm=SHA1&digits=${otp.digits}&counter=${counter}"
	}
	$else { 
		panic("VOTP can only generate URLs with HOTP or TOTP!")
	}
}

Todo

  • Add a buffer for TOTP token verification.
  • Refactor code to match RFCs for HOTP and TOTP.
  • Test the results of HOTP and TOTP tokens on a physical device.

License

V otp is licensed under MIT.

Contributing

Follow the instructions in CONTRIBUTING.md

About

otp module for v, written in v

Resources

Contributing

Stars

0 stars

Watchers

0 watching

Forks

Releases

Packages

Contributors

Languages