Перейти до вмісту

Adler-32

Матеріал з Вікіпедії — вільної енциклопедії.

Adler-32 геш-функція, яку розробив Марк Адлер[en]. Модифікація контрольної суми Флетчера. Обчислює значення контрольної суми відповідно до RFC 1950 для масиву байтів або його фрагмента. Від CRC32 цей алгоритм розрахунку контрольної суми відрізняється продуктивністю. Використовується в бібліотеці Zlib. Rolling checksum версія функції використовується в утиліті rsync.

Історія

[ред. | ред. код]

Так само, як і у випадку контрольної суми Флетчера, під час розробляння суми Adler стояло завдання отримати контрольну суму з ефективністю виявлення помилок порівнянною з CRC. Хоча показники пошуку помилок контрольних сум Adler і Флетчера практично такі ж, як і у відносно слабких CRC, але в деяких важливих випадках вони поводяться значно гірше, ніж хороші CRC.

Алгоритм

[ред. | ред. код]

Контрольну суму Adler-32 отримують обчисленням двох 16-бітових контрольних сум A і Б та конкатенації їхніх бітів у 32-бітове ціле. А дорівнює сумі всіх байтів у рядку плюс один , а Б — сума всіх окремих значень А на кожному кроці. На початку виконання функції Adler-32 А ініціалізується одиницею, а Б — нулем. Суми беруться за модулем 65521 (найбільше просте число менше від 216). Байти записуються в мережевому порядку, Б займає 2 старші байти.

Функцію можна виразити як:

A = 1 + D1 + D2 + ... + Dn (mod 65521)
B = (1 + D1) + (1 + D1 + D2) + ... + (1 + D1 + D2 + ... + Dn) (mod 65521)
  = n × D1 + (n -1) × D2 + (n -2) × D3 + ... + Dn + n (mod 65521)

 Adler-32 (D) = B × 65536 + A

де D — рядок байтів, для яких слід обчислити контрольну суму, а n — довжина D.

Приклад

[ред. | ред. код]

Значення Adler-32 для ASCII рядка «Wikipedia» обчислюється так:

 Код ASCII AB
 (У десятковому вигляді)
 W: 87 1 + 87 = 88 0 + 88 = 88
 i: 105 88 + 105 = 193 88 + 193 = 281
 k: 107193 + 107 = 300281 + 300 = 581
 i: 105300 + 105 = 405581 + 405 = 986
 p: 112405 + 112 = 517986 + 517 = 1503
 e: 101517 + 101 = 618 1503 + 618 = 2121
 d: 100618 + 100 = 718 2121 + 718 = 2839
 i: 105718 + 105 = 823 2839 + 823 = 3662
 a: 97823 + 97 = 920 3662 + 920 = 4582

 A = 920 = 398 hex (base 16)
 B = 4582 = 11E6 hex

 Output = 300286872 = 11E60398 hex

Операція додавання за модулем не має в цьому прикладі ніякого ефекту, оскільки жодне зі значень не досягло 65521.

Порівняння з контрольною сумою Флетчера

[ред. | ред. код]

Алгоритм обчислення контрольної суми Adler ідентичний алгоритму обчислення суми Fletcher крім деяких відмінностей. Перша відмінність полягає в тому, що у випадку функції Adler сума А ініціалізується значенням 1. Друга відмінність між двома алгоритмами в тому, що сума в алгоритмі Adler-32 обчислюється за модулем простого числа 65521, тоді як суми Fletcher обчислюються за модулем -1, -1, -1 (залежно від використовуваної кількості біт), які є складеними числами. Цю зміну в алгоритмі зроблено з метою досягти кращого перемішування біт. Використання простого числа дає змогу функції Adler-32 помічати відмінності в деяких комбінаціях байт, які функція Fletcher неспроможна зафіксувати. Третя відмінність, яка найбільше впливає на швидкість алгоритму, полягає в тому, що суми функції Adler-32 обчислюються над 8-бітовими, а не над 16-бітовими словами, що призводить до подвоєння кількості ітерацій циклу. Як наслідок, обчислення контрольної суми Adler-32 займає у півтора-два рази більше часу, ніж контрольної суми Fletcher для даних, розбитих на 16-бітові слова. Для даних, розбитих на байти, Adler-32 працює швидше, ніж алгоритм Fletcher.

Хоча контрольна сума Adler не визначена офіційно для інших довжин слів даних, можна використовувати найбільше просте ціле менше 24 = 16 і 28 = 256, щоб, з метою порівняння, реалізувати 8- і 16-бітові контрольні суми Adler. Маючи схожий алгоритм, контрольна сума Adler має продуктивність, схожу із сумою Fletcher. Усі 2-бітові помилки виявлено для слів даних довжиною менше, ніж M*(k/2) біт, де k — розмір контрольної суми, M — модуль суми Adler. Як і у випадку з контрольною сумою Fletcher, найгірше значення ймовірності невиявленої помилки спостерігається за однакової кількості нулів та одиниць у кожному блоці даних. Adler-8 і Adler-16 виявляють усі групові помилки завдовжки менше, ніж k/2 біт. Adler-32 виявляє всі групові помилки завдовжки трохи більше 7 біт. Рисунок1 показує залежність імовірності невиявлених помилок для контрольних сум Adler та Fletcher для частоти бітових помилок 10−5.

