| Crates.io | libr2fa |
| lib.rs | libr2fa |
| version | 0.1.3 |
| created_at | 2023-04-10 11:01:37.850239+00 |
| updated_at | 2023-06-05 13:14:45.246762+00 |
| description | rust implementation for HTOP, TOTP and steam guard tow-factor-authentication |
| homepage | https://github.com/Alex222222222222/r2fa |
| repository | https://github.com/Alex222222222222/r2fa |
| max_upload_size | |
| id | 835043 |
| size | 101,749 |
Rust implementation for HTOP, TOTP and steam guard tow-factor-authentication.
Use ring 0.16.20,
may be incompatible with other version of ring.
qrcode
qrcodegenqrcodereadThe qrcode feature is enabled by default,
need to add default-features = false to disable the default feature.
Or, you can enable the qrcodegen feature explicitly
which used to generate the qrcode with the given opt auth data.
Or, the qrcoderead feature
which used to read the qrcode with the given opt auth qrcode.
Both qrcodegen and qrcoderead feature use the image
crate, which will greatly increase the package size.
logThis feature provided log support for the library.
use libr2fa::HOTPKey;
use libr2fa::HMACType;
use libr2fa::Key;
let mut hotp_key = HOTPKey {
key: "MFSWS5LGNBUXKZLBO5TGQ33JO5SWC2DGNF2WCZLIMZUXKZLXMFUGM2LVNFQWK53IMZUXK2A=".to_string(),
// SHA1 is the default method, however it is deprecated
hmac_type: HMACType::SHA1,
..Default::default()
};
let code = hotp_key.get_code().unwrap();
use libr2fa::otpauth_from_uri;
use libr2fa::TOTPKey;
use libr2fa::HMACType;
use libr2fa::Key;
let totp_key1 = otpauth_from_uri("otpauth://totp/ACME%20Co:john.doe@email.com?secret=HXDMVJECJJWSRB3HWIZR4IFUGFTMXBOZ&issuer=ACME%20Co&algorithm=SHA256&digits=7&period=60");
if let Err(err) = totp_key1 {
panic!("{}", err);
}
let mut totp_key1 = totp_key1.unwrap();
let mut totp_key2 = TOTPKey {
name: "ACME Co:john.doe@email.com".to_string(),
key: "HXDMVJECJJWSRB3HWIZR4IFUGFTMXBOZ".to_string(),
digits: 7,
time_step: 60,
hmac_type: HMACType::SHA256,
issuer: Some("ACME Co".to_string()),
..Default::default()
};
assert_eq!(totp_key1.get_name(), totp_key2.get_name());
assert_eq!(totp_key1.get_type(), totp_key2.get_type());
assert_eq!(totp_key1.get_code(), totp_key2.get_code());
If given a opt auth struct, it can also be converted to a uri formate string.
use libr2fa::HOTPKey;
use libr2fa::HMACType;
use libr2fa::Key;
let mut hotp_key = HOTPKey {
key: "MFSWS5LGNBUXKZLBO5TGQ33JO5SWC2DGNF2WCZLIMZUXKZLXMFUGM2LVNFQWK53IMZUXK2A=".to_string(),
// SHA1 is the default method, however it is deprecated
hmac_type: HMACType::SHA1,
..Default::default()
};
let uri = hotp_key.get_uri();
See the Cargo Features part first.
The original qrcode:

use libr2fa::otpauth_from_uri_qrcode;
use libr2fa::TOTPKey;
use libr2fa::HMACType;
use libr2fa::Key;
let totp_key1 = otpauth_from_uri_qrcode("public/uri_qrcode_test.png");
if let Err(err) = totp_key1 {
panic!("{}", err);
}
let mut totp_key1 = totp_key1.unwrap();
let mut totp_key2 = TOTPKey {
name: "ACME Co:john.doe@email.com".to_string(),
issuer: Some("ACME Co".to_string()),
key: "HXDMVJECJJWSRB3HWIZR4IFUGFTMXBOZ".to_string(),
digits: 7,
time_step: 60,
hmac_type: HMACType::SHA256,
..Default::default()
};
assert_eq!(totp_key1.get_name(), totp_key2.get_name());
assert_eq!(totp_key1.get_type(), totp_key2.get_type());
assert_eq!(totp_key1.get_code(), totp_key2.get_code());
Or, generate the qrcode with the given opt auth data.
Note, all encoded image will be 2048x2048.
use libr2fa::otpauth_from_uri_qrcode;
use libr2fa::TOTPKey;
use libr2fa::HMACType;
use libr2fa::Key;
use libr2fa::OptAuthKey;
let totp_key = TOTPKey {
name: "ACME Co:john.doe@email.com".to_string(),
issuer: Some("ACME Co".to_string()),
key: "HXDMVJECJJWSRB3HWIZR4IFUGFTMXBOZ".to_string(),
digits: 7,
time_step: 60,
hmac_type: HMACType::SHA256,
..Default::default()
};
let uri = totp_key.to_uri_struct();
// convert to image::DynamicImage data
let img: image::DynamicImage = uri.into();
// Or, save to a path
uri.to_qr_code("public/uri_qrcode_encode_test.png").unwrap();
The encoded qrcode:

You need to have a mafile first.
On what is a mafile and how to get a mafile, follow ASF 2FA.
It will give you a .maFile at config folder.
use libr2fa::SteamKey;
use libr2fa::Key;
use libr2fa::steam::MaFile;
let mafile = MaFile::from_file("./public/mafile_test.mafile");
assert!(mafile.is_ok());
let steam_key = SteamKey::from_mafile(mafile.unwrap());
assert!(steam_key.is_ok());
let mut steam_key = steam_key.unwrap();
let code = steam_key.get_code();
assert!(code.is_ok());
let code = code.unwrap();
println!("steam code: {}", code);
Test whether a phone number is valid and is a voip.
Host: store.steampowered.com
Endpoint: /phone/validate
Method: POST
Content-Type: application/x-www-form-urlencoded; charset=UTF-8
Request Body:
sessionID : session idphoneNumber: phone numberResponse: json
Response Sample:
{
"success":true,
"number":"your phone number",
"is_valid":true,
"is_voip":false,
"is_fixed":false
}
This is a multi process procedure.
phone number to steam.Email Verification.sms code to the phone number.sms code.However all this process have the same host, endpoint, method
and content type.
The only difference is the request body.
Host: store.steampowered.com
Endpoint: /phone/add_ajaxop
Method: POST
Content-Type: application/x-www-form-urlencoded; charset=UTF-8
Request Body:
op : get_phone_numberinput : your phone numbersessionID : your session idconfirmed : 1checkfortos : 1bisediting : 0token : 0Response Sample:
{
"success":true,
"showResend":false,
"state":"email_verification",
"errorText":"",
"token":"0",
"phoneNumber":"your phone number"
}
The state is email_verification means you could go for email verification.
The state is get_sms_code means you could go for check sms code.
Request Body:
op : email_verificationinput : emptysessionID : your session idconfirmed : 1checkfortos : 1bisediting : 0token : 0Response Sample:
{
"success":true,
"showResend":false,
"state":"get_sms_code",
"errorText":"",
"token":"0",
"inputSize":"20",
"maxLength":"5"
}
The state is email_verification means you could go for email verification.
The state is get_sms_code means you could go for check sms code.
Request Body:
op : get_sms_codeinput : sms code you receivesessionID : your session idconfirmed : 1checkfortos : 1bisediting : 0token : 0Response Sample:
{
"success":true,
"showResend":false,
"state":"done",
"errorText":"",
"token":"0",
"vac_policy":0,
"tos_policy":2,
"showDone":true,
"maxLength":"5"
}
The state is done means the process is done.