4个版本
0.1.3 | 2023年6月5日 |
---|---|
0.1.2 | 2023年4月11日 |
0.1.1 | 2023年4月10日 |
0.1.0 | 2023年4月10日 |
在身份认证类别中排名第407
每月下载量29次
69KB
1K SLoC
r2fa
Rust语言的HTOP、TOTP和Steam Guard双因素认证实现。
使用ring
0.16.20
,可能与其他版本的ring
不兼容。
特性
- HOTP, TOTP
- 用户可配置设置
- 数字
- 密钥
- TOTP密钥时间步长(周期)
- TOTP密钥起始时间(t0)
- HOTP密钥初始计数器
- 用户可配置设置
- Steam Guard(尚未实现)
- 验证
- 代码生成
Cargo特性
qrcode
qrcode
qrcodegen
qrcoderead
qrcode
特性默认启用,需要添加default-features = false
来禁用默认特性。
或者,可以显式启用qrcodegen
特性,该特性用于使用给定的opt认证数据生成二维码。
或者,启用qrcoderead
特性,该特性用于使用给定的opt认证二维码读取二维码。
这两个qrcodegen
和qrcoderead
特性都使用了image
包,这将大大增加包的大小。
日志
日志
此特性为库提供了日志支持。
待办事项
- 日志特性
- Steam Guard
- 从mafile生成Steam Guard代码
- Steam登录
- 添加电话号码到Steam
- 添加Steam Guard方法
- 删除Steam Guard方法
- 确认
用法
手动创建结构体
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();
从URI格式字符串
use libr2fa::otpauth_from_uri;
use libr2fa::TOTPKey;
use libr2fa::HMACType;
use libr2fa::Key;
let totp_key1 = otpauth_from_uri("otpauth://totp/ACME%20Co:[email protected]?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:[email protected]".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());
如果给定一个opt认证结构体,也可以将其转换为URI格式字符串。
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();
从URI二维码
首先查看Cargo特性部分。
原始二维码:
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:[email protected]".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());
或者,使用给定的opt认证数据生成二维码。
请注意,所有编码后的图像都将为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:[email protected]".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();
编码后的二维码:
Steam Guard 代码生成
首先您需要一个 mafile
文件。
关于mafile是什么以及如何获取mafile,请参考 ASF 2FA。
它将在 config
文件夹中给您一个 .maFile
文件。
获取Steam Guard代码
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);
Steam API
手机验证API
测试手机号码是否有效并且是VoIP。
主机:store.steampowered.com
端点:/phone/validate
方法:POST
内容类型:application/x-www-form-urlencoded; charset=UTF-8
请求体
sessionID
: 会话IDphoneNumber
: 手机号码
响应: json
响应示例
{
"success":true,
"number":"your phone number",
"is_valid":true,
"is_voip":false,
"is_fixed":false
}
添加手机号码
这是一个多步骤过程。
- 首先您将您的
phone number
发送到Steam。 - 然后Steam可能会要求您进行
Email Verification
。 - 您点击发送到您邮箱的邮件验证链接。
- 您向Steam发送请求,表明您已点击链接。
- 然后Steam将向手机号码发送
sms code
。 - 您向Steam发送包含
sms code
的请求。 - 完成。
然而,所有这些过程的 host
、endpoint
、method
和 content type
都相同。唯一的区别是 request body
。
主机:store.steampowered.com
端点:/phone/add_ajaxop
方法:POST
内容类型:application/x-www-form-urlencoded; charset=UTF-8
发送手机号码
请求体
op
:get_phone_number
input
: 您的手机号码sessionID
: 您的会话IDconfirmed
:1
checkfortos
:1
bisediting
:0
token
:0
响应示例
{
"success":true,
"showResend":false,
"state":"email_verification",
"errorText":"",
"token":"0",
"phoneNumber":"your phone number"
}
如果 state
是 email_verification
,则表示您可以进行邮件验证。如果 state
是 get_sms_code
,则表示您可以去检查 sms code
。
邮件验证
请求体
op
:email_verification
input
: 空值sessionID
: 您的会话IDconfirmed
:1
checkfortos
:1
bisediting
:0
token
:0
响应示例
{
"success":true,
"showResend":false,
"state":"get_sms_code",
"errorText":"",
"token":"0",
"inputSize":"20",
"maxLength":"5"
}
如果 state
是 email_verification
,则表示您可以进行邮件验证。如果 state
是 get_sms_code
,则表示您可以去检查 sms code
。
短信代码验证
请求体
op
:get_sms_code
input
: 您收到的短信代码sessionID
: 您的会话IDconfirmed
:1
checkfortos
:1
bisediting
:0
token
:0
响应示例
{
"success":true,
"showResend":false,
"state":"done",
"errorText":"",
"token":"0",
"vac_policy":0,
"tos_policy":2,
"showDone":true,
"maxLength":"5"
}
如果 state
是 done
,则表示过程已完成。
依赖项
~10–31MB
~497K SLoC