modernized_vigenere/
lib.rs

1//! a modernized Vigenere algorithm
2//!
3//! We are not working on paper any more.\
4//! Therefore, instead of shifting the letters of the alphabet, we will shift every single byte.\
5//! That's why this lib is capable to encrypt/decrypt any file:\
6//! Not only ASCII-files, but also pictures, data or even binaries.
7#![forbid(unsafe_code)]
8
9use std::fs::File;
10use std::io;
11use std::io::prelude::*;
12use std::io::BufWriter;
13
14const BUFFSIZE: usize = 1024;
15
16/// modulo add of 2 bytes
17///
18/// input parameter: u8, u8
19/// output parameter: u8
20fn dec(b: &u8, p: &u8) -> u8 {
21    ((*b as i16 - *p as i16) % 256) as u8
22}
23
24/// modulo subtraction of 2 bytes
25///
26/// input parameter: u8, u8
27/// output parameter: u8
28fn enc(b: &u8, p: &u8) -> u8 {
29    ((*b as u16 + *p as u16) % 256) as u8
30}
31
32/// create the pass-vector
33/// 
34/// input parameter: &str
35///     can be the path to a file (which will be used as a pass-phrase),
36///     or a passphrase, itself
37/// output parameter: Vec<u8>
38fn mk_pass(pphrase: &str) -> Vec<u8> {
39    let bytes = std::fs::read(pphrase);
40    let pass: Vec<u8> = match bytes {
41        Ok(b) => b,
42        Err(_) => pphrase.as_bytes().to_vec(),
43    };
44    pass
45}
46
47/// shift all bytes
48///
49/// input parameter:
50/// - in_file       (name of the input file)
51/// - passphrase    (phrase use for en/de-cryption)
52/// - out_file      (name of the output file)
53/// - func          (shift-function to use: either enc or dec)
54fn worker(
55    in_file: &str,
56    passphrase: &str,
57    out_file: &str,
58    func: &dyn Fn(&u8, &u8) -> u8,
59) -> io::Result<()> {
60    let pass: Vec<u8> = mk_pass(passphrase);
61
62    let mut f = match File::open(in_file) {
63        Ok(file) => file,
64        Err(error) => {
65            println!("Problem opening the file {}: {:?}", in_file, error);
66            return Err(error);
67        }
68    };
69    let mut buff = [0; BUFFSIZE];
70    let mut offset: usize = 0;
71    let g = match File::create(out_file) {
72        Ok(file) => file,
73        Err(error) => {
74            println!("Problem opening the file {}: {:?}", out_file, error);
75            return Err(error);
76        }
77    };
78    let mut writer = BufWriter::new(g);
79    let mut n = f.read(&mut buff)?;
80    while 0 < n {
81        for i in 0..n {
82            buff[i] = func(&buff[i], &pass[offset]);
83            offset = (offset + 1) % pass.len();
84        }
85        if n == BUFFSIZE {
86            //writer.write_all(&buff)?;
87            match writer.write_all(&buff) {
88                Ok(_) => (),
89                _ => println!("Problem witing to file {}.", out_file),
90            };
91        } else {
92            for b in buff.iter().take(n) {
93                match writer.write(&[*b]) {
94                    Ok(1) => (),
95                    _ => println!("Problem witing to file {}.", out_file),
96                };
97            }
98        }
99        n = f.read(&mut buff)?;
100    }
101    Ok(())
102}
103
104/// public wrapper to start function worker for encryption
105///
106/// input parameter:
107/// - in_file       (name of the input file)
108/// - passphrase    (phrase use for en/de-cryption)
109/// - out_file      (name of the output file)
110pub fn encrypt(in_file: &str, passphrase: &str, out_file: &str) -> io::Result<()> {
111    worker(in_file, passphrase, out_file, &enc)
112}
113
114/// public wrapper to start function worker for decryption
115///
116/// input parameter:
117/// - in_file       (name of the input file)
118/// - passphrase    (phrase use for en/de-cryption)
119/// - out_file      (name of the output file)
120pub fn decrypt(in_file: &str, passphrase: &str, out_file: &str) -> io::Result<()> {
121    worker(in_file, passphrase, out_file, &dec)
122}