blob: 41e45a5323ec76a9d89a0f7f4a0bb46674839d78 [file] [log] [blame]
Yingdi Yude222c72014-08-15 16:06:52 -07001/* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
2/**
Alexander Afanasyev574aa862017-01-10 19:53:28 -08003 * Copyright (c) 2013-2017 Regents of the University of California.
Yingdi Yude222c72014-08-15 16:06:52 -07004 *
5 * This file is part of ndn-cxx library (NDN C++ library with eXperimental eXtensions).
6 *
7 * ndn-cxx library is free software: you can redistribute it and/or modify it under the
8 * terms of the GNU Lesser General Public License as published by the Free Software
9 * Foundation, either version 3 of the License, or (at your option) any later version.
10 *
11 * ndn-cxx library is distributed in the hope that it will be useful, but WITHOUT ANY
12 * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A
13 * PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details.
14 *
15 * You should have received copies of the GNU General Public License and GNU Lesser
16 * General Public License along with ndn-cxx, e.g., in COPYING.md file. If not, see
17 * <http://www.gnu.org/licenses/>.
18 *
19 * See AUTHORS.md for complete list of ndn-cxx authors and contributors.
20 */
21
22#ifndef NDN_UTIL_DIGEST_HPP
23#define NDN_UTIL_DIGEST_HPP
24
25#include "../encoding/buffer.hpp"
26#include "../encoding/block.hpp"
Alexander Afanasyev2fa59392016-07-29 17:24:23 -070027#include "../security/v1/cryptopp.hpp"
Yingdi Yude222c72014-08-15 16:06:52 -070028#include "concepts.hpp"
29
30namespace ndn {
31namespace util {
32
33/**
Alexander Afanasyev574aa862017-01-10 19:53:28 -080034 * @brief provides a stateful digest calculation
Yingdi Yude222c72014-08-15 16:06:52 -070035 *
Alexander Afanasyev574aa862017-01-10 19:53:28 -080036 * SHA256 example:
Yingdi Yude222c72014-08-15 16:06:52 -070037 *
38 * Digest<CryptoPP::SHA256> digest;
39 * digest.update(buf1, size1);
40 * digest.update(buf2, size2);
41 * ...
42 * ConstBufferPtr result = digest.computeDigest();
Yingdi Yude222c72014-08-15 16:06:52 -070043 */
44template<typename Hash>
45class Digest
46{
47public:
48 BOOST_CONCEPT_ASSERT((Hashable<Hash>));
49
50 typedef Hash HashFunction;
51
52 class Error : public std::runtime_error
53 {
54 public:
55 explicit
56 Error(const std::string& what)
57 : std::runtime_error(what)
58 {
59 }
60 };
61
62 Digest();
63
64 /**
Alexander Afanasyev574aa862017-01-10 19:53:28 -080065 * @brief Calculate digest of the input stream @p is
Alexander Afanasyevd27334f2015-07-01 21:44:36 -070066 * @param is input stream
67 */
68 explicit
69 Digest(std::istream& is);
70
71 /**
Alexander Afanasyev574aa862017-01-10 19:53:28 -080072 * @brief Discard the current state and start a new digest calculation.
Yingdi Yude222c72014-08-15 16:06:52 -070073 */
74 void
75 reset();
76
77 /**
78 * @brief Check if digest is empty.
79 *
80 * An empty digest means nothing has been taken into calculation.
81 */
82 bool
83 empty() const
84 {
85 return !m_isInProcess;
86 }
87
88 /**
Alexander Afanasyev574aa862017-01-10 19:53:28 -080089 * @brief Finalize and return the digest based on all previously supplied inputs.
Yingdi Yude222c72014-08-15 16:06:52 -070090 */
91 ConstBufferPtr
92 computeDigest();
93
94 /**
Alexander Afanasyev574aa862017-01-10 19:53:28 -080095 * @brief Check if the supplied digest equals to this digest
Yingdi Yude222c72014-08-15 16:06:52 -070096 *
Alexander Afanasyev574aa862017-01-10 19:53:28 -080097 * @note This method will invoke computeDigest(), finalizing the digest.
Yingdi Yude222c72014-08-15 16:06:52 -070098 */
99 bool
100 operator==(Digest<Hash>& digest);
101
102 /**
Alexander Afanasyev574aa862017-01-10 19:53:28 -0800103 * @brief Check if the supplied digest is not equal to this digest
Yingdi Yude222c72014-08-15 16:06:52 -0700104 *
Alexander Afanasyev574aa862017-01-10 19:53:28 -0800105 * @note This method will invoke computeDigest(), finalizing the digest.
Yingdi Yude222c72014-08-15 16:06:52 -0700106 */
107 bool
108 operator!=(Digest<Hash>& digest)
109 {
110 return !(*this == digest);
111 }
112
113 /**
Alexander Afanasyev574aa862017-01-10 19:53:28 -0800114 * @brief Add existing digest to the digest calculation
Yingdi Yude222c72014-08-15 16:06:52 -0700115 * @param src digest to combine with
116 *
Alexander Afanasyev574aa862017-01-10 19:53:28 -0800117 * The result of this combination is `digest(digest(...))`
118 *
119 * @note This method will invoke computeDigest(), finalizing the digest.
Yingdi Yude222c72014-08-15 16:06:52 -0700120 */
121 Digest<Hash>&
122 operator<<(Digest<Hash>& src);
123
124 /**
Alexander Afanasyev574aa862017-01-10 19:53:28 -0800125 * @brief Add string to the digest calculation
Yingdi Yude222c72014-08-15 16:06:52 -0700126 * @param str string to put into digest
127 */
128 Digest<Hash>&
129 operator<<(const std::string& str);
130
131 /**
Alexander Afanasyev574aa862017-01-10 19:53:28 -0800132 * @brief Add block to the digest calculation
133 * @param block data block to put into digest
134 * @throw Error the digest has been finalized.
Yingdi Yude222c72014-08-15 16:06:52 -0700135 */
136 Digest<Hash>&
137 operator<<(const Block& block);
138
139 /**
Alexander Afanasyev574aa862017-01-10 19:53:28 -0800140 * @brief Add uint64_t value to the digest calculation
141 * @param value the integer value to put into digest
142 * @throw Error the digest has been finalized.
Yingdi Yude222c72014-08-15 16:06:52 -0700143 */
144 Digest<Hash>&
145 operator<<(uint64_t value);
146
147 /**
Alexander Afanasyev574aa862017-01-10 19:53:28 -0800148 * @brief Add a buffer to the digest calculation
Yingdi Yude222c72014-08-15 16:06:52 -0700149 *
Alexander Afanasyev574aa862017-01-10 19:53:28 -0800150 * Update the state of the digest if it has not been finalized and mark the digest as
151 * InProcess.
Yingdi Yude222c72014-08-15 16:06:52 -0700152 *
153 * @param buffer the input buffer
154 * @param size the size of the input buffer.
Alexander Afanasyev574aa862017-01-10 19:53:28 -0800155 * @throw Error the digest has been finalized.
Yingdi Yude222c72014-08-15 16:06:52 -0700156 */
157 void
158 update(const uint8_t* buffer, size_t size);
159
160 /**
161 * @brief Compute one-time digest
162 * @param buffer the input buffer
163 * @param size the size of the input buffer.
Alexander Afanasyev574aa862017-01-10 19:53:28 -0800164 * @return digest computed according to the `Hash` algorithm
Yingdi Yude222c72014-08-15 16:06:52 -0700165 */
166 static ConstBufferPtr
167 computeDigest(const uint8_t* buffer, size_t size);
168
Yingdi Yu9ad2d722014-08-30 16:13:57 -0700169 /**
170 * @brief Convert digest to std::string
171 *
Alexander Afanasyev574aa862017-01-10 19:53:28 -0800172 * @note This method will invoke computeDigest(), finalizing the digest.
Yingdi Yu9ad2d722014-08-30 16:13:57 -0700173 */
174 std::string
175 toString();
Yingdi Yude222c72014-08-15 16:06:52 -0700176
177private:
178 /**
179 * @brief Finalize digest.
180 *
181 * All subsequent calls to "operator<<" will throw an exception
182 */
183 void
184 finalize();
185
186private:
187 Hash m_hash;
188 BufferPtr m_buffer;
189 bool m_isInProcess;
190 bool m_isFinalized;
191};
192
Yingdi Yu9ad2d722014-08-30 16:13:57 -0700193template<typename Hash>
194std::ostream&
195operator<<(std::ostream& os, Digest<Hash>& digest);
196
Yingdi Yude222c72014-08-15 16:06:52 -0700197/**
198 * @brief A digest using SHA256 as the hash function.
199 */
200typedef Digest<CryptoPP::SHA256> Sha256;
201
202} // namespace util
203} // namespace ndn
204
205#endif // NDN_UTIL_DIGEST_HPP