CRC - Sumy kontrolne plików

Johnny_Bit

Sumy kontrolne (CRC) są ostatnio bardzo popularną metodą zabezpieczania progów, sprawdzania plików w archiwach, sprawdzania heurystycznego itd...

Jako że każdemu może się przydać rozumienie zasad tworzenia i sprawdzania crc, postanowiłem napisać o tym arta (komentarze po angielsku, na życzenie dodam tłumaczenie)


Spis treści:

  1. Tablice CRC
    -Dynamiczne
    -statyczne

  2. Obliczanie CRC
    a)CRC8
    b)CRC16
    c)CRC32
    d)CRC64 [Przy pożądnym QWord kod wygląda troszeczkę inaczej]

  3. Zapis CRC
    A)Plik CRC
    B)Biblioteka DLL

  4. Sprawdzanie CRC
    A)Plik CRC
    B)Biblioteka DLL

  5. Materiały Dodatkowe


  1. Tablice CRC

CRC w moim wydaniu wymaga kilku typów:

type
  HWord=0..$FF;                 //Half Word :)
  SWord=0..$FFFF;               //Single Word
  DWord=0..$FFFFFFFF;           //Double Word
  QWord=Packed array[0..1]of DWord;    //Quad Word (It should be 0..$FFFFFFFFFFFFFFFF)

  TCRC8Table = Packed array [0..255] of HWord;
  TCRC16Table= Packed array [0..255] of SWord;
  TCRC32Table= Packed array [0..255] of DWord;
  TCRC64Table= Packed array [0..255] of QWord;

-Dynamiczne

W dynamicznym tworzeniu tablic CRC potrzebne są globalne zmienne:

var
  CRC8Table :TCRC8Table;
  CRC16Table:TCRC16Table;
  CRC32Table:TCRC32Table;
  CRC64Table:TCRC64Table; 

Do stworzenia tablicy wykorzysuje generator liczb pseudo-losowych z ustawioną zmienną RandSeed (więcej o RandSeed w pomocy delphi) oraz pętle For.
Daje to bardzo porządany efekt uboczny: Tablica zawsze będzie posiadać te same wartości, niezależnie od komputera, Windozy, i innych czynników.
Oczywiście biędzie nam równierz potrzebna funckja generująca liczby w danym zakresie:

function RandomRange(AFrom, ATo: DWord): DWord;
begin
  if AFrom>ATo then
    Result:=Random(AFrom-ATo)+ATo
  else
    Result:=Random(ATo-AFrom)+AFrom;
end;

Mając wszystkie potrzebne pierdoły procedura tworząca wpisy w tablicach wygląda następująco:

Procedure InitCRCTabs;
var
  I: Integer;

  function RandomRange(AFrom, ATo: DWord): DWord;
  begin
    if AFrom > ATo then
      Result := Random(AFrom - ATo) + ATo
    else
      Result := Random(ATo - AFrom) + AFrom;
  end;

begin
  //CRC8
  RandSeed:=$07162534;
  For I:=0 to 255 do
    begin
      CRC8Table[I]:=RandomRange(0, $FF);
    end;
  //CRC16
  RandSeed:=$38B30E81;
  For I:=0 to 255 do
    begin
      CRC16Table[I]:=RandomRange(0, $FFFF);
    end;
  //CRC32
  RandSeed:=$09ACDC90;
  For I:=0 to 255 do
    begin
      CRC32Table[I]:=RandomRange(0, $FFFFFFFF);
    end;
  //CRC64
  RandSeed:=$23101987;
  For I:=0 To 255 do
    begin
      CRC64Table[I,0]:=RandomRange(0, $FFFFFFFF);
      CRC64Table[I,1]:=RandomRange(0, $FFFFFFFF);
    end;
end;

Prosta, co?

Wystarczy teraz pod koniec unita wrzucić:

initialization

InitCRCTabs;

Tyle o dynamicznym tworzeniu tablic CRC, jeżeli chcesz wiedzieć co wygenerowała ta procedura looknij do tworzenia statycznego.

-Statyczne

Statyczne tworzenie tablic to nic innego jak:

