README                      |    2 +
 src/base/Makefile.am        |   17 ++++--
 src/base/hash.cc            |   28 +++++++++++
 src/base/hash.h             |   67 +++++++++++++++++++++++++++
 src/base/tests/hash_test.cc |  109 ++++++++++++++++++++++++++++++++++++++++++++
 5 files changed, 217 insertions(+), 6 deletions(-)


Add a function that takes a string as input and returns another string which is
a hash of the input string generated using a collision-resistant hash function.

diff --git a/README b/README
--- a/README
+++ b/README
@@ -425,6 +425,7 @@ The following software is required to bu
 
     * libc6-dev (2.11 or later)
     * libxml2-dev (2.7 or later)
+    * libssl-dev (0.9.8 or later)
     * automake (1.11.1 or later)
     * m4
     * autoconf (2.64 or later)
@@ -959,6 +960,7 @@ minimum version requirements of the foll
 - GNU C Library (Glibc), version 2.11 or later
 - GNU Compiler Collection (GCC), version 4.8.1 or later
 - Libxml2, version 2.7 or later
+- Libopenssl, version 0.9.8 or later
 - Libsqlite3, version 3.6 or later (only needed when configuring with
   --enable-imm-pbe)
 - OpenHPI, version 2.17.0 or later (only needed when configuring with
diff --git a/src/base/Makefile.am b/src/base/Makefile.am
--- a/src/base/Makefile.am
+++ b/src/base/Makefile.am
@@ -35,6 +35,7 @@ lib_libopensaf_core_la_SOURCES += \
        src/base/daemon.c \
        src/base/file_notify.cc \
        src/base/getenv.cc \
+       src/base/hash.cc \
        src/base/hj_dec.c \
        src/base/hj_edp.c \
        src/base/hj_edu.c \
@@ -79,6 +80,7 @@ noinst_HEADERS += \
        src/base/daemon.h \
        src/base/file_notify.h \
        src/base/getenv.h \
+       src/base/hash.h \
        src/base/log_message.h \
        src/base/logtrace.h \
        src/base/macros.h \
@@ -176,16 +178,19 @@ bin_libbase_test_CPPFLAGS = \
 
 bin_libbase_test_LDFLAGS = \
        $(AM_LDFLAGS) \
-       src/base/lib_libopensaf_core_la-unix_socket.lo \
-       src/base/lib_libopensaf_core_la-unix_server_socket.lo \
+       -lcrypto \
+       src/base/lib_libopensaf_core_la-file_notify.lo \
        src/base/lib_libopensaf_core_la-getenv.lo \
+       src/base/lib_libopensaf_core_la-hash.lo \
        src/base/lib_libopensaf_core_la-log_message.lo \
        src/base/lib_libopensaf_core_la-process.lo \
-       src/base/lib_libopensaf_core_la-file_notify.lo
+       src/base/lib_libopensaf_core_la-unix_server_socket.lo \
+       src/base/lib_libopensaf_core_la-unix_socket.lo
 
 bin_libbase_test_SOURCES = \
-       src/base/tests/unix_socket_test.cc \
+       src/base/tests/file_notify_test.cc \
        src/base/tests/getenv_test.cc \
+       src/base/tests/hash_test.cc \
        src/base/tests/log_message_test.cc \
        src/base/tests/mock_logtrace.cc \
        src/base/tests/mock_osaf_abort.cc \
@@ -193,8 +198,8 @@ bin_libbase_test_SOURCES = \
        src/base/tests/time_add_test.cc \
        src/base/tests/time_compare_test.cc \
        src/base/tests/time_convert_test.cc \
-       src/base/tests/file_notify_test.cc \
-       src/base/tests/time_subtract_test.cc
+       src/base/tests/time_subtract_test.cc \
+       src/base/tests/unix_socket_test.cc
 
 bin_libbase_test_LDADD = \
        $(GTEST_DIR)/lib/libgtest.la \
diff --git a/src/base/hash.cc b/src/base/hash.cc
new file mode 100644
--- /dev/null
+++ b/src/base/hash.cc
@@ -0,0 +1,28 @@
+/*      -*- OpenSAF  -*-
+ *
+ * Copyright Ericsson AB 2017 - All Rights Reserved.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
+ * or FITNESS FOR A PARTICULAR PURPOSE. This file and program are licensed
+ * under the GNU Lesser General Public License Version 2.1, February 1999.
+ * The complete license can be accessed from the following location:
+ * http://opensource.org/licenses/lgpl-license.php
+ * See the Copying file included with the OpenSAF distribution for full
+ * licensing terms.
+ *
+ */
+
+#include "base/hash.h"
+
+namespace base {
+
+const char kHashFunctionAlphabet[64] = {
+  'A', 'B', 'C', 'D', 'E', 'F', 'G', 'H', 'I', 'J', 'K', 'L', 'M', 'N', 'O',
+  'P', 'Q', 'R', 'S', 'T', 'U', 'V', 'W', 'X', 'Y', 'Z', 'a', 'b', 'c', 'd',
+  'e', 'f', 'g', 'h', 'i', 'j', 'k', 'l', 'm', 'n', 'o', 'p', 'q', 'r', 's',
+  't', 'u', 'v', 'w', 'x', 'y', 'z', '0', '1', '2', '3', '4', '5', '6', '7',
+  '8', '9', '-', '_'
+};
+
+}  // namespace base
diff --git a/src/base/hash.h b/src/base/hash.h
new file mode 100644
--- /dev/null
+++ b/src/base/hash.h
@@ -0,0 +1,67 @@
+/*      -*- OpenSAF  -*-
+ *
+ * Copyright Ericsson AB 2017 - All Rights Reserved.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
+ * or FITNESS FOR A PARTICULAR PURPOSE. This file and program are licensed
+ * under the GNU Lesser General Public License Version 2.1, February 1999.
+ * The complete license can be accessed from the following location:
+ * http://opensource.org/licenses/lgpl-license.php
+ * See the Copying file included with the OpenSAF distribution for full
+ * licensing terms.
+ *
+ */
+
+#ifndef BASE_HASH_H_
+#define BASE_HASH_H_
+
+#include <openssl/sha.h>
+#include <cstdint>
+#include <string>
+
+namespace base {
+
+extern const char kHashFunctionAlphabet[64];
+
+// This function takes an arbitrary string as input parameter and returns
+// another string which is a hash of the input string generated using a
+// collision-resistant hash function. The probability that two different inputs
+// would generate the same output is small enough that it can be safely ignored
+// for all practical purposes.
+//
+// The return value of this function is a string of printable ASCII characters.
+// The length of the returned string will always be exactly 32 characters, and
+// the returned string is guaranteed to not contain any character that would be
+// illegal for use in a file name.
+//
+// Note: if you use this function you need to link your program with -lcrypto
+inline std::string Hash(const std::string& message) {
+  SHA512_CTX context;
+  SHA512_Init(&context);
+  context.h[0] = UINT64_C(0x010176140648b233);
+  context.h[1] = UINT64_C(0xdb92aeb1eebadd6f);
+  context.h[2] = UINT64_C(0x83a9e27aa1d5ea62);
+  context.h[3] = UINT64_C(0xec95f77eb609b4e1);
+  context.h[4] = UINT64_C(0x71a99185c75caefa);
+  context.h[5] = UINT64_C(0x006e8f08baf32e3c);
+  context.h[6] = UINT64_C(0x6a2b21abd2db2aec);
+  context.h[7] = UINT64_C(0x24926cdbd918a27f);
+  SHA512_Update(&context, message.data(), message.size());
+  unsigned char result[SHA512_DIGEST_LENGTH];
+  SHA512_Final(result, &context);
+  std::string encoded;
+  encoded.reserve(32);
+  for (int i = 0; i != 24; i += 3) {
+    uint64_t a = (result[i] << 16) | (result[i + 1] << 8) | result[i + 2];
+    encoded.push_back(kHashFunctionAlphabet[a >> 18]);
+    encoded.push_back(kHashFunctionAlphabet[(a >> 12) & 63]);
+    encoded.push_back(kHashFunctionAlphabet[(a >> 6) & 63]);
+    encoded.push_back(kHashFunctionAlphabet[a & 63]);
+  }
+  return encoded;
+}
+
+}  // namespace base
+
+#endif  // BASE_HASH_H_
diff --git a/src/base/tests/hash_test.cc b/src/base/tests/hash_test.cc
new file mode 100644
--- /dev/null
+++ b/src/base/tests/hash_test.cc
@@ -0,0 +1,109 @@
+/*      -*- OpenSAF  -*-
+ *
+ * Copyright Ericsson AB 2017 - All Rights Reserved.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
+ * or FITNESS FOR A PARTICULAR PURPOSE. This file and program are licensed
+ * under the GNU Lesser General Public License Version 2.1, February 1999.
+ * The complete license can be accessed from the following location:
+ * http://opensource.org/licenses/lgpl-license.php
+ * See the Copying file included with the OpenSAF distribution for full
+ * licensing terms.
+ *
+ */
+
+#include <endian.h>
+#include <cstddef>
+#include <random>
+#include <string>
+#include "base/hash.h"
+#include "gtest/gtest.h"
+
+struct TestVector {
+  const char* key_data;
+  size_t key_size;
+  const char* hash_value;
+};
+
+#define TEST_VECTOR(key, hash) { key, sizeof(key) - 1, hash }
+
+static const TestVector test_vectors[] = {
+  TEST_VECTOR("", "mJbyfHPNxOzI7KPhb27rY6_gS2wNOSds"),
+  TEST_VECTOR("\000", "U-4lHisMY1zsvi2ry5wqlYKUMhhb_MX8"),
+  TEST_VECTOR("\001", "7R0FXuGlh60oucbCoEIyp97oPDI34hNn"),
+  TEST_VECTOR("\376", "X-7TtfTMWhw7T9CK1-yk8bRAlF_544MB"),
+  TEST_VECTOR("\377", "OMGVy2Bhf3bPvd_yYKNVn8AK-EhkSJN4"),
+  TEST_VECTOR(" ", "LOR-HJ8c_bFoH7LVc45B67zrxvqNp2ih"),
+  TEST_VECTOR("\t", "jwSZSrsTHsB4kB2nUvpebPSpvDdt8d7V"),
+  TEST_VECTOR("\n", "WlgTrOkNrltdky0QZv1B3jMG0D73h3YC"),
+  TEST_VECTOR("\r\n", "pAv_qrHWSbOLxiJmXB2ETosp_FiE-G4H"),
+  TEST_VECTOR("\\/:", "wyC3ktDwB4tvyzXBO5zx_iH76GKFmjxB"),
+  TEST_VECTOR("$abc", "xSHQCvFJpVfx4ofdholD-mzgxyJJHjYg"),
+  TEST_VECTOR("\000\000\000\000\000", "mzklNJ6l6vWVe73PvthH61RRsl90ygC_"),
+  TEST_VECTOR("123456", "E_7JXvueRDhde3Wq3W5jYSsts_LOWJNZ"),
+  TEST_VECTOR("1234567", "0cAgD2NO2ASyz39axMrnBdV_VuHn2PhC"),
+  TEST_VECTOR("12345678", "Uzmag7xvTQg40VBwOumXaugZxFZyRpB8"),
+  TEST_VECTOR("123456789", "3YfQdE3kVpdmBEaBHM4uCj1feXvixjYA"),
+  
TEST_VECTOR("\200\201\202\203\204\205\206\207\210\211\212\213\214\215\216\217"
+              
"\220\221\222\223\224\225\226\227\230\231\232\233\234\235\236\237"
+              
"\240\241\242\243\244\245\246\247\250\251\252\253\254\255\256\257"
+              
"\260\261\262\263\264\265\266\267\270\271\272\273\274\275\276\277"
+              
"\300\301\302\303\304\305\306\307\310\311\312\313\314\315\316\317"
+              
"\320\321\322\323\324\325\326\327\330\331\332\333\334\335\336\337"
+              "\340\341\342\343\344\345\346\347\350\351\352\353\354\355",
+              "z2V3p2mUUigcBkYWSEw0yhz2f1v4M8Nb"),
+  
TEST_VECTOR("\200\201\202\203\204\205\206\207\210\211\212\213\214\215\216\217"
+              
"\220\221\222\223\224\225\226\227\230\231\232\233\234\235\236\237"
+              
"\240\241\242\243\244\245\246\247\250\251\252\253\254\255\256\257"
+              
"\260\261\262\263\264\265\266\267\270\271\272\273\274\275\276\277"
+              
"\300\301\302\303\304\305\306\307\310\311\312\313\314\315\316\317"
+              
"\320\321\322\323\324\325\326\327\330\331\332\333\334\335\336\337"
+              "\340\341\342\343\344\345\346\347\350\351\352\353\354\355\356",
+              "WprfN6xOSNY9RHaNCkR12yEEx5hGfwHj"),
+  
TEST_VECTOR("\200\201\202\203\204\205\206\207\210\211\212\213\214\215\216\217"
+              
"\220\221\222\223\224\225\226\227\230\231\232\233\234\235\236\237"
+              
"\240\241\242\243\244\245\246\247\250\251\252\253\254\255\256\257"
+              
"\260\261\262\263\264\265\266\267\270\271\272\273\274\275\276\277"
+              
"\300\301\302\303\304\305\306\307\310\311\312\313\314\315\316\317"
+              
"\320\321\322\323\324\325\326\327\330\331\332\333\334\335\336\337"
+              "\340\341\342\343\344\345\346\347\350\351\352\353\354\355\356"
+              "\357",
+              "K3wQd-ZX5k7_AZ7p1qOwrehV5vkaJq9E"),
+  
TEST_VECTOR("\200\201\202\203\204\205\206\207\210\211\212\213\214\215\216\217"
+              
"\220\221\222\223\224\225\226\227\230\231\232\233\234\235\236\237"
+              
"\240\241\242\243\244\245\246\247\250\251\252\253\254\255\256\257"
+              
"\260\261\262\263\264\265\266\267\270\271\272\273\274\275\276\277"
+              
"\300\301\302\303\304\305\306\307\310\311\312\313\314\315\316\317"
+              
"\320\321\322\323\324\325\326\327\330\331\332\333\334\335\336\337"
+              
"\340\341\342\343\344\345\346\347\350\351\352\353\354\355\356\357"
+              "\360",
+              "O-ERJdo-W-iCV4b2QogLJmtR1gMIhlkx")
+};
+
+TEST(BaseHash, TestVectors) {
+  for (size_t i = 0; i < sizeof(test_vectors) / sizeof(test_vectors[0]); ++i) {
+    std::string key = std::string(test_vectors[i].key_data,
+                                  test_vectors[i].key_size);
+    std::string hash = std::string(test_vectors[i].hash_value);
+    std::string computed_hash = base::Hash(key);
+    EXPECT_EQ(hash, computed_hash);
+  }
+}
+
+TEST(BaseHash, LongRandomString) {
+  std::string key;
+  key.reserve(8000);
+  std::mt19937_64 generator(4711);
+  for (size_t i = 0; i != 1000; ++i) {
+    union {
+      char bytes[sizeof(uint64_t)];
+      uint64_t word;
+    };
+    word = htobe64(generator());
+    key.append(bytes, sizeof(uint64_t));
+  }
+  std::string hash = std::string("C_r2XVQjnVbnpQTMHO2OQJ2sn0YZi1py");
+  std::string computed_hash = base::Hash(key);
+  EXPECT_EQ(hash, computed_hash);
+}

------------------------------------------------------------------------------
Check out the vibrant tech community on one of the world's most
engaging tech sites, SlashDot.org! http://sdm.link/slashdot
_______________________________________________
Opensaf-devel mailing list
Opensaf-devel@lists.sourceforge.net
https://lists.sourceforge.net/lists/listinfo/opensaf-devel

Reply via email to