bug-commoncpp
[Top][All Lists]
Advanced

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

Re: SHA1Digest and SHA256Digest


From: Elizabeth Barham
Subject: Re: SHA1Digest and SHA256Digest
Date: 20 Nov 2002 14:22:35 -0600

Federico Montesino Pouzols <address@hidden> writes:

>       Good. I think these classes fit perfectly with cc++.

Great!

>       Personally, I think that adding the two exception cases is ok.

Done.

Here is the diff from anonymous CVS. Following that will be the two
files:

   src/sha.cpp
   demo/shadigest.cpp

Note that I did make some adjustments to some of the files in order to
build, most notably socket.h.

Thank you, Elizabeth

# ###################################################################### #
# diff file

? include
? lib
? demo/shadigest
? demo/shadigest.cpp
? src/sha.cpp
? tests/Makefile
? tests/Makefile.in
Index: demo/Makefile.am
===================================================================
RCS file: /cvsroot/commoncpp/commoncpp/demo/Makefile.am,v
retrieving revision 1.20
diff -u -p -3 -r1.20 Makefile.am
--- demo/Makefile.am    3 Feb 2002 14:04:37 -0000       1.20
+++ demo/Makefile.am    20 Nov 2002 20:15:25 -0000
@@ -17,7 +17,7 @@ LDADD = $(top_srcdir)/src/libccgnu.la $(
 Z_LIBS = -lz
 
 noinst_PROGRAMS = tcp tcpthread tcpservice serial cmdlineopt \
-       urlfetch xmlfetch portsample slogTest
+       urlfetch xmlfetch portsample slogTest shadigest
 noinst_HEADERS = serialecho.h SampleSocketPort.h
 
 urlfetch_SOURCES = urlfetch.cpp
@@ -41,3 +41,7 @@ serial_LDADD = $(top_srcdir)/src/libccex
 
 cmdlineopt_SOURCES = cmdlineopt.cpp
 cmdlineopt_LDADD = $(top_srcdir)/src/libccext.la $(XML_LIBS) $(Z_LIBS) $(LDADD)
+
+shadigest_SOURCES = shadigest.cpp
+shadigest_LDADD = $(top_srcdir)/src/libccext.la $(XML_LIBS) $(Z_LIBS) $(LDADD)
+
Index: src/Makefile.am
===================================================================
RCS file: /cvsroot/commoncpp/commoncpp/src/Makefile.am,v
retrieving revision 1.8
diff -u -p -3 -r1.8 Makefile.am
--- src/Makefile.am     4 Dec 2001 19:03:24 -0000       1.8
+++ src/Makefile.am     20 Nov 2002 20:15:25 -0000
@@ -31,7 +31,7 @@ libccgnu_la_SOURCES = thread.cpp mutex.c
 
 libccext_la_SOURCES = buffer.cpp fifo.cpp pipe.cpp numbers.cpp \
        cmdoptns.cpp url.cpp xml.cpp persist.cpp engine.cpp digest.cpp \
-       date.cpp groups.cpp md5.cpp
+       date.cpp groups.cpp md5.cpp sha.cpp
 
 # private.h are internal headers
 # export.h are used by other library
Index: src/digest.h
===================================================================
RCS file: /cvsroot/commoncpp/commoncpp/src/digest.h,v
retrieving revision 1.10
diff -u -p -3 -r1.10 digest.h
--- src/digest.h        2 Jun 2002 08:02:31 -0000       1.10
+++ src/digest.h        20 Nov 2002 20:15:26 -0000
@@ -62,6 +62,8 @@ class CCXX_CLASS_EXPORT Digest;
 class CCXX_CLASS_EXPORT ChecksumDigest;
 class CCXX_CLASS_EXPORT CRC16Digest;
 class CCXX_CLASS_EXPORT MD5Digest;
+class CCXX_CLASS_EXPORT SHA1Digest;
+class CCXX_CLASS_EXPORT SHA256Digest;
 #endif
 
 /**
@@ -245,6 +247,214 @@ public:
 
        void putDigest(const unsigned char *buffer, unsigned len);
 };
+
+/**
+ * DigestException
+ *
+ * Exception classes that pertain to errors when making or otherwise
+ * working with digests.
+ *
+ * @author Elizabeth Barham <address@hidden>
+ * @short Exceptions involving digests.
+ */
+
+class DigestException : public Exception {
+public:
+  DigestException(const std::string & what_arg) throw();
+  virtual ~DigestException() throw();
+};
+ 
+
+/**
+ * SHATumbler
+ *
+ * Class used by the SHA Digest Classes.
+ *
+ * Represents a "tumbler" group, similar to a row in a combination
+ * lock. Each part is made to roll-over, its size dependent upon
+ * int_type.
+ *
+ * @author Elizabeth Barham <address@hidden>
+ * @short SHA Helper Class */
+
+template <class int_type>
+class SHATumbler {
+
+public:
+  SHATumbler(int);
+
+  SHATumbler(const SHATumbler&);
+  SHATumbler& operator=(const SHATumbler&);
+
+  int_type& operator[](int);
+
+  ~SHATumbler();
+  
+  SHATumbler operator+(const SHATumbler& addend) const;
+  SHATumbler& operator+=(const SHATumbler& addend);
+  std::ostream & toString(std::ostream & os);
+
+  friend std::ostream &operator<<(std::ostream &os, SHATumbler<int_type>& ia)
+  {return ia.toString(os);};
+  
+  unsigned getSize();
+  unsigned placeInBuffer(unsigned char *);
+    
+private:
+  int_type * h;
+  int size;
+};
+
+/**
+ * SHAConstant
+ *
+ * Note that this constant is set in sha.cpp and that each constant in
+ * the array is 64 bits wide. The constants themselves pertain to both
+ * SHA-256 and SHA-512, the only difference is that SHA-256 expects
+ * her constants to be 32 bits wide and only 64 are needed.
+ *
+ * @auther Elizabeth Barham <address@hidden>
+ * @short Contains SHA constants
+ */
+
+class SHAConstant {
+protected:
+  const static uint64_t K[];
+};
+
+/**
+ * SHADigest
+ *
+ * Generic Class that is the base class of the various SHA*Digest
+ * classes.
+ *
+ * uint_type == The "Unsigned Integer Type" which is large enough to
+ * hold the total length of a given message in bits. For SHA1 and
+ * SHA256, this is 64 bits, so we use "uint64_t";
+ *
+ * "blockSizeInBytes" == various SHA digests use different message
+ * size blocks - the basic units in which to split a message up in.
+ * For example, SHA1 and SHA256 use 512 bit blocks, and so in
+ * bytes this is 64.
+ *
+ * @author Elizabeth Barham <address@hidden>
+ * @short Base class for the SHA*Digests
+ */
+
+template <class uint_type, unsigned blockSizeInBytes>
+class SHADigest : public Digest {
+private:
+  uint_type totalLengthInBits;
+
+  void copyTempBlock(const SHADigest &);
+
+protected:
+  unsigned char tempBlock[blockSizeInBytes];
+  void initDigest(void);
+
+  virtual void processBlock(const unsigned char * buffer) = 0;
+  void padBuffer(unsigned char * buffer);
+
+  bool completed;
+
+  SHADigest();
+  SHADigest(const SHADigest & other);
+  SHADigest & operator=(const SHADigest & other);
+
+public:
+  unsigned getSize(void) = 0;
+  void putDigest(const unsigned char * buffer, unsigned length) 
throw(DigestException);
+  std::ostream & strDigest(std::ostream &os) = 0;
+
+};
+
+#define S(n,X) ( ( ( X ) << ( n ) ) | ( ( X ) >> ( 32 - n ) ) )
+
+/* ** ** ** ** ** ** ** ** ** ** ** ** ** ** ** ** ** ** ** ** ** ** */
+/* RR == "right rotation by n bits" (Sn)                             */
+/* RS == "right shift by n byts"    (Rn)                             */
+/* (see p. 2, "Descriptions of SHA-256, SHA-384, SHA-512"            */
+/*   <http://csrc.nist.gov/encryption/shs/sha256-384-512.pdf>)       */
+/* ** ** ** ** ** ** ** ** ** ** ** ** ** ** ** ** ** ** ** ** ** ** */
+
+#define RR(n,X) ( ( ( X ) >> n ) | ( ( X ) << ( 32 - n ) ) )
+#define RS(n,X) ( ( ( X ) >> n ) )
+
+/**
+ * SHA64DigestHelper
+ *
+ * Simply a base class for the SHA*Digest classes that share
+ * functionality after their "unsigned int" type and block size are
+ * known (uint64_t and 64)
+ *
+ * @author Elizabeth Barham <address@hidden>
+ * @short Base class for the 64-bit wide SHA*Digests.
+ */
+
+class SHA64DigestHelper: public SHADigest<uint64_t, 64> {
+protected:
+  SHATumbler<uint32_t> h;
+  SHATumbler<uint32_t> a;
+
+  SHA64DigestHelper(unsigned);
+  SHATumbler<uint32_t> getDigest();
+
+public:
+  unsigned getDigest(unsigned char * buffer) { return 
getDigest().placeInBuffer(buffer); }
+  std::ostream & strDigest(std::ostream & os);
+
+  SHA64DigestHelper(const SHA64DigestHelper & other);
+  SHA64DigestHelper & operator=(const SHA64DigestHelper & other);
+};
+
+/**
+ * SHA1Digest
+ *
+ * SHA1Digest proper.
+ *
+ * @author Elizabeth Barham <address@hidden>
+ * @short SHA-1 Digest Implementation
+ */
+
+class SHA1Digest : public SHA64DigestHelper {
+protected:
+  void processBlock(const unsigned char * buffer);
+
+public:
+  SHA1Digest();
+  void initDigest();
+  unsigned getSize() { return 20; }
+  SHA1Digest(const SHA1Digest & other);
+};
+
+/**
+ * SHA256Digest
+ * @author Elizabeth Barham <address@hidden>
+ * @short SHA-256 Digest Implementation
+ */
+
+class SHA256Digest : public SHA64DigestHelper, public SHAConstant {
+protected:
+  void processBlock(const unsigned char * buffer);
+
+public:
+  SHA256Digest();
+  SHA256Digest(const SHA256Digest &);
+  void initDigest();
+  unsigned getSize() { return 32; }
+};
+
+/* In case anyone is wondering why SHA-512 and SHA-384 are not
+ * implemented, it is the better way to make them is to use an 128-bit
+ * unsigned integer. To my understanding, the gcc 3.* has either
+ * introduced uint128_t or shall introduce it. When it does, something
+ * similar to SHA64DigestHelper can easily be made, perhaps:
+ *
+ * "class SHA128DigestHelper : public SHADigest<uint128_t, 128>"
+ *
+ * -- Elizabeth Barham, November 20, 2002, Fort Worth, TX, USA
+ */
+
 
 #ifdef CCXX_NAMESPACES
 };
