подобрать алгоритм расчета контрольной суммы

Тема в разделе "WASM.CRYPTO", создана пользователем hypertonyc, 14 мар 2011.

  1. hypertonyc

    hypertonyc New Member

    Публикаций:
    0
    Регистрация:
    14 мар 2011
    Сообщения:
    6
    Существует клиент и сервер, которые обмениваются данными по сети. В конце каждого пакета имеется контр.сумма. Не располагаю описанием алгоритма её расчета, но есть необходимость его узнать. У меня есть список пакетов(около 260 тысяч штук).На основе анализа этих пакетов составил функцию, которая вычисляет эту сумму, но в некоторых пакетах она всё же не сходится(эти пакеты посылались на сервер еще несколько раз и в разном порядке и контрольная сумма в них действительно рассчитывается НЕ по моему алгоритму, так что это исключает возможность того что пакеты некорректны). Помогите пожалуйста.

    результат программы 0.39% not good

    списки пакетов:
    http://rghost.ru/4766108 все пакеты
    http://rghost.ru/4766189 результат программы(пакеты где контр.сумма рассчитана с ошибкой)

    Код (Text):
    1. #include <stdio.h>
    2.  
    3. unsigned short calc_crc(unsigned char* bytes)
    4. {
    5.     unsigned short real_crc=0x0000;
    6.     unsigned short tmp_crc=0x0000;
    7.     for(int i=2;i<7;i++)
    8.     {
    9.         tmp_crc = (bytes[i])<<(6-i);
    10.         real_crc=(real_crc + tmp_crc);     
    11.     }
    12.  
    13.     while(real_crc>0xFF)
    14.     {      
    15.         real_crc = ((real_crc & 0xFF00)>>8) + (real_crc & 0x00FF);
    16.     }
    17.    
    18.     return real_crc;
    19. }
    20. void main(void)
    21. {
    22.     unsigned char bytes[9];
    23.     int number=0,all=0,bad=0;
    24.     unsigned short __CRC;
    25.  
    26.     FILE *file = fopen("list.txt","r");
    27.     FILE *file_res = fopen("list_res.txt","w+");
    28.     while(!feof(file))
    29.     {
    30.         all++;
    31.         fscanf(file,"%d %hx %hx %hx %hx %hx %hx %hx %hx %hx\n",&number,&bytes[0],&bytes[1],&bytes[2],&bytes[3],&bytes[4],&bytes[5],&bytes[6],&bytes[7],&bytes[8]);
    32.  
    33.         __CRC = calc_crc(bytes);       
    34.         if(bytes[7] != __CRC)
    35.         {
    36.             bad++;
    37.             fprintf(file_res,"%06d 0x%02x 0x%02x 0x%02x 0x%02x 0x%02x 0x%02x 0x%02x 0x%02x 0x%02x : 0x%02x\n",bad,bytes[0],bytes[1],bytes[2],bytes[3],bytes[4],bytes[5],bytes[6],bytes[7],bytes[8],__CRC);
    38.         }
    39.     }
    40.     printf("%03.2f%% not good\n",((float)bad/(float)all)*100.0);
    41.     fclose(file_res);
    42.     fclose(file);
    43.     scanf("%d",&number);
    44. }
     
  2. Black_mirror

    Black_mirror Active Member

    Публикаций:
    0
    Регистрация:
    14 окт 2002
    Сообщения:
    1.035
    hypertonyc
    Похоже на пакеты укороченной длины с контрольной суммой в предпоследнем байте. А последний байт может сигнатура или просто мусор.
     
  3. hypertonyc

    hypertonyc New Member

    Публикаций:
    0
    Регистрация:
    14 мар 2011
    Сообщения:
    6
    Абсолютно согласен. Задача то как раз выяснить алгоритм расчета предпоследнего байта.
     
  4. OLS

    OLS New Member

    Публикаций:
    0
    Регистрация:
    8 янв 2005
    Сообщения:
    322
    Адрес:
    Russia
    Не вижу в выявленной закономерности никакого смысла, но все исключения попадают под три правила :

    Код (Text):
    1.     for i:=1 to 5 do
    2.         begin
    3.         u:=u + (q[i] shl (5-i));
    4.         if (i=3) and (u=$7FC) then u:=0;
    5.         if (i=5) and (u=$7FA) then u:=0;
    6.         if (i=5) and (u=$3FE) then u:=0;
    7.         end;
    Может на что-то натолкнет. Извини, нумерация байт другая (u=real_crc).
     
  5. hypertonyc

    hypertonyc New Member

    Публикаций:
    0
    Регистрация:
    14 мар 2011
    Сообщения:
    6
    Действительно с такой функцией 0.00% not good
    Код (Text):
    1. unsigned short calc_crc(unsigned char* bytes)
    2. {
    3.     unsigned short real_crc=0x0000;
    4.     unsigned short tmp_crc=0x0000;
    5.     for(int i=2;i<7;i++)
    6.     {
    7.         tmp_crc = (bytes[i])<<(6-i);
    8.         real_crc=(real_crc + tmp_crc);
    9.         if ((i==4) && (real_crc==0x7FC)) real_crc=0;
    10.         if ((i==6) && (real_crc==0x7FA)) real_crc=0;
    11.         if ((i==6) && (real_crc==0x3FE)) real_crc=0;
    12.     }
    13.    
    14.     while(real_crc>0xFF)
    15.     {      
    16.         real_crc = ((real_crc & 0xFF00)>>8) + (real_crc & 0x00FF);
    17.     }
    18.    
    19.     return real_crc;
    20. }
    ви заметили что первые два байта и последний AF FF FA...похожи байты на те, что в условиях(if)...может нужна маска какая-нибудь( на что-нибудь :) )?
     
  6. Black_mirror

    Black_mirror Active Member

    Публикаций:
    0
    Регистрация:
    14 окт 2002
    Сообщения:
    1.035
    hypertonyc
    есть подозрение, что алгоритм там примерно такой:
    Код (Text):
    1. s=0
    2. for i=2 to 6
    3.   add s,s
    4.   adc s,b[i]
     
  7. hypertonyc

    hypertonyc New Member

    Публикаций:
    0
    Регистрация:
    14 мар 2011
    Сообщения:
    6
    если я всё правильно понял, то вы предлагаете такой код:
    Код (Text):
    1. unsigned short calc_crc(unsigned char* bytes)
    2. {
    3.     unsigned short real_crc=0x0000;
    4.     unsigned short tmp_crc=0x0000;
    5.     for(int i=2;i<7;i++)
    6.     {        
    7.         tmp_crc=bytes[i];
    8.         _asm
    9.         {
    10.             mov ax,real_crc
    11.             add ax,ax
    12.             mov bx,tmp_crc
    13.             adc ax,bx
    14.             mov real_crc,ax
    15.         }
    16.     }
    17.    
    18.     while(real_crc>0xFF)
    19.     {      
    20.         real_crc = ((real_crc & 0xFF00)>>8) + (real_crc & 0x00FF);
    21.     }
    22.    
    23.     return real_crc;
    24. }
    результат программы как и в самом начале - 0.39% not good
     
  8. Black_mirror

    Black_mirror Active Member

    Публикаций:
    0
    Регистрация:
    14 окт 2002
    Сообщения:
    1.035
    hypertonyc
    неа, сумма восьмибитная, если на си, то можно так:
    Код (Text):
    1. unsigned char s=0;
    2. for(int i=2;i<7;i++)
    3.   s+=s+b[i]+(s>>7);
     
  9. hypertonyc

    hypertonyc New Member

    Публикаций:
    0
    Регистрация:
    14 мар 2011
    Сообщения:
    6
    62.77% not good =|
    причем если на результирующий файл глянуть то получается что где-то двойка теряется...
    в ошибочных пакетах сумма отличается на 2 от рассчитанной
     
  10. OLS

    OLS New Member

    Публикаций:
    0
    Регистрация:
    8 янв 2005
    Сообщения:
    322
    Адрес:
    Russia
    Кстати, если "коррекция" нужна только на шагах, отличающихся с шагом 2,
    то может быть первично сумма считается 16-битная с коррекцией ?
    (а потом на последнем шаге ее старший и младший байты складываются)
     
  11. hypertonyc

    hypertonyc New Member

    Публикаций:
    0
    Регистрация:
    14 мар 2011
    Сообщения:
    6
    Спасибо всем за участие. Особая благодарность Black_mirror, он то и расколол алгоритм.
    "байт суммы расширяется до слова, прибавляется к самому себе, потом к нему добавляется расширенный байт из массива, а дальше к младшему байту суммы добавляется старший, а потом младший байт используется в следующей итерации"
    Тема закрыта.