blob: 664df2b0a303980d4f6f4e768cf698face1c6493 [file] [log] [blame]
Yingdi Yude222c72014-08-15 16:06:52 -07001/* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
2/**
3 * Copyright (c) 2013-2014 Regents of the University of California.
4 *
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#include "digest.hpp"
Alexander Afanasyev6800e1f2014-09-30 13:20:12 -070023#include <sstream>
Yingdi Yude222c72014-08-15 16:06:52 -070024
25namespace ndn {
26namespace util {
27
28template<typename Hash>
29Digest<Hash>::Digest()
30{
31 reset();
32}
33
34template<typename Hash>
Alexander Afanasyevd27334f2015-07-01 21:44:36 -070035Digest<Hash>::Digest(std::istream& is)
36 : m_isInProcess(false)
37 , m_isFinalized(true)
38{
39 using namespace CryptoPP;
40
41 m_buffer = make_shared<Buffer>(m_hash.DigestSize());
42 FileSource(is, true,
43 new HashFilter(m_hash,
44 new ArraySink(m_buffer->get(), m_buffer->size())));
45}
46
47template<typename Hash>
Yingdi Yude222c72014-08-15 16:06:52 -070048void
49Digest<Hash>::reset()
50{
51 m_hash.Restart();
52 m_buffer = make_shared<Buffer>(m_hash.DigestSize());
53 m_isInProcess = false;
54 m_isFinalized = false;
55}
56
57template<typename Hash>
58void
59Digest<Hash>::finalize()
60{
61 // return immediately if Digest is finalized already.
62 if (m_isFinalized)
63 return;
64
65 m_hash.Final(m_buffer->get());
66
67 m_isFinalized = true;
68}
69
70template<typename Hash>
71ConstBufferPtr
72Digest<Hash>::computeDigest()
73{
74 finalize();
75 return m_buffer;
76}
77
78template<typename Hash>
79bool
80Digest<Hash>::operator==(Digest<Hash>& digest)
81{
82 return *computeDigest() == *digest.computeDigest();
83}
84
85template<typename Hash>
86Digest<Hash>&
87Digest<Hash>::operator<<(Digest<Hash>& src)
88{
89 ConstBufferPtr buffer = src.computeDigest();
90 update(buffer->get(), buffer->size());
91
92 return *this;
93}
94
95template<typename Hash>
96Digest<Hash>&
97Digest<Hash>::operator<<(const std::string& str)
98{
99 update(reinterpret_cast<const uint8_t*>(str.c_str()), str.size());
100
101 return *this;
102}
103
104template<typename Hash>
105Digest<Hash>&
106Digest<Hash>::operator<<(const Block& block)
107{
108 update(block.wire(), block.size());
109
110 return *this;
111}
112
113template<typename Hash>
114Digest<Hash>&
115Digest<Hash>::operator<<(uint64_t value)
116{
117 update(reinterpret_cast<const uint8_t*>(&value), sizeof(uint64_t));
118
119 return *this;
120}
121
122template<typename Hash>
123void
124Digest<Hash>::update(const uint8_t* buffer, size_t size)
125{
126 // cannot update Digest when it has been finalized
127 if (m_isFinalized)
128 throw Error("Digest has been already finalized");
129
130 m_hash.Update(buffer, size);
131
132 m_isInProcess = true;
133}
134
135template<typename Hash>
136ConstBufferPtr
137Digest<Hash>::computeDigest(const uint8_t* buffer, size_t size)
138{
139 Hash hash;
140 BufferPtr result = make_shared<Buffer>(hash.DigestSize());
141 hash.Update(buffer, size);
142 hash.Final(result->get());
143
144 return result;
145}
146
Yingdi Yu9ad2d722014-08-30 16:13:57 -0700147template<typename Hash>
148std::string
149Digest<Hash>::toString()
150{
151 std::ostringstream os;
152 os << *this;
153
154 return os.str();
155}
156
157template<typename Hash>
158std::ostream&
159operator<<(std::ostream& os, Digest<Hash>& digest)
160{
161 using namespace CryptoPP;
162
163 std::string output;
164 ConstBufferPtr buffer = digest.computeDigest();
165 StringSource(buffer->buf(), buffer->size(), true, new HexEncoder(new FileSink(os)));
166
167 return os;
168}
169
170template
171class Digest<CryptoPP::SHA256>;
172
173template
174std::ostream&
175operator<<(std::ostream& os, Digest<CryptoPP::SHA256>& digest);
176
Yingdi Yude222c72014-08-15 16:06:52 -0700177
178} // namespace util
179} // namespace ndn