Invalid utf-8 when using .read_to_string from a file

Basically, I am making a program to encrypt or decrypt the contents of a .txt file. However, the algorithm I used to encrypt the file results in a bunch of invalid utf-8, For example: ��OX�&�.~`�Y�{߆�~�&�5�聾����. Sadly, when I try to read the encrypted bytes to a string, it spits out an error. Is there any way that I can avoid this, or perhaps dump the contents of the encrypted file into some other variable with a different type?
PS: I am new to rust, and have not finished reading "the book", so you may have to keep any answers relatively simple. :slightly_smiling_face:

here is my code:

fn decrypt(
    key: String,
    nonce: String,
    filename: String
) {
    let thekey = GenericArray::clone_from_slice(key.trim().as_bytes());
    let thenonce = GenericArray::from_slice(nonce.trim().as_bytes().as_ref());
    let mut cyphertext: String = String::new();
    let aead = Aes256Gcm::new(thekey);
    let mut f = match File::open(&filename[..].trim()) {
        Ok(file) => {
            file
        }
        Err(e) => {
            match e.kind() {
                ErrorKind::PermissionDenied => {
                    panic!("permission denied on opening the encrypted file");
                }
                ErrorKind::NotFound => {
                    panic!("your encrypted file was not found!!");
                }
                _ => {
                    panic!("failed to open your encrypted file");
                }
            }
        }
    };

    f.read_to_string(&mut cyphertext).expect("failed to read your encrypted file to a string");

    println!("writing the decrypted contents of {} to decrypted.txt", filename);
    let mut f2 = match File::open("decrypted.txt") {
        Ok(file) => {
            file
        }
        Err(e) => {
            match e.kind() {
                ErrorKind::NotFound => {
                    println!("The file decrypted.txt was not found!");
                    println!("Treating decrypted.txt...");
                    match File::create("decrypted.txt") {
                        Ok(file) => {
                            file
                        }
                        Err(e) => {
                            panic!("failed to create decrypted.txt");
                        }
                    }
                }
                ErrorKind::PermissionDenied => {
                    panic!("Permission denied to open decrypted.txt");
                }
                _ => {
                    panic!("Failed to open decrypted.txt");
                }
            }
        }
    };

    let decryptedtext: Vec<u8> = aead.decrypt(thenonce, cyphertext.as_ref()).expect("Couldn't decrypt file!");

    f2.write_all(&decryptedtext[..]).expect("couldn't write the decrypted text to decrypted.txt");

}

Since rust's Strings must always contain valid UTF-8, the solution here is to not use a String: check out read_to_end instead.

You'll need to use create a Vec to hold the ciphertext instead:

let mut ciphertext: Vec<u8> = Vec::new();
// ...
f.read_to_end(&mut ciphertext).expect(...);
3 Likes

Oh, ok. That works like a charm. Thanks!

1 Like