Sha1算法实现流程(基于OpenSSL源码)

SHA1是一种160位的密码散列函数,用于生成消息的唯一摘要。文章详细描述了其工作原理,包括消息的补位规则、长度补充、常量和函数的使用,以及计算消息摘要的步骤。此外,还提供了SHA1算法的宏定义和函数声明,展示了一个SHA1实现的框架。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

1. SHA1算法简介

SHA-1(Secure Hash Algorithm 1)是一种密码散列函数,美国国家安全局设计,并由美国国家标准技术研究所(NIST)发布为联邦数据处理标准(FIPS)。SHA-1可以生成一个被称为消息摘要的160位(20字节)散列值,散列值通常的呈现形式为40个十六进制数。
SHA1有如下特性:

  • 不可以从消息摘要中复原信息;
  • 两个不同的消息不会产生同样的消息摘要。

注: 2017年2月23日,Google公司公告宣称他们与CWI Amsterdam合作共同创建了两个有着相同的SHA-1值但内容不同的PDF文件,这代表SHA-1算法已被正式攻破。

2. 术语和概念

位(bit),字节(byte),双字(dword)

SHA1始终把消息当成一个位字符串来处理。正常情况下,一个“双字”是32位,而一个“字节”是8位。
比如,字符串“abc”可以被转换成一个位字符串:01100001 01100010 01100011。
它也可以被表示成16进制字符串: 0x616263。

3. SHA1算法描述

由于SHA1算法只接受位作为输入。因此在SHA1算法中,我们必须把原始消息(字符串,文件等)转换成位字符串。
假设我们对字符串“sha1”产生消息摘要。首先,我们将它转换成位字符串如下:

01110011 01110011 01100001 00110001

这个位字符串的长度为len = 4 * 8 = 32。下面我们需要5个步骤来计算SHA1。

定义如下变量:

byte *data; // 原始数据
dowrd len_lower; // 原始数据长度低32位
dowrd len_higher; // 原始数据长度高32位
qword len = len_lower | len_higher << 32;
dword n; // 补位后数据长度
3.1 补位

SHA1按照64byte间隔进行数据分批处理,且需要填充标志位和数据长度,因此消息必须进行补位。
补位规则:

根据Sha1,原始数据末尾需要先追加一个字节填充(0x80);
若此时数据长度不满足 len % 512 = 448, 填充(0x00)至满足条件。

以“sha1”为例,补位是这样进行的:

原始信息: 01110011 01110011 01100001 00110001
补位第一步:01110011 01110011 01100001 00110001 
           1 //补充1     
补位第二步:01110011 01110011 01100001 00110001 
           10000000 00000000 ......  //补充415个00

转换为16进制如下显示:

73686131 80000000 00000000 00000000
00000000 00000000 00000000 00000000
00000000 00000000 00000000 00000000
00000000 00000000
3.2 补长度

将len补到已经进行了补位操作的消息后面。
通常用一个64位的数据来表示原始消息的长度。
在补长度以后,整个消息如下显示:

73686131 80000000 00000000 00000000
00000000 00000000 00000000 00000000
00000000 00000000 00000000 00000000
00000000 00000000 00000000 00000020
3.3 使用的常量

常量K(0), K(1), … , K(79),用于不同轮次的计算。

/* const hash value for step */
#define K_00_19 0x5a827999UL  // step:00~19
#define K_20_39 0x6ed9eba1UL  // step:20~39
#define K_40_59 0x8f1bbcdcUL  // step:40~59
#define K_60_79 0xca62c1d6UL  // step:60~79
3.4 需要使用的函数

