MHash-384 development repository
Revision | 586d5497a0c89b790ce24a947abcfbeafde12926 (tree) |
---|---|
Zeit | 2020-02-17 05:39:30 |
Autor | ![]() |
Commiter | LoRd_MuldeR |
Added support for Base85 (Ascii85) encoding.
@@ -71,7 +71,7 @@ typedef struct | ||
71 | 71 | { |
72 | 72 | bool keep_going; |
73 | 73 | bool short_format; |
74 | - bool base64; | |
74 | + int base_enc; | |
75 | 75 | bool lower_case; |
76 | 76 | bool benchmark; |
77 | 77 | } |
@@ -97,6 +97,7 @@ static void print_manpage(const CHAR_T *const argv0) | ||
97 | 97 | FPUTS(STR(" --short Print the digest in short format (no file names)\n"), stderr); |
98 | 98 | FPUTS(STR(" --lower-case Print the digest in lower-case letters (default: upper-case)\n"), stderr); |
99 | 99 | FPUTS(STR(" --base64 Print the digest in Base64 format (default: Hex format)\n"), stderr); |
100 | + FPUTS(STR(" --base85 Print the digest in Base85 format (default: Hex format)\n"), stderr); | |
100 | 101 | FPUTS(STR(" --help Print help screen and exit\n"), stderr); |
101 | 102 | FPUTS(STR(" --version Print program version and exit\n"), stderr); |
102 | 103 | FPUTS(STR(" --self-test Run self-test and exit\n"), stderr); |
@@ -106,6 +107,21 @@ static void print_manpage(const CHAR_T *const argv0) | ||
106 | 107 | } |
107 | 108 | |
108 | 109 | /* |
110 | + * Encode digest string | |
111 | + */ | |
112 | +static std::string encode_digest(const uint8_t *const digest, const options_t &options) | |
113 | +{ | |
114 | + if (options.base_enc) | |
115 | + { | |
116 | + return ((options.base_enc > 1U) ? bytes_to_base85(digest, MHASH384_SIZE) : bytes_to_base64(digest, MHASH384_SIZE)); | |
117 | + } | |
118 | + else | |
119 | + { | |
120 | + return bytes_to_hex(digest, MHASH384_SIZE, options.lower_case); | |
121 | + } | |
122 | +} | |
123 | + | |
124 | +/* | |
109 | 125 | * Parse command-line options |
110 | 126 | */ |
111 | 127 | static opmode_t parse_options(int &arg_offset, options_t &options, const int argc, const CHAR_T *const *const argv) |
@@ -131,7 +147,11 @@ static opmode_t parse_options(int &arg_offset, options_t &options, const int arg | ||
131 | 147 | } |
132 | 148 | else if (!STRICMP(argstr, STR("base64"))) |
133 | 149 | { |
134 | - options.base64 = true; | |
150 | + options.base_enc = (options.base_enc != 1) ? (options.base_enc + 1) : options.base_enc; | |
151 | + } | |
152 | + else if (!STRICMP(argstr, STR("base85"))) | |
153 | + { | |
154 | + options.base_enc = (options.base_enc != 2) ? (options.base_enc + 2) : options.base_enc; | |
135 | 155 | } |
136 | 156 | else if(!STRICMP(argstr, STR("lower-case"))) |
137 | 157 | { |
@@ -168,10 +188,17 @@ static opmode_t parse_options(int &arg_offset, options_t &options, const int arg | ||
168 | 188 | ++arg_offset; |
169 | 189 | } |
170 | 190 | |
171 | - if (options.base64 && options.lower_case) | |
191 | + if (options.base_enc > 2) | |
192 | + { | |
193 | + print_logo(); | |
194 | + FPUTS(STR("Error: Options \"--base64\" and \"--base85\" are mutually exclusive!\n"), stderr); | |
195 | + fflush(stderr); | |
196 | + return MODE_UNKNOWN; | |
197 | + } | |
198 | + else if (options.base_enc && options.lower_case) | |
172 | 199 | { |
173 | 200 | print_logo(); |
174 | - FPUTS(STR("Error: Options \"--base64\" and \"--lower-case\" are mutually exclusive!\n"), stderr); | |
201 | + FPRINTF(stderr, STR("Error: Options \"--%") PRI_CHAR STR("\" and \"--lower-case\" are mutually exclusive!\n"), (options.base_enc > 1U) ? STR("base85") : STR("base64")); | |
175 | 202 | fflush(stderr); |
176 | 203 | return MODE_UNKNOWN; |
177 | 204 | } |
@@ -230,10 +257,9 @@ static bool process_file(const CHAR_T *const file_name, const options_t options) | ||
230 | 257 | if(!ferror(input)) |
231 | 258 | { |
232 | 259 | const uint8_t *const digest = mhash384.finish(); |
233 | - const std::string string = options.base64 ? bytes_to_base64(digest, MHASH384_SIZE) : bytes_to_hex(digest, MHASH384_SIZE, options.lower_case); | |
234 | 260 | const CHAR_T *const source_name = file_name ? file_name : STR("-"); |
235 | 261 | const CHAR_T *const format = options.short_format ? STR("%") PRI_char STR("\n") : STR("%") PRI_char STR(" %") PRI_CHAR STR("\n"); |
236 | - FPRINTF(stdout, format, string.c_str(), source_name); | |
262 | + FPRINTF(stdout, format, encode_digest(digest, options).c_str(), source_name); | |
237 | 263 | fflush(stdout); |
238 | 264 | } |
239 | 265 | else |
@@ -154,6 +154,21 @@ static bool read_line(FILE *const input, char *const line, const int max_count, | ||
154 | 154 | } |
155 | 155 | |
156 | 156 | /* |
157 | + * Encode digest string | |
158 | + */ | |
159 | +static std::string encode_digest(const uint8_t *const digest, const options_t &options) | |
160 | +{ | |
161 | + if (options.base_enc) | |
162 | + { | |
163 | + return ((options.base_enc > 1U) ? bytes_to_base85(digest, MHASH384_SIZE) : bytes_to_base64(digest, MHASH384_SIZE)); | |
164 | + } | |
165 | + else | |
166 | + { | |
167 | + return bytes_to_hex(digest, MHASH384_SIZE, options.lower_case); | |
168 | + } | |
169 | +} | |
170 | + | |
171 | +/* | |
157 | 172 | * Compute hash and compare against reference |
158 | 173 | */ |
159 | 174 | static bool test_string(const uint32_t count, const char *const text, const uint8_t *const expected, const options_t &options) |
@@ -167,9 +182,7 @@ static bool test_string(const uint32_t count, const char *const text, const uint | ||
167 | 182 | const uint8_t *const digest = mhash384.finish(); |
168 | 183 | const bool success = (!memcmp(digest, expected, MHASH384_SIZE)); |
169 | 184 | |
170 | - const std::string string = options.base64 ? bytes_to_base64(digest, MHASH384_SIZE) : bytes_to_hex(digest, MHASH384_SIZE, options.lower_case); | |
171 | - const CHAR_T *const result = success ? STR("OK") : STR("Error!"); | |
172 | - FPRINTF(stderr, STR("%") PRI_char STR(" - %") PRI_CHAR STR("\n"), string.c_str(), result); | |
185 | + FPRINTF(stderr, STR("%") PRI_char STR(" - %") PRI_CHAR STR("\n"), encode_digest(digest, options).c_str(), success ? STR("OK") : STR("Error!")); | |
173 | 186 | |
174 | 187 | fflush(stderr); |
175 | 188 | return success; |
@@ -178,14 +191,12 @@ static bool test_string(const uint32_t count, const char *const text, const uint | ||
178 | 191 | /* |
179 | 192 | * Compute hash and append to hashset |
180 | 193 | */ |
181 | -static bool append_string(UnorderedHashSet &hash_set, std::vector<std::array<uint64_t,256U>> &stats, const char *const text, const bool base64, const bool lower_case) | |
194 | +static bool append_string(UnorderedHashSet &hash_set, std::vector<std::array<uint64_t,256U>> &stats, const char *const text, const options_t &options) | |
182 | 195 | { |
183 | 196 | std::array<uint8_t, MHASH384_SIZE> digest; |
184 | 197 | mhash384_compute(digest.data(), reinterpret_cast<const uint8_t*>(text), strlen(text)); |
185 | 198 | |
186 | - const std::string string = base64 ? bytes_to_base64(digest.data(), MHASH384_SIZE) : bytes_to_hex(digest.data(), MHASH384_SIZE, lower_case); | |
187 | - FPRINTF(stderr, STR("%") PRI_char STR("\n"), string.c_str()); | |
188 | - | |
199 | + FPRINTF(stderr, STR("%") PRI_char STR("\n"), encode_digest(digest.data(), options).c_str()); | |
189 | 200 | for(size_t i = 0U; i < MHASH384_SIZE; ++i) |
190 | 201 | { |
191 | 202 | stats[i][digest[i]]++; |
@@ -263,7 +274,7 @@ bool stress_test(const CHAR_T *const file_name, const options_t &options) | ||
263 | 274 | /*FPRINTF(stderr, STR("\"%") PRI_char STR("\"\n"), line);*/ |
264 | 275 | if(line[0U]) |
265 | 276 | { |
266 | - if(!append_string(hash_set, stats, line, options.base64, options.lower_case)) | |
277 | + if(!append_string(hash_set, stats, line, options)) | |
267 | 278 | { |
268 | 279 | success = false; |
269 | 280 | if(!options.keep_going) |
@@ -96,3 +96,67 @@ std::string bytes_to_base64(const uint8_t *const data, const size_t len) | ||
96 | 96 | |
97 | 97 | return result.str(); |
98 | 98 | } |
99 | + | |
100 | +/* | |
101 | + * Convert byte array to Base85-string | |
102 | + * implementation based on code created by Doug Currie <https://github.com/dcurrie/ascii85> | |
103 | + */ | |
104 | +std::string bytes_to_base85(const uint8_t *const data, const size_t len) | |
105 | +{ | |
106 | + static const char BASE_CHAR = '!'; | |
107 | + | |
108 | + size_t pos = 0U; | |
109 | + std::ostringstream result; | |
110 | + char temp[6U]; | |
111 | + memset(temp, 0, sizeof(char) * 6U); | |
112 | + | |
113 | + while (pos < len) | |
114 | + { | |
115 | + uint32_t chunk; | |
116 | + size_t n = len - pos; | |
117 | + | |
118 | + if (n >= 4U) | |
119 | + { | |
120 | + chunk = (((uint32_t)data[pos++]) << 24U); | |
121 | + chunk |= (((uint32_t)data[pos++]) << 16U); | |
122 | + chunk |= (((uint32_t)data[pos++]) << 8U); | |
123 | + chunk |= (((uint32_t)data[pos++])); | |
124 | + } | |
125 | + else | |
126 | + { | |
127 | + chunk = (((uint32_t)data[pos++]) << 24U); | |
128 | + if (pos < len) | |
129 | + { | |
130 | + chunk |= (((uint32_t)data[pos++]) << 16U); | |
131 | + if (pos < len) | |
132 | + { | |
133 | + chunk |= (((uint32_t)data[pos++]) << 8U); | |
134 | + if (pos < len) | |
135 | + { | |
136 | + chunk |= (((uint32_t)data[pos++])); | |
137 | + } | |
138 | + } | |
139 | + } | |
140 | + } | |
141 | + | |
142 | + if(chunk || (n < 4U)) | |
143 | + { | |
144 | + temp[4U] = ((char)(BASE_CHAR + (chunk % 85U))); | |
145 | + chunk /= 85U; | |
146 | + temp[3U] = ((char)(BASE_CHAR + (chunk % 85U))); | |
147 | + chunk /= 85U; | |
148 | + temp[2U] = ((char)(BASE_CHAR + (chunk % 85U))); | |
149 | + chunk /= 85U; | |
150 | + temp[1U] = ((char)(BASE_CHAR + (chunk % 85U))); | |
151 | + chunk /= 85U; | |
152 | + temp[0U] = ((char)(BASE_CHAR + chunk)); | |
153 | + result << temp; | |
154 | + } | |
155 | + else | |
156 | + { | |
157 | + result << 'z'; /*encode z for zero*/ | |
158 | + } | |
159 | + } | |
160 | + | |
161 | + return result.str(); | |
162 | +} |
@@ -29,5 +29,6 @@ | ||
29 | 29 | const CHAR_T * get_basename(const CHAR_T *const path); |
30 | 30 | std::string bytes_to_hex(const uint8_t *const data, const size_t len, const bool lower_case); |
31 | 31 | std::string bytes_to_base64(const uint8_t *const data, const size_t len); |
32 | +std::string bytes_to_base85(const uint8_t *const data, const size_t len); | |
32 | 33 | |
33 | 34 | #endif /*INC_MHASH384_UTILS_H*/ |