utf-8 - Rust UTF-8 错误,线程 'main' 在 '调用 `Result::unwrap() 处惊慌失措
问题描述
我正在研究cryptopals挑战集1挑战3:
十六进制编码的字符串:
1b37373331363f78151b7f2b783431333d78397828372d363c78373e783a393b3736
...已对单个字符进行了异或运算。找到密钥,解密消息。
您可以手动执行此操作。但不要:编写代码为你做这件事。
如何?设计一些方法来“评分”一段英文明文。字符频率是一个很好的指标。评估每个输出并选择得分最高的输出。
我已经编程了这个:
extern crate num_traits;
use num_traits::pow;
use std::io;
fn main() {
let mut hex_string = String::new();
let mut bin_string = String::new();
let mut vec_bin: Vec<String> = Vec::new();
let mut vec_plain: Vec<String> = Vec::new();
println!("Please enter the string: ");
io::stdin()
.read_line(&mut hex_string)
.expect("Failed to read line");
bin_string = string_to_hex(hex_string.trim());
for i in 0..256 {
let mut tmp = bin_string.clone();
vec_bin.push(xor(tmp, i));
}
for s in vec_bin {
let mut vec_utf8: Vec<u8> = Vec::new();
for i in 0..(s.len() / 8) {
vec_utf8.push(bits_to_int(s[(i * 8)..((i * 8) + 8)].to_string()));
}
vec_plain.push(String::from_utf8(vec_utf8).unwrap());
}
for s in vec_plain {
println!("{}", s);
}
}
fn string_to_hex(text: &str) -> String {
let mut hex_string = String::new();
for c in text.chars() {
hex_string.push_str(&hex_to_bits(c));
}
hex_string
}
fn hex_to_bits(c: char) -> String {
let mut result = String::new();
let x = c.to_digit(16).unwrap();
let mut tmp = x;
while tmp != 0 {
result = (tmp % 2).to_string() + &result;
tmp = tmp / 2;
}
while result.len() < 4 {
result = "0".to_string() + &result;
}
result
}
fn xor(s: String, u: u16) -> String {
let mut result = String::new();
let bin = dec_to_bin(u);
for i in 0..(s.len() / 8) {
let mut tmp = bin.clone();
result = result + &single_byte_xor(s[(i * 8)..((i * 8) + 8)].to_string(), tmp);
}
result
}
fn dec_to_bin(u: u16) -> String {
let mut result = String::new();
let mut tmp = u;
while tmp != 0 {
result = (tmp % 2).to_string() + &result;
tmp = tmp / 2;
}
while result.len() < 8 {
result = "0".to_string() + &result;
}
result
}
fn single_byte_xor(s: String, u: String) -> String {
let mut result = String::new();
for i in 0..s.len() {
if &s[i..(i + 1)] == "1" && &u[i..(i + 1)] == "1" {
result = result + &"0".to_string();
} else if &s[i..(i + 1)] == "1" || &u[i..(i + 1)] == "1" {
result = result + &"1".to_string();
} else {
result = result + &"0".to_string();
}
}
result
}
fn bits_to_int(s: String) -> u8 {
let mut result: u8 = 0;
let mut counter = 0;
for c in s.chars().rev() {
let x = c.to_digit(10).unwrap();
if x == 1 {
result += pow(2u8, counter);
}
counter += 1;
}
result
}
当我运行程序时,我得到这个错误:
Please enter the string:
1b37373331363f78151b7f2b783431333d78397828372d363c78373e783a393b3736
thread 'main' panicked at 'called `Result::unwrap()` on an `Err` value: FromUtf8Error { bytes: [155, 183, 183, 179, 177, 182, 191, 248, 149, 155, 255, 171, 248, 180, 177, 179, 189, 248, 185, 248, 168, 183, 173, 182, 188, 248, 183, 190, 248, 186, 185, 187, 183, 182], error: Utf8Error { valid_up_to: 0, error_len: Some(1) } }', /checkout/src/libcore/result.rs:916:5
stack backtrace:
0: std::sys::unix::backtrace::tracing::imp::unwind_backtrace
at /checkout/src/libstd/sys/unix/backtrace/tracing/gcc_s.rs:49
1: std::sys_common::backtrace::print
at /checkout/src/libstd/sys_common/backtrace.rs:68
at /checkout/src/libstd/sys_common/backtrace.rs:57
2: std::panicking::default_hook::{{closure}}
at /checkout/src/libstd/panicking.rs:381
3: std::panicking::default_hook
at /checkout/src/libstd/panicking.rs:397
4: std::panicking::rust_panic_with_hook
at /checkout/src/libstd/panicking.rs:577
5: std::panicking::begin_panic
at /checkout/src/libstd/panicking.rs:538
6: std::panicking::begin_panic_fmt
at /checkout/src/libstd/panicking.rs:522
7: rust_begin_unwind
at /checkout/src/libstd/panicking.rs:498
8: core::panicking::panic_fmt
at /checkout/src/libcore/panicking.rs:71
9: core::result::unwrap_failed
at /checkout/src/libcore/macros.rs:23
10: <core::result::Result<T, E>>::unwrap
at /checkout/src/libcore/result.rs:782
11: nr3::main
at src/main.rs:24
12: std::rt::lang_start::{{closure}}
at /checkout/src/libstd/rt.rs:74
13: std::panicking::try::do_call
at /checkout/src/libstd/rt.rs:59
at /checkout/src/libstd/panicking.rs:480
14: __rust_maybe_catch_panic
at /checkout/src/libpanic_unwind/lib.rs:101
15: std::rt::lang_start_internal
at /checkout/src/libstd/panicking.rs:459
at /checkout/src/libstd/panic.rs:365
at /checkout/src/libstd/rt.rs:58
16: std::rt::lang_start
at /checkout/src/libstd/rt.rs:74
17: main
18: __libc_start_main
19: _start
我无法弄清楚问题是什么。
解决方案
您应该检查您获得的字符串是否是有效的 UTF-8 字符串。String::from_utf8
将为您检查并返回Ok(s)
or Err(_)
。然后,您应该匹配返回值并打印解码的字符串,或者报告失败。像这样的东西可以解决问题。
use std::io;
fn main() {
let mut hex_string = "1b37373331363f78151b7f2b783431333d78397828372d363c78373e783a393b3736";
let raw:Vec<u8> = hex_string_to_raw(hex_string);
for i in 0..255 {
// Get XOR'd version
let mut vec_utf8:Vec<u8> = raw.iter().map(|v| v ^ i ).collect();
// Try to decode it
let s = String::from_utf8(vec_utf8);
match s {
Err(_) => { println!("Failed to decode using {}", i); }
Ok(s) => { println!("Decoded with {} to '{}'", i, s); }
}
}
}
fn hex_string_to_raw(hex: &str) -> Vec<u8> {
let chars:Vec<char> = hex.chars().collect();
let mut raw:Vec<u8> = vec![];
for cs in chars.chunks(2) {
let c0:char = cs[0];
let c1:char = cs[1];
raw.push( (c0.to_digit(16).unwrap()*16 + c1.to_digit(16).unwrap()) as u8);
}
raw
}
推荐阅读
- java - 如何在coldfusion中实现jCrypt java类?
- firebase - React Native Notification Websockets v/s Firestore listener v/s SSE
- azure-active-directory - Azure B2C Active Directory:更新所有用户的一个属性
- java - Javax 验证不适用于值为数组或列表的 Hashmap
- php - 如何从文件返回 ['field1','field2'] 打开数组
- python - 我无法在将用于数据库连接的函数之外访问此变量
- javascript - 扩展 textarea onload 不会扩展 HTML
- c++ - UE4 和 Azure 存储 sdk
- rxjs - redux-observable testing forkJoin 大理石图
- microsoft-graph-api - Microsoft Graph 502 Bad Gateway - 创建专用通道时无法执行后端请求(测试版 API)