自学内容网 自学内容网

Rust学习(九):密码生成器

Rust学习(九):密码生成器

到目前为止,我们已经介绍了不少Rust基础内容,虽然还有很多知识难以覆盖,但是,我们依然可以以一个Rust项目来深入了解和掌握,Rust构建项目的哲学。我们将在下面编写一个生成密码的命令行工具,可以通过seed参数控制生成密码的账户,通过length参数来控制生成密码的长度,默认长度是16位。

首先我们来整理一下项目的功能:

  1. 求梅森哈希值
  2. 生成密码
  3. 获取命令行参数

我们可以分别使用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)!