aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorAvatar Ciaran McCreesh <ciaran.mccreesh@googlemail.com> 2006-04-26 11:10:29 +0000
committerAvatar Ciaran McCreesh <ciaran.mccreesh@googlemail.com> 2006-04-26 11:10:29 +0000
commitcee3c8f4e93883d656298f6653c049a6eb4da2e0 (patch)
tree7aa72c1e35e9c95eddd7bfd31689a16540a6c3ce
parent829547eefc341b0a6735cfebedda03a814490c4a (diff)
downloadpaludis-cee3c8f4e93883d656298f6653c049a6eb4da2e0.tar.gz
paludis-cee3c8f4e93883d656298f6653c049a6eb4da2e0.tar.xz
Implement RMD160 to avoid openssl dep
-rw-r--r--ebuild/digests/Makefile.am19
-rwxr-xr-xebuild/digests/dormd1604
-rw-r--r--ebuild/digests/dormd160.cc52
-rw-r--r--ebuild/digests/dormd160_TEST.cc95
-rw-r--r--ebuild/digests/rmd160.cc211
-rw-r--r--ebuild/digests/rmd160.hh69
6 files changed, 441 insertions, 9 deletions
diff --git a/ebuild/digests/Makefile.am b/ebuild/digests/Makefile.am
index f38f2df..fb49d6a 100644
--- a/ebuild/digests/Makefile.am
+++ b/ebuild/digests/Makefile.am
@@ -5,24 +5,29 @@ SUBDIRS = .
libexecprogdir = $(libexecdir)/paludis/digests/
libexecprog_SCRIPTS = \
- domd5 \
- dormd160
+ domd5
libexecprog_PROGRAMS = \
- dosha256
+ dosha256 \
+ dormd160
dosha256_SOURCES = \
sha256.cc \
sha256.hh \
dosha256.cc
+dormd160_SOURCES = \
+ rmd160.cc \
+ rmd160.hh \
+ dormd160.cc
+
TESTS_ENVIRONMENT = env \
PALUDIS_EBUILD_DIR="$(srcdir)/ebuild/" \
TEST_SCRIPT_DIR="$(srcdir)/" \
$(SHELL) $(top_srcdir)/test/run_test.sh
-TESTS = dosha256_TEST
-EXTRA_DIST = $(libexecprog_SCRIPTS) dosha256_TEST.cc
+TESTS = dosha256_TEST dormd160_TEST
+EXTRA_DIST = $(libexecprog_SCRIPTS) dosha256_TEST.cc dormd160_TEST.cc
check_SCRIPTS =
check_PROGRAMS = $(TESTS)
@@ -31,3 +36,7 @@ dosha256_TEST_SOURCES = sha256.cc sha256.hh dosha256_TEST.cc
dosha256_TEST_CXXFLAGS = -I$(top_srcdir)
dosha256_TEST_LDADD = $(top_builddir)/test/libtest.a
+dormd160_TEST_SOURCES = rmd160.cc rmd160.hh dormd160_TEST.cc
+dormd160_TEST_CXXFLAGS = -I$(top_srcdir)
+dormd160_TEST_LDADD = $(top_builddir)/test/libtest.a
+
diff --git a/ebuild/digests/dormd160 b/ebuild/digests/dormd160
deleted file mode 100755
index 1c5661f..0000000
--- a/ebuild/digests/dormd160
+++ /dev/null
@@ -1,4 +0,0 @@
-#!/bin/bash
-
-openssl dgst -rmd160 "$1" | cut -d= -f2 | tr -d ' '
-
diff --git a/ebuild/digests/dormd160.cc b/ebuild/digests/dormd160.cc
new file mode 100644
index 0000000..b71565c
--- /dev/null
+++ b/ebuild/digests/dormd160.cc
@@ -0,0 +1,52 @@
+/* vim: set sw=4 sts=4 et foldmethod=syntax : */
+
+/*
+ * Copyright (c) 2006 Ciaran McCreesh <ciaran.mccreesh@blueyonder.co.uk>
+ *
+ * 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 "rmd160.hh"
+#include <iostream>
+#include <cstdlib>
+
+int
+main(int argc, char * argv[])
+{
+ if (argc >= 3)
+ {
+ std::cerr << "usage: " << argv[0] << " [filename]" << std::endl;
+ return EXIT_FAILURE;
+ }
+
+ if (argc == 2)
+ {
+ std::ifstream f(argv[1]);
+ if (! f)
+ {
+ std::cerr << argv[0] << ": could not open '" << argv[1] << "'" << std::endl;
+ return EXIT_FAILURE;
+ }
+ rmd160::RMD160 sum(f);
+ std::cout << sum.hexsum() << std::endl;
+ }
+ else
+ {
+ rmd160::RMD160 sum(std::cin);
+ std::cout << sum.hexsum() << std::endl;
+ }
+
+}
+
+
diff --git a/ebuild/digests/dormd160_TEST.cc b/ebuild/digests/dormd160_TEST.cc
new file mode 100644
index 0000000..b17bfc1
--- /dev/null
+++ b/ebuild/digests/dormd160_TEST.cc
@@ -0,0 +1,95 @@
+/* vim: set sw=4 sts=4 et foldmethod=syntax : */
+
+/*
+ * Copyright (c) 2006 Ciaran McCreesh <ciaran.mccreesh@blueyonder.co.uk>
+ *
+ * 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 "rmd160.hh"
+#include <test/test_framework.hh>
+#include <test/test_runner.hh>
+
+using namespace test;
+
+namespace
+{
+ unsigned char dehex_c(unsigned char c)
+ {
+ if (c >= '0' && c <= '9')
+ return c - '0';
+ else if (c >= 'a' && c <= 'f')
+ return c + 10 - 'a';
+ else
+ throw "meh!";
+ }
+
+ std::string dehex(const std::string & s)
+ {
+ std::string result;
+ std::string::size_type p(0);
+ while (p < s.length())
+ {
+ unsigned char c;
+ c = (dehex_c(s.at(p)) << 4) + dehex_c(s.at(p + 1));
+ result.append(1, c);
+ p += 2;
+ }
+ return result;
+ }
+}
+
+namespace test_cases
+{
+ struct RMD160TestCase : TestCase
+ {
+ std::string data;
+ std::string expected;
+
+ RMD160TestCase(const std::string & s, const std::string & d,
+ const std::string & e) :
+ TestCase("rmd160 " + s),
+ data(d),
+ expected(e)
+ {
+ }
+
+ void run()
+ {
+ std::stringstream ss(data);
+ rmd160::RMD160 s(ss);
+ TEST_CHECK_EQUAL(s.hexsum(), expected);
+ }
+ };
+
+ RMD160TestCase t_0("empty", "", "9c1185a5c5e9fc54612808977ee8f548b2258d31");
+ RMD160TestCase t_1("a", "a", "0bdc9d2d256b3ee9daae347be6f4dc835a467ffe");
+ RMD160TestCase t_2("abc", "abc", "8eb208f7e05d987a9b044a8e98c6b087f15a0bfc");
+ RMD160TestCase t_3("message digest", "message digest", "5d0689ef49d2fae572b881b123a85ffa21595f36");
+ RMD160TestCase t_4("a..z", "abcdefghijklmnopqrstuvwxyz",
+ "f71c27109c692c1b56bbdceb5b9d2865b3708dbc");
+ RMD160TestCase t_5("abcdbcde...nopq",
+ "abcdbcdecdefdefgefghfghighijhijkijkljklmklmnlmnomnopnopq",
+ "12a053384a9c0c88e405a06c27dcf49ada62eb2b");
+ RMD160TestCase t_6("A...Za...z0...9",
+ "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789",
+ "b0e20b6e3116640286ed3a87a5713079b21f5189");
+ RMD160TestCase t_7("8 times 1234567890",
+ "12345678901234567890123456789012345678901234567890123456789012345678901234567890",
+ "9b752e45573d4b39f4dbd3323cab82bf63326bfb");
+ RMD160TestCase t_8("one million times a",
+ std::string(1000000, 'a'),
+ "52783243c1697bdbe16d37f97f68f08325dc1528");
+}
+
diff --git a/ebuild/digests/rmd160.cc b/ebuild/digests/rmd160.cc
new file mode 100644
index 0000000..ecbf570
--- /dev/null
+++ b/ebuild/digests/rmd160.cc
@@ -0,0 +1,211 @@
+/* vim: set sw=4 sts=4 et foldmethod=syntax : */
+
+/*
+ * Copyright (c) 2006 Ciaran McCreesh <ciaran.mccreesh@blueyonder.co.uk>
+ *
+ * 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 "rmd160.hh"
+#include <paludis/util/attributes.hh>
+#include <sstream>
+
+using namespace rmd160;
+
+/*
+ * Implemented based upon the description at:
+ * http://homes.esat.kuleuven.be/~bosselae/ripemd160.html
+ */
+
+namespace
+{
+ inline uint32_t rl(uint32_t x, unsigned int shift) PALUDIS_ATTRIBUTE((always_inline));
+ inline uint32_t rl(uint32_t x, unsigned int shift)
+ {
+ return (x << shift) | (x >> (32 - shift));
+ }
+
+ inline uint32_t _f(uint32_t j, uint32_t x, uint32_t y, uint32_t z) PALUDIS_ATTRIBUTE((always_inline));
+ inline uint32_t _f(uint32_t j, uint32_t x, uint32_t y, uint32_t z)
+ {
+ switch (j / 16)
+ {
+ case 0:
+ return x ^ y ^ z;
+
+ case 1:
+ return (x & y) | (~x & z);
+
+ case 2:
+ return (x | ~y) ^ z;
+
+ case 3:
+ return (x & z) | (y & ~z);
+
+ case 4:
+ return x ^ (y | ~z);
+ }
+
+ throw 0;
+ }
+
+ inline uint32_t _x(unsigned i, const uint8_t * const block) PALUDIS_ATTRIBUTE((always_inline));
+ inline uint32_t _x(unsigned i, const uint8_t * const block)
+ {
+ return
+ (block[(i << 2) + 3] << 24) |
+ (block[(i << 2) + 2] << 16) |
+ (block[(i << 2) + 1] << 8) |
+ (block[(i << 2) + 0]);
+ }
+
+ inline uint32_t _e(const uint32_t x) PALUDIS_ATTRIBUTE((always_inline));
+ inline uint32_t _e(const uint32_t x)
+ {
+ return
+ ((x & 0xff) << 24) |
+ ((x & 0xff00) << 8) |
+ ((x & 0xff0000) >> 8) |
+ ((x & 0xff000000) >> 24);
+ }
+}
+
+void
+RMD160::_update(const uint8_t * const block)
+{
+ uint32_t a(_h[0]), b(_h[1]), c(_h[2]), d(_h[3]), e(_h[4]);
+ uint32_t ap(_h[0]), bp(_h[1]), cp(_h[2]), dp(_h[3]), ep(_h[4]);
+ uint32_t t;
+
+ for (unsigned j(0) ; j <= 79 ; ++j)
+ {
+ t = a + _f(j, b, c, d) + _x(_r[j], block) + _k[j / 16];
+ t = rl(t, _s[j]) + e;
+ a = e;
+ e = d;
+ d = rl(c, 10);
+ c = b;
+ b = t;
+
+ t = ap + _f(79 - j, bp, cp, dp) + _x(_rp[j], block) + _kp[j / 16];
+ t = rl(t, _sp[j]) + ep;
+ ap = ep;
+ ep = dp;
+ dp = rl(cp, 10);
+ cp = bp;
+ bp = t;
+ }
+
+ t = _h[1] + c + dp;
+ _h[1] = _h[2] + d + ep;
+ _h[2] = _h[3] + e + ap;
+ _h[3] = _h[4] + a + bp;
+ _h[4] = _h[0] + b + cp;
+ _h[0] = t;
+}
+
+RMD160::RMD160(std::istream & stream) :
+ _size(0),
+ _done_one_pad(false)
+{
+ _h[0] = 0x67452301;
+ _h[1] = 0xefcdab89;
+ _h[2] = 0x98badcfe;
+ _h[3] = 0x10325476;
+ _h[4] = 0xc3d2e1f0;
+
+ uint8_t buffer[64];
+ int c, s(0);
+ while (-1 != ((c = _get(stream))))
+ {
+ buffer[s++] = c;
+ if (64 == s)
+ {
+ _update(&buffer[0]);
+ s = 0;
+ }
+ }
+ while (56 != s)
+ {
+ buffer[s++] = 0;
+ if (64 == s)
+ {
+ _update(&buffer[0]);
+ s = 0;
+ }
+ }
+
+ buffer[56] = static_cast<uint8_t>(_size >> (0 * 8));
+ buffer[57] = static_cast<uint8_t>(_size >> (1 * 8));
+ buffer[58] = static_cast<uint8_t>(_size >> (2 * 8));
+ buffer[59] = static_cast<uint8_t>(_size >> (3 * 8));
+ buffer[60] = static_cast<uint8_t>(_size >> (4 * 8));
+ buffer[61] = static_cast<uint8_t>(_size >> (5 * 8));
+ buffer[62] = static_cast<uint8_t>(_size >> (6 * 8));
+ buffer[63] = static_cast<uint8_t>(_size >> (7 * 8));
+ _update(&buffer[0]);
+}
+
+std::string
+RMD160::hexsum() const
+{
+ std::stringstream result;
+
+ for (int j(0) ; j < 5 ; ++j)
+ result << std::hex << std::right << std::setw(8) << std::setfill('0') <<
+ _e(static_cast<unsigned int>(_h[j])) << std::flush;
+
+ return result.str();
+}
+
+const uint8_t RMD160::_r[80] = {
+ 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15,
+ 7, 4, 13, 1, 10, 6, 15, 3, 12, 0, 9, 5, 2, 14, 11, 8,
+ 3, 10, 14, 4, 9, 15, 8, 1, 2, 7, 0, 6, 13, 11, 5, 12,
+ 1, 9, 11, 10, 0, 8, 12, 4, 13, 3, 7, 15, 14, 5, 6, 2,
+ 4, 0, 5, 9, 7, 12, 2, 10, 14, 1, 3, 8, 11, 6, 15, 13
+};
+
+const uint8_t RMD160::_rp[80] = {
+ 5, 14, 7, 0, 9, 2, 11, 4, 13, 6, 15, 8, 1, 10, 3, 12,
+ 6, 11, 3, 7, 0, 13, 5, 10, 14, 15, 8, 12, 4, 9, 1, 2,
+ 15, 5, 1, 3, 7, 14, 6, 9, 11, 8, 12, 2, 10, 0, 4, 13,
+ 8, 6, 4, 1, 3, 11, 15, 0, 5, 12, 2, 13, 9, 7, 10, 14,
+ 12, 15, 10, 4, 1, 5, 8, 7, 6, 2, 13, 14, 0, 3, 9, 11
+};
+
+const uint8_t RMD160::_s[80] = {
+ 11, 14, 15, 12, 5, 8, 7, 9, 11, 13, 14, 15, 6, 7, 9, 8,
+ 7, 6, 8, 13, 11, 9, 7, 15, 7, 12, 15, 9, 11, 7, 13, 12,
+ 11, 13, 6, 7, 14, 9, 13, 15, 14, 8, 13, 6, 5, 12, 7, 5,
+ 11, 12, 14, 15, 14, 15, 9, 8, 9, 14, 5, 6, 8, 6, 5, 12,
+ 9, 15, 5, 11, 6, 8, 13, 12, 5, 12, 13, 14, 11, 8, 5, 6
+};
+
+const uint8_t RMD160::_sp[80] = {
+ 8, 9, 9, 11, 13, 15, 15, 5, 7, 7, 8, 11, 14, 14, 12, 6,
+ 9, 13, 15, 7, 12, 8, 9, 11, 7, 7, 12, 7, 6, 15, 13, 11,
+ 9, 7, 15, 11, 8, 6, 6, 14, 12, 13, 5, 14, 13, 13, 7, 5,
+ 15, 5, 8, 11, 14, 14, 6, 14, 6, 9, 12, 9, 12, 5, 15, 8,
+ 8, 5, 12, 9, 12, 5, 14, 6, 8, 13, 6, 5, 15, 13, 11, 11
+};
+
+const uint32_t RMD160::_k[5] = {
+ 0x00000000, 0x5a827999, 0x6ed9eba1, 0x8f1bbcdc, 0xa953fd4e
+};
+
+const uint32_t RMD160::_kp[5] = {
+ 0x50a28be6, 0x5c4dd124, 0x6d703ef3, 0x7a6d76e9, 0x00000000
+};
+
diff --git a/ebuild/digests/rmd160.hh b/ebuild/digests/rmd160.hh
new file mode 100644
index 0000000..2b25c39
--- /dev/null
+++ b/ebuild/digests/rmd160.hh
@@ -0,0 +1,69 @@
+/* vim: set sw=4 sts=4 et foldmethod=syntax : */
+
+/*
+ * Copyright (c) 2006 Ciaran McCreesh <ciaran.mccreesh@blueyonder.co.uk>
+ *
+ * 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_EBUILD_DIGESTS_RMD160_HH
+#define PALUDIS_GUARD_EBUILD_DIGESTS_RMD160_HH 1
+
+#include <fstream>
+#include <iomanip>
+#include <string>
+#include <inttypes.h>
+
+namespace rmd160
+{
+ class RMD160
+ {
+ private:
+ static const uint8_t _r[80], _rp[80];
+ static const uint8_t _s[80], _sp[80];
+ static const uint32_t _k[5], _kp[5];
+
+ uint32_t _h[5];
+ uint64_t _size;
+ bool _done_one_pad;
+
+ void _update(const uint8_t * const block);
+
+ inline int _get(std::istream & stream) __attribute__((always_inline))
+ {
+ char c;
+ if (stream.get(c))
+ {
+ _size += 8;
+ return static_cast<unsigned char>(c);
+ }
+ else if (! _done_one_pad)
+ {
+ _done_one_pad = true;
+ return 0x80;
+ }
+ else
+ return -1;
+ }
+
+ public:
+ RMD160(std::istream & stream);
+
+ std::string hexsum() const;
+ };
+
+}
+
+#endif
+