锈打印!在某些情况下打印奇怪的字符
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。
我正在尝试编写一个简短的程序(足够短,它有一个简单的主要功能)。首先,我应该在 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。