diff options
-rw-r--r-- | NEWS | 2 | ||||
-rw-r--r-- | butl/sha256 | 15 | ||||
-rw-r--r-- | butl/sha256.cxx | 64 | ||||
-rw-r--r-- | tests/sha256/driver.cxx | 9 |
4 files changed, 90 insertions, 0 deletions
@@ -15,6 +15,8 @@ Version 0.3.0 * Implement timestamp from_string(). + * Implement sha256_to_fingerprint (), fingerprint_to_sha256 (). + Version 0.2.0 * First public release. diff --git a/butl/sha256 b/butl/sha256 index d583701..a1d0c38 100644 --- a/butl/sha256 +++ b/butl/sha256 @@ -79,6 +79,21 @@ namespace butl mutable digest_type bin_; mutable bool done_; }; + + // Convert a SHA256 string representation (64 hex digits) to the fingerprint + // canonical representation (32 colon-separated upper case hex digit pairs, + // like 01:AB:CD:...). Throw invalid_argument if the argument is not a valid + // SHA256 string. + // + std::string + sha256_to_fingerprint (const std::string&); + + // Convert a fingerprint (32 colon-separated hex digit pairs) to the SHA256 + // string representation (64 lower case hex digits). Throw invalid_argument + // if the argument is not a valid fingerprint. + // + std::string + fingerprint_to_sha256 (const std::string&); }; #endif // BUTL_SHA256 diff --git a/butl/sha256.cxx b/butl/sha256.cxx index feca9a7..7c0b21e 100644 --- a/butl/sha256.cxx +++ b/butl/sha256.cxx @@ -9,6 +9,9 @@ #include <stdint.h> #include <stddef.h> // size_t +#include <cctype> // isxdigit(), toupper(), tolower() +#include <stdexcept> // invalid_argument + using SHA256_CTX = butl::sha256::context; extern "C" @@ -24,6 +27,8 @@ using namespace std; namespace butl { + // sha256 + // sha256:: sha256 () : done_ (false) @@ -73,4 +78,63 @@ namespace butl return str_; } + + // Conversion functions + // + string + sha256_to_fingerprint (const string& s) + { + auto bad = []() {throw invalid_argument ("invalid SHA256 string");}; + + size_t n (s.size ()); + if (n != 64) + bad (); + + string f; + f.reserve (n + 31); + for (size_t i (0); i < n; ++i) + { + char c (s[i]); + if (!isxdigit (c)) + bad (); + + if (i > 0 && i % 2 == 0) + f += ":"; + + f += toupper (c); + } + + return f; + } + + string + fingerprint_to_sha256 (const string& f) + { + auto bad = []() {throw invalid_argument ("invalid fingerprint");}; + + size_t n (f.size ()); + if (n != 32 * 3 - 1) + bad (); + + string s; + s.reserve (64); + for (size_t i (0); i < n; ++i) + { + char c (f[i]); + if ((i + 1) % 3 == 0) + { + if (c != ':') + bad (); + } + else + { + if (!isxdigit (c)) + bad (); + + s += tolower (c); + } + } + + return s; + } } diff --git a/tests/sha256/driver.cxx b/tests/sha256/driver.cxx index 8c2e525..ae2bd4a 100644 --- a/tests/sha256/driver.cxx +++ b/tests/sha256/driver.cxx @@ -37,4 +37,13 @@ main () string s (h.string ()); assert (s == "204d9db65789fbede7829ed77f72ba1f0fe21a833d95abad4849b82f33a69b9d"); + + string fp ("F4:9D:C0:02:C6:B6:62:06:A5:48:AE:87:35:32:95:64:C2:B8:C9:6D:9B:" + "28:85:6D:EF:CA:FA:7F:04:B5:4F:A6"); + + string sh ( + "f49dc002c6b66206a548ae8735329564c2b8c96d9b28856defcafa7f04b54fa6"); + + assert (fingerprint_to_sha256 (fp) == sh); + assert (sha256_to_fingerprint (sh) == fp); } |