Індіанці, шифрування і type cast

Feb 08, 2009 20:03

Не індіанці, звісно, а endianess.

Як відомо, дані у пам'яті комп'ютера адресуються до байта. Але інформація може займати більше одного байта. Наприклад тип uint32_t займає цілих чотири байти. Існує дві логіки розташування цих байтів: людська і логічна :) Люди звикли записувати числа старшими розрядами вперед. Це називається Little Endian (не "маленький індіанець" а "останній - молодший"). Наприклад, 2009: 2 у старшому розряді, 9 у молодшому. Так працюють і процесори архітектури x86. Але логічніше було б записувати навпаки: байти з більшими адресами старші, а з меншими - полодші. Це називається Big Endian (не "великий індіанець", звісно, а "останній - старший"). Так працюють, наприклад, процессори з архітектурою sparc/sparc64. Це створює додатковий головний біль для програміста. Наприклад, у нас у пам'яті записані такі дані (16-кова система числення):
01 02 03 04 05 06 07 08
Ми знаємо, що це два 32-бітних числа (наприклад uint32_t). Що це за числа? Або 0x01020304 0x05060708 (little endian) або 0x04030201 0x08070605 (big endian). Цікаво, що ця проблема характерна не тільки для одиничної машини, а і для комп'ютерних мереж. За домовленністю, у мережах використовується "Network Byte Order" - "Мережевий Порядок Байт". Фактично, це - big endian. Хто коли-небуть писав програми для роботи з мережею на C знає про функції htons/ntohs й інші, які "перевертають" байти.
Минулого тижня на форумі людина поскаржилась на роботу stargazer на Sun sparc64 (з Gentoo на борту). Не вдавалось авторизуватись конфігуратором з x86 на sparc64 і навпаки. Проблема була в реалізації алгоритму шифрування. Ми використовуємо реалізацію від Paul Kocher. Алгоритм блочний, оперує блоками довжиною 8 байт. Кожен блок розбивається на 2 32-бітних слова. Сам розробник пише, що його реалізація не піклується про порядок байт і перекладає цю справу на плечі користувачів (коду, звісно). Трошки ранніше я писав про проблему сумісності шифрування у stargazer з OpenSSL. Тут я наступив на ті-ж граблі. OpenSSL використовує big endian. А поточна реалізація залежала від архітектури процессора. Ну тепер мені було вже легше, і я замість type cast написав явне перетворення 4 байтів на uint32_t.
Погано лише те, що для сумісності зі старими версіями конфігураторів і, особливо, авторизаторів довелось забути про сумісність з OpenSSL і використовувати little endian. Але чого ж не зробиш заради користувачів?

blowfish, криптографія, робота, stargazer, програмування

Previous post Next post
Up