aboutsummaryrefslogtreecommitdiff
path: root/libbutl/sha256.mxx
diff options
context:
space:
mode:
authorBoris Kolpackov <boris@codesynthesis.com>2017-09-22 23:32:28 +0200
committerBoris Kolpackov <boris@codesynthesis.com>2017-09-22 23:32:28 +0200
commitc09cd7512491cee1e82c1ad8128ce9fd4bc3f79b (patch)
treea659ed768d849130ab5780a11b7f791a463a1a91 /libbutl/sha256.mxx
parent2a00871f07067f8f9e2de08bb9c8f50e1bf6a650 (diff)
Initial modularization with both Clang and VC hacks
Note: gave up on VC about half way though.
Diffstat (limited to 'libbutl/sha256.mxx')
-rw-r--r--libbutl/sha256.mxx146
1 files changed, 146 insertions, 0 deletions
diff --git a/libbutl/sha256.mxx b/libbutl/sha256.mxx
new file mode 100644
index 0000000..c5e5864
--- /dev/null
+++ b/libbutl/sha256.mxx
@@ -0,0 +1,146 @@
+// file : libbutl/sha256.mxx -*- C++ -*-
+// copyright : Copyright (c) 2014-2017 Code Synthesis Ltd
+// license : MIT; see accompanying LICENSE file
+
+#ifndef __cpp_modules
+#pragma once
+#endif
+
+// C includes.
+
+#ifndef __cpp_lib_modules
+#include <string>
+#include <cstddef> // size_t
+#include <cstdint>
+#include <cstring> // strlen(), memcpy()
+#include <type_traits> // enable_if, is_integral
+#endif
+
+// Other includes.
+
+#ifdef __cpp_modules
+export module butl.sha256;
+#ifdef __cpp_lib_modules
+import std.core;
+#endif
+#endif
+
+#include <libbutl/export.hxx>
+
+LIBBUTL_MODEXPORT namespace butl
+{
+ // SHA256 checksum calculator.
+ //
+ // For a single chunk of data a sum can be obtained in one line, for
+ // example:
+ //
+ // cerr << sha256 ("123").string () << endl;
+ //
+ class LIBBUTL_SYMEXPORT sha256
+ {
+ public:
+ sha256 ();
+
+ // Append binary data.
+ //
+ void
+ append (const void*, std::size_t);
+
+ sha256 (const void* b, std::size_t n): sha256 () {append (b, n);}
+
+ // Append string.
+ //
+ // Note that the hash includes the '\0' terminator. Failed that, a call
+ // with an empty string will be indistinguishable from no call at all.
+ //
+ void
+ append (const std::string& s) {append (s.c_str (), s.size () + 1);}
+
+ void
+ append (const char* s) {append (s, std::strlen (s) + 1);}
+
+ explicit
+ sha256 (const std::string& s): sha256 () {append (s);}
+
+ explicit
+ sha256 (const char* s): sha256 () {append (s);}
+
+ // Append an integral type with a fast path optimization (see
+ // SHA256_Update() for details).
+ //
+ void
+ append (char c)
+ {
+ std::uint32_t r ((ctx_.count >> 3) & 0x3f);
+
+ if (1 < 64 - r)
+ {
+ ctx_.buf[r] = static_cast<std::uint8_t> (c);
+ ctx_.count += 8;
+ }
+ else
+ append (&c, 1);
+ }
+
+ template <typename T>
+ typename std::enable_if<std::is_integral<T>::value>::type
+ append (T x)
+ {
+ const std::size_t len (sizeof (x));
+ std::uint32_t r ((ctx_.count >> 3) & 0x3f);
+
+ if (len < 64 - r)
+ {
+ std::memcpy (&ctx_.buf[r], &x, sizeof (x));
+ ctx_.count += len << 3;
+ }
+ else
+ append (&x, len);
+ }
+
+ // Extract result.
+ //
+ // It can be obtained as either a 32-byte binary digest or as a 64-
+ // character hex-encoded C-string.
+ //
+ using digest_type = std::uint8_t[32];
+
+ const digest_type&
+ binary () const;
+
+ const char*
+ string () const;
+
+ private:
+ struct context // Note: identical to SHA256_CTX.
+ {
+ uint32_t state[8];
+ uint64_t count;
+ uint8_t buf[64];
+ };
+
+ union
+ {
+ mutable context ctx_;
+ mutable char buf_[sizeof (context)]; // Also used to store string rep.
+ };
+
+ 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.
+ //
+ LIBBUTL_SYMEXPORT 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.
+ //
+ LIBBUTL_SYMEXPORT std::string
+ fingerprint_to_sha256 (const std::string&);
+}