//
//! \file  libecc/sha.h
//! \brief SHA-1
//!
//! This header file declares <code>class libecc::sha1</code>, the Secure Hash Algorithm version 1.
//
// This file is part of the libecc package.
// Copyright (C) 2002, by
//
// Carlo Wood, Run on IRC <carlo@alinoe.com>
// RSA-1024 0x624ACAD5 1997-01-26                    Sign & Encrypt
// Fingerprint16 = 32 EC A7 B6 AC DB 65 A6  F6 F6 55 DD 1C DC FF 61
//
// This program is free software; you can redistribute it and/or
// modify it under the terms of the GNU General Public License
// as published by the Free Software Foundation; either version 2
// of the License, or (at your option) any later version.
// 
// This program 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 LIBECC_SHA_H
#define LIBECC_SHA_H

#include <libecc/bitset.h>

namespace libecc {

/**\class sha1
 * \brief SHA-1
 *
 * This class allows one to calculate a hash value
 * of a bitset using the Secure Hash Algorithm 1,
 * as described in the <a href="http://www.itl.nist.gov/fipspubs/fip180-1.htm">FIPS PUB 180-1</a>.
 *
 * Unlike most implementations, this is a bit oriented implementation and therefore more
 * suitable to calculate hash values of bitsets then to calculate hash values of character
 * strings (like for example a text file).
 *
 * The correct use is as follows.
 *
 * \code
 * libecc::bitset<10> msg("3FF");	// A bit set of 10 ones.
 * libecc::sha1 hash_obj;
 * hash_obj.process_msg(msg);
 * libecc::bitset<160> hash(hash_obj.digest());
 * \endcode
 */
class sha1 {
  private:
    uint32_t H0;
    uint32_t H1;
    uint32_t H2;
    uint32_t H3;
    uint32_t H4;
    uint32_t A;
    uint32_t B;
    uint32_t C;
    uint32_t D;
    uint32_t E;
    uint32_t W[80];

  public:
    /**
     * \brief Constructor.  Constructs a SHA-1 object.
     */
    sha1(void);

    /**
     * \brief Process a complete message.
     *
     * Calculate the hash value of a message of \a number_of_bits, passed as an array of \c bitset_digit_t.&nbsp;
     * The last bit of the message is the least significant bit of the first digit.
     *
     * \param message        A pointer to an array of \c bitset_digit_t, containing the message bits.
     * \param number_of_bits The number of valid bits in the array, only the first \a number_of_bits
     *                       are considered to be part of the message.
     *
     * <b>Example:</b>
     *
     * The following code would correctly print the hash value of a string of characters.
     *
     * \code
     * void print_hash(std::string const& message)
     * {
     *   using libecc::bitset_digit_t;
     *   size_t digits = (message.size() + sizeof(bitset_digit_t) - 1) / sizeof(bitset_digit_t);
     *   bitset_digit_t* buf = new bitset_digit_t[digits];
     *   int shift = 0, digit = -1;
     *   for (std::string::const_reverse_iterator iter = message.rbegin();
     *        iter != message.rend(); ++iter)
     *   {
     *     if (shift == 0)
     *       buf[++digit] = *iter;
     *     else
     *       buf[digit] |= *iter << 8 * shift;
     *     shift = (shift + 1) % sizeof(bitset_digit_t);
     *   }
     *   libecc::sha1 hash_obj;
     *   hash_obj.process_msg(buf, 8 * message.size());
     *   delete [] buf;
     *   std::cout << hash_obj.digest() << '\n';
     * }
     * \endcode
     */
    void process_msg(bitset_digit_t const* message, size_t number_of_bits);

    /**
     * \brief Process a complete message.
     *
     * \param message        A bitset containing the message that the hash has to be calculated for.&nbsp; Only the first
     *                       \a number_of_bits least significant bits are considered to be part of the message.
     * \param number_of_bits The number of bits in the message.&nbsp; This value must be less or equal to the size of the bitset.
     */
    template<unsigned int n> void process_msg(bitset<n> const& message, size_t number_of_bits = n)
        { process_msg(message.digits_ptr(), number_of_bits); }

    /**
     * \brief The resulting hash value.
     *
     * This method returns the hash value of the last message that was processed, as a 160 bit bitset.
     */
    bitset<160> digest(void) const;

  protected:
    /**
     * \brief Reset the state of the SHA-1 object.
     *
     * This method needs to be called prior to calculating
     * the hash value of a message with sha1::process_block.&nbsp;
     */
    void reset();

    /**
     * \brief Process the next data block.
     *
     * This method will process the next block of data.
     * The argument \a block should be a pointer to an array of \c bitset_digit_t
     * having a total size of 512 bits.
     */
    void process_block(bitset_digit_t const* block);
};

} // namespace libecc

#endif // LIBECC_SHA_H
