SHA1 計算類

來源:互聯網
上載者:User

 

//SHA1_Class.h#pragma once//RFC 3174           US Secure Hash Algorithm 1 (SHA1)/* * If you do not have the ISO standard stdint.h header file, then you * must typdef the following: *    name              meaning *  uint32_t         unsigned 32 bit integer *  uint8_t          unsigned 8 bit integer (i.e., unsigned char) *  int_least16_t    integer of >= 16 bits * */class CSHA1_Class{  typedef unsigned long uint32_t;  typedef unsigned char uint8_t;  typedef unsigned short int_least16_t;  typedef unsigned long UINT4;  #define SHA1HashSize 20  /*   *  This structure will hold context information for the SHA-1   *  hashing operation   */  typedef struct SHA1Context  {    uint32_t Intermediate_Hash[SHA1HashSize/4]; /* Message Digest  */    uint32_t Length_Low;            /* Message length in bits      */    uint32_t Length_High;           /* Message length in bits      */                                     /* Index into message block array   */    int_least16_t Message_Block_Index;    uint8_t Message_Block[64];      /* 512-bit message blocks      */    int Computed;               /* Is the digest computed?         */    int Corrupted;             /* Is the message digest corrupted? */  } SHA1Context;  SHA1Context m_SHA1Context;public:  enum  {    shaSuccess = 0,    shaNull,            /* Null pointer parameter */    shaInputTooLong,    /* input data too long */    shaStateError       /* called Input after Result */  };  typedef struct _PROC_INFO  {    ULONGLONG uLL_TotalSize;     //需要校正的總位元組數    ULONGLONG uLL_ProcessedSize; //已經校正的位元組數    double f_ProcPercent;        //精度百分百 %    TCHAR  m_rawHash[2*SHA1HashSize+1];    //校正結果    BOOL bDone;                  //完成標誌  }PROC_INFO, *LPPROC_INFO;  /*   *  Function Prototypes   */  int SHA1Reset();  int SHA1Input(const uint8_t *,  unsigned);  int SHA1Result(uint8_t Message_Digest[SHA1HashSize]);    int FileCalculate(LPCTSTR lpszFile, LPPROC_INFO pProcInfo=NULL);/* Local Function Prototyptes */private:  void SHA1PadMessage();  void SHA1ProcessMessageBlock();  /*   *  Define the SHA1 circular left shift macro   */  #define SHA1CircularShift(bits,word) \                  (((word) << (bits)) | ((word) >> (32-(bits))))};

 

