《算法》Adler-32校验和算法

Posted Bruceoxl

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了《算法》Adler-32校验和算法相关的知识,希望对你有一定的参考价值。

Adler-32是Mark Adler在1995年提出的一种校验算法,该算法在FastLZ、zlib 等压缩算法中被广泛使用。

Adler-32算法和32位CRC算法相比具有更快的执行效率,但这两者的安全性都不高。Adler-32的可靠性介于fletcher-16和fletcher-32之间,在输入较短的消息时Adler-32变得很不可靠。




1 Adler-32算法描述

Adler-32算法通过计算两个16位校验和A和B并将它们的位连接成32位整数来获得Adler-32校验和。
在Adler-32运行开始时,A初始化为1,B初始化为0.总和以模数65521(小于216的最大素数)完成。字节以网络顺序(大端)存储,B占用两个最重要的字节。

假设我们要得到D的Adler-32校验码,n是D的长度(以字节为单位).那我们可以用以下公式来取得:

以Wikipedia中的实例来具体说明Adler-32算法实现过程。

最后A = 92010 = 38916,B = 458210 = 11E616

因此,最终的校验和结果为11E6039816。




2 Adler-32算法实现

Adler-32算法很简单,Wikipedia也有实例,下面就根据Adler-32的算法描述来实现Adler-32算法。
【C语言实现】

/**
  ******************************************************************************
  * @file                main.c
  * @author              BruceOu
  * @version             V1.0
  * @date                2021-09-06
  * @blog                https://blog.bruceou.cn/
  * @Official Accounts   嵌入式实验楼
  * @brief               
  ******************************************************************************
  */
/**Include*********************************************************************/
#include <stdio.h>
#include <stdint.h>
#include <string.h>

//
const uint32_t MOD_ADLER = 65521;

/**
  * @brief  adler32
  * @param  pData, unLen
  * @retval unCheckSum 
  */
uint32_t adler32(uint8_t *pData, size_t unLen) 
{
    uint32_t s1 = 1, s2 = 0;
    size_t ulIndex;
    uint32_t unCheckSum = 0 ;

    // Process each byte of the data in order
    for (ulIndex = 0; ulIndex < unLen; ++ulIndex)
    {
        s1 = (s1 + pData[ulIndex]) % MOD_ADLER;
        s2 = (s2 + s1) % MOD_ADLER;
    }
    
    unCheckSum = (s2 << 16) | s1;

    return unCheckSum;
}

/**
  * @brief  main
  * @param  None
  * @retval int
  */
int main()
{
    char chData[] = "Wikipedia";
    uint32_t unResult = 0;
    
    unResult = adler32(chData, strlen(chData));

    printf("result : %x", unResult);

    return 0;
}

运行结果如下:

和理论值是相符的。

以上代码是Adler-32算法的直接实现,效率不高,改进后如下:

/**
  * @brief  adler32
  * @param  unCheckSum, pBuf, nLen
  * @retval unCheckSum 
  */
static uint32_t adler32(uint32_t unCheckSum, const void* pBuf, size_t nLen) 
{
  
  const uint8_t* ptr = (const uint8_t*)pBuf;
  uint32_t s1 = unCheckSum & 0xffff;
  uint32_t s2 = (unCheckSum >> 16) & 0xffff;

  while (nLen > 0) 
  {
    uint32_t k = nLen < 5552 ? nLen : 5552;
    nLen -= k;

    while (k >= 8) 
    {
      s1 += *ptr++;
      s2 += s1;
      s1 += *ptr++;
      s2 += s1;
      s1 += *ptr++;
      s2 += s1;
      s1 += *ptr++;
      s2 += s1;
      s1 += *ptr++;
      s2 += s1;
      s1 += *ptr++;
      s2 += s1;
      s1 += *ptr++;
      s2 += s1;
      s1 += *ptr++;
      s2 += s1;
      k -= 8;
    }

    while (k-- > 0) 
    {
      s1 += *ptr++;
      s2 += s1;
    }
    s1 = s1 % MOD_ADLER;
    s2 = s2 % MOD_ADLER;
  }
  return (s2 << 16) + s1;
}

最后结算的结果都是一样的。

参考资料




欢迎访问我的网站

BruceOu的哔哩哔哩
BruceOu的主页
BruceOu的博客
BruceOu的CSDN博客
BruceOu的简书
BruceOu的知乎


欢迎订阅我的微信公众号

以上是关于《算法》Adler-32校验和算法的主要内容,如果未能解决你的问题,请参考以下文章

ZIP:Checksum

文件快速上传和下载原理

CRC和校验和有啥区别?

php 压缩函数gzencode gzdeflate gzcompress

摘要算法

在 python 中为大文件创建校验和的最快方法