与常量对应,用于不同轮次输出双字的预定函数。
f t ( B , C , D ) = { ( ( c   ˆ   d ) &   b ) ˆ ( d ) ( 0 < = t < = 19 ) ( b   ˆ   c   ˆ   d ) ( 20 < = t < = 39 ) ( ( b   &   c ) ∣ ( ( b   ∣   c ) & d ) ) ( 40 < = t < = 59 ) ( b   ˆ   c   ˆ   d ) ( 60 < = t < = 79 ) f_t(B,C,D) = {\begin{cases} ((c \medspace\^{\enspace}\medspace d) \&\medspace b) \^{\enspace}(d) & ( 0 <= t <= 19) \\ (b \medspace\^{\enspace}\medspace c \medspace\^{\enspace}\medspace d) & (20 <= t <= 39) \\ ((b \medspace\&\medspace c) | ((b \medspace|\medspace c) \& d)) & ( 40 <= t <= 59) \\ (b \medspace\^{\enspace}\medspace c \medspace\^{\enspace}\medspace d) & ( 60 <= t <= 79) \\ \end{cases}} ft(B,C,D)= ((cˆd)&b)ˆ(d)(bˆcˆd)((b&c)((bc)&d))(bˆcˆd)(0<=t<=19)(20<=t<=39)(40<=t<=59)(60<=t<=79)

3.5 计算消息摘要

必须使用进行了补位和补长度后的消息来计算消息摘要。
计算需要两个160位的缓冲区,每个都由5个32位的字组成;还需要一个512位的数据缓冲区。
第一个5个字的缓冲区被标识为A,B,C,D,E。
第二个5个字的缓冲区被标识为H0, H1, H2, H3, H4
16个双字的缓冲区被标识为W0, W1,…, W15
另外还需要一个双字的TEMP缓冲区。

为了产生消息摘要,对数据块按照512位分割为M1, M2,…, Mn;
对每个数据块Mi 进行包含80个步骤的计算。

在处理每个数据块之前,初始化缓冲区

#define INIT_DATA_h0 0x67452301UL
#define INIT_DATA_h1 0xefcdab89UL
#define INIT_DATA_h2 0x98badcfeUL
#define INIT_DATA_h3 0x10325476UL
#define INIT_DATA_h4 0xc3d2e1f0UL

  ctx_.h0 = INIT_DATA_h0;
  ctx_.h1 = INIT_DATA_h1;
  ctx_.h2 = INIT_DATA_h2;
  ctx_.h3 = INIT_DATA_h3;
  ctx_.h4 = INIT_DATA_h4;

现在开始处理M1, M2, … , Mn。为了处理 Mi,需要进行下面的步骤
(1). 将 Mi 分成 16 个字 W0, W1, … , W15
(2). 初始化

  A = ctx_.h0;
  B = ctx_.h1;
  C = ctx_.h2;
  D = ctx_.h3;
  E = ctx_.h4;

(3). 对于 t = 16 到 79 令

Wt = S^1(W(t-3) ^ W(t-8) ^ W(t-14) ^ W(t-16))

(4) 对于 t = 0 到 79,执行下面的循环

        T = S^5(A) + F((B), (C), (D)) + (E) + W(t) + K(t);
        E = D;
        D = C;
        C = S^30(B);
        B = A;
        A = T;

(5). Let H0 = H0 + A, H1 = H1 + B, H2 = H2 + C, H3 = H3 + D, H4 = H4 + E.

    ctx_.h0 = (ctx_.h0 + A) & 0xffffffffL;
    ctx_.h1 = (ctx_.h1 + B) & 0xffffffffL;
    ctx_.h2 = (ctx_.h2 + C) & 0xffffffffL;
    ctx_.h3 = (ctx_.h3 + D) & 0xffffffffL;
    ctx_.h4 = (ctx_.h4 + E) & 0xffffffffL;

(6). 在处理完所有的 Mi后,将消息摘要以大端序写入缓冲区

4. 参考实现

4.1 宏
#define SHA_LBLOCK 16
#define SHA_CBLOCK (SHA_LBLOCK * 4)
#define SHA_LAST_BLOCK (SHA_CBLOCK - 8)
#define SHA_DIGEST_LENGTH 20

#define X(i) XX##i

/* default hash value */
#define INIT_DATA_h0 0x67452301UL
#define INIT_DATA_h1 0xefcdab89UL
#define INIT_DATA_h2 0x98badcfeUL
#define INIT_DATA_h3 0x10325476UL
#define INIT_DATA_h4 0xc3d2e1f0UL

/* const hash value for step */
#define K_00_19 0x5a827999UL  // step:00~19
#define K_20_39 0x6ed9eba1UL  // step:20~39
#define K_40_59 0x8f1bbcdcUL  // step:40~59
#define K_60_79 0xca62c1d6UL  // step:60~79

/* hash function for step */
#define F_00_19(b, c, d) ((((c) ^ (d)) & (b)) ^ (d))          // step:00~19
#define F_20_39(b, c, d) ((b) ^ (c) ^ (d))                    // step:20~39
#define F_40_59(b, c, d) (((b) & (c)) | (((b) | (c)) & (d)))  // step:40~59
#define F_60_79(b, c, d) F_20_39(b, c, d)                     // step:60~79

/* swap left and right by n */
#define ROTATE(a, n) (((a) << (n)) | (((a)&0xffffffff) >> (32 - (n))))

/*
 * SHA1:
 * W(t) = S^1(W(t-3) XOR W(t-8) XOR W(t-14) XOR W(t-16)).
 */
#define Xupdate(a, ix, ia, ib, ic, id) \
  ((a) = (ia ^ ib ^ ic ^ id), ix = (a) = ROTATE((a), 1))

#define BODY_00_15(i, a, b, c, d, e, f, xi)                           \
  (f) = ROTATE((a), 5) + F_00_19((b), (c), (d)) + (e) + xi + K_00_19; \
  (b) = ROTATE((b), 30);

#define BODY_16_19(i, a, b, c, d, e, f, xi, xa, xb, xc, xd)       \
  Xupdate(f, xi, xa, xb, xc, xd);                                 \
  (f) += (e) + K_00_19 + ROTATE((a), 5) + F_00_19((b), (c), (d)); \
  (b) = ROTATE((b), 30);

#define BODY_20_31(i, a, b, c, d, e, f, xi, xa, xb, xc, xd)       \
  Xupdate(f, xi, xa, xb, xc, xd);                                 \
  (f) += (e) + K_20_39 + ROTATE((a), 5) + F_20_39((b), (c), (d)); \
  (b) = ROTATE((b), 30);

#define BODY_32_39(i, a, b, c, d, e, f, xa, xb, xc, xd)           \
  Xupdate(f, xa, xa, xb, xc, xd);                                 \
  (f) += (e) + K_20_39 + ROTATE((a), 5) + F_20_39((b), (c), (d)); \
  (b) = ROTATE((b), 30);

#define BODY_40_59(i, a, b, c, d, e, f, xa, xb, xc, xd)           \
  Xupdate(f, xa, xa, xb, xc, xd);                                 \
  (f) += (e) + K_40_59 + ROTATE((a), 5) + F_40_59((b), (c), (d)); \
  (b) = ROTATE((b), 30);

#define BODY_60_79(i, a, b, c, d, e, f, xa, xb, xc, xd)               \
  Xupdate(f, xa, xa, xb, xc, xd);                                     \
  (f) = xa + (e) + K_60_79 + ROTATE((a), 5) + F_60_79((b), (c), (d)); \
  (b) = ROTATE((b), 30);

/* swap little-endian to big-endian, assign to l */
/* address increase dword size  */
#define HOST_c2l(c, l)                       \
  (l = (((unsigned long)(*((c)++))) << 24),  \
   l |= (((unsigned long)(*((c)++))) << 16), \
   l |= (((unsigned long)(*((c)++))) << 8),  \
   l |= (((unsigned long)(*((c)++)))))

/* swap little-endian to big-endian, assign to c */
/* address increase dword size  */
#define HOST_l2c(l, c)                             \
  (*((c)++) = (unsigned char)(((l) >> 24) & 0xff), \
   *((c)++) = (unsigned char)(((l) >> 16) & 0xff), \
   *((c)++) = (unsigned char)(((l) >> 8) & 0xff),  \
   *((c)++) = (unsigned char)(((l)) & 0xff), l)
4.2 函数声明
typedef unsigned char byte;
typedef unsigned int dword;

struct SHA_CTX {
  // default hash value, and storage the final hashed value
  dword h0, h1, h2, h3, h4;
  // num_lower storage the lower 32 bits of data's length, by bits.
  // num_higher storage the higher 32 bits of data's length, by bits.
  dword num_lower, num_higher;
  // buff storage origin data, complement data, length aligned data
  dword data[SHA_LBLOCK];
  // record the length been used in buff
  dword num_used;
};

class Sha1Context : public IDigestInterface {
 public:
  virtual dword Context_Init();
  virtual dword Context_Update(const byte *data, const size_t len);
  virtual dword Context_Final(byte *md);
  // when sha only once, use this
  virtual byte *Digest(const byte *data, const size_t len, byte *md);

 private:
  void SHA1_Block_Data_Order(const void *p, size_t num_block);

 private:
  SHA_CTX ctx_;
};
4.2 实现
dword Sha1Context::Context_Update(const byte *data, const size_t len) {
  dword lower = 0;
  dword offset = 0;
  dword num_block = 0;
  size_t length = 0;
  byte *p = nullptr;
  if (len == 0) {
    return 1;
  }

  // convert length by byte to length by bit
  lower = (ctx_.num_lower + (((dword)len) << 3)) & 0xffffffffUL;
  // when happen overflow
  if (lower < ctx_.num_lower) {
    ++ctx_.num_higher;
  }

  // update length of data
  ctx_.num_higher += (dword)(len >> 29);
  ctx_.num_lower = lower;

  offset = ctx_.num_used;
  length = len;
  // when last time's data remains
  if (0 < offset) {
    p = (byte *)ctx_.data;
    // complement buff by move data
    if (length >= SHA_CBLOCK || length + offset >= SHA_CBLOCK) {
      memcpy(p + offset, data, SHA_CBLOCK - offset);
      SHA1_Block_Data_Order(p, 1);
      offset = SHA_CBLOCK - offset;
      data += offset;
      length -= offset;
      ctx_.num_used = 0;
      memset(p, 0, SHA_CBLOCK);
    } else {
      memcpy(p + offset, data, length);
      ctx_.num_used += (dword)length;
      return 1;
    }
  }

  num_block = length / SHA_CBLOCK;
  // when length bigger than SHA_CBLOCK
  if (num_block > 0) {
    SHA1_Block_Data_Order(data, num_block);
    offset = num_block * SHA_CBLOCK;
    data += offset;
    length -= offset;
  }

  // when remains length smaller than SHA_CBLOCK
  if (length != 0) {
    p = (byte *)ctx_.data;
    memcpy(p, data, length);
    ctx_.num_used = (dword)length;
  }
  return 1;
}

dword Sha1Context::Context_Final(byte *md) {
  byte *p = (byte *)ctx_.data;
  size_t n = ctx_.num_used;

  /* complement 1000 0000 */
  p[n] = 0x80;
  n++;

  /* if n > 56byte(448bit) */
  if (n > (SHA_CBLOCK - 8)) {
    memset(p + n, 0, SHA_CBLOCK - n);
    n = 0;
    SHA1_Block_Data_Order(p, 1);
  }
  /* complement 0000 0000 .... .... */
  memset(p + n, 0, SHA_CBLOCK - 8 - n);

  /* append data size to end */
  p += SHA_CBLOCK - 8;
  (void)HOST_l2c(ctx_.num_higher, p);
  (void)HOST_l2c(ctx_.num_lower, p);

  /* the end digest */
  p -= SHA_CBLOCK;
  SHA1_Block_Data_Order(p, 1);

  /* clean */
  ctx_.num_used = 0;
  memset(p, 0x00, SHA_CBLOCK);

  /* genarate digest messgae */
  HASH_MAKE_STRING(&ctx_, md);

  return 1;
}

byte *Sha1Context::Digest(const byte *data, const size_t len, byte *md) {
  static byte m[SHA_DIGEST_LENGTH];
  if (md == nullptr) {
    md = m;
  }
  Context_Init();
  Context_Update(data, len);
  Context_Final(md);
  return md;
}

void Sha1Context::SHA1_Block_Data_Order(const void *p, size_t num_block) {
  const byte *data = (const byte *)p;
  register dword A, B, C, D, E, T, l;
  dword XX0, XX1, XX2, XX3, XX4, XX5, XX6, XX7, XX8, XX9, XX10, XX11, XX12,
      XX13, XX14, XX15;

  /*
   * SHA1 Document:
   * The words of the first 5-word buffer are labeled A,B,C,D,E.
   * The words of the second 5-word buffer are labeled H0, H1, H2, H3, H4.
   * Let A = H0, B = H1, C = H2, D = H3, E = H4.
   */
  A = ctx_.h0;
  B = ctx_.h1;
  C = ctx_.h2;
  D = ctx_.h3;
  E = ctx_.h4;

  for (;;) {
    // for check endianness
    const union {
      long one;
      char little;
    } is_endian = {1};

    /*
     * SHA1 Document:
     * The words of the 80-word sequence are labeled W(0), W(1),..., W(79).
     * Divide M(i) into 16 words W(0), W(1), ... , W(15), where W(0) is the
     left-most word.
     * For t = 0 to 15 do:
        T = S^5(A) + F((B), (C), (D)) + (E) + W(t) + K(t);
        E = D;
        D = C;
        C = S^30(B);
        B = A;
        A = T;

     * fact do:
        T = S^5(A) + F((B), (C), (D)) + (E) + W(t) + K(t);
        B = S^30(B);
     * and change the significance when next call
    */
    if (!is_endian.little && sizeof(dword) == 4 && ((size_t)p % 4) == 0) {
      const dword *W = (const dword *)data;

      X(0) = W[0];
      BODY_00_15(0, A, B, C, D, E, T, X(0));
      X(1) = W[1];
      BODY_00_15(1, T, A, B, C, D, E, X(1));
      X(2) = W[2];
      BODY_00_15(2, E, T, A, B, C, D, X(2));
      X(3) = W[3];
      BODY_00_15(3, D, E, T, A, B, C, X(3));
      X(4) = W[4];
      BODY_00_15(4, C, D, E, T, A, B, X(4));
      X(5) = W[5];
      BODY_00_15(5, B, C, D, E, T, A, X(5));
      X(6) = W[6];
      BODY_00_15(6, A, B, C, D, E, T, X(6));
      X(7) = W[7];
      BODY_00_15(7, T, A, B, C, D, E, X(7));
      X(8) = W[8];
      BODY_00_15(8, E, T, A, B, C, D, X(8));
      X(9) = W[9];
      BODY_00_15(9, D, E, T, A, B, C, X(9));
      X(10) = W[10];
      BODY_00_15(10, C, D, E, T, A, B, X(10));
      X(11) = W[11];
      BODY_00_15(11, B, C, D, E, T, A, X(11));
      X(12) = W[12];
      BODY_00_15(12, A, B, C, D, E, T, X(12));
      X(13) = W[13];
      BODY_00_15(13, T, A, B, C, D, E, X(13));
      X(14) = W[14];
      BODY_00_15(14, E, T, A, B, C, D, X(14));
      X(15) = W[15];
      BODY_00_15(15, D, E, T, A, B, C, X(15));

      data += SHA_CBLOCK;
    } else {
      (void)HOST_c2l(data, l);
      X(0) = l;
      (void)HOST_c2l(data, l);
      X(1) = l;
      BODY_00_15(0, A, B, C, D, E, T, X(0));
      (void)HOST_c2l(data, l);
      X(2) = l;
      BODY_00_15(1, T, A, B, C, D, E, X(1));
      (void)HOST_c2l(data, l);
      X(3) = l;
      BODY_00_15(2, E, T, A, B, C, D, X(2));
      (void)HOST_c2l(data, l);
      X(4) = l;
      BODY_00_15(3, D, E, T, A, B, C, X(3));
      (void)HOST_c2l(data, l);
      X(5) = l;
      BODY_00_15(4, C, D, E, T, A, B, X(4));
      (void)HOST_c2l(data, l);
      X(6) = l;
      BODY_00_15(5, B, C, D, E, T, A, X(5));
      (void)HOST_c2l(data, l);
      X(7) = l;
      BODY_00_15(6, A, B, C, D, E, T, X(6));
      (void)HOST_c2l(data, l);
      X(8) = l;
      BODY_00_15(7, T, A, B, C, D, E, X(7));
      (void)HOST_c2l(data, l);
      X(9) = l;
      BODY_00_15(8, E, T, A, B, C, D, X(8));
      (void)HOST_c2l(data, l);
      X(10) = l;
      BODY_00_15(9, D, E, T, A, B, C, X(9));
      (void)HOST_c2l(data, l);
      X(11) = l;
      BODY_00_15(10, C, D, E, T, A, B, X(10));
      (void)HOST_c2l(data, l);
      X(12) = l;
      BODY_00_15(11, B, C, D, E, T, A, X(11));
      (void)HOST_c2l(data, l);
      X(13) = l;
      BODY_00_15(12, A, B, C, D, E, T, X(12));
      (void)HOST_c2l(data, l);
      X(14) = l;
      BODY_00_15(13, T, A, B, C, D, E, X(13));
      (void)HOST_c2l(data, l);
      X(15) = l;
      BODY_00_15(14, E, T, A, B, C, D, X(14));
      BODY_00_15(15, D, E, T, A, B, C, X(15));
    }

    /*
     * SHA1 Document:
     * For t = 16 to 79 let:
         W(t) = S^1(W(t-3) XOR W(t-8) XOR W(t-14) XOR W(t-16)).
         T = S^5(A) + F((B), (C), (D)) + (E) + W(t) + K(t);
         E = D;
         D = C;
         C = S^30(B);
         B = A;
         A = T;
     * description
         when step 0-15 end, register val as follows:
         { C = T; B = E; A = D; T = C; E = B; D = A; }
         so next call as follows:
         (A,C,B,D,E,...) = {C,D,E,T,A,...}
    */
    BODY_16_19(16, C, D, E, T, A, B, X(0), X(0), X(2), X(8), X(13));
    BODY_16_19(17, B, C, D, E, T, A, X(1), X(1), X(3), X(9), X(14));
    BODY_16_19(18, A, B, C, D, E, T, X(2), X(2), X(4), X(10), X(15));
    BODY_16_19(19, T, A, B, C, D, E, X(3), X(3), X(5), X(11), X(0));

    BODY_20_31(20, E, T, A, B, C, D, X(4), X(4), X(6), X(12), X(1));
    BODY_20_31(21, D, E, T, A, B, C, X(5), X(5), X(7), X(13), X(2));
    BODY_20_31(22, C, D, E, T, A, B, X(6), X(6), X(8), X(14), X(3));
    BODY_20_31(23, B, C, D, E, T, A, X(7), X(7), X(9), X(15), X(4));
    BODY_20_31(24, A, B, C, D, E, T, X(8), X(8), X(10), X(0), X(5));
    BODY_20_31(25, T, A, B, C, D, E, X(9), X(9), X(11), X(1), X(6));
    BODY_20_31(26, E, T, A, B, C, D, X(10), X(10), X(12), X(2), X(7));
    BODY_20_31(27, D, E, T, A, B, C, X(11), X(11), X(13), X(3), X(8));
    BODY_20_31(28, C, D, E, T, A, B, X(12), X(12), X(14), X(4), X(9));
    BODY_20_31(29, B, C, D, E, T, A, X(13), X(13), X(15), X(5), X(10));
    BODY_20_31(30, A, B, C, D, E, T, X(14), X(14), X(0), X(6), X(11));
    BODY_20_31(31, T, A, B, C, D, E, X(15), X(15), X(1), X(7), X(12));

    BODY_32_39(32, E, T, A, B, C, D, X(0), X(2), X(8), X(13));
    BODY_32_39(33, D, E, T, A, B, C, X(1), X(3), X(9), X(14));
    BODY_32_39(34, C, D, E, T, A, B, X(2), X(4), X(10), X(15));
    BODY_32_39(35, B, C, D, E, T, A, X(3), X(5), X(11), X(0));
    BODY_32_39(36, A, B, C, D, E, T, X(4), X(6), X(12), X(1));
    BODY_32_39(37, T, A, B, C, D, E, X(5), X(7), X(13), X(2));
    BODY_32_39(38, E, T, A, B, C, D, X(6), X(8), X(14), X(3));
    BODY_32_39(39, D, E, T, A, B, C, X(7), X(9), X(15), X(4));

    BODY_40_59(40, C, D, E, T, A, B, X(8), X(10), X(0), X(5));
    BODY_40_59(41, B, C, D, E, T, A, X(9), X(11), X(1), X(6));
    BODY_40_59(42, A, B, C, D, E, T, X(10), X(12), X(2), X(7));
    BODY_40_59(43, T, A, B, C, D, E, X(11), X(13), X(3), X(8));
    BODY_40_59(44, E, T, A, B, C, D, X(12), X(14), X(4), X(9));
    BODY_40_59(45, D, E, T, A, B, C, X(13), X(15), X(5), X(10));
    BODY_40_59(46, C, D, E, T, A, B, X(14), X(0), X(6), X(11));
    BODY_40_59(47, B, C, D, E, T, A, X(15), X(1), X(7), X(12));
    BODY_40_59(48, A, B, C, D, E, T, X(0), X(2), X(8), X(13));
    BODY_40_59(49, T, A, B, C, D, E, X(1), X(3), X(9), X(14));
    BODY_40_59(50, E, T, A, B, C, D, X(2), X(4), X(10), X(15));
    BODY_40_59(51, D, E, T, A, B, C, X(3), X(5), X(11), X(0));
    BODY_40_59(52, C, D, E, T, A, B, X(4), X(6), X(12), X(1));
    BODY_40_59(53, B, C, D, E, T, A, X(5), X(7), X(13), X(2));
    BODY_40_59(54, A, B, C, D, E, T, X(6), X(8), X(14), X(3));
    BODY_40_59(55, T, A, B, C, D, E, X(7), X(9), X(15), X(4));
    BODY_40_59(56, E, T, A, B, C, D, X(8), X(10), X(0), X(5));
    BODY_40_59(57, D, E, T, A, B, C, X(9), X(11), X(1), X(6));
    BODY_40_59(58, C, D, E, T, A, B, X(10), X(12), X(2), X(7));
    BODY_40_59(59, B, C, D, E, T, A, X(11), X(13), X(3), X(8));

    BODY_60_79(60, A, B, C, D, E, T, X(12), X(14), X(4), X(9));
    BODY_60_79(61, T, A, B, C, D, E, X(13), X(15), X(5), X(10));
    BODY_60_79(62, E, T, A, B, C, D, X(14), X(0), X(6), X(11));
    BODY_60_79(63, D, E, T, A, B, C, X(15), X(1), X(7), X(12));
    BODY_60_79(64, C, D, E, T, A, B, X(0), X(2), X(8), X(13));
    BODY_60_79(65, B, C, D, E, T, A, X(1), X(3), X(9), X(14));
    BODY_60_79(66, A, B, C, D, E, T, X(2), X(4), X(10), X(15));
    BODY_60_79(67, T, A, B, C, D, E, X(3), X(5), X(11), X(0));
    BODY_60_79(68, E, T, A, B, C, D, X(4), X(6), X(12), X(1));
    BODY_60_79(69, D, E, T, A, B, C, X(5), X(7), X(13), X(2));
    BODY_60_79(70, C, D, E, T, A, B, X(6), X(8), X(14), X(3));
    BODY_60_79(71, B, C, D, E, T, A, X(7), X(9), X(15), X(4));
    BODY_60_79(72, A, B, C, D, E, T, X(8), X(10), X(0), X(5));
    BODY_60_79(73, T, A, B, C, D, E, X(9), X(11), X(1), X(6));
    BODY_60_79(74, E, T, A, B, C, D, X(10), X(12), X(2), X(7));
    BODY_60_79(75, D, E, T, A, B, C, X(11), X(13), X(3), X(8));
    BODY_60_79(76, C, D, E, T, A, B, X(12), X(14), X(4), X(9));
    BODY_60_79(77, B, C, D, E, T, A, X(13), X(15), X(5), X(10));
    BODY_60_79(78, A, B, C, D, E, T, X(14), X(0), X(6), X(11));
    BODY_60_79(79, T, A, B, C, D, E, X(15), X(1), X(7), X(12));

    /*
     * SHA1 Document:
     * Let H0 = H0 + A, H1 = H1 + B, H2 = H2 + C, H3 = H3 + D, H4 = H4 + E.
     */
    ctx_.h0 = (ctx_.h0 + E) & 0xffffffffL;
    ctx_.h1 = (ctx_.h1 + T) & 0xffffffffL;
    ctx_.h2 = (ctx_.h2 + A) & 0xffffffffL;
    ctx_.h3 = (ctx_.h3 + B) & 0xffffffffL;
    ctx_.h4 = (ctx_.h4 + C) & 0xffffffffL;

    if (--num_block == 0) break;

    /*
     * SHA1 Document:
     * Let A = H0, B = H1, C = H2, D = H3, E = H4.
     */
    A = ctx_.h0;
    B = ctx_.h1;
    C = ctx_.h2;
    D = ctx_.h3;
    E = ctx_.h4;
  }
}
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值