const //all constant tabled generated by InitCRCTables

  CRC8Table :TCRC8Table =(
    $57, $EB, $DA, $4C, $85, $D9, $27, $73, $CB, $A4, $C9, $DC, $3D, $73, $2F,
    $89, $E2, $4D, $75, $F0, $60, $83, $9E, $C6, $26, $DB, $31, $B7, $B5, $1C,
    $E6, $96, $C9, $F9, $5E, $73, $6B, $B5, $F3, $9E, $3F, $C6, $3A, $8E, $93,
    $73, $A7, $22, $0E, $2B, $84, $C6, $E2, $04, $23, $6C, $06, $BB, $EC, $5E,
    $C7, $09, $DD, $55, $B7, $30, $59, $6C, $D1, $17, $93, $CC, $46, $62, $EF,
    $2C, $66, $3D, $FA, $7D, $82, $E4, $01, $6A, $C5, $20, $50, $79, $59, $25,
    $B1, $F6, $60, $AA, $AB, $FA, $90, $1F, $83, $32, $7D, $43, $30, $36, $D5,
    $A0, $9F, $A2, $2F, $9C, $01, $34, $1A, $1E, $FC, $99, $99, $0D, $0C, $C5,
    $40, $14, $50, $ED, $86, $7C, $A4, $81, $1B, $FC, $CB, $C2, $4B, $DE, $E9,
    $D4, $B8, $D0, $B4, $5F, $00, $40, $05, $22, $04, $1F, $C0, $15, $04, $61,
    $30, $EE, $AE, $AA, $4A, $36, $D2, $DF, $8C, $27, $6D, $A3, $50, $22, $28,
    $F3, $D2, $6A, $8B, $66, $4A, $58, $7B, $BC, $C7, $68, $C2, $D2, $C4, $A1,
    $BD, $1B, $87, $57, $6A, $2C, $D8, $46, $72, $1A, $9E, $6F, $F4, $90, $68,
    $57, $19, $F0, $F2, $77, $BF, $F6, $33, $06, $D9, $88, $7D, $6B, $2C, $C8,
    $B8, $09, $92, $98, $D5, $24, $0F, $02, $E5, $17, $2A, $55, $89, $1F, $72,
    $E4, $99, $6C, $33, $A8, $44, $45, $9A, $3D, $F5, $62, $E6, $FE, $CD, $D2,
    $69, $36, $7F, $17, $64, $9F, $CE, $3F, $0E, $B9, $13, $27, $4C, $9E, $6E,
    $41);//RandSeed=$07162534

//------------------------------------------------------------------------------

  CRC16Table:TCRC16Table=(
    $EB00, $18AD, $EC07, $3D4C, $A1F2, $2BE1, $B230, $8D9A, $A8C3, $CD18, $5BB8,
    $9540, $28CF, $D70B, $29EC, $453A, $EB2D, $5C2D, $F1B0, $E166, $8C74, $9950,
    $88DA, $9359, $8AAE, $2B98, $83C7, $8E61, $2997, $75A2, $DF40, $D0D7, $6918,
    $5FF5, $7292, $CEA8, $8A08, $E0AA, $45E9, $9124, $DD22, $F658, $28EE, $1807,
    $D844, $0245, $25A2, $07C6, $ADE8, $ADC8, $AB7A, $F11C, $E2E5, $C702, $8EBC,
    $BDD5, $9E68, $C0BE, $381B, $0EDC, $B02E, $C1A6, $A08F, $9781, $8905, $6EA9,
    $F577, $C20C, $A183, $DCAA, $00F4, $2989, $0B06, $556C, $B27D, $B4CA, $26ED,
    $DBBA, $63C8, $5EC3, $C015, $9ADB, $B5DA, $F805, $0298, $AD36, $226D, $6D98,
    $0DC3, $E643, $9D83, $60FF, $1C56, $8BB3, $E34A, $1D87, $7F00, $29E2, $4E31,
    $36D0, $E51A, $EF79, $5148, $5C9F, $AFA4, $3C68, $F2DD, $2FE4, $4A80, $5005,
    $E355, $2508, $C7EB, $427E, $0C4A, $BF79, $3A42, $B586, $B3E4, $B279, $87F3,
    $E83D, $9079, $B324, $B5C2, $1A62, $6869, $07C1, $E33F, $6AB5, $1A35, $204B,
    $7586, $9CAF, $28DF, $C440, $2C37, $7167, $2887, $A1AA, $1CB5, $7FBC, $A743,
    $496D, $CFA3, $B7C8, $6E40, $E4D0, $FC9C, $FD88, $3719, $3050, $A034, $86C6,
    $3175, $87A2, $682E, $E848, $F4E3, $0F07, $B1FD, $FE3C, $BAFB, $45D5, $977E,
    $1BE4, $FDAF, $8E43, $C5F4, $2E7F, $D5F1, $7676, $1B46, $BF78, $B689, $CECA,
    $4575, $01D4, $5F36, $D963, $E060, $56D5, $2404, $1EF6, $CDBD, $F5F3, $E4EC,
    $B4D1, $C350, $A3FF, $51B3, $0032, $4B71, $A590, $55FE, $42C7, $B3BB, $58B0,
    $C9B2, $7C81, $A615, $21C9, $C194, $6E9F, $67E8, $97D1, $1C20, $CBF8, $FB97,
    $1BB6, $26A2, $E289, $A044, $4705, $769C, $4A41, $6BC5, $DDDF, $535A, $650A,
    $FAE1, $3020, $4BCE, $BC19, $73D1, $15C7, $D4B2, $8677, $56F4, $F2A9, $0AE0,
    $E4D0, $D9D2, $6D5D, $F5E9, $9E7D, $C855, $C55F, $E6FD, $6BCF, $2844, $F487,
    $CFFD, $199B, $1B02, $07B0, $AEDB, $120C, $B984, $5AA2, $6934, $16A4, $E699,
    $A341, $B42D, $3794);//RandSeed=$38B30E81

