blob: d66af3e51f54d3ca671c9a1801d0fb4980ae8725 [file] [log] [blame]
Alexander Afanasyev8f25cbb2012-03-01 23:53:40 -08001/* -*- Mode: C++; c-file-style: "gnu"; indent-tabs-mode:nil -*- */
2/*
Alexander Afanasyev8722d872014-07-02 13:00:29 -07003 * Copyright (c) 2012-2014 University of California, Los Angeles
Alexander Afanasyev8f25cbb2012-03-01 23:53:40 -08004 *
Alexander Afanasyev8722d872014-07-02 13:00:29 -07005 * This file is part of ChronoSync, synchronization library for distributed realtime
6 * applications for NDN.
Alexander Afanasyev8f25cbb2012-03-01 23:53:40 -08007 *
Alexander Afanasyev8722d872014-07-02 13:00:29 -07008 * ChronoSync is free software: you can redistribute it and/or modify it under the terms
9 * of the GNU General Public License as published by the Free Software Foundation, either
10 * version 3 of the License, or (at your option) any later version.
Alexander Afanasyev8f25cbb2012-03-01 23:53:40 -080011 *
Alexander Afanasyev8722d872014-07-02 13:00:29 -070012 * ChronoSync is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY;
13 * without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
14 * PURPOSE. See the GNU General Public License for more details.
Alexander Afanasyev8f25cbb2012-03-01 23:53:40 -080015 *
Alexander Afanasyev8722d872014-07-02 13:00:29 -070016 * You should have received a copy of the GNU General Public License along with
17 * ChronoSync, e.g., in COPYING.md file. If not, see <http://www.gnu.org/licenses/>.
18 *
19 * @author Zhenkai Zhu <http://irl.cs.ucla.edu/~zhenkai/>
20 * @author Chaoyi Bian <bcy@pku.edu.cn>
21 * @author Alexander Afanasyev <http://lasr.cs.ucla.edu/afanasyev/index.html>
Alexander Afanasyev8f25cbb2012-03-01 23:53:40 -080022 */
23
24#ifndef SYNC_DIGEST_H
25#define SYNC_DIGEST_H
26
27#include <boost/exception/all.hpp>
28#include <openssl/evp.h>
29#include <boost/cstdint.hpp>
Alexander Afanasyevd95c2312013-11-07 13:45:34 -080030#include <vector>
Alexander Afanasyev8f25cbb2012-03-01 23:53:40 -080031
Alexander Afanasyev8f25cbb2012-03-01 23:53:40 -080032namespace Sync {
33
Alexander Afanasyev8f25cbb2012-03-01 23:53:40 -080034/**
35 * @ingroup sync
36 * @brief A simple wrapper for libcrypto hash functions
37 */
38class Digest
39{
40public:
41 /**
42 * @brief Default constructor. Will initialize internal libssl structures
43 */
44 Digest ();
45
46 /**
Alexander Afanasyevb71beab2012-03-05 21:13:49 -080047 * @brief Check if digest is empty
48 */
49 bool
50 empty () const;
Yingdi Yu7c64e5c2014-04-30 14:06:37 -070051
Alexander Afanasyevb71beab2012-03-05 21:13:49 -080052 /**
Alexander Afanasyeve00ffbe2012-03-05 00:01:36 -080053 * @brief Reset digest to the initial state
54 */
55 void
56 reset ();
57
58 /**
Alexander Afanasyev8f25cbb2012-03-01 23:53:40 -080059 * @brief Destructor
60 */
61 ~Digest ();
62
Alexander Afanasyev8f25cbb2012-03-01 23:53:40 -080063 /**
64 * @brief Obtain a short version of the hash (just first sizeof(size_t) bytes
65 *
Alexander Afanasyev1fbdcdd2012-03-05 23:14:33 -080066 * Side effect: finalize() will be called on `this'
Alexander Afanasyev8f25cbb2012-03-01 23:53:40 -080067 */
68 std::size_t
Alexander Afanasyeva5858032012-03-09 15:55:10 -080069 getHash () const;
Alexander Afanasyev8f25cbb2012-03-01 23:53:40 -080070
71 /**
Alexander Afanasyev1fbdcdd2012-03-05 23:14:33 -080072 * @brief Finalize digest. All subsequent calls to "operator <<" will fire an exception
73 */
74 void
75 finalize ();
76
77 /**
Alexander Afanasyev8f25cbb2012-03-01 23:53:40 -080078 * @brief Compare two full digests
79 *
80 * Side effect: Finalize will be called on `this' and `digest'
81 */
82 bool
Alexander Afanasyevb71beab2012-03-05 21:13:49 -080083 operator == (const Digest &digest) const;
84
85 bool
86 operator != (const Digest &digest) const
87 { return ! (*this == digest); }
Yingdi Yu7c64e5c2014-04-30 14:06:37 -070088
Alexander Afanasyev8f25cbb2012-03-01 23:53:40 -080089
Alexander Afanasyevdf718f52012-03-02 00:23:04 -080090 /**
Alexander Afanasyeve00ffbe2012-03-05 00:01:36 -080091 * @brief Add existing digest to digest calculation
Alexander Afanasyevdf718f52012-03-02 00:23:04 -080092 * @param src digest to combine with
93 *
94 * The result of this combination is hash (hash (...))
95 */
96 Digest &
97 operator << (const Digest &src);
98
Alexander Afanasyeve00ffbe2012-03-05 00:01:36 -080099 /**
100 * @brief Add string to digest calculation
101 * @param str string to put into digest
102 */
103 inline Digest &
104 operator << (const std::string &str);
Alexander Afanasyevdf718f52012-03-02 00:23:04 -0800105
Alexander Afanasyev58c77b02012-03-05 21:52:25 -0800106 /**
Yingdi Yu280bb962014-01-30 09:52:43 -0800107 * @brief Add uint64_t value to digest calculation
108 * @param value uint64_t value to put into digest
Alexander Afanasyev58c77b02012-03-05 21:52:25 -0800109 */
Alexander Afanasyeve00ffbe2012-03-05 00:01:36 -0800110 inline Digest &
Yingdi Yu280bb962014-01-30 09:52:43 -0800111 operator << (uint64_t value);
Alexander Afanasyeve00ffbe2012-03-05 00:01:36 -0800112
Alexander Afanasyevdd0eba72012-03-13 13:57:10 -0700113 /**
114 * @brief Checks if the stored hash is zero-root hash
115 *
116 * Zero-root hash is a valid hash that optimally represents an empty state
117 */
118 bool
Alexander Afanasyev763855a2012-03-13 14:17:37 -0700119 isZero () const;
Yingdi Yu7c64e5c2014-04-30 14:06:37 -0700120
Alexander Afanasyev8f25cbb2012-03-01 23:53:40 -0800121private:
Alexander Afanasyeve00ffbe2012-03-05 00:01:36 -0800122 Digest &
Chaoyi Bianb1190282012-06-13 17:15:07 -0700123 operator = (Digest &digest) { (void)digest; return *this; }
Yingdi Yu7c64e5c2014-04-30 14:06:37 -0700124
Alexander Afanasyeve00ffbe2012-03-05 00:01:36 -0800125 /**
Alexander Afanasyeve00ffbe2012-03-05 00:01:36 -0800126 * @brief Add size bytes of buffer to the hash
127 */
128 void
129 update (const uint8_t *buffer, size_t size);
Alexander Afanasyev2fc2d672012-03-05 16:57:39 -0800130
131 friend std::ostream &
132 operator << (std::ostream &os, const Digest &digest);
133
134 friend std::istream &
135 operator >> (std::istream &is, Digest &digest);
Yingdi Yu7c64e5c2014-04-30 14:06:37 -0700136
Alexander Afanasyev8f25cbb2012-03-01 23:53:40 -0800137private:
138 EVP_MD_CTX *m_context;
Alexander Afanasyevd95c2312013-11-07 13:45:34 -0800139 std::vector<uint8_t> m_buffer;
Alexander Afanasyev8f25cbb2012-03-01 23:53:40 -0800140};
141
Alexander Afanasyevc1030192012-03-08 22:21:28 -0800142namespace Error {
Alexander Afanasyev87c9b5d2012-03-07 17:23:21 -0800143struct DigestCalculationError : virtual boost::exception, virtual std::exception { };
Alexander Afanasyevc1030192012-03-08 22:21:28 -0800144}
Alexander Afanasyev8f25cbb2012-03-01 23:53:40 -0800145
Alexander Afanasyevd94542d2012-03-05 08:41:46 -0800146typedef boost::shared_ptr<Digest> DigestPtr;
147typedef boost::shared_ptr<const Digest> DigestConstPtr;
Alexander Afanasyeve00ffbe2012-03-05 00:01:36 -0800148
149Digest &
150Digest::operator << (const std::string &str)
151{
152 update (reinterpret_cast<const uint8_t*> (str.c_str ()), str.size ());
153 return *this;
154}
155
156inline Digest &
Yingdi Yu280bb962014-01-30 09:52:43 -0800157Digest::operator << (uint64_t value)
Alexander Afanasyeve00ffbe2012-03-05 00:01:36 -0800158{
Yingdi Yu280bb962014-01-30 09:52:43 -0800159 update (reinterpret_cast<const uint8_t*> (&value), sizeof (uint64_t));
Alexander Afanasyeve00ffbe2012-03-05 00:01:36 -0800160 return *this;
161}
162
Alexander Afanasyevb080dbf2012-03-05 10:25:22 -0800163std::ostream &
164operator << (std::ostream &os, const Digest &digest);
165
Alexander Afanasyev2fc2d672012-03-05 16:57:39 -0800166std::istream &
167operator >> (std::istream &is, Digest &digest);
168
Alexander Afanasyeve00ffbe2012-03-05 00:01:36 -0800169// template<class INT>
170// Digest &
171// Digest::operator << (INT value)
172// {
173// update (&value, sizeof (INT));
174// return *this;
175// }
176
Alexander Afanasyevf3c03a92012-05-09 12:00:37 -0700177struct DigestPtrHash : public std::unary_function<Digest, std::size_t>
178{
179 std::size_t
180 operator() (DigestConstPtr digest) const
181 {
182 // std::cout << "digest->getHash: " << digest->getHash () << " (" << *digest << ")" << std::endl;
183 return digest->getHash ();
184 }
185};
186
187struct DigestPtrEqual : public std::unary_function<Digest, std::size_t>
188{
189 bool
190 operator() (DigestConstPtr digest1, DigestConstPtr digest2) const
191 {
192 // std::cout << boost::cref(*digest1) << " == " << boost::cref(*digest2) << " : " << (*digest1 == *digest2) << std::endl;
193 return *digest1 == *digest2;
194 }
195};
196
Alexander Afanasyeve00ffbe2012-03-05 00:01:36 -0800197
Alexander Afanasyev8f25cbb2012-03-01 23:53:40 -0800198} // Sync
Alexander Afanasyev8f25cbb2012-03-01 23:53:40 -0800199
200#endif // SYNC_DIGEST_H