Рисунок 1. Імовірність невиявлених помилок для контрольних сум Adler та Fletcher для частоти бітових помилок 10−5.

Краще перемішування біт, яке забезпечує контрольна сума Adler, мало дати кращі показники пошуку помилок, ніж у суми Fletcher. Але, як свідчить RFC 3385, Fletcher-32 працює краще, ніж Adler-32 на 8 KB. Контрольна сума Adler перевищує суму Fletcher тільки у випадку 16-бітових контрольних сум, і при цьому тільки в тій ділянці цих сум, де відстань Геммінга дорівнює 3. Проблема в тому, що, попри краще перемішування біт завдяки використанню як модуля операції простого числа, в результаті виходить менша кількість слів. Найчастіше це зводить нанівець позитивний ефект кращого перемішування. Отже, контрольна сума Fletcher перевищує суму Adler у всіх випадках, крім суми Adler-16, яка застосовується до коротких слів даних. Навіть збільшення ефективності пошуку помилок, можливо, не варте збільшення обчислювальних накладних витрат, спричиненого використанням модульних операцій.

Порівняння з іншими контрольними сумами

[ред. | ред. код]

Автори RFC 3385 провели порівняння ефективності виявлення помилок. Зведення отриманих результатів наведено в таблиці:

Алгоритм d Block i/байт Tsize T-look Pudb Puds
Adler-32 3 219 3 - - 10−36 10−35
Fletcher-32 3 219 2 - - 10−37 10−36
IEEE-802 3 216 2,75 218 0,5/b 10−41 10−40
CRC32C 3 231−1 2,75 218 0,5/b 10−41 10−40

У таблиці: d — найменша відстань на блоці довжини Block, Block — довжина блоку в бітах, i/байт — кількість програмних інструкцій, що припадають на байт, Tsize — розмір таблиці (в разі, якщо необхідний перегляд), T-look — кількість переглядів на байт, Pudb — ймовірність невиявлених групових помилок, Puds — ймовірність невиявлених поодиноких помилок. Імовірності невиявлених помилок у таблиці обчислено з припущенням рівномірної розподіленості даних.

Переваги та недоліки

[ред. | ред. код]

«Хороша» геш-функція відрізняється більш-менш рівномірним розподілом обчислених значень. Очевидно, що Adler-32 не задовольняє цю вимогу для коротких даних (найбільше значення A для 128-байтового повідомлення дорівнює 32640, менше, ніж 65521 — число, за яким береться операція модуля). Через цей недолік розробники протоколу SCTP надали перевагу алгоритму CRC32, оскільки в мережевому протоколі необхідне гешування коротких послідовностей байтів.

Так само як і для CRC32, для Adler-32 можна легко сконструювати колізію, тобто для даного геша знайти інші початкові дані, що мають таке саме значення функції.

Має перевагу над CRC32 в тому, що швидше обчислюється програмними засобами.

Приклад реалізації мовою C

[ред. | ред. код]

Наведений код містить просту реалізацю алгоритму мовою Сі:

uint32_t adler32( const unsigned char* buf, size_t buf_length )
{
  uint32_t s1 = 1;
  uint32_t s2 = 0;
 
  while( buf_length-- )
  {
    s1 = ( s1 + *( buf++ ) ) % 65521;
    s2 = ( s2 + s1 ) % 65521;
  }
  return ( s2 << 16 ) + s1;
 }

Ефективну реалізацію дивіться в коді бібліотеки zlib.

Adler-32 в інших мовах програмування

[ред. | ред. код]
  • У Java існує клас java.util.zip.Adler32, що реалізує алгоритм.[1]
  • У стандартній бібліотеці D, std.zlib: adler32
  • У Perl існує Digest::Adler32, див. CPAN.[2]
  • Часткова реалізація для Python.
  • У PHP доступна через функцію hash()
  • Для Erlang доступні кілька вбудованих функцій (BIF) adler32(…)
  • Для Go доступна в стандартній бібліотеці «hash/adler32»

Примітки

[ред. | ред. код]
  1. Adler32 (Java Platform SE 8). Архів оригіналу за 25 грудня 2015. Процитовано 24 грудня 2015.
  2. Digest::Adler32 на CPAN. Архів оригіналу за 12 січня 2014. Процитовано 12 січня 2014.

Література

[ред. | ред. код]