//------------------------------------------------------------------------------

  CRC32Table:TCRC32Table=(
    $B69A8ED0, $41308E15, $6FE61E6E, $42A7D42B, $D80DD4DC, $E8EF1C51, $49D5D59A,
    $38291807, $49719828, $0AF51CCD, $F013C806, $5BBE8423, $47FB24B4, $B47D0B89,
    $ACB461B2, $077E347F, $DC890680, $320FA485, $5F534E9E, $3E22851B, $0C2F098C,
    $323FE3C1, $1ABF7ACA, $6F6611F7, $1E0239D8, $52A7053D, $D5E71236, $9C9FB713,
    $C224E364, $132084F9, $1C0380E2, $799E906F, $26129230, $6B461EF5, $E80572CE,
    $65C5FA0B, $422C123C, $7E2BCF31, $1740D3FA, $59698FE7, $EC836F88, $285BD1AD,
    $1F58D066, $23692E03, $7CE7F614, $6412A269, $F36BD412, $930CF05F, $0E3231E0,
    $BFBAFD65, $447F8AFE, $6A2132FB, $A8CFEEEC, $62A9DEA1, $892CE12A, $335291D7,
    $E2903938, $5C1A821D, $788C0296, $58C9E8F3, $BFAF5CC4, $386A63D9, $E4605B42,
    $1708544F, $E122E590, $18953FD5, $1E84972E, $28032FEB, $4C259F9C, $C7F11211,
    $5596A25A, $428017C7, $570396E8, $8C2A168D, $94E3A8C6, $C9B0E7E3, $87261774,
    $AB7EC949, $53941672, $490FBC3F, $6C5FAD40, $E53BE645, $BF17975E, $987AF0DB,
    $C578244C, $58786981, $2CD1178A, $C49121B7, $79F88898, $95118EFD, $5F02C2F6,
    $174D2AD3, $35372624, $D2E6D2B9, $88FA05A2, $DCE2282F, $AEA388F0, $8B55F0B5,
    $3E7B8B8E, $C0D775CB, $EB527CFC, $F0F6E4F1, $BA6F40BA, $DF64AFA7, $04CA0E48,
    $0197EB6D, $28CC5126, $E70DB1C3, $410D88D4, $2E798029, $DFC528D2, $E67E981F,
    $87E978A0, $D6CA5F25, $B43373BE, $A2A7BEBB, $817FA9AC, $10638461, $D5441DEA,
    $9119C197, $EA1327F8, $7AC42BDD, $DB635356, $D2A17CB3, $E7143F84, $184DD199,
    $F6688002, $CA240C0F, $696C7C50, $69C03195, $67024FEE, $2BBACBAB, $E90AAA5C,
    $47F547D1, $AF62AF1A, $A00F5787, $05AED5A8, $37DD504D, $272AC986, $57F78BA3,
    $D8F64A34, $34BAC709, $DE970B32, $2C5183FF, $05A79400, $2C9E6805, $FCEB201E,
    $261F9C9B, $D03E7F0C, $AB232F41, $061DF44A, $8AE47177, $CCB81758, $6E6A58BD,
    $B3C5B3B6, $C93EDE93, $ED9EA8E4, $E2576079, $4D43CA62, $E1C5FFEF, $0055BFB0,
    $BE0C0275, $AB30E44E, $2825318B, $E2A627BC, $3FA43AB1, $5208ED7A, $78780F67,
    $FD89ED08, $C232452D, $501711E6, $3CE67583, $D1385B94, $A9FA9DE9, $CAA1BD92,
    $DF807FDF, $9E71FF60, $E2F000E5, $66569C7E, $845A8A7B, $790CA46C, $6D6F6A21,
    $F6F69AAA, $27E93157, $4FBF56B8, $B53C159D, $2241E416, $7D9D5073, $B52E6244,
    $AEBB7F59, $E223E4C2, $2AC003CF, $76375310, $F6716355, $121F48AE, $398EA76B,
    $497CF51C, $6EBBBD91, $73F9FBDA, $E096D747, $24335468, $17CECA0D, $D7A92A46,
    $FA526F63, $002BBCF4, $1DF104C9, $527D3FF2, $C9038BBF, $1F20BAC0, $59F729C5,
    $B18DE8DE, $E2D0885B, $174219CC, $C0003501, $9366110A, $62200137, $3500E618,
    $7871627D, $D4EFE476, $B634D253, $FE1B6BA4, $9F322E39, $3DA0CF22, $B00A17AF,
    $E1E93670, $E5285435, $96E57D0E, $A76F2D4B, $62E7127C, $8FF3D071, $9ACDDA3A,
    $D463AF27, $45830BC8, $93EADEED, $65F912A6, $38B37943, $90286E54, $C455FBA9,
    $58C19252, $B5D2A79F, $688BC620, $55EBE2A5, $93A9053E, $2AF9963B, $1A36DF2C,
    $2F8D8FE1, $7B04576A, $B780E117, $D254C578, $C5423F5D, $EDE7B4D6, $7D7D6433,
    $DCBDC504, $79736D19, $1C528982, $809C3B8F);//RandSeed=$09ACDC90