Index: src/socket.cpp
===================================================================
RCS file: /cvsroot/commoncpp/commoncpp/src/socket.cpp,v
retrieving revision 1.19
diff -u -p -3 -r1.19 socket.cpp
--- src/socket.cpp      2 Jun 2002 08:50:19 -0000       1.19
+++ src/socket.cpp      20 Nov 2002 20:15:26 -0000
@@ -73,7 +73,7 @@ using namespace std;
 #endif
 
 #ifdef WIN32
-static SOCKET dupSocket(SOCKET so,enum Socket::State state)
+static SOCKET dupSocket(SOCKET so, sockstate_t state)
 {
        if (state == Socket::STREAM)
                return dup(so);
Index: src/socket.h
===================================================================
RCS file: /cvsroot/commoncpp/commoncpp/src/socket.h,v
retrieving revision 1.15
diff -u -p -3 -r1.15 socket.h
--- src/socket.h        2 Jun 2002 08:50:19 -0000       1.15
+++ src/socket.h        20 Nov 2002 20:15:27 -0000
@@ -569,7 +569,7 @@ private:
        mutable const char *errstr;
 
        void setSocket(void);
-       friend SOCKET dupSocket(SOCKET s,Socket::State state);
+       friend SOCKET dupSocket(SOCKET s, sockstate_t state);
 
 protected:
        mutable struct
Index: src/xml.cpp
===================================================================
RCS file: /cvsroot/commoncpp/commoncpp/src/xml.cpp,v
retrieving revision 1.8
diff -u -p -3 -r1.8 xml.cpp
--- src/xml.cpp 29 May 2002 08:55:40 -0000      1.8
+++ src/xml.cpp 20 Nov 2002 20:15:28 -0000
@@ -51,9 +51,9 @@
 
 #ifdef HAVE_LIBXML
 
-#include <parser.h>
-#include <parserInternals.h>
-#include <xmlIO.h>
+#include <libxml/parser.h>
+#include <libxml/parserInternals.h>
+#include <libxml/xmlIO.h>
 #include <cstdarg>
 
 #ifdef CCXX_NAMESPACES

# ################################################################## #
# src/sha.cpp

/* -*- C++ -*- */
// Copyright (C) 1999-2002 Open Source Telecom Corporation.
//  
// 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.
// 
// As a special exception to the GNU General Public License, permission is 
// granted for additional uses of the text contained in its release 
// of Common C++.
// 
// The exception is that, if you link the Common C++ library with other files
// to produce an executable, this does not by itself cause the
// resulting executable to be covered by the GNU General Public License.
// Your use of that executable is in no way restricted on account of
// linking the Common C++ library code into it.
// 
// This exception does not however invalidate any other reasons why
// the executable file might be covered by the GNU General Public License.
// 
// This exception applies only to the code released under the 
// name Common C++.  If you copy code from other releases into a copy of
// Common C++, as the General Public License permits, the exception does
// not apply to the code that you add in this way.  To avoid misleading
// anyone as to the status of such modified files, you must delete
// this exception notice from them.
// 
// If you write modifications of your own for Common C++, it is your choice
// whether to permit this exception to apply to your modifications.
// If you do not wish that, delete this exception notice.  

#include "config.h"
#include "export.h"
#include "strchar.h"
#include "exception.h"
#include "thread.h"
#include "digest.h"
#include <cstdio>
#include <iomanip>

#ifdef  WIN32
#include <io.h>
#endif

#ifdef  CCXX_NAMESPACES
namespace ost {
using namespace std;
#endif

/**
 * DigestException
 */

DigestException::DigestException(const std::string & what_arg) throw() :
  Exception(what_arg)
{ }

DigestException::~DigestException() throw()
{ }


/** 
 * SHAConstant::K
 */

/* note to use K32_ADJUST when attempting to access K with a 32 bit
 * integer.
 */

#if __BYTE_ORDER == __LITTLE_ENDIAN
#define K32_ADJUST 1
#else
#define K32_ADJUST 0
#endif

const uint64_t SHAConstant::K[] = {
  0x428a2f98d728ae22LL,
  0x7137449123ef65cdLL,
  0xb5c0fbcfec4d3b2fLL,
  0xe9b5dba58189dbbcLL,
  0x3956c25bf348b538LL,
  0x59f111f1b605d019LL,
  0x923f82a4af194f9bLL,
  0xab1c5ed5da6d8118LL,
  0xd807aa98a3030242LL,
  0x12835b0145706fbeLL,
  0x243185be4ee4b28cLL,
  0x550c7dc3d5ffb4e2LL,
  0x72be5d74f27b896fLL,
  0x80deb1fe3b1696b1LL,
  0x9bdc06a725c71235LL,
  0xc19bf174cf692694LL,
  0xe49b69c19ef14ad2LL,
  0xefbe4786384f25e3LL,
  0x0fc19dc68b8cd5b5LL,
  0x240ca1cc77ac9c65LL,
  0x2de92c6f592b0275LL,
  0x4a7484aa6ea6e483LL,
  0x5cb0a9dcbd41fbd4LL,
  0x76f988da831153b5LL,
  0x983e5152ee66dfabLL,
  0xa831c66d2db43210LL,
  0xb00327c898fb213fLL,
  0xbf597fc7beef0ee4LL,
  0xc6e00bf33da88fc2LL,
  0xd5a79147930aa725LL,
  0x06ca6351e003826fLL,
  0x142929670a0e6e70LL,
  0x27b70a8546d22ffcLL,
  0x2e1b21385c26c926LL,
  0x4d2c6dfc5ac42aedLL,
  0x53380d139d95b3dfLL,
  0x650a73548baf63deLL,
  0x766a0abb3c77b2a8LL,
  0x81c2c92e47edaee6LL,
  0x92722c851482353bLL,
  0xa2bfe8a14cf10364LL,
  0xa81a664bbc423001LL,
  0xc24b8b70d0f89791LL,
  0xc76c51a30654be30LL,
  0xd192e819d6ef5218LL,
  0xd69906245565a910LL,
  0xf40e35855771202aLL,
  0x106aa07032bbd1b8LL,
  0x19a4c116b8d2d0c8LL,
  0x1e376c085141ab53LL,
  0x2748774cdf8eeb99LL,
  0x34b0bcb5e19b48a8LL,
  0x391c0cb3c5c95a63LL,
  0x4ed8aa4ae3418acbLL,
  0x5b9cca4f7763e373LL,
  0x682e6ff3d6b2b8a3LL,
  0x748f82ee5defb2fcLL,
  0x78a5636f43172f60LL,
  0x84c87814a1f0ab72LL,
  0x8cc702081a6439ecLL,
  0x90befffa23631e28LL,
  0xa4506cebde82bde9LL,
  0xbef9a3f7b2c67915LL,
  0xc67178f2e372532bLL,
  0xca273eceea26619cLL,
  0xd186b8c721c0c207LL,
  0xeada7dd6cde0eb1eLL,
  0xf57d4f7fee6ed178LL,
  0x06f067aa72176fbaLL,
  0x0a637dc5a2c898a6LL,
  0x113f9804bef90daeLL,
  0x1b710b35131c471bLL,
  0x28db77f523047d84LL,
  0x32caab7b40c72493LL,
  0x3c9ebe0a15c9bebcLL,
  0x431d67c49c100d4cLL,
  0x4cc5d4becb3e42b6LL,
  0x597f299cfc657e2aLL,
  0x5fcb6fab3ad6faecLL,
  0x6c44198c4a475817LL
};


/* *********************************************************************
   SHATumbler
   ********************************************************************* */

template <class int_type>
SHATumbler<int_type>::SHATumbler(int s): size(s) {
  h = new int_type[size];
}

template <class int_type>
SHATumbler<int_type>::SHATumbler(const SHATumbler<int_type>& copy) {
  size = copy.size;
  h = new int_type[size];
  memcpy((void*)h,(void*)copy.h,sizeof(int_type) * size);
}

template <class int_type>
SHATumbler<int_type> & SHATumbler<int_type>::operator=(const 
SHATumbler<int_type> & assign) {
  memcpy((void*)h,(void*)assign.h,sizeof(int_type) * size);
  return *this;
}

template <class int_type>
int_type & SHATumbler<int_type>::operator[](int x) {
  return h[x];
}

template <class int_type>
SHATumbler<int_type>::~SHATumbler() {
  delete[] h;
}

template <class int_type>
SHATumbler<int_type> SHATumbler<int_type>::operator+(const 
SHATumbler<int_type>& addend) const {
  SHATumbler<int_type> rv = *this;
  rv += addend;
  return(rv);
}

template <class int_type>
SHATumbler<int_type>& SHATumbler<int_type>::operator+=(const 
SHATumbler<int_type>& addend)  {
  for(int i = 0; i < size; i++) {
    h[i] += addend.h[i];
  }
  return(*this);
}

template <class int_type>
std::ostream & SHATumbler<int_type>::toString(std::ostream & os) {
  for(int i = 0 ; i < size ; i++) {

#ifdef DEBUG_SHATUMBLER
    if(i != 0)
      os << " ";
#endif
      
    os << std::hex << std::setw(sizeof(h[i]) * 2) << std::setfill('0') << h[i];
  }
  return(os);
}

template <class int_type>
unsigned SHATumbler<int_type>::placeInBuffer(unsigned char * buffer) {
  unsigned memsize = getSize();
  memcpy((void*) buffer, (void*) h, memsize);
  return(memsize);
}

template <class int_type>
unsigned SHATumbler<int_type>::getSize() {
  unsigned memsize = sizeof(int_type) * size;
  return(memsize);
}

/* *********************************************************************
   SHADigest
   ********************************************************************* */
template <class uint_type, unsigned blockSizeInBytes>
SHADigest<uint_type, blockSizeInBytes>::SHADigest() {
  initDigest();
}


template <class uint_type, unsigned blockSizeInBytes>
void SHADigest<uint_type, blockSizeInBytes>::padBuffer(unsigned char * buffer) {
  int lengthOfTotalLength     = blockSizeInBytes / 8;
  uint_type totalLengthInBytes = totalLengthInBits / 8;
  int remainder = totalLengthInBytes % blockSizeInBytes;

  int fillTo;

  if( (blockSizeInBytes - ( remainder + 1 )) >= lengthOfTotalLength ) {
    fillTo = (blockSizeInBytes - lengthOfTotalLength);
  } else {
    fillTo = blockSizeInBytes;
  }
  
  buffer[remainder++] = 0x80;

  do {
    bzero(buffer + remainder, fillTo - remainder);
    if(fillTo != blockSizeInBytes) {
      *((uint_type*)(buffer + fillTo)) = totalLengthInBits;
    }
    processBlock(buffer);
    remainder = 0;
    fillTo -= lengthOfTotalLength;
  } while(fillTo >= (blockSizeInBytes - lengthOfTotalLength));
  completed = true;
}

template <class uint_type, unsigned blockSizeInBytes>
void SHADigest<uint_type, blockSizeInBytes>::initDigest() {
  totalLengthInBits = 0;
  completed = false;
}

template <class uint_type, unsigned blockSizeInBytes>
void SHADigest<uint_type, blockSizeInBytes>::putDigest(const unsigned char * 
buffer, unsigned length) 
  throw(DigestException)
{

  if(completed) {
    throw(DigestException("Corrupted Digest!"));
  }
  
  if( length > (totalLengthInBits / 8) + length ) {
    throw(DigestException("Digest Length Overflow!"));
  }

  // fill in tempBlock if necessarry, then process it...

  uint_type bytesInTempBlock;

  if(bytesInTempBlock = (totalLengthInBits/8) % blockSizeInBytes) {
    unsigned bytesLeftInTempBlock = blockSizeInBytes - bytesInTempBlock;
    unsigned numToCopy;

    if(length < bytesLeftInTempBlock) {
      numToCopy = length;
    } else {
      numToCopy = bytesLeftInTempBlock;
    }

    memcpy(tempBlock + bytesInTempBlock, buffer, numToCopy);
    length -= numToCopy;
  }

  unsigned numBlocksToProcess = length / blockSizeInBytes;
  unsigned numBytesToStore   = length % blockSizeInBytes;

  // process incoming stream

  for(unsigned i = 0; i < numBlocksToProcess; i++) {
    processBlock(buffer + (i * blockSizeInBytes));
  }

  // place any data that could not be processed into tempBlock

  for(unsigned i = 0; i < numBytesToStore; i++) {
    tempBlock[i] = (buffer + (numBlocksToProcess * blockSizeInBytes))[i];
  }
  totalLengthInBits += 8 * (bytesInTempBlock +  (numBlocksToProcess * 
blockSizeInBytes) + numBytesToStore);
}

template <class uint_type, unsigned blockSizeInBytes>
SHADigest<uint_type, blockSizeInBytes>::SHADigest(const SHADigest<uint_type, 
blockSizeInBytes> & other) :
  totalLengthInBits(other.totalLengthInBits),
  completed(other.completed)
 {
   copyTempBlock(other);
 }

template <class uint_type, unsigned blockSizeInBytes>
SHADigest<uint_type, blockSizeInBytes> &  SHADigest<uint_type, 
blockSizeInBytes>::operator=(const SHADigest & other) {
  if(this == &other) {
    return *this;
  }

  this->completed = other.completed;
  this->totalLengthInBits = other.totalLengthInBits;
  copyTempBlock(other);
}

template <class uint_type, unsigned blockSizeInBytes>
void  SHADigest<uint_type, blockSizeInBytes>::copyTempBlock(const SHADigest & 
other) {
  if(uint_type remainder = ( (totalLengthInBits / 8) % blockSizeInBytes)) {
    memcpy( (void*)tempBlock, (void*)other.tempBlock, remainder * 
(sizeof(unsigned char)));
  }
}

/* *********************************************************************
   SHA64DigestHelper
   ********************************************************************* */

SHA64DigestHelper::SHA64DigestHelper(unsigned tumblerSize):
  h(SHATumbler<uint32_t>(tumblerSize)), 
  a(SHATumbler<uint32_t>(tumblerSize))
{ }

SHATumbler<uint32_t> SHA64DigestHelper::getDigest() {
  if(!completed) {
    padBuffer(tempBlock);
  }
  return h;
}

std::ostream & SHA64DigestHelper::strDigest(std::ostream & os) {
  SHATumbler<uint32_t> hCopy = getDigest();
  os << hCopy;
  return(os);
}

SHA64DigestHelper::SHA64DigestHelper(const SHA64DigestHelper & other) :
  SHADigest<uint64_t, 64>(other),
  h(other.h),
  a(other.a)
{ }

SHA64DigestHelper & SHA64DigestHelper::operator=(const SHA64DigestHelper & 
other)
{
  if(this == &other) {
    return(*this);
  }

  SHADigest<uint64_t, 64>::operator=(other);

  this->h = other.h;
  this->a = other.a;

  return *this;
}



/* *********************************************************************
   SHA1Digest
   ********************************************************************* */

SHA1Digest::SHA1Digest(): SHA64DigestHelper(5) {
  initDigest();
}

void SHA1Digest::initDigest() {
  h[0] = 0x67452301;
  h[1] = 0xefcdab89;
  h[2] = 0x98badcfe;
  h[3] = 0x10325476;
  h[4] = 0xc3d2e1f0;
  SHADigest<uint64_t, 64>::initDigest();
}

SHA1Digest::SHA1Digest(const SHA1Digest & other): SHA64DigestHelper(other)
{ }

void SHA1Digest::processBlock(const unsigned char * buffer) {
  uint32_t W[80];

  memcpy((void*)W, (void*)buffer, sizeof(uint32_t) * 16);
  for(int t = 16; t < 80; t++) {
    W[t] = S(1,(W[t-3] ^ W[t-8] ^ W[t-14] ^ W[t-16]));
  }
  a = h;
  uint32_t temp;
  for(int t = 0; t < 80; t++) {
    switch(t/20) {
    case(0):
      temp = ((a[1] & a[2]) | (~a[1] & a[3])) + 0x5a827999;
      break;
    case(1):
      temp = ((a[1] ^ a[2] ^ a[3]) + 0x6ed9eba1);
      break;
    case(2):
      temp = ((a[1] & a[2]) | (a[1] & a[3]) | (a[2] & a[3])) + 0x8f1bbcdc;
      break;
    default:
      temp = (a[1] ^ a[2] ^ a[3]) + 0xca62c1d6;
    }
    temp += S(5,a[0]) + a[4] + W[t];
    a[4] = a[3];
    a[3] = a[2];
    a[2] = S(30,a[1]);
    a[1] = a[0];
    a[0] = temp;

#ifdef DEBUG_SHA1
    std::cerr << std::setw(2) << std::dec << t << ": " << a << std::endl;
#endif
    
  }
  h += a;
}

/* *********************************************************************
   SHA256Digest
   ********************************************************************* */

SHA256Digest::SHA256Digest(): SHA64DigestHelper(8) {
  initDigest();
}


SHA256Digest::SHA256Digest(const SHA256Digest & other):
  SHA64DigestHelper(other)
{ }


void SHA256Digest::initDigest() {
  h[0] = 0x6a09e667;
  h[1] = 0xbb67ae85;
  h[2] = 0x3c6ef372;
  h[3] = 0xa54ff53a;
  h[4] = 0x510e527f;
  h[5] = 0x9b05688c;
  h[6] = 0x1f83d9ab;
  h[7] = 0x5be0cd19;
  SHADigest<uint64_t, 64>::initDigest();
}

#define Ch(x,y,z) ( ( ( x ) & ( y ) ) ^ (  ( ~ x  ) & ( z ) ) )
#define Maj(x,y,z) ( ( ( x ) & ( y ) ) ^ ( ( x ) & ( z ) ) ^ ( ( y ) & ( z ) ) )
#define E0(x) ( RR(2,x) ^ RR(13,x) ^ RR(22,x) )
#define E1(x) ( RR(6,x) ^ RR(11,x) ^ RR(25,x) )
#define o0(x) ( RR(7,x) ^ RR(18,x) ^ RS(3,x) )
#define o1(x) ( RR(17,x) ^ RR(19,x) ^ RS(10,x) )

void SHA256Digest::processBlock(const unsigned char * buffer) {
  uint32_t t1, t2;
  uint32_t W[64];
  uint32_t * M = (uint32_t*)buffer;
  uint32_t * K32 = (uint32_t*)SHAConstant::K;

  a = h;
  for(int j = 0; j < 64 ; j++) {
    if(j < 16) {
      W[j] = M[j];
    } else {
      W[j] = o1(W[j-2]) + W[j-7] + o0(W[j-15]) + W[j-16];
    }

    t1 = a[7] + E1(a[4]) + Ch(a[4],a[5],a[6]) + K32[(j * 2) + K32_ADJUST] + 
W[j];
    t2 = E0(a[0]) + Maj(a[0],a[1],a[2]);
    
    a[7] = a[6];
    a[6] = a[5];
    a[5] = a[4];
    a[4] = a[3] + t1;
    a[3] = a[2];
    a[2] = a[1];
    a[1] = a[0];
    a[0] = t1 + t2;
#ifdef DEBUG_SHA256
    std::cerr << std::setw(2) << std::dec << j << std::hex << ": " << a << 
std::endl;
#endif
  }
  h += a;
}


#ifdef  CCXX_NAMESPACES
};
#endif  


#ifdef TEST_SHA
#define BUFF_SIZE 1024
#include <stdio.h>

int main(int argc, char * argv[]) {
  unsigned char buff[1024];

  SHA256Digest d256;
  unsigned length;

  for(int i = 1 ; i < argc; i++) {
    FILE * fp = fopen(argv[i], "rb");
    d256.initDigest();

    if(fp) {
      while(length = fread(buff, sizeof(unsigned char), BUFF_SIZE, fp)) {
        try {
          d256.putDigest(buff, length);
        } catch(DigestException & d) {
          std::cerr << "Digest Exception: " << d.getString() << std::endl;
          fclose(fp);
          break;
        }
      }

      std::cout << d256 << "  " << argv[i] << std::endl;

      fclose(fp);
    }

  }
}
#endif


# ###################################################################### #
# demo/shadigest.cpp

#include "config.h"
#include "strchar.h"
#include "exception.h"
#include "thread.h"
#include "digest.h"
#include <stdio.h>

#define BUFF_SIZE 1024

int main(int argc, char * argv[]) {
  unsigned char buff[1024];
  ost::SHA256Digest d256;
  unsigned length;

  for(int i = 1 ; i < argc; i++) {
    FILE * fp = fopen(argv[i], "rb");
    d256.initDigest();

    if(fp) {
      while(length = fread(buff, sizeof(unsigned char), BUFF_SIZE, fp)) {
        d256.putDigest(buff, length);
      }

      std::cout << d256 << "  " << argv[i] << std::endl;

      fclose(fp);
    }
  }
}

# ##################################################################### #




reply via email to

[Prev in Thread] Current Thread [Next in Thread]