wordlists/lib.rs
1//! Wordlists is a set of functionality and abstractions for turning binary into lists of UTF-8
2//! english (for now) words.
3//!
4//! This wordlists package has been implemented to fill a purpose for me; to generate a
5//! printable list of words for building a hard-copy of some sort of binary data (certificates,
6//! base64 encoded keys, etc). But because this functionality is fairly generic, I've pulled it
7//! out into a separate package.
8//!
9//! Some wordlists have different licensing potentially. Take this in mind when enabling their
10//! feature-flags as they may pull in other requirements. For me, I am not using this in any
11//! public way, just as a personal project; but feel free to yell at me if I did something stupid.
12//!
13
14#![deny(missing_docs)]
15
16use bitvec::prelude::*;
17use thiserror::Error;
18
19// General Library usage.
20mod bits;
21
22// High-level types of word-lists. These are always present types.
23mod types;
24pub use types::*;
25
26// Implementations, which are exported from here if enabled.
27mod gen;
28use crate::bits::index_width;
29pub use gen::*;
30
31/// The set of possible error which this crate will emit. We should not be emitting
32/// IO issues or generic panics as we should conform to the Result type structure.
33#[derive(Error, Debug)]
34pub enum WordlistError {
35 /// Given an indexed wordlist, the index is out of bounds.
36 #[error("Index `{0}` is out of bounds (`{1}`).")]
37 IndexOutOfBounds(usize, usize), // (index given, size bound)
38
39 /// If the indexed wordlist should have had a value but could not be unwrapped.
40 /// This may happen if there was a problem pulling in the wordlist at compile-time.
41 #[error("Wordlist is potentially incomplete as unable to index into it.")]
42 WordlistIsIncomplete,
43
44 /// The word given is invalid, and not part of the wordlist.
45 #[error("The given word ('{0}') is not known to the given wordlist.")]
46 InvalidWord(String),
47
48 /// If the wordlist is not a safely index-able length (i.e. not of size 2^N).
49 #[error("The wordlist has an invalid size ('{0}').")]
50 InvalidWordlistSize(usize),
51}
52
53/// Simple Result type wrapper with the WordlistError as the error type.
54pub type Result<T> = std::result::Result<T, WordlistError>;
55
56/// A Vector of words is a vector of static string references into the backing wordlist.
57pub type WordVec = std::vec::Vec<&'static str>;
58
59/// A wordlist byte-converter is a utility that can convert bits/bytes into sets of words.
60pub trait WordlistByteConverter {
61 /// Convert a list of bits into a list of words.
62 ///
63 /// This can fail if the wordlist was loaded incorrectly at compile-time or if
64 /// indexing fails for some unexpected reason.
65 fn to_words(&self, bytes: &BitVec) -> Result<WordVec>;
66
67 /// Convert a list of words into a list of bits.
68 ///
69 /// This can fail if the words in the list are not present in the wordlist; or there
70 /// is some issue packing the indexes as binary for some unexpected reason.
71 fn to_bytes(&self, words: &WordVec) -> Result<BitVec>;
72}
73
74/// A wordlist is pretty simply one or more lists of words. We can
75pub trait Wordlist {
76 /// The name of this Wordlist.
77 fn name(&self) -> &String;
78
79 /// The length of the wordlist. If this wordlist describes multiple lists,
80 /// this will be one more than the highest acceptable index.
81 fn size(&self) -> usize;
82
83 /// Check whether the given word exists in this Wordlist.
84 fn contains(&self, word: &str) -> bool;
85
86 /// Get the number of bits required to index into this wordlist. This may fail if the length of
87 /// the wordlist is not a valid one for indexing into.
88 fn index_bit_width(&self) -> Result<usize> {
89 index_width(self.size())
90 }
91
92 /// Confirm all words in the given list exist in this wordlist.
93 fn validate_word_list(&self, possible_words: &Vec<String>) -> bool {
94 possible_words.iter().all(|v| self.contains(v))
95 }
96}