《算法》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的知乎


欢迎订阅我的微信公众号

在这里插入图片描述

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

Bruceoxl

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值