锈打印!在某些情况下打印奇怪的字符

Rust println! prints weird characters under certain circumstances

我正在尝试编写一个简短的程序(足够短,它有一个简单的主要功能)。首先,我应该在 cargo.toml 文件中列出依赖项:

[dependencies]

passwords = {version = "3.1.3", features = ["crypto"]}

然后当我在main.rs中使用箱子时:

extern crate passwords;

use passwords::hasher;

fn main() {
    let args: Vec<String> = std::env::args().collect();

    if args.len() < 2
    {
        println!("Error! Needed second argument to demonstrate BCrypt Hash!");
        return;
    }

    let password = args.get(1).expect("Expected second argument to exist!").trim();

    let hash_res = hasher::bcrypt(10, "This_is_salt", password);

    match hash_res
    {
        Err(_) => {println!("Failed to generate a hash!");},
        Ok(hash) => { 
            let str_hash = String::from_utf8_lossy(&hash);
            println!("Hash generated from password {} is {}", password, str_hash);
        }
    }
}

当我 运行 以下命令时出现问题:

$ target/debug/extern_crate.exe trooper1

这成为输出:

?sC�M����k��ed from password trooper1 is ���Ka .+:�

然而,这个输入:

$ target/debug/extern_crate.exe trooper3

产生这个:

Hash generated from password trooper3 is ��;��l�ʙ�Y1�>R��G�Ѡd

我对第二个输出很满意,但是 UTF-8 中是否有某些东西可能导致输出语句的“Hash generat”部分被覆盖?有没有我可以用来防止这种情况的代码?

注意:代码是在 Visual Studio 中开发的 Windows 10 中的代码,并使用嵌入式 Git Bash 终端编译和 运行。

P.S.: 我看过类似的问题,例如 Rust println! problem - weird behavior inside the println macro and ,但这些问题似乎是换行符的问题,我认为这不是这里的问题。

您可以在打印之前将哈希值转换为十六进制以防止出现这种情况

为了补充前面的内容,请回答您的问题“UTF-8 中是否存在可能导致输出语句的“Hash generat”部分被覆盖的内容?”是:

let str_hash = String::from_utf8_lossy(&hash);

原因就在名称中:from_utf8_lossy 有损。 UTF8 是一种非常规范的格式。您可以使用此函数“解码”实际上不是 UTF8 的内容(无论出于何种原因),但它执行此解码的方式是:

replace any invalid UTF-8 sequences with U+FFFD REPLACEMENT CHARACTER, which looks like this: �

这就是您得到的奇怪替换:无法解码为 UTF8 的字节序列,并被“替换字符”替换。

这是因为散列函数通常return random-looking 二进制数据,意思是整个范围(0到255)的字节并且没有结构. UTF8 是结构化的,绝对不允许此类任意数据,因此虽然哈希可能是有效的 UTF8(尽管这不是很有用),但可能性非常低。

这就是为什么散列(和一般的二进制数据)通常以替代表示形式显示的原因,例如十六进制、base32 或 base64。