//------------------------------------------------------------------------------

  CRC64Table:TCRC64Table=(
    ($00B21BA3, $D6DB1A34), ($A572D709, $7A6F5B32), ($40CB13FF, $9A476400),
    ($FAFD7805, $8906701E), ($77E82C9B, $53694F0C), ($CE393F41, $95CC444A),
    ($BA8C0177, $A13DE758), ($144768BD, $6D5703B6), ($D6556E93, $514F78E4),
    ($800B7079, $BA081A62), ($BADB8FEF, $DC018FB0), ($1FA71275, $0778344E),
    ($3AC9C18B, $9A1CF7BC), ($98364AB1, $DD233D7A), ($413B9F67, $3F9BBD08),
    ($BBCB552D, $9C5461E6), ($D7590583, $67B52B94), ($75AAADE9, $0D520D92),
    ($96320FDF, $3E29CF60), ($48C710E5, $C7C9EC7E), ($60DB1A7B, $91CF746C),
    ($DC7D7A21, $E27CEAAA), ($82C8C157, $DC5D26B8), ($5391259D, $962B3416),
    ($8E6BE073, $0B773244), ($69678F59, $BFC034C2), ($980D93CF, $16FB2310),
    ($91847355, $6DBE98AE), ($A8EB376B, $B08BC51C), ($9545CD91, $E4EC4BDA),
    ($86926747, $985D2468), ($6BDFDA0D, $C83E7A46), ($2A7CFF63, $63408CF4),
    ($489914C9, $50058FF2), ($85ED1BBF, $BDF08AC0), ($1B4639C5, $BC5938DE),
    ($6E09185B, $799CE9CC), ($FF064501, $6EC4610A), ($CC379137, $EDB6B618),
    ($533E727D, $57313476), ($6EBB6253, $7AFC3BA4), ($7AD63E39, $A0151F22),
    ($158FA7AF, $3BC50670), ($7DB36435, $C5DCCD0E), ($9783BD4B, $2D8DE27C),
    ($0875E071, $85982A3A), ($3B973F27, $5FC4DBC8), ($8673EEED, $4EE662A6),
    ($A2960943, $F3D53E54), ($51F60BA9, $2521E252), ($DCF4379F, $FA739620),
    ($36B2F2A5, $1BCC553E), ($88EA263B, $7A29AF2C), ($C28B9FE1, $DA3AA76A),
    ($14D07117, $2B229578), ($20874F5D, $D28104D6), ($81BBF433, $B4369504),
    ($7A0F7D19, $179ED982), ($4259CB8F, $753739D0), ($1A6BE515, $FEEAD16E),
    ($120B532B, $2A7B4FDC), ($D07E8351, $F8BED89A), ($E0422707, $F5AAE328),
    ($4ABF93CD, $4C641B06), ($2C1C2323, $97CB3FB4), ($69799289, $A33F04B2),
    ($6C3F637F, $E88AF180), ($C3453B85, $8F3B419E), ($5EF6441B, $D6CDC48C),
    ($D7C58AC1, $7877BDCA), ($5E8B60F7, $7E78C4D8), ($ACA3BC3D, $9E32A536),
    ($15E59613, $1F7E3E64), ($D0CB4BF9, $16F563E2), ($3163FF6F, $0229BD30),
    ($01E5F5F5, $FC00A5CE), ($E7F9F90B, $94AC0D3C), ($F017B631, $2BF856FA),
    ($788B1EE7, $4DE73A88), ($DBFAC8AD, $50CFA366), ($F7874D03, $217A9114),
    ($0ADBA969, $14F4F712), ($08C69F5F, $910E9CE0), ($4D351465, $B3BDFDFE),
    ($61A571FB, $A6E129EC), ($136C05A1, $5113A42A), ($2F6060D7, $65914438),
    ($CCCBB91D, $C45E1596), ($BDB047F3, $792B37C4), ($8CC1AAD9, $C2B0BE42),
    ($F9A6434F, $35749090), ($325996D5, $94364A2E), ($ACC7AEEB, $2D781A9C),
    ($8DF97911, $C0DCA55A), ($8C6A26C7, $F051E1E8), ($415D8D8D, $6040FBC6),
    ($794F86E3, $B73B3274), ($55D45049, $F8DBB972), ($8B81EB3F, $10D69840),
    ($C4BA7D45, $1A6C8A5E), ($C66FAFDB, $D5BBDF4C), ($6E371081, $1FA65A8A),
    ($914770B7, $F2441398), ($3A3745FD, $C31B55F6), ($4F9409D3, $D1958124),
    ($5FAA99B9, $7368E8A2), ($B618972F, $75EFB3F0), ($0DFEC7B5, $92A3BE8E),
    ($B7EC74CB, $8A3777FC), ($F4DBCBF1, $0D03C3BA), ($27D73EA7, $F8C2D948),
    ($661FE26D, $F2D02426), ($69ECD0C3, $D36523D4), ($0E1B8729, $018B4BD2),
    ($D169471F, $98BAE3A0), ($7E0D7625, $485EE6BE), ($86CCFDBB, $22B5E4AC),
    ($04DEAB61, $53C7E0EA), ($12389097, $CA6932F8), ($921E62DD, $8C826656),
    ($E608DBB3, $8D151A84), ($9F3E1899, $B5B5E302), ($85B2FB0F, $3E732750),
    ($5B0D8895, $B66102EE), ($24E04AAB, $1442255C), ($9376AED1, $1A05B21A),
    ($DACA6687, $171220A8), ($1979C74D, $F4951C86), ($C5D72AA3, $44506534),
    ($9B694E09, $159BAE32), ($BB74B2FF, $6D937F00), ($3165FF05, $B6AD131E),
    ($60355B9B, $21273A0C), ($181AD641, $1110374A), ($C42BC077, $27D8A258),
    ($55B90FBD, $86AB46B6), ($DF86BD93, $640203E4), ($45342779, $4A2FAD62),
    ($8B6D6EEF, $1DD6EAB0), ($43BDD975, $B286174E), ($D31B308B, $08F022BC),
    ($FC8221B1, $A57A707A), ($B93B9E67, $8F17B808), ($0EA33C2D, $C5A7E4E6),
    ($CD869483, $2C54F694), ($0975A4E9, $4FA4E092), ($2E9C2EDF, $E8386A60),
    ($FAFC17E5, $D26F0F7E), ($D420C97B, $3867DF6C), ($0CA39121, $2F175DAA),
    ($3D190057, $D86A61B8), ($EA3F4C9D, $8BADF716), ($DE85AF73, $62B43D44),
    ($EF44C659, $256E47C2), ($EE3FF2CF, $B6F2FE10), ($5647BA55, $2E2AFBAE),
    ($6615266B, $7999701C), ($E6B62491, $20F9FEDA), ($5B22E647, $38AB9F68),
    ($DCD4410D, $3A207D46), ($05730E63, $01CAD7F4), ($07F88BC9, $FE3EE2F2),
    ($13D7BABF, $7581A5C0), ($5B07C0C5, $FCBCDBDE), ($2807475B, $A3CFD4CC),
    ($6B30DC01, $3975540A), ($96F85037, $3DF67118), ($98E9197D, $E9A27776),
    ($C97DB153, $E983C6A4), ($DF27F539, $7009B222), ($D92286AF, $C09F6170),
    ($84E32B35, $C467B00E), ($45462C4B, $4B960D7C), ($2CCAB771, $B21C5D3A),
    ($DC783E27, $7FA5D6C8), ($FF44D5ED, $9A16E5A6), ($36149843, $8F0A0954),
    ($EAAA02A9, $A401B552), ($581F569F, $96473120), ($35C0F9A5, $8AAE783E),
    ($6560D53B, $72B71A2C), ($E07AB6E1, $6FC21A6A), ($6FC1B017, $4E54D078),
    ($8EEE765D, $62A0C7D6), ($CAE6C333, $ACC8A004), ($FA95B419, $8699EC82),
    ($7B0D2A8F, $05B414D0), ($25C82C15, $0454346E), ($9C26422B, $383DFADC),
    ($CD77DA51, $32798B9A), ($DD33A607, $63DE5E28), ($D52CFACD, $A1A31E06),
    ($6BE33223, $F26A8AB4), ($A9420989, $F78557B2), ($EC6B027F, $DF610C80),
    ($D35FC285, $C55BE49E), ($59A5731B, $8875AF8C), ($3D3921C1, $C595B0CA),
    ($E96D1FF7, $935D7FD8), ($DD87633D, $2CC0E836), ($5138E513, $B4DAC964),
    ($CB4602F9, $F9B6F6E2), ($06F7DE6F, $65091830), ($F32EBCF5, $710888CE),
    ($5A2D680B, $CCE9383C), ($EB758D31, $2FA989FA), ($814D1DE7, $792D3588),
    ($A1C4AFAD, $80DD2666), ($F756DC03, $9E445C14), ($DF78A069, $E361CA12),
    ($C5B2BE5F, $F9A737E0), ($E01C1B65, $E9DD20FE), ($964D20FB, $9C6394EC),
    ($76241CA1, $E288172A), ($A9F29FD7, $2AE87F38), ($79EBE01D, $F21AD896),
    ($0EEC16F3, $5E1242C4), ($7EF0E1D9, $8DF8D142), ($B3DAA24F, $D1766B90),
    ($0B4EDDD5, $819CAD2E), ($32D39DEB, $6AEFC59C), ($CD7BD011, $EB44585A),
    ($70BCA5C7, $E76A5CE8), ($8C43F48D, $DBDCFEC6), ($6CE795E3, $58EF7D74),
    ($CD05C749, $862F0C72), ($DCEE8A3F, $A1F1B340), ($6C2E0445, $294A2D5E),
    ($70CFDEDB, $39D8CA4C), ($A3F3A781, $22314D8A), ($DB4A2FB7, $C6CDCE98),
    ($3D53ECFD, $D0C698F6), ($FA7858D3, $58C70C24), ($E74E50B9, $3BF77BA2),
    ($BCAD762F, $51D40EF0), ($F0608EB5, $A128A18E), ($9D90E3CB, $47A9A2FC),
    ($DE42A2F1, $5AE1F6BA), ($D77A3DA7, $6A6DD448), ($9FE2C96D, $CABAA726),
    ($A50D5FC3, $3CC3EED4), ($55A17E29, $32851ED2), ($2F16661F, $A9187EA0),
    ($EBCD7D25, $A8BB09BE), ($02A5ACBB, $C02D4FAC), ($035FC261, $942953EA),
    ($2B6BCF97, $ACE56DF8), ($E4F789DD, $5ADC2956), ($4E55AAB3, $A9512584),
    ($7A164F99, $304AF602), ($60685A0F, $00FA0250), ($889BCF95, $2EC465EE),
    ($D5DD39AB, $6C6ED05C), ($AC8205D1, $281A651A), ($657DE587, $520F9BA8),
    ($CBD92E4D, $D98E1F86));//RandSeed=$23101987

