b2sum_rust/
lib.rs

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
use blake2_rfc::blake2b::Blake2b;
use filebuffer::FileBuffer;
use std::path::Path;

// For Reading Files without use FileBuffer
use std::fs;

// For Developer:
// * All outputs are in upper hexadecimal
// * You can use `as_bytes()` to convert from hexadecimal string to bytes
// * Blake2b digest size is between 1 and 64 bytes and will always be returned in hexadecimal format as a `String`
// * One function `read_using_fs()` uses the standard library as opposed to filebuffer to read files.

/// ## Blake2b File Hash Constructor
/// 
/// This is the official constructor used to call the new() function with the parameter of the intended digest size.
/// 
/// ## Example
/// 
/// ```no_run
/// use b2sum_rust::Blake2bSum;
/// 
/// fn main() {
///     // Creates a new File Instance
///     let context = Blake2bSum::new(64);
///     
///     // Outputs a Hexadecimal String
///     let hash = context.read("example_file.txt");
/// 
///     // Converts the hexadecimal string to a vector of bytes
///     let _bytes = Blake2bSum::as_bytes(&hash);
/// 
///     // Prints The Hexadecimal Representation
///     println!("Hash: {}",hash);
/// 
///     // Asserts That These Are Equal
///     assert_eq!(hash,"33B20D15383F97EB46D4FA69442596170CCA01008963A7D0E47210C33AEEF991C78323850C012550C227954A40B3D7AD612568ABC73DB9233FAB9EA4F002B0CB");
/// }
/// 
/// ```
/// 
/// All outputs are in **UPPER Hexadecimal** and between 1 and 64 bytes.
#[derive(Debug)]
pub struct Blake2bSum {
    digest_size: usize,
}

impl Blake2bSum {
    pub fn new(digest: usize) -> Self {
        if digest > 0 && digest <= 64 {
            return Blake2bSum {
                digest_size: digest,
            }
        }
        else {
            panic!("Digest Size is either too large or too small. It should be 1-64.")
        }
    }
    /// ## Hash File
    /// This is a function that hashes a file using **Blake2b** and returns the **Hexadecimal Representation** of it as a **String**. It takes as input any reference to Path.
    /// 
    /// It should be noted that changes to the file during hashing, such as truncating the file may cause problems.
    /// 
    /// ### About Filebuffer
    /// 
    /// > Filebuffer can map files into memory. This is often faster than using the primitives in std::io, and also more convenient. Furthermore this crate offers prefetching and checking whether file data is resident in physical memory (so access will not incur a page fault). This enables non-blocking file reading.
    pub fn read<T: AsRef<Path>>(&self, path: T) -> String {

        // Opens File Using File Buffer
        let fbuffer = FileBuffer::open(path).expect("failed to open file");
        
        // Sets Blake2b Context at the given digest size
        let mut context = Blake2b::new(self.digest_size);
        context.update(&fbuffer);
        let hash = context.finalize();
        
        // Return as Upper Hexadecimal Encoded String
        return hex::encode_upper(hash.as_bytes());
    }
    /// ## Hash File (Using Key)
    /// This is a function that hashes a file (using a key) with **Blake2b** and then returns the **Hexadecimal Representation** of it as a **String**. It takes as input any reference to Path.
    pub fn read_with_key<T: AsRef<Path>>(&self, path: T, key: &[u8]) -> String {

        // Opens File Using File Buffer
        let fbuffer = FileBuffer::open(path).expect("failed to open file");
        
        // Sets Blake2b Context at the given digest size and hashes with the provided key
        let mut context = Blake2b::with_key(self.digest_size, key);
        context.update(&fbuffer);
        let hash = context.finalize();
        
        // Return as Upper Hexadecimal Encoded String
        return hex::encode_upper(hash.as_bytes());
    }
    /// ## Hash File (using standard library)
    /// **Note: `read()` or `read_with_key()` should be used as opposed to this function.**
    /// 
    /// This is a function that hashes a file using **Blake2b** and returns the **Hexadecimal Representation** of it as a **String**. It takes as input any reference to Path.
    /// 
    /// This does not use `filebuffer` and instead uses the standard library. Filebuffer is much faster.
    #[deprecated(
        note = "Please use the `read()` function instead which uses Filebuffer. This function uses the standard library."
    )]
    pub fn read_using_fs<T: AsRef<Path>>(&self, path: T) -> String {

        // Opens File Using Standard Library (fs) and read file to string
        let fbuffer = fs::read_to_string(path).expect("failed to open file");

        
        // Sets Blake2b Context at the given digest size
        let mut context = Blake2b::new(self.digest_size);
        // Convert str to bytes and updated context
        context.update(&fbuffer.as_bytes());
        let hash = context.finalize();
        
        // Return as Upper Hexadecimal Encoded String
        return hex::encode_upper(hash.as_bytes());
    }
    /// # Read String
    /// This function will allow you to take a `String` or `str`, convert it to bytes, then hash it.
    pub fn read_str<T: AsRef<str>>(&self, string: T) -> String {
        
        // Sets Blake2b Context at the given digest size
        let mut context = Blake2b::new(self.digest_size);
        // Convert str to bytes
        context.update(string.as_ref().as_bytes());
        let hash = context.finalize();

        return hex::encode_upper(hash.as_bytes())
    }
    /// # Read Bytes
    /// This function will allow you to **read bytes** and then **hash the bytes** given the digest size.
    pub fn read_bytes(&self, bytes: &[u8]) -> String {
        
        // Sets Blake2b Context at the given digest size
        let mut context = Blake2b::new(self.digest_size);
        context.update(bytes);
        let hash = context.finalize();

        // Return encoded in upper hexadecimal
        return hex::encode_upper(hash.as_bytes())
    }
    /// ## as_bytes()
    /// `as_bytes()` converts from a **Hexadecimal String** to a **Vector of Bytes**
    pub fn as_bytes(s: &str) -> Vec<u8> {
        return hex::decode(s).unwrap()
    }
    /// ## Return Digest Size
    /// This method will return the provided digest size that the struct contains. It should be between 1 and 64 of type `usize`.
    pub fn return_digest_size(&self) -> usize {
        return self.digest_size
    }
}