【问题标题】:How can I pad my md5 message with c/c++如何用 c/c++ 填充我的 md5 消息
【发布时间】:2012-09-07 02:07:29
【问题描述】:

我正在用 C++ 编写一个程序来执行 md5 校验和。我这样做主要是因为我想我会学到很多关于 c++、校验和、OOP 以及我遇到的任何其他东西的不同知识。

我在校验和遇到问题,我认为问题出在执行消息填充的函数 padbuff 中。

#include "HashMD5.h"

int leftrotate(int x, int y);
void padbuff(uchar * buffer);

//HashMD5 constructor
HashMD5::HashMD5()
{
  Type = "md5";
  Hash = "";
}

HashMD5::HashMD5(const char * hashfile)
{
  Type = "md5";
  std::ifstream filestr;
  filestr.open(hashfile, std::fstream::in | std::fstream::binary);
  if(filestr.fail())
  {
    std::cerr << "File " << hashfile << " was not opened.\n";
    std::cerr << "Open failed with error ";
  }
}

std::string HashMD5::GetType()
{
  return this->Type;
}

std::string HashMD5::GetHash()
{
  return this->Hash;
}

bool HashMD5::is_open()
{
  return !((this->filestr).fail());
}

void HashMD5::CalcHash(unsigned int * hash)
{
  unsigned int *r, *k;
  int r2[4] = {0, 4, 9, 15};
  int r3[4] = {0, 7, 12, 19};
  int r4[4] = {0, 4, 9, 15};
  uchar * buffer;
  int bufLength = (2<<20)*8;
  int f,g,a,b,c,d, temp;
  int *head;
  uint32_t maxint = 1<<31;

  //Initialized states
  unsigned int h[4]{ 0x67452301, 0xefcdab89, 0x98badcfe, 0x10325476};

  r = new unsigned int[64];
  k = new unsigned int[64];
  buffer = new uchar[bufLength];
  if(r==NULL || k==NULL || buffer==NULL)
  {
    std::cerr << "One of the dyn alloc failed\n";
  }

  // r specifies the per-round shift amounts
  for(int i = 0; i<16; i++)
    r[i] = 7 + (5 * ((i)%4) );

  for(int i = 16; i < 32; i++)
    r[i] = 5 + r2[i%4];

  for(int i = 32; i< 48; i++)
    r[i] = 4 + r3[i%4];

  for(int i = 48; i < 63; i++)
    r[i] = 6 + r4[i%4];

  for(int i = 0; i < 63; i++)
  {
    k[i] = floor( fabs( sin(i + 1)) * maxint);
  }

  while(!(this->filestr).eof())
  {
    //Read in 512 bits
    (this->filestr).read((char *)buffer, bufLength-512);

    padbuff(buffer);

    //The 512 bits are now 16 32-bit ints
    head = (int *)buffer;

    for(int i = 0; i < 64; i++)
    {
      if(i >=0 && i <=15)
      {
        f = (b & c) | (~b & d);
        g = i;
      }
      else if(i >= 16 && i <=31)
      {
        f = (d & b) | (~d & b);
        g = (5*i +1) % 16;
      }
      else if(i >=32 && i<=47)
      {
        f = b ^ c ^ d;
        g = (3*i + 5 ) % 16;
      }
      else
      {
        f = c ^ (b | ~d);
        g = (7*i) % 16;
      }

      temp = d;
      d = c;
      c = b;
      b = b + leftrotate((a + f + k[i] + head[g]), r[i]);
      a = temp;

    }

    h[0] +=a;
    h[1] +=b;
    h[2] +=c;
    h[3] +=d;         
  }


  delete[] r;
  delete[] k;

  hash = h;
}

int leftrotate(int x, int y)
{
   return(x<<y) | (x >> (32 -y));
}

void padbuff(uchar* buffer)
{
   int lack;
   int length = strlen((char *)buffer);
   uint64_t mes_size = length % UINT64_MAX;
   if((lack = (112 - (length % 128) ))>0)
   {
     *(buffer + length) = ('\0'+1 ) << 3;
     memset((buffer + length + 1),0x0,lack);  
     memcpy((void*)(buffer+112),(void *)&mes_size, 64);
   }

}

在我的测试程序中,我在一条空消息上运行它。因此,padbuff 中的length 为0。然后当我执行*(buffer + length) = ('\0'+1 ) &lt;&lt; 3; 时,我试图用1 填充消息。在Netbeans 调试器中,我将buffer 转换为uint64_t,它显示buffer=8。我试图将1 bit 放在缓冲区最重要的位置,所以我的演员应该是UINT64_MAX。不是,所以我对填充代码的工作方式感到困惑。有人可以告诉我我在做什么以及我应该在 padbuff 中做什么吗?谢谢,对于这个冗长的问题,我深表歉意。

为了清楚填充应该做什么,这里是来自维基百科的填充摘录: 对消息进行填充,使其长度可以被 512 整除。填充的工作方式如下:首先将单个位 1 附加到消息的末尾。后面跟着尽可能多的零,使消息的长度最多比 512 的倍数少 64 位。剩余的位用 64 位填充,表示原始消息的长度,模 264。

我主要是为padbuff寻求帮助,但由于我正在尝试学习所有cmet,因此受到赞赏。

【问题讨论】:

    标签: c++ c md5


    【解决方案1】:

    第一个问题是你做了什么:

    1. length % UINT64_MAX 完全没有意义,因为长度以字节为单位,而 MAX 是您可以存储在 UINT64 中的值。
    2. 您认为将 1 位放在最高有效位会给出最大值。实际上,您需要在所有位中输入 1 才能得到它。
    3. 您将 1 移动 3。它只是字节长度的一半。
    4. buffer 指向的字节在little endian 中是最不重要的。 (我假设你有小端,因为调试器显示 8)。

    第二个问题应该如何工作。 我不知道 padbuff 到底应该做什么,但如果你想填充并获得 UINT64_MAX,你需要这样的东西:

    int length = strlen((char *)buffer);
    int len_of_padding = sizeof(uint64_t) - length % sizeof(uint64_t);
    if(len_of_padding > 0)
    {
      memset((void*)(buffer + length), 0xFF, len_of_padding);
    }
    

    您使用了两个 uint64 值的长度。可能你想将下一个归零:

    uint64_t *after = (uint64_t*)(buffer + length + len_of_padding);
    *after = 0;
    

    【讨论】:

      猜你喜欢
      • 2015-04-25
      • 1970-01-01
      • 2014-10-22
      • 2014-03-25
      • 1970-01-01
      • 2022-07-20
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多