Ale należy pamiętać aby dane statyczne i generowane dynamicznie zgadzały się ze sobą. Więcej o tym w Materiałach Dodatkowych.

  1. Obliczanie CRC

To jest najbardziej skomplikowane ze wszystkich części CRC.
CRC pliku musi być inne niż CRC tego samego pliku, ze zmienionym jednym Bajtem!

Teoretycznie im większa liczba bitów w CRC tym dokładniejsze oddanie pliku.

Pierwsze było CRC8 (na systemach 8 bitowych), mimo iż very stare, jest bardzo dobrym przykładem do tworzenia własnych, bardziej zaawansowanych algorytmów CRC.
Przedstawiony algorytm CRC8 jest zmieniony przeze mnie (orginalny kożystał z File of Byte):

function HAKGER_CRC8(Data: TStream): HWord;
var
  I: Integer;
  Buff: HWord;
begin
  Result:=0;
  Data.Position:=0;
  For I:=1 To Data.Size do
    begin
      Data.ReadBuffer(Buff, SizeOf(Buff));
      Result:=Result xor CRC8Table[Buff Xor Result];
      If Result=0 then
        Result:=CRC8Table[Buff or $AC]; //we like AC but DC is dangerous!
    end;
end;

Jak widać powyższy algorytm kożysta z operatora Xor i często odwołuje się do tablicy CRC, równierz należy pamiętać o tym aby CRC zależało od całego pliku, nie tylko od ostatniego bajtu, jak to robią początkujący:

