2024-04-29

Navigation

Skip Navigation Links

Hash algorithms

Asymmetric Algorithms

Symmetric Cipher Algorithms

Encoding Algorithms

Compression Algorithms

Pseudo Random Number Algorithms

Steganography

Library Wrappers

String Comparison

Others

Syntax highlighting by Prism
PBCrypto.com Mirror

Adler32

Algorithm creator(s)

Mark Adler


PB author(s)

Marc Sven Schulte, Wayne Diamond


Description

Adler-32 is an algorithm used by ZIP files that creates a 32-bit checksum. The algorithm is approximately 33% faster than CRC32, and nearly as reliable. Adler32 is a 32-bit extension and improvement of the Fletcher algorithm, used in the ITU-T x.224 / ISO 8073 standard.


Note

Adler32 is also known as Fletch-32/Fletcher-32, and is used in ZLib. Marc Sven Schulte has recently (July 2003) written a faster PB implementation that my original (see below).


Source

https://forum.powerbasic.com/forum/user-to-user-discussions/source-code/24064-adler-32-checksum?t=23439


See also

n/a


Source Code

Download source code file adler32.bas (Right-click -> "Save as ...")

'Adler-32 is composed of two sums accumulated per byte: s1 is the sum
'of all bytes, s2 is the sum of all s1 values. Both sums are done
'modulo 65521. s1 is initialised to 1, s2 to zero. The Adler-32 checksum
'is stored as s2*65536 + s1 in most-significant-byte first (network) order.
'
'The algorithm is much faster than the CRC32 algorithm yet still provides
'an extremely low probability of undetected errors.
'
'The modulo on unsigned long accumulators can be delayed for 5552 bytes,
'so the modulo operation time is negligible. If the bytes are a, b, c,
'the second sum is 3a + 2b + c + 3, and so is position and order sensitive,
'unlike the first sum, which is just a checksum. That 65521 is prime is
'important to avoid a possible large class of two-byte errors that leave
'the check unchanged. (The Fletcher checksum uses 255, which is not prime
'and which also makes the Fletcher check insensitive to single byte
'changes 0-255).
'
'The sum s1 is initialised to 1 instead of zero to make the length of the
'sequence part of s2, so that the length does not have to be checked
'separately. (Any sequence of zeroes has a Fletcher checksum of zero.)")
'

#COMPILE EXE  'PBCC.  Replace STDOUT with MSGBOX to compile with PBDLL
#INCLUDE "win32api.inc" 
 
FUNCTION Adler32(sBuffer AS STRING) AS LONG
    DIM Seed AS LONG
    DIM S1 AS LONG
    DIM S2 AS LONG
    DIM N AS LONG
    %CrcBase = 65521
    Seed = 1
    S1 = Seed AND &HFFFF
    S2 = (Seed / 65536) AND &HFFFF
    FOR N = 1 TO LEN(sBuffer)
        S1 = (S1 + ASC(MID$(sBuffer, N,1))) MOD %CrcBase
        S2 = (S2 + S1) MOD %CrcBase
    NEXT
    Adler32 = (S2 * 65536) + S1
END FUNCTION 

FUNCTION Adler32asm(sBuffer AS STRING) AS LONG
#REGISTER NONE
DIM Seed AS LONG, S1 AS LONG, S2 AS LONG, N AS LONG
DIM sPtr AS LONG
sPtr = STRPTR(sBuffer) - 1
N = LEN(sBuffer) + sPtr
  '// S1 = Seed AND &HFFFF
    ! mov   Seed, 1
    ! xor   eax, eax
    ! add   eax, Seed
    ! mov   ebx, eax
    ! and   eax, &hFFFF
    ! mov   eax, ebx
    ! mov   S1, eax
  '// S2 = (Seed / 65536) AND &HFFFF
    ! mov   eax, Seed
    ! mov   ebx, &h10000
    ! xor   edx, edx
    ! div   ebx
    ! and   eax, &hFFFF
    ! mov   S2, eax
    ! mov   ecx, sPtr
    StartLoop: '// FOR N = 1 TO LEN(sBuffer)
    ! inc   ecx
    ! cmp   ecx, N
    ! jg    EndLoop
      '//S1 = (S1 + ASC(MID$(sBuffer, N,1))) MOD %CrcBase
        ! mov   eax, S1
        ! xor   ebx, ebx
        ! mov   bl, [ecx]
        ! add   eax, ebx
        ! mov   ebx, &hFFF1
        ! xor   edx, edx
        ! div   ebx
        ! mov   S1, edx
      '//S2 = (S2 + S1) MOD %CrcBase
        ! mov   eax, S2
        ! add   eax, S1
        ! mov   ebx, &hFFF1
        ! xor   edx, edx
        ! div   ebx
        ! mov   S2, edx
        ! jmp   StartLoop   ;// NEXT
    EndLoop:
    '// FUNCTION = (S2 * 65536) + S1
        ! mov   eax, S2
        ! mov   ecx, &h10000
        ! mul   ecx
        ! add   eax, S1
        ! mov   N, eax
    FUNCTION = N
END FUNCTION  

FUNCTION PBMAIN() AS LONG
ON ERROR RESUME NEXT
DIM TestBuffer AS STRING
DIM Adler AS LONG
TestBuffer = CHR$(17) & CHR$(34) & CHR$(51)
Adler = Adler32(TestBuffer)    'PB basic code
'Adler = Adler32asm(TestBuffer) 'PB inline asm
IF Adler = 11337831 THEN
    STDOUT "Calculated correctly"
ELSE
    STDOUT "Calculation failed"
END IF
STDOUT "Adler32 checksum=" & STR$(Adler)
END FUNCTION


'#####################################################################################
'ADLER32, by Marc Sven Schulte, 10th July 2003.
'Note: This is the fastest implementation so far.
'
FUNCTION ADLER32(BYVAL Address AS DWORD, _
  BYVAL Length AS LONG, _
  BYVAL Seed AS DWORD) AS DWORD
  #REGISTER NONE
  ! mov edx, Seed
  ! movzx ecx, dx
  ! shr edx, 16
  ! mov esi, Address
  ! mov eax, Length
  ! add eax, esi
  ! xor ebx, ebx
  LP:
  ! mov bl, [esi]
  ! add ecx, ebx
  ! cmp ecx, 65521
  ! jb M1
  ! sub ecx, 65521
  M1:
  ! add edx, ecx
  ! cmp edx, 65521
  ! jb M2
  ! sub edx, 65521
  M2:
  ! inc esi
  ! cmp esi, eax
  ! jnz LP
  ! shl edx, 16
  ! add ecx, edx
  ! mov FUNCTION, ecx
END FUNCTION
 
FUNCTION PBMAIN() AS LONG
  DIM crc AS DWORD
  DIM str AS STRING
  str = "Mark Adler"
  crc = 1
  crc = ADLER32(STRPTR(str), LEN(str), crc)
  MSGBOX "ADLER32: " & HEX$(crc, 8) & " (should be: 13070394)"
END FUNCTION

Mirror provided by Knuth Konrad