otp-std

Crates.iootp-std
lib.rsotp-std
version0.1.0
sourcesrc
created_at2024-11-16 08:06:27.540923
updated_at2024-11-16 08:06:27.540923
descriptionGenerating and checking one-time passwords.
homepage
repositoryhttps://github.com/nekitdev/otp-std
max_upload_size
id1450230
size107,307
Nikita Tikhonov (nekitdev)

documentation

https://docs.rs/otp-std

README

otp-std

License Version Downloads Test

Generating and checking one-time passwords.

Installation

cargo

You can add otp-std as a dependency with the following command:

$ cargo add otp-std

Or by directly specifying it in the configuration like so:

[dependencies]
otp-std = "0.1.0"

Alternatively, you can add it directly from the source:

[dependencies.otp-std]
git = "https://github.com/nekitdev/otp-std.git"

Examples

For demonstration purposes, all code examples are going to use the following encoded secret: JEQDYMZAN5YGK3RAONXXK4TDMU.

Base

use otp_std::{Base, Secret};

fn main() {
    let secret = Secret::decode("JEQDYMZAN5YGK3RAONXXK4TDMU").unwrap();

    let base = Base::builder().secret(secret).build();

    let input = 0;

    let output = base.generate(input);

    assert!(base.verify(input, output));
}

HOTP

use otp_std::{Base, Hotp, Secret};

fn main() {
    let secret = Secret::decode("JEQDYMZAN5YGK3RAONXXK4TDMU").unwrap();

    let counter = Counter::new(0);

    let base = Base::builder().secret(secret).build();
    let mut hotp = Hotp::builder().base(base).counter(counter).build();

    let code = hotp.generate();

    hotp.increment();  // increment the counter, as the code has been used

    let other = hotp.generate();

    assert_ne!(code, other);  // the codes have to be different because of the increment
}

TOTP

use std::{thread::sleep, time::Duration};

use otp_std::{Base, Secret, Totp};

fn main() {
    let secret = Secret::decode("JEQDYMZAN5YGK3RAONXXK4TDMU").unwrap();

    let base = Base::builder().secret(secret).build();
    let totp = Totp::builder().base(base).build();

    let duration = Duration::from_secs(totp.period.get());

    let code = totp.generate();
    sleep(duration);

    let other = totp.generate();

    assert_ne!(code, other);
}

Features

generate-secret

The generate-secret feature enables secret generation:

use otp_std::{Length, Secret};

fn main() {
    let secret = Secret::generate(Length::default());

    println!("{secret}");
}

unsafe-length

By default, otp-std does not allow secret length below 16 bytes.

Some services, however, generate secrets with length below the aforementioned limit. To counter this, one can enable the unsafe-length feature:

use otp_std::{Length, Secret};

fn main() {
    let length = Length::new(10).unwrap();

    let secret = Secret::generate(length);

    println!("{secret}");
}

Note that unwrapping here is absolutely fine, as the new function returns Result<Self, !> (i.e. it never returns an error). Conversely, this code would panic without unsafe-length because 10 < 16.

auth

The auth feature implements building and parsing OTP URLs:

use otp_std::{Auth, Base, Label, Part, Secret, Totp};

fn main() {
    let secret = Secret::decode("JEQDYMZAN5YGK3RAONXXK4TDMU").unwrap();

    let base = Base::builder().secret(secret).build();
    let totp = Totp::builder().base(base).build();

    let issuer = Part::borrowed("MelodyKit").unwrap();
    let user = Part::borrowed("nekitdev").unwrap();

    let label = Label::builder().issuer(issuer).user(user).build();

    let auth = Auth::totp(totp, label);

    let url = auth.build_url();

    println!("{url}");

    let parsed = Auth::parse_url(url).unwrap();

    assert_eq!(auth, parsed);
}

sha2

The default algorithm used by OTP is SHA1. In order to use SHA256 or SHA512, one can enable the sha2 feature:

use otp_std::{Algorithm, Base, Secret, Totp};

fn main() {
    let secret = Secret::decode("JEQDYMZAN5YGK3RAONXXK4TDMU").unwrap();

    let base = Base::builder()
        .secret(secret)
        .algorithm(Algorithm::Sha256)
        .build();

    let totp = Totp::builder().base(base).build();

    let code = totp.generate();

    println!("{code}");
}

serde

The serde feature, when enabled, implements Serialize and Deserialize for types provided by otp-std:

use otp_std::{Base, Secret, Totp};
use serde_json::{json, to_value};

fn main() {
    let string = "JEQDYMZAN5YGK3RAONXXK4TDMU";

    let data = json!({
        "secret": string,
        // all of the following fields are optional
        "algorithm": "SHA1",
        "digits": 6,
        "skew": 1,
        "period": 30,
    });

    let secret = Secret::decode(string).unwrap();

    let base = Base::builder().secret(secret).build();
    let totp = Totp::builder().base(base).build();

    let value = to_value(&totp).unwrap();

    assert_eq!(value, data);
}

Documentation

You can find the documentation here.

Support

If you need support with the library, you can send an email.

Changelog

You can find the changelog here.

Security Policy

You can find the Security Policy of otp-std here.

Contributing

If you are interested in contributing to otp-std, make sure to take a look at the Contributing Guide, as well as the Code of Conduct.

License

otp-std is licensed under the MIT License terms. See License for details.

Commit count: 6

cargo fmt