aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--NEWS2
-rw-r--r--butl/sha25615
-rw-r--r--butl/sha256.cxx64
-rw-r--r--tests/sha256/driver.cxx9
4 files changed, 90 insertions, 0 deletions
diff --git a/NEWS b/NEWS
index 2c5645d..bce5db3 100644
--- a/NEWS
+++ b/NEWS
@@ -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);
}