///////////////////////////////////////////////SHA1_Class.cpp#include "stdafx.h"#include "SHA1_Class.h"/* *  sha1_class.cpp * *  Description: *    This file implements the Secure Hashing Algorithm 1 as *    defined in FIPS PUB 180-1 published April 17, 1995. * *    The SHA-1, produces a 160-bit message digest for a given *    data stream.  It should take about 2**n steps to find a *    message with the same digest as a given message and *    2**(n/2) to find any two messages with the same digest, *    when n is the digest size in bits.  Therefore, this *    algorithm can serve as a means of providing a *    "fingerprint" for a message. * *  Portability Issues: *    SHA-1 is defined in terms of 32-bit "words".  This code *    uses <stdint.h> (included via "sha1.h" to define 32 and 8 *    bit unsigned integer types.  If your C compiler does not *    support 32 bit unsigned integers, this code is not *    appropriate. * *  Caveats: *    SHA-1 is designed to work with messages less than 2^64 bits *    long.  Although SHA-1 allows a message digest to be generated *    for messages of any number of bits less than 2^64, this *    implementation only works with messages with a length that is *    a multiple of the size of an 8-bit character. * *//* *  SHA1Reset * *  Description: *    This function will initialize the SHA1Context in preparation *    for computing a new SHA1 message digest. * *  Parameters: *    context: [in/out] *      The context to reset. * *  Returns: *    sha Error Code. * */int CSHA1_Class::SHA1Reset(){  memset(&m_SHA1Context, 0, sizeof(m_SHA1Context));  m_SHA1Context.Intermediate_Hash[0]   = 0x67452301;  m_SHA1Context.Intermediate_Hash[1]   = 0xEFCDAB89;  m_SHA1Context.Intermediate_Hash[2]   = 0x98BADCFE;  m_SHA1Context.Intermediate_Hash[3]   = 0x10325476;  m_SHA1Context.Intermediate_Hash[4]   = 0xC3D2E1F0;  m_SHA1Context.Computed   = 0;  m_SHA1Context.Corrupted  = 0;  return shaSuccess;}/* *  SHA1Result * *  Description: *    This function will return the 160-bit message digest into the *    Message_Digest array  provided by the caller. *    NOTE: The first octet of hash is stored in the 0th element, *      the last octet of hash in the 19th element. * *  Parameters: *    context: [in/out] *      The context to use to calculate the SHA-1 hash. *    Message_Digest: [out] *      Where the digest is returned. * *  Returns: *    sha Error Code. * */int CSHA1_Class::SHA1Result(uint8_t Message_Digest[SHA1HashSize]){  int i;  if ( !Message_Digest )  {    return shaNull;  }  if (m_SHA1Context.Corrupted)  {    return m_SHA1Context.Corrupted;  }  if (!m_SHA1Context.Computed)  {    SHA1PadMessage();    for(i=0; i<64; ++i)    {      /* message may be sensitive, clear it out */      m_SHA1Context.Message_Block[i] = 0;    }    m_SHA1Context.Length_Low = 0;  /* and clear length */    m_SHA1Context.Length_High = 0;    m_SHA1Context.Computed = 1;  }  for(i = 0; i < SHA1HashSize; ++i)  {    Message_Digest[i] = (uint8_t)( m_SHA1Context.Intermediate_Hash[i>>2]              >> 8 * ( 3 - ( i & 0x03 ) ) );  }  return shaSuccess;}/* *  SHA1Input * *  Description: *    This function accepts an array of octets as the next portion *    of the message. * *  Parameters: *    context: [in/out] *      The SHA context to update *    message_array: [in] *      An array of characters representing the next portion of *      the message. *    length: [in] *      The length of the message in message_array * *  Returns: *    sha Error Code. * */int CSHA1_Class::SHA1Input(          const uint8_t  *message_array,          unsigned     length){  if (!length)  {    return shaSuccess;  }  if (!message_array)  {    return shaNull;  }  if (m_SHA1Context.Computed)  {    m_SHA1Context.Corrupted = shaStateError;    return shaStateError;  }  if (m_SHA1Context.Corrupted)  {     return m_SHA1Context.Corrupted;  }  while(length-- && !m_SHA1Context.Corrupted)  {    m_SHA1Context.Message_Block[m_SHA1Context.Message_Block_Index++] =            (*message_array & 0xFF);    m_SHA1Context.Length_Low += 8;    if (m_SHA1Context.Length_Low == 0)    {      m_SHA1Context.Length_High++;      if (m_SHA1Context.Length_High == 0)      {        /* Message is too long */        m_SHA1Context.Corrupted = 1;      }    }    if (m_SHA1Context.Message_Block_Index == 64)    {      SHA1ProcessMessageBlock();    }    message_array++;  }  return shaSuccess;}int CSHA1_Class::FileCalculate(LPCTSTR lpszFile, LPPROC_INFO pProcInfo/*=NULL*/){  SHA1Reset();  if(pProcInfo)  {    memset(pProcInfo, 0, sizeof(PROC_INFO));  }  if(_tcslen( lpszFile ) > 0)  {    HANDLE hFile = CreateFile(      lpszFile,       GENERIC_READ ,// 如果要對應檔:此處必設定為唯讀(GENERIC_READ)或讀寫      0,    // 此設為開啟檔案的任何嘗試均將失敗      NULL,       OPEN_EXISTING,       FILE_ATTRIBUTE_NORMAL, //|FILE_FLAG_WRITE_THROUGH,【解1】      NULL);    if (hFile != INVALID_HANDLE_VALUE)// 檔案開啟失敗返回控制代碼為-1    {      HANDLE hFileMap = CreateFileMapping(        hFile, // 如果這值為INVALID_HANDLE_VALUE,是合法的,上步一定測試啊        NULL,   // 預設安全性        PAGE_READONLY,   //唯讀        0, // 2個32位元示1個64位元,最大檔案位元組數,        0,//dwFileSize, // 此為低位元組,也就是最主要的參數,如果為0,取檔案真實大小        NULL);      if (hFileMap != NULL)      {        LARGE_INTEGER dwFileSize = {0};        GetFileSizeEx(hFile, &dwFileSize);        if(pProcInfo)          pProcInfo->uLL_TotalSize = dwFileSize.QuadPart;        LARGE_INTEGER dwOffset = {0};        while(dwOffset.QuadPart < dwFileSize.QuadPart)        {          ULONGLONG partLen = dwFileSize.QuadPart - dwOffset.QuadPart;          UINT4 dwLen = (64 * 1024) * 1024; //64M 64K對齊          if(partLen < dwLen) dwLen = (UINT4)partLen;          LPVOID pvFile = MapViewOfFileEx( //pvFile就是得到的指標,用它來直接操作檔案            hFileMap,             FILE_MAP_READ ,    //讀            dwOffset.HighPart,     // 檔案指標頭位置 高位元組            dwOffset.LowPart, // 檔案指標頭位置 低位元組 必為分配粒度的整倍數,windows的粒度為64K            dwLen,   // 要映射的檔案尾,如果為0,則從指標頭到真實檔案尾            NULL);          if (pvFile != NULL)          {              SHA1Input((unsigned char *)pvFile, dwLen);//calc            UnmapViewOfFile(pvFile); // 釋放記憶體對應檔的頭指標          }          else          {            TRACE( _T("MapViewOfFile Error=%d\n"), GetLastError());          }          dwOffset.QuadPart += dwLen;          if(pProcInfo)          {            pProcInfo->uLL_ProcessedSize = dwOffset.QuadPart;            pProcInfo->f_ProcPercent =               (double)pProcInfo->uLL_ProcessedSize/(double)pProcInfo->uLL_TotalSize * 100.0;          }        }         CloseHandle(hFileMap);   // 記憶體對應檔控制代碼               }      else      {        TRACE( _T("CreateFileMapping Error=%d\n"), GetLastError());      }      CloseHandle(hFile);    // 關閉檔案    }    else    {      TRACE( _T("CreateFile Error=%d\n"), GetLastError());    }  }  BYTE Message_Digest[SHA1HashSize];  SHA1Result( Message_Digest );  TCHAR m_sHash[2*SHA1HashSize + 1] = {0};  for(int i=0; i<SHA1HashSize; i++)  {    TCHAR buff[16];    _stprintf_s(buff, _T("%02X"), Message_Digest[i]);    _tcscat_s(m_sHash, buff);  }  if(pProcInfo)  {    _tcscpy_s(pProcInfo->m_rawHash, m_sHash);    pProcInfo->bDone = TRUE;  }  return shaSuccess;}/* *  SHA1ProcessMessageBlock * *  Description: *    This function will process the next 512 bits of the message *    stored in the Message_Block array. * *  Parameters: *    None. * *  Returns: *    Nothing. * *  Comments: *    Many of the variable names in this code, especially the *    single character names, were used because those were the *    names used in the publication. * * */void CSHA1_Class::SHA1ProcessMessageBlock(){  const uint32_t K[] =  {     /* Constants defined in SHA-1   */              0x5A827999,              0x6ED9EBA1,              0x8F1BBCDC,              0xCA62C1D6              };  int       t;         /* Loop counter        */  uint32_t    temp;        /* Temporary word value    */  uint32_t    W[80];       /* Word sequence         */  uint32_t    A, B, C, D, E;   /* Word buffers        */  /*   *  Initialize the first 16 words in the array W   */  for(t = 0; t < 16; t++)  {    W[t] = m_SHA1Context.Message_Block[t * 4] << 24;    W[t] |= m_SHA1Context.Message_Block[t * 4 + 1] << 16;    W[t] |= m_SHA1Context.Message_Block[t * 4 + 2] << 8;    W[t] |= m_SHA1Context.Message_Block[t * 4 + 3];  }  for(t = 16; t < 80; t++)  {    W[t] = SHA1CircularShift(1,W[t-3] ^ W[t-8] ^ W[t-14] ^ W[t-16]);  }  A = m_SHA1Context.Intermediate_Hash[0];  B = m_SHA1Context.Intermediate_Hash[1];  C = m_SHA1Context.Intermediate_Hash[2];  D = m_SHA1Context.Intermediate_Hash[3];  E = m_SHA1Context.Intermediate_Hash[4];  for(t = 0; t < 20; t++)  {    temp =  SHA1CircularShift(5,A) +        ((B & C) | ((~B) & D)) + E + W[t] + K[0];    E = D;    D = C;    C = SHA1CircularShift(30,B);    B = A;    A = temp;  }  for(t = 20; t < 40; t++)  {    temp = SHA1CircularShift(5,A) + (B ^ C ^ D) + E + W[t] + K[1];    E = D;    D = C;    C = SHA1CircularShift(30,B);    B = A;    A = temp;  }  for(t = 40; t < 60; t++)  {    temp = SHA1CircularShift(5,A) +         ((B & C) | (B & D) | (C & D)) + E + W[t] + K[2];    E = D;    D = C;    C = SHA1CircularShift(30,B);    B = A;    A = temp;  }  for(t = 60; t < 80; t++)  {    temp = SHA1CircularShift(5,A) + (B ^ C ^ D) + E + W[t] + K[3];    E = D;    D = C;    C = SHA1CircularShift(30,B);    B = A;    A = temp;  }  m_SHA1Context.Intermediate_Hash[0] += A;  m_SHA1Context.Intermediate_Hash[1] += B;  m_SHA1Context.Intermediate_Hash[2] += C;  m_SHA1Context.Intermediate_Hash[3] += D;  m_SHA1Context.Intermediate_Hash[4] += E;  m_SHA1Context.Message_Block_Index = 0;}/* *  SHA1PadMessage * *  Description: *    According to the standard, the message must be padded to an even *    512 bits.  The first padding bit must be a '1'.  The last 64 *    bits represent the length of the original message.  All bits in *    between should be 0.  This function will pad the message *    according to those rules by filling the Message_Block array *    accordingly.  It will also call the ProcessMessageBlock function *    provided appropriately.  When it returns, it can be assumed that *    the message digest has been computed. * *  Parameters: *    context: [in/out] *      The context to pad *    ProcessMessageBlock: [in] *      The appropriate SHA*ProcessMessageBlock function *  Returns: *    Nothing. * */void CSHA1_Class::SHA1PadMessage(){  /*   *  Check to see if the current message block is too small to hold   *  the initial padding bits and length.  If so, we will pad the   *  block, process it, and then continue padding into a second   *  block.   */  if (m_SHA1Context.Message_Block_Index > 55)  {    m_SHA1Context.Message_Block[m_SHA1Context.Message_Block_Index++] = 0x80;    while(m_SHA1Context.Message_Block_Index < 64)    {      m_SHA1Context.Message_Block[m_SHA1Context.Message_Block_Index++] = 0;    }    SHA1ProcessMessageBlock();    while(m_SHA1Context.Message_Block_Index < 56)    {      m_SHA1Context.Message_Block[m_SHA1Context.Message_Block_Index++] = 0;    }  }  else  {    m_SHA1Context.Message_Block[m_SHA1Context.Message_Block_Index++] = 0x80;    while(m_SHA1Context.Message_Block_Index < 56)    {      m_SHA1Context.Message_Block[m_SHA1Context.Message_Block_Index++] = 0;    }  }  /*   *  Store the message length as the last 8 octets   */  m_SHA1Context.Message_Block[56] = (uint8_t)(m_SHA1Context.Length_High >> 24);  m_SHA1Context.Message_Block[57] = (uint8_t)(m_SHA1Context.Length_High >> 16);  m_SHA1Context.Message_Block[58] = (uint8_t)(m_SHA1Context.Length_High >> 8);  m_SHA1Context.Message_Block[59] = (uint8_t)(m_SHA1Context.Length_High);  m_SHA1Context.Message_Block[60] = (uint8_t)(m_SHA1Context.Length_Low >> 24);  m_SHA1Context.Message_Block[61] = (uint8_t)(m_SHA1Context.Length_Low >> 16);  m_SHA1Context.Message_Block[62] = (uint8_t)(m_SHA1Context.Length_Low >> 8);  m_SHA1Context.Message_Block[63] = (uint8_t)(m_SHA1Context.Length_Low);  SHA1ProcessMessageBlock();}

 

//應用舉例void CSHA1_CalculatorDlg::OnBnClickedStringCal(){  // TODO: 在此添加控制項通知處理常式代碼  CHAR szInput[2049];  GetDlgItemTextA(GetSafeHwnd(), IDC_STRING_EDIT, szInput, 2048);  BYTE Message_Digest[SHA1HashSize];  CSHA1_Class m_SHA1;  m_SHA1.SHA1Reset();  m_SHA1.SHA1Input((const unsigned char*)szInput, strlen(szInput));  m_SHA1.SHA1Result(Message_Digest);  CString itemStr;  for(int i=0; i<SHA1HashSize; i++)  {    TCHAR buff[16];    _stprintf_s(buff, _T("%02X"), Message_Digest[i]);    itemStr += buff;  }  SetDlgItemText(IDC_STRING_RESULT, itemStr);}

 

 

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.