Ошибка Rust UTF-8, поток 'main' запаниковал 'под названием `Result :: unwrap () - PullRequest
0 голосов
/ 15 ноября 2018

Я работаю над вызовом cryptopals, вызов 1, вызов 3 :

Шестнадцатеричная строка:

1b37373331363f78151b7f2b783431333d78397828372d363c78373e783a393b3736

... был XOR против одного персонажа. Найдите ключ, расшифруйте сообщение.

Вы можете сделать это вручную. Но не пишите код, чтобы сделать это за вас.

Как? Придумайте какой-нибудь метод для «озвучивания» фрагмента английского текста. Частота символов является хорошим показателем. Оцените каждый результат и выберите тот, который имеет лучший результат.

Я запрограммировал это:

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

Не могу понять, в чем проблема.

Ответы [ 2 ]

0 голосов
/ 16 ноября 2018

Вы должны проверить, является ли полученная строка допустимой строкой UTF-8.String::from_utf8 проверит это для вас и вернет либо Ok(s), либо 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
}
0 голосов
/ 15 ноября 2018

Я решил это, изменив это

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_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()));
    }
    let mut tmp = String::new();
    tmp.push_str(&String::from_utf8_lossy(&vec_utf8));
    vec_plain.push(tmp);

}
...