PageRenderTime 174ms CodeModel.GetById 60ms app.highlight 18ms RepoModel.GetById 93ms app.codeStats 0ms

/mordor/streams/hash.h

http://github.com/mozy/mordor
C Header | 228 lines | 181 code | 40 blank | 7 comment | 0 complexity | eefe6e3b6ee3bca4dd6e2a199123bb23 MD5 | raw file
  1#ifndef __MORDOR_HASH_STREAM_H__
  2#define __MORDOR_HASH_STREAM_H__
  3// Copyright (c) 2009 - Mozy, Inc.
  4
  5#include <vector>
  6
  7#include <openssl/sha.h>
  8#include <openssl/md5.h>
  9
 10#include "assert.h"
 11#include "filter.h"
 12#include "buffer.h"
 13#include "hashfwd.h"
 14
 15namespace Mordor {
 16
 17class HashStream : public FilterStream
 18{
 19public:
 20    typedef boost::shared_ptr<HashStream> ptr;
 21
 22public:
 23    HashStream(Stream::ptr parent, bool own = true)
 24        : FilterStream(parent, own)
 25    {}
 26
 27    bool supportsSeek() { return false; }
 28    bool supportsTruncate() { return false; }
 29    bool supportsUnread() { return false; }
 30
 31    size_t read(Buffer &buffer, size_t length);
 32    size_t read(void *buffer, size_t length);
 33    size_t write(const Buffer &buffer, size_t length);
 34    size_t write(const void *buffer, size_t length);
 35    long long seek(long long offset, Anchor anchor = BEGIN);
 36
 37    // Returns the hash in *binary*
 38    virtual std::string hash() const;
 39    virtual size_t hashSize() const = 0;
 40    virtual void hash(void *result, size_t length) const = 0;
 41    /// dump variant Hash context into buffer for later resuming
 42    virtual Buffer dumpContext() const = 0;
 43
 44    virtual void reset() = 0;
 45
 46protected:
 47    virtual void updateHash(const void *buffer, size_t length) = 0;
 48};
 49
 50template<HASH_TYPE H> struct HashOps {};
 51
 52#ifndef OPENSSL_NO_SHA0
 53template<>
 54struct HashOps<SHA0>
 55{
 56    typedef SHA_CTX ctx_type;
 57
 58    static int init(ctx_type *ctx)
 59    { return SHA_Init(ctx); }
 60    static int update(ctx_type *ctx, const void *data, size_t len)
 61    { return SHA_Update(ctx, data, len); }
 62    static int final(unsigned char *md, ctx_type *ctx)
 63    { return SHA_Final(md, ctx); }
 64    static size_t digestLength() { return SHA_DIGEST_LENGTH; }
 65};
 66#endif
 67
 68#ifndef OPENSSL_NO_SHA1
 69template<>
 70struct HashOps<SHA1>
 71{
 72    typedef SHA_CTX ctx_type;
 73
 74    static int init(ctx_type *ctx)
 75    { return SHA1_Init(ctx); }
 76    static int update(ctx_type *ctx, const void *data, size_t len)
 77    { return SHA1_Update(ctx, data, len); }
 78    static int final(unsigned char *md, ctx_type *ctx)
 79    { return SHA1_Final(md, ctx); }
 80    static size_t digestLength() { return SHA_DIGEST_LENGTH; }
 81};
 82#endif
 83
 84#ifndef OPENSSL_NO_SHA256
 85template<>
 86struct HashOps<SHA224>
 87{
 88    typedef SHA256_CTX ctx_type;
 89
 90    static int init(ctx_type *ctx)
 91    { return SHA224_Init(ctx); }
 92    static int update(ctx_type *ctx, const void *data, size_t len)
 93    { return SHA224_Update(ctx, data, len); }
 94    static int final(unsigned char *md, ctx_type *ctx)
 95    { return SHA224_Final(md, ctx); }
 96    static size_t digestLength() { return SHA224_DIGEST_LENGTH; }
 97};
 98
 99template<>
100struct HashOps<SHA256>
101{
102    typedef SHA256_CTX ctx_type;
103
104    static int init(ctx_type *ctx)
105    { return SHA256_Init(ctx); }
106    static int update(ctx_type *ctx, const void *data, size_t len)
107    { return SHA256_Update(ctx, data, len); }
108    static int final(unsigned char *md, ctx_type *ctx)
109    { return SHA256_Final(md, ctx); }
110    static size_t digestLength() { return SHA256_DIGEST_LENGTH; }
111};
112#endif
113
114template<>
115struct HashOps<MD5>
116{
117    typedef MD5_CTX ctx_type;
118
119    static int init(ctx_type *ctx)
120    { return MD5_Init(ctx); }
121    static int update(ctx_type *ctx, const void *data, size_t len)
122    { return MD5_Update(ctx, data, len); }
123    static int final(unsigned char *md, ctx_type *ctx)
124    { return MD5_Final(md, ctx); }
125    static size_t digestLength() { return MD5_DIGEST_LENGTH; }
126};
127
128template<HASH_TYPE H>
129class _HashStream : public HashStream
130{
131public:
132    typedef typename HashOps<H>::ctx_type ctx_type;
133    typedef boost::shared_ptr<_HashStream<H> > ptr;
134
135private:
136    typedef HashOps<H> hash_ops;
137
138public:
139    _HashStream(Stream::ptr parent, bool own = true)
140        : HashStream(parent, own)
141    { hash_ops::init(&m_ctx); }
142
143    _HashStream(Stream::ptr parent, const ctx_type &ctx, bool own = true)
144        : HashStream(parent, own)
145        , m_ctx(ctx)
146    {}
147
148    _HashStream(Stream::ptr parent, const Buffer &buffer, bool own = true)
149        : HashStream(parent, own)
150    { buffer.copyOut(&m_ctx, sizeof(ctx_type)); }
151
152    size_t hashSize() const { return hash_ops::digestLength(); }
153    void reset() { hash_ops::init(&m_ctx); }
154    ctx_type ctx() const { return m_ctx; }
155
156    using HashStream::hash;
157    void hash(void *result, size_t length) const
158    {
159        ctx_type copy(m_ctx);
160        hash_ops::final((unsigned char *)result, &copy);
161    }
162
163    Buffer dumpContext() const
164    {
165        Buffer buffer;
166        buffer.copyIn(&m_ctx, sizeof(ctx_type));
167        return buffer;
168    }
169
170private:
171    void updateHash(const void *buffer, size_t length)
172    { hash_ops::update(&m_ctx, buffer, length); }
173
174protected:
175    ctx_type m_ctx;
176};
177
178#ifndef OPENSSL_NO_SHA0
179typedef _HashStream<SHA0>   SHA0Stream;
180#endif
181#ifndef OPENSSL_NO_SHA1
182typedef _HashStream<SHA1>   SHA1Stream;
183#endif
184#ifndef OPENSSL_NO_SHA256
185typedef _HashStream<SHA224> SHA224Stream;
186typedef _HashStream<SHA256> SHA256Stream;
187#endif
188typedef _HashStream<MD5>    MD5Stream;
189
190class CRC32Stream : public HashStream
191{
192public:
193    /// Using a well-known polynomial will automatically select a precomputed table
194    enum WellknownPolynomial
195    {
196        /// CRC-32-IEEE, used in V.42, Ethernet, MPEG-2, PNG, POSIX cksum, etc.
197        IEEE = 0x04C11DB7,
198        /// CRC-32C used in iSCSI and SCTP
199        CASTAGNOLI = 0x1EDC6F41,
200        /// CRC-32K
201        KOOPMAN = 0x741B8CD7
202    };
203public:
204    CRC32Stream(Stream::ptr parent, unsigned int polynomial = IEEE,
205        bool own = true);
206    CRC32Stream(Stream::ptr parent, const unsigned int *precomputedTable,
207        bool own = true);
208
209    static std::vector<unsigned int> precomputeTable(unsigned int polynomial);
210
211    size_t hashSize() const;
212    using HashStream::hash;
213    void hash(void *result, size_t length) const;
214    void reset();
215    Buffer dumpContext() const { return Buffer(); }
216
217protected:
218    void updateHash(const void *buffer, size_t length);
219
220private:
221    unsigned int m_crc;
222    const std::vector<unsigned int> m_tableStorage;
223    const unsigned int *m_table;
224};
225
226}
227
228#endif