function HAKGER_CRC8(Data: TStream): HWord;
var
  I: Integer;
  Buff: HWord;
begin
  Result:=0;
  Data.Position:=0;
  For I:=1 To Data.Size do
    begin
      Data.ReadBuffer(Buff, SizeOf(Buff));
      Result:=CRC8Table[Buff]; //<- głupota
      If Result=0 then
        Result:=CRC8Table[Buff or $AC]; //we like AC but DC is dangerous!
    end;
end;

Kolejne algorytmy CRC mojego wykonania prezentują się następująco:

function HAKGER_CRC16(Data: TStream): SWord;
var
  I: Integer;
  Buff: HWord;
begin
  Result:=0;
  Data.Position:=0;
  For I:=1 to Data.Size do
    begin
      Data.ReadBuffer(Buff, SizeOf(Buff));
      Result:=Hi(Result) xor CRC16Table[Buff xor Lo(Result)];
    end;
end;

Function HAKGER_CRC32(Data: TStream): DWord;
var
  I: Integer;
  Buff: HWord;
  Temp: DWord;
begin
  Result:=0;
  Data.Position:=0;
  for I:=1 to Data.Size do
    begin
      Data.ReadBuffer(Buff, SizeOf(Buff));
      Result:=(Result shl 4)+CRC32Table[Buff];
      Temp:=CRC32Table[Byte(Buff xor I)];
      if Temp<>0 then
        begin
    	  Result:=Result xor (Temp Shr 24);
        end;
      Result:=Result and not Temp;
    end;
