当前位置: 首页 > article >正文

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之旅更加顺利!


http://www.kler.cn/a/412322.html

相关文章:

  • 【Linux庖丁解牛】—软件安装vim!
  • qt 读写文本、xml文件
  • 《免费的学习网站推荐3》
  • 【青牛科技】D1671 75Ω 带4级低通滤波的单通道视频放大电 路芯片介绍
  • CentOS7卸载node
  • ctfshow单身杯2024wp
  • QT:生成二维码 QRCode
  • AIGC学习笔记(7)——AI大模型开发工程师
  • LeetCode题练习与总结:第三大的数--414
  • 【设计模式】【行为型模式(Behavioral Patterns)】之责任链模式(Chain of Responsibility Pattern)
  • 极狐GitLab 17.6 正式发布几十项与 DevSecOps 相关的功能【二】
  • 【力扣】125. 验证回文串
  • 集成金蝶云星空数据至MySQL的完整案例解析
  • 【es6】原生js在页面上画矩形及删除的实现方法
  • 【Linux】基础IO-文件描述符
  • 【Linux学习】【Ubuntu入门】2-5 shell脚本入门
  • CentOS 环境使用代理下载数据失败-EOF occurred in violation of protocol (_ssl.c:1002)
  • 自主研发,基于PHP+ vue2+element+ laravel8+ mysql5.7+ vscode开发的不良事件管理系统源码,不良事件管理系统源码
  • 一篇文章了解Linux
  • react项目初始化配置步骤
  • 关于 Android LocalSocket、LocalServerSocket
  • C++中虚继承为什么可以解决菱形继承的数据冗余问题
  • EasyAnimate:基于Transformer架构的高性能长视频生成方法
  • LeetCode 2924. Find Champion II
  • CRTP mixins EBO
  • 代理模式 (Proxy Pattern)