Rust学习(九):密码生成器
Rust学习(九):密码生成器
到目前为止,我们已经介绍了不少Rust基础内容,虽然还有很多知识难以覆盖,但是,我们依然可以以一个Rust项目来深入了解和掌握,Rust构建项目的哲学。我们将在下面编写一个生成密码的命令行工具,可以通过seed参数控制生成密码的账户,通过length参数来控制生成密码的长度,默认长度是16位。
首先我们来整理一下项目的功能:
- 求梅森哈希值
- 生成密码
- 获取命令行参数
我们可以分别使用hash、encryptor和main三个crate实现这三个功能:
$ mkdir PasswdGenerator && cd PasswdGenerator
然后创建一个Cargo.toml文件:
[workspace]
members = [
"hash",
"encryptor",
"main",
]
使用cargo包管理工具生成库和主函数:
$ cargo new hash --lib
$ cargo new encryptor --lib
$ cagro new main
为了方便代码的管理和维护,我们最终的目录如下:
|----Cargo.toml
|----encryptor
| |----Cargo.toml
| |----src
| |----lib.rs
| |----password.rs
|----hash
| |----Cargo.toml
| |----src
| |----lib.rs
| |----merhash.rs
|----main
| |----Cargo.toml
| |----src
| |----main.rs
下面分别在相应的模块中实现梅森哈希值、密码、命令行参数获取三大功能:
hash/src/lib.rs:
pub mod merhash;
#[cfg(test)]
mod tests {
use crate::merhash::mersenne_hash;
#[test]
fn mersenne_hash_works() {
let seed = String::from("jdxjp");
let hash = mersenne_hash(&seed);
assert_eq!(2000375, hash);
}
}
hash/src/merhash.rs:
pub fn mersenne_hash(seed: &str) -> usize {
let mut hash: usize = 0;
for (i, c) in seed.chars().enumerate() {
hash += (i + 1) * (c as usize);
}
(hash % 127).pow(3) - 1
}
encryptor/Cargo.toml:
[dependencies]
anyhow = "1.0.56"
base64 = "0.13.0"
hash = {path = "../hash"}
encryptor/src/lib.rs:
pub mod password;
encryptor/src/password.rs:
use anyhow::{bail, Error, Result};
use base64::encode;
use hash::merhash::mersenne_hash;
const CRYPTO: &str = "!pqHr$*+ST1Vst_uv:?wW%X&Y-/Z01_2.34<ABl9ECo|x#yDE^F{GHEI[]JK>LM#NOBWPQ:RaKU@}cde56R7=8f/9gIhi,jkzmn";
pub fn generate_password(seed: &str, length: usize) -> Result<String, Error> {
if length < 6 {
bail!("length must >= 6");
}
let p = match length {
6..=10 => 1,
11..=15 => 2,
16..=20 => 3,
_ => 3,
};
let mut mer_hash = mersenne_hash(seed).pow(p);
let mut passwd = String::new();
let crypto_len = CRYPTO.len();
while mer_hash > 9 {
let loc = mer_hash % crypto_len;
let nthc = CRYPTO.chars().nth(loc).expect("Error while getting char");
passwd.push(nthc);
mer_hash /= crypto_len;
}
let interval = passwd.clone();
for c in seed.chars() {
passwd.push(c);
passwd += &interval;
}
passwd = encode(passwd);
passwd = passwd.replace("+", "*").replace("/", "*");
let interval = passwd.clone();
while passwd.len() < length {
passwd += &interval;
}
Ok(format!("{}: {}", seed, &passwd[..length]))
}
main/Cargo.toml:
[package]
name = "PasswdGenerator"
version = "0.1.0"
edition = "2021"
[dependencies]
anyhow = "1.0.56"
clap = {version = "3.1.6", features = ["derive"]}
encryptor = {path = "../encryptor"}
main/src/main.rs:
use anyhow::{bail, Result};
use clap::Parser;
use encryptor::password::generate_password;
#[derive(Parser, Debug)]
#[clap(version, about, long_about = None)]
struct Args {
#[clap(short, long)]
seed: String,
#[clap(short, long, default_value_t = 16)]
length: usize,
}
fn main() -> Result<()> {
let args = Args::parse();
if args.seed.len() < 4 {
bail!("seed {} length must >= 4", &args.seed);
}
let (seed, length) = (args.seed, args.length);
let passwd = generate_password(&seed[..], length);
match passwd {
Ok(val) => println!("{}",val),
Err(err) => println!("{}",err),
}
Ok(())
}
执行cargo bulid就可以完成我们密码生成器项目的构建了,希望你能通过这个小项目,增强对Rust基础知识的理解,使得Rust之旅更加顺利!
原文地址:https://blog.csdn.net/2301_77286822/article/details/144021587
免责声明:本站文章内容转载自网络资源,如本站内容侵犯了原著者的合法权益,可联系本站删除。更多内容请关注自学内容网(zxcms.com)!