end;

function HAKGER_CRC64(Data: TStream): QWord;
var
  I: Integer;
  Buff: HWord;
begin
  Result[0]:=$FFFFFFFF;
  Result[1]:=$FFFFFFFF;
  Data.Position:=0;
  For I:=1 to Data.Size do
    begin
      Data.ReadBuffer(Buff, SizeOf(Buff));
      Result[0]:=Result[1] xor CRC64Table[Buff, 0];
      Result[1]:=CRC64Table[Byte(Buff xor I), 1] xor Result[0];
    end;
end;

Jak widać sporo różnią się od siebie :-)

Jak by ktoś nie wiedział co to jest shr czy shl to polecam pomoc delphi oraz przejrzenie kodów funkcji RGB, CMYK & other colors.

  1. Zapis CRC

A)Plik CRC

Najprostrza metoda zapisu CRC. Równierz bardzo nieodpowiedzialna (Jeżeli nie zakoduje się pliku).

A oto i kod procedury zapisującej CRC32 (w innych jest identycznie, wystarczy zmienić typ zmiennej przechowującej CRC:

Procedure SaveCRC(FileToCRC, CRCFile: String);
var
  FS: TFileStream;
  CRC: DWord;
begin
  FS:=TFileStream.Create(FileToCRC, fmOpenRead or fmShareDenyWrite);
  CRC:=HAKGER_CRC32(FS);
  FS.Free;
  FS:=TFileStream.Create(CRCFile, fmCreate or fmShareExclusive);
  FS.WiteBuff(CRC, SizeOf(CRC));
  FS.Free;
end;

Potem plik CRC należy zakodować. Więcej o kodowaniu w tym serwisie programistycznym (wystarczy poszukać), ale ostrzegam: dotychczas opisane algorytmy kodowania są do stringów i do plików typowanych i takich jak pliki CRC się nienadają (Stringi są terminowane znakiem #0 czyli $00, a o natrafienie się na takowy znak w pliku jest nietrudno)

B)Biblioteka DLL (żadnego kodu w tej części)

Zapis w bibliotece dll to 3 proste kroki:

  1. Program który obliczy CRC i wyświetli w postaci Hexadecymalnej
  2. do bliblioteki wstawiasz stałą crc=${tutaj obliczone crc}
  3. kompilacja biblioteki

Jak któryś podpunkt wydaje Ci się za trudny, to zapytaj na forum.

  1. Sprawdzanie CRC

A)Plik CRC

Jeżeli plik został zakodowany, to najpierw go odkoduj (?zdekoduj?) oraz wywołaj procedure:

procedure CheckCRC(CRCFile: String);
var
  FS: TFileStream;
  CRC: DWord;
begin
  FS:=TFileStream.Create(CRCFile, fmOpenRead or fmShareDenyWrite);
  FS.ReadBuffer(CRC, SizeOf(CRC));
  FS.Free;
  FS:=TFileStream.Create(Application.ExeName, fmOpenRead or fmShareDenyWrite);
  if not (CRC=HAKGER_CRC32(FS)) then
    Application.Terminate;
end;

I już żaden program skrakowany przez Pseudo-Crackera nie będzie chodził.

B)Biblioteka DLL (żadnego kodu w tej części)

Sprawdzanie CRC zapisanego w bibliotece dll to 3 proste kroki:

  1. Biblioteka zawierająca w stałej crc execa exportuje funkcje podobną do powyższej CheckCRC (result będzie tru albo fals)
  2. Aplikacja wywołuje funkcje z biblioteki dll z CRC
  3. Gdy funkcja zwraca że crc się różnią to aplikacja się terminuje.

Jak któryś podpunkt wydaje Ci się za trudny, to zapytaj na forum.

  1. Materiały Dodatkowe

-Zapis plików z tablicami crc (aby statyczne zgadzały się z dynamicznymi):

Procedure WriteTables; //provided only for example how we maked constant tables
var
  TF: TextFile;
  I: Integer;
