aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorAvatar David Leverton <levertond@googlemail.com> 2008-02-04 03:44:57 +0000
committerAvatar David Leverton <levertond@googlemail.com> 2008-02-04 03:44:57 +0000
commit8d97ead992117e05c690c66e5a0a37dc6116e17c (patch)
tree6104e876dc25e3fe812c30d6868a8605d4601c32
parent5ea3259964cf5639c1b1cc8e8189473eb23857d7 (diff)
downloadpaludis-8d97ead992117e05c690c66e5a0a37dc6116e17c.tar.gz
paludis-8d97ead992117e05c690c66e5a0a37dc6116e17c.tar.xz
Add a SHA1 implementation.
-rw-r--r--paludis/util/files.m41
-rw-r--r--paludis/util/sha1.cc207
-rw-r--r--paludis/util/sha1.hh66
-rw-r--r--paludis/util/sha1_TEST.cc92
4 files changed, 366 insertions, 0 deletions
diff --git a/paludis/util/files.m4 b/paludis/util/files.m4
index af83b22..44c7958 100644
--- a/paludis/util/files.m4
+++ b/paludis/util/files.m4
@@ -51,6 +51,7 @@ add(`rmd160', `hh', `cc', `test')
add(`save', `hh', `test')
add(`sequence', `hh', `fwd', `impl')
add(`set', `hh', `fwd', `impl')
+add(`sha1', `hh', `cc', `test')
add(`sha256', `hh', `cc', `test')
add(`sr', `hh', `cc')
add(`stringify', `hh', `test')
diff --git a/paludis/util/sha1.cc b/paludis/util/sha1.cc
new file mode 100644
index 0000000..d519f26
--- /dev/null
+++ b/paludis/util/sha1.cc
@@ -0,0 +1,207 @@
+/* vim: set sw=4 sts=4 et foldmethod=syntax : */
+
+/*
+ * Copyright (c) 2008 David Leverton
+ *
+ * This file is part of the Paludis package manager. Paludis is free software;
+ * you can redistribute it and/or modify it under the terms of the GNU General
+ * Public License version 2, as published by the Free Software Foundation.
+ *
+ * Paludis 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. See the GNU General Public License for more
+ * details.
+ *
+ * You should have received a copy of the GNU General Public License along with
+ * this program; if not, write to the Free Software Foundation, Inc., 59 Temple
+ * Place, Suite 330, Boston, MA 02111-1307 USA
+ */
+
+#include "config.h"
+
+#include <paludis/util/sha1.hh>
+#include <paludis/util/byte_swap.hh>
+#include <sstream>
+#include <istream>
+#include <iomanip>
+
+using namespace paludis;
+
+/*
+ * Implemented based upon the description in RFC3174.
+ */
+
+namespace
+{
+#if WORDS_BIGENDIAN
+ inline uint32_t from_bigendian(uint32_t x)
+ {
+ return x;
+ }
+
+ inline uint32_t to_bigendian(uint32_t x)
+ {
+ return x;
+ }
+#else
+ inline uint32_t from_bigendian(uint32_t x)
+ {
+ return byte_swap(x);
+ }
+
+ inline uint32_t to_bigendian(uint32_t x)
+ {
+ return byte_swap(x);
+ }
+#endif
+
+ inline uint32_t s(int n, uint32_t x)
+ {
+ return (x << n) | (x >> (32 - n));
+ }
+
+ inline uint32_t f_0_19(uint32_t b, uint32_t c, uint32_t d)
+ {
+ return (b & c) | (~b & d);
+ }
+
+ inline uint32_t f_20_39(uint32_t b, uint32_t c, uint32_t d)
+ {
+ return b ^ c ^ d;
+ }
+
+ inline uint32_t f_40_59(uint32_t b, uint32_t c, uint32_t d)
+ {
+ return (b & c) | (b & d) | (c & d);
+ }
+
+ inline uint32_t f_60_79(uint32_t b, uint32_t c, uint32_t d)
+ {
+ return b ^ c ^ d;
+ }
+
+ const uint32_t k_0_19 = 0x5A827999U;
+ const uint32_t k_20_39 = 0x6ED9EBA1U;
+ const uint32_t k_40_59 = 0x8F1BBCDCU;
+ const uint32_t k_60_79 = 0xCA62C1D6U;
+}
+
+void
+SHA1::process_block(uint32_t * w)
+{
+ uint32_t a, b, c, d, e, temp;
+
+ std::transform(&w[0], &w[16], &w[0], from_bigendian);
+
+ for (int t = 16; t < 80; ++t)
+ w[t] = s(1, w[t - 3] ^ w[t - 8] ^ w[t - 14] ^ w[t - 16]);
+
+ a = h0;
+ b = h1;
+ c = h2;
+ d = h3;
+ e = h4;
+
+ for (int t = 0; t < 20; ++t)
+ {
+ temp = s(5, a) + f_0_19(b, c, d) + e + w[t] + k_0_19;
+ e = d;
+ d = c;
+ c = s(30, b);
+ b = a;
+ a = temp;
+ }
+
+ for (int t = 20; t < 40; ++t)
+ {
+ temp = s(5, a) + f_20_39(b, c, d) + e + w[t] + k_20_39;
+ e = d;
+ d = c;
+ c = s(30, b);
+ b = a;
+ a = temp;
+ }
+
+ for (int t = 40; t < 60; ++t)
+ {
+ temp = s(5, a) + f_40_59(b, c, d) + e + w[t] + k_40_59;
+ e = d;
+ d = c;
+ c = s(30, b);
+ b = a;
+ a = temp;
+ }
+
+ for (int t = 60; t < 80; ++t)
+ {
+ temp = s(5, a) + f_60_79(b, c, d) + e + w[t] + k_60_79;
+ e = d;
+ d = c;
+ c = s(30, b);
+ b = a;
+ a = temp;
+ }
+
+ h0 += a;
+ h1 += b;
+ h2 += c;
+ h3 += d;
+ h4 += e;
+}
+
+
+SHA1::SHA1(std::istream & s) :
+ h0(0x67452301U),
+ h1(0xEFCDAB89U),
+ h2(0x98BADCFEU),
+ h3(0x10325476U),
+ h4(0xC3D2E1F0U)
+{
+ std::streambuf * buf(s.rdbuf());
+ uint64_t size(0);
+
+ union
+ {
+ uint8_t m[64];
+ uint32_t w[80];
+ } block;
+ std::streamsize block_size;
+
+ do
+ {
+ block_size = buf->sgetn(reinterpret_cast<char *>(&block.m[0]), 64);
+ size += block_size * 8;
+
+ if (64 != block_size)
+ {
+ block.m[block_size++] = 0x80U;
+
+ if (56 < block_size)
+ {
+ std::fill(&block.m[block_size], &block.m[64], 0);
+ process_block(block.w);
+ block_size = 0;
+ }
+
+ std::fill(&block.m[block_size], &block.m[56], 0);
+ block.w[14] = to_bigendian((size >> 32) & 0xFFFFFFFFU);
+ block.w[15] = to_bigendian(size & 0xFFFFFFFFU);
+ }
+
+ process_block(block.w);
+ } while (64 == block_size);
+}
+
+std::string
+SHA1::hexsum() const
+{
+ std::stringstream result;
+ result << std::hex << std::right << std::setfill('0');
+ result << std::setw(8) << h0;
+ result << std::setw(8) << h1;
+ result << std::setw(8) << h2;
+ result << std::setw(8) << h3;
+ result << std::setw(8) << h4;
+ return result.str();
+}
+
diff --git a/paludis/util/sha1.hh b/paludis/util/sha1.hh
new file mode 100644
index 0000000..f1fc702
--- /dev/null
+++ b/paludis/util/sha1.hh
@@ -0,0 +1,66 @@
+/* vim: set sw=4 sts=4 et foldmethod=syntax : */
+
+/*
+ * Copyright (c) 2006, 2007 Ciaran McCreesh
+ * Copyright (c) 2008 David Leverton
+ *
+ * This file is part of the Paludis package manager. Paludis is free software;
+ * you can redistribute it and/or modify it under the terms of the GNU General
+ * Public License version 2, as published by the Free Software Foundation.
+ *
+ * Paludis 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. See the GNU General Public License for more
+ * details.
+ *
+ * You should have received a copy of the GNU General Public License along with
+ * this program; if not, write to the Free Software Foundation, Inc., 59 Temple
+ * Place, Suite 330, Boston, MA 02111-1307 USA
+ */
+
+#ifndef PALUDIS_GUARD_PALUDIS_UTIL_SHA1_HH
+#define PALUDIS_GUARD_PALUDIS_UTIL_SHA1_HH 1
+
+#include <iosfwd>
+#include <string>
+#include <inttypes.h>
+#include <paludis/util/attributes.hh>
+
+/** \file
+ * Declarations for the SHA1 digest class.
+ *
+ * \ingroup g_digests
+ *
+ * \section Examples
+ *
+ * - None at this time.
+ */
+
+namespace paludis
+{
+ /**
+ * SHA1 digest class.
+ *
+ * \ingroup g_digests
+ */
+ class PALUDIS_VISIBLE SHA1
+ {
+ private:
+ uint32_t h0, h1, h2, h3, h4;
+
+ void PALUDIS_HIDDEN process_block(uint32_t *);
+
+ public:
+ /**
+ * Constructor.
+ */
+ SHA1(std::istream & stream);
+
+ /**
+ * Our checksum, as a string of hex characters.
+ */
+ std::string hexsum() const;
+ };
+}
+
+#endif
diff --git a/paludis/util/sha1_TEST.cc b/paludis/util/sha1_TEST.cc
new file mode 100644
index 0000000..14b8134
--- /dev/null
+++ b/paludis/util/sha1_TEST.cc
@@ -0,0 +1,92 @@
+/* vim: set sw=4 sts=4 et foldmethod=syntax : */
+
+/*
+ * Copyright (c) 2006, 2007 Ciaran McCreesh
+ * Copyright (c) 2008 David Leverton
+ *
+ * This file is part of the Paludis package manager. Paludis is free software;
+ * you can redistribute it and/or modify it under the terms of the GNU General
+ * Public License version 2, as published by the Free Software Foundation.
+ *
+ * Paludis 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. See the GNU General Public License for more
+ * details.
+ *
+ * You should have received a copy of the GNU General Public License along with
+ * this program; if not, write to the Free Software Foundation, Inc., 59 Temple
+ * Place, Suite 330, Boston, MA 02111-1307 USA
+ */
+
+#include <paludis/util/sha1.hh>
+#include <test/test_framework.hh>
+#include <test/test_runner.hh>
+
+using namespace paludis;
+using namespace test;
+
+namespace test_cases
+{
+ /**
+ * \name Test cases for paludis::SHA1
+ * \{
+ */
+
+ struct SHA1TestCase : TestCase
+ {
+ std::string data;
+ std::string expected;
+
+ SHA1TestCase(const std::string & s, const std::string & d,
+ const std::string & e) :
+ TestCase("sha1 " + s),
+ data(d),
+ expected(e)
+ {
+ }
+
+ void run()
+ {
+ std::stringstream ss(data);
+ SHA1 s(ss);
+ TEST_CHECK_EQUAL(s.hexsum(), expected);
+ }
+ };
+
+ SHA1TestCase t_0("empty", "", "da39a3ee5e6b4b0d3255bfef95601890afd80709");
+ SHA1TestCase t_1("a", "a", "86f7e437faa5a7fce15d1ddcb9eaeaea377667b8");
+ SHA1TestCase t_2("abc", "abc", "a9993e364706816aba3e25717850c26c9cd0d89d");
+ SHA1TestCase t_3("message digest", "message digest", "c12252ceda8be8994d5fa0290a47231c1d16aae3");
+ SHA1TestCase t_4("a..z", "abcdefghijklmnopqrstuvwxyz",
+ "32d10c7b8cf96570ca04ce37f2a19d84240d3a89");
+ SHA1TestCase t_6("A...Za...z0...9",
+ "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789",
+ "761c457bf73b14d27e9e9265c46f4b4dda11f940");
+ SHA1TestCase t_7("8 times 1234567890",
+ "12345678901234567890123456789012345678901234567890123456789012345678901234567890",
+ "50abf5706a150990a08b2c5ea40fa0e585554732");
+ SHA1TestCase t_8("one million times a",
+ std::string(1000000, 'a'),
+ "34aa973cd4c4daa4f61eeb2bdbad27316534016f");
+ SHA1TestCase t_9("a-db-ec-fd-ge-hf-ig-jh-ki-lj-mk-nl-om-pn-q",
+ "abcdbcdecdefdefgefghfghighijhijkijkljklmklmnlmnomnopnopq",
+ "84983e441c3bd26ebaae4aa1f95129e5e54670f1");
+ SHA1TestCase t_10("80 times 01234567",
+ "0123456701234567012345670123456701234567012345670123456701234567"
+ "0123456701234567012345670123456701234567012345670123456701234567"
+ "0123456701234567012345670123456701234567012345670123456701234567"
+ "0123456701234567012345670123456701234567012345670123456701234567"
+ "0123456701234567012345670123456701234567012345670123456701234567"
+ "0123456701234567012345670123456701234567012345670123456701234567"
+ "0123456701234567012345670123456701234567012345670123456701234567"
+ "0123456701234567012345670123456701234567012345670123456701234567"
+ "0123456701234567012345670123456701234567012345670123456701234567"
+ "0123456701234567012345670123456701234567012345670123456701234567",
+ "dea356a2cddd90c7a7ecedc5ebb563934f460452");
+
+ /**
+ * \}
+ */
+}
+
+