Skip to content
This repository has been archived by the owner on Apr 20, 2022. It is now read-only.

Latest commit

 

History

History
40 lines (29 loc) · 1.59 KB

checksum.md

File metadata and controls

40 lines (29 loc) · 1.59 KB

Checksum

According to the apple docs the Fletcher's checksum algorithm is used. Apple uses a variant of the algorithm described in a paper by John Kodis. The following algorithm shows this procedure. The input is the block without the first 8 byte.

func createChecksum(data []byte) uint64 {
    var sum1, sum2 uint64

    modValue := uint64(2<<31 - 1)

    for i := 0; i < len(data)/4; i++ {
        d := binary.LittleEndian.Uint32(data[i*4 : (i+1)*4])
        sum1 = (sum1 + uint64(d)) % modValue
        sum2 = (sum2 + sum1) % modValue
    }

    check1 := modValue - ((sum1 + sum2) % modValue)
    check2 := modValue - ((sum1 + check1) % modValue)

    return (check2 << 32) | check1
}

The nice feature of the algorithm is, that when you check a block in APFS with the following algorithm you should get null as a result. Note that the input in this case is the whole block, including the checksum. However, because APFS stores the checksum at the start, this means that you have to feed through everything except the checksum, followed by the checksum.

func checkChecksum(data []byte) uint64 {
    var sum1, sum2 uint64

    modValue := uint64(2<<31 - 1)

    for i := 0; i < len(data)/4; i++ {
        d := binary.LittleEndian.Uint32(data[i*4 : (i+1)*4])
        sum1 = (sum1 + uint64(d)) % modValue
        sum2 = (sum2 + sum1) % modValue
    }

    return (sum2 << 32) | sum1
}