begin
  InitCRCTabs;
  AssignFile(TF,'C:CRC8');
  ReWrite(TF);
  For I:=0 to 255 do
    begin
      Write(TF, HexDisplayPrefix+IntToHex(CRC8Table[I], 2)+', ');
    end;
  CloseFile(TF);
  AssignFile(TF,'C:CRC16');
  ReWrite(TF);
  For I:=0 to 255 do
    begin
      Write(TF, HexDisplayPrefix+IntToHex(CRC16Table[I], 4)+', ');
    end;
  CloseFile(TF);
  AssignFile(TF,'C:CRC32');
  ReWrite(TF);
  For I:=0 to 255 do
    begin
      Write(TF, HexDisplayPrefix+IntToHex(CRC32Table[I], 8)+', ');
    end;
  CloseFile(TF);
  AssignFile(TF,'C:CRC64');
  ReWrite(TF);
  For I:=0 to 255 do
    begin
      Write(TF, '('+HexDisplayPrefix+IntToHex(CRC64Table[I, 0], 8)+', '+HexDisplayPrefix+IntToHex(CRC64Table[I, 1], 8)+'), ');
    end;
  CloseFile(TF);
end;

Unit przykładowy: http://www.4programmers.net/download.php?id=741

10 komentarzy

Borysf: CRC to rodzaj kompresji stratnej. Pozwala określić, czy suma kontrolna zostałą stworzona na podstawie tego pliku. Jeżeli wynik jest negatywny, możesz być pewny, że chodzi o iny plik. JEdnak wynik pozytywny jest obarczony pewnym błędem. Jeżeli zmienisz jeden bajt w pliku, to dobry sposób kodowania pokaże to - zmieni się suma kontrolna, a wiec to, co powstanie po "skomprersowaniu". Ale jak zmienisz dwa bajty, to może sięzdażyć, że zmiany wzajemnie się zniosą.
Szczególnie duże ryzyko jest przy sumach o małej długości. Jednak dlatego, że straty przy kompresji sąkonieczne, ( aby zmniejszyć rozmiar sumy i uniemożliwić odtworzenie danych na podstawie sumy - szczególnie ważne przy kodowaniu haseł). Jeżeli zmiana będzie dotyczyć właśnie tych "traconych" danych, to suma nie ulegnie zmianie.

witam! mam 'maly' problemik... Otoz pisze aplikacje, ktora w rejestrze systemowym ma za zadanie zapisywac CRC wybranych plikow, a nastepnie porownywac CRC dowolnego uruchamianego pliku i jesli beda zgodne, wywalac jakis tam komunikat. Problem jest tego typu, ze dla niektorych plikow to dziala, ale dla niektorych juz nie... CRC pliku uruchamianego ktory nie byl wpisany do rejestru zgadza sie z CRC pliku z rejestru (pliki sa rozne!) i w zwiazku z tym rozpoznaje ten plik jako kontrolowany. Mysle ze problem tkwi w zapisie i odczycie CRC z rejestru. Zapisuje i odczytuje te dane funkcjami WriteFloat i ReadFloat i stad moze sie brac przeklamanie. Stad moje pytanie: co z tym zrobic, aby zadzialalo? Jak te dane zapisac i odczytac aby nie bylo przeklaman? W Unicie nic nie modyfikowalem. Jesli to mozliwe odpisz jak najszybciej. Pozdrawiam!

I już żaden program skrakowany przez Pseudo-Crackera nie będzie chodził.

"_ z tym to przesadziles :)

nie wiem, czy kopiwales, czy nie, ja tam w tym nie siedze:), ale wazne, ze mi sie przydało:)
thx

No artykół spoko przeczytałem go ale jakoś nie potrafie znaleźć praktycznego zastosowania w moich aplikacjach :)

Pochwalony! No Drajwer. Sam byś się wziął za pisanie jakiegoś porządnego arta, lub zamilkł, a nie, pasożycie jeden, kogoś o jakąś herezję ;P posądzasz!
PS. Administratorzy, nie gniewajcie się na mnie, po prostu po niektórych Drajwera wypowiedziach, flaki mi się skręcają :P

Drajwer, masz rację kopiowałem... z tekstu napisanego przeze mnie w notatniku (fragmenty kodu do niego kopiowałem z mojego unita w delphi) a tak w ogóle to dla czego to ma być plagiat? Sam pisałem, wzorując się na IdHashCRC.pas oraz na własnych pomysłach na algorytmy kodowania hashowego (które mi nie wyszły). Jak ktoś zna strony z artami o hashowaniu, source-kody i inne pomocne to słać mi na maila pomoc (lub udowodninie plagiatu)

Jak pisałem pracę dyplomową to mój prowadzący powiedział że jak się spisuje z jednej pracy to jest plagiat. A jak z kilku to rozprawa naukowa :) więc nie przeszkadza mi że ktoś coś kopiuje. Ważne że znalazł i udostępnił to czego ja nie znalazłem a było mi potrzebne ...

hehehehe fajnie żeś skopiował;)

Nawt jakby skopiował n netu to itak się liczą chęci.