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
qrcodegen
qrcoderead
The 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.
log
This feature provided log support for the library.
```rust use libr2fa::HOTPKey; use libr2fa::HMACType; use libr2fa::Key;
let mut hotpkey = HOTPKey { key: "MFSWS5LGNBUXKZLBO5TGQ33JO5SWC2DGNF2WCZLIMZUXKZLXMFUGM2LVNFQWK53IMZUXK2A=".tostring(), // SHA1 is the default method, however it is deprecated hmac_type: HMACType::SHA1, ..Default::default() };
let code = hotpkey.getcode().unwrap(); ```
```rust use libr2fa::otpauthfromuri; use libr2fa::TOTPKey; use libr2fa::HMACType; use libr2fa::Key;
let totpkey1 = otpauthfromuri("otpauth://totp/ACME%20Co:john.doe@email.com?secret=HXDMVJECJJWSRB3HWIZR4IFUGFTMXBOZ&issuer=ACME%20Co&algorithm=SHA256&digits=7&period=60"); if let Err(err) = totpkey1 { panic!("{}", err); } let mut totpkey1 = totpkey1.unwrap();
let mut totpkey2 = TOTPKey { name: "ACME Co:john.doe@email.com".tostring(), key: "HXDMVJECJJWSRB3HWIZR4IFUGFTMXBOZ".tostring(), digits: 7, timestep: 60, hmactype: HMACType::SHA256, issuer: Some("ACME Co".tostring()), ..Default::default() };
asserteq!(totpkey1.getname(), totpkey2.getname()); asserteq!(totpkey1.gettype(), totpkey2.gettype()); asserteq!(totpkey1.getcode(), totpkey2.get_code()); ```
If given a opt auth struct, it can also be converted to a uri formate string.
```rust use libr2fa::HOTPKey; use libr2fa::HMACType; use libr2fa::Key;
let mut hotpkey = HOTPKey { key: "MFSWS5LGNBUXKZLBO5TGQ33JO5SWC2DGNF2WCZLIMZUXKZLXMFUGM2LVNFQWK53IMZUXK2A=".tostring(), // SHA1 is the default method, however it is deprecated hmac_type: HMACType::SHA1, ..Default::default() };
let uri = hotpkey.geturi(); ```
See the Cargo Features part first.
The original qrcode:
```rust use libr2fa::otpauthfromuri_qrcode; use libr2fa::TOTPKey; use libr2fa::HMACType; use libr2fa::Key;
let totpkey1 = otpauthfromuriqrcode("public/uriqrcodetest.png"); if let Err(err) = totpkey1 { panic!("{}", err); } let mut totpkey1 = totp_key1.unwrap();
let mut totpkey2 = TOTPKey { name: "ACME Co:john.doe@email.com".tostring(), issuer: Some("ACME Co".tostring()), key: "HXDMVJECJJWSRB3HWIZR4IFUGFTMXBOZ".tostring(), digits: 7, timestep: 60, hmactype: HMACType::SHA256, ..Default::default() };
asserteq!(totpkey1.getname(), totpkey2.getname()); asserteq!(totpkey1.gettype(), totpkey2.gettype()); asserteq!(totpkey1.getcode(), totpkey2.get_code()); ```
Or, generate the qrcode with the given opt auth data.
Note, all encoded image will be 2048x2048.
```rust use libr2fa::otpauthfromuri_qrcode; use libr2fa::TOTPKey; use libr2fa::HMACType; use libr2fa::Key; use libr2fa::OptAuthKey;
let totpkey = TOTPKey { name: "ACME Co:john.doe@email.com".tostring(), issuer: Some("ACME Co".tostring()), key: "HXDMVJECJJWSRB3HWIZR4IFUGFTMXBOZ".tostring(), digits: 7, timestep: 60, hmactype: HMACType::SHA256, ..Default::default() };
let uri = totpkey.touri_struct();
// convert to image::DynamicImage data let img: image::DynamicImage = uri.into();
// Or, save to a path uri.toqrcode("public/uriqrcodeencode_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.
```rust use libr2fa::SteamKey; use libr2fa::Key; use libr2fa::steam::MaFile;
let mafile = MaFile::fromfile("./public/mafiletest.mafile");
assert!(mafile.is_ok());
let steamkey = SteamKey::frommafile(mafile.unwrap());
assert!(steamkey.isok());
let mut steamkey = steamkey.unwrap();
let code = steamkey.getcode();
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:
json
{
"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_number
input
: your phone numbersessionID
: your session idconfirmed
: 1
checkfortos
: 1
bisediting
: 0
token
: 0
Response Sample:
json
{
"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_verification
input
: emptysessionID
: your session idconfirmed
: 1
checkfortos
: 1
bisediting
: 0
token
: 0
Response Sample:
json
{
"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_code
input
: sms code you receivesessionID
: your session idconfirmed
: 1
checkfortos
: 1
bisediting
: 0
token
: 0
Response Sample:
json
{
"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.