Мета цього виклику - знайти неможливе коротке виконання наступної функції p
у вибраному вами ланцюзі. Ось код C, що реалізує його (див.
Це посилання TIO, яке також друкує результати) та сторінку вікіпедії, що містить його.
unsigned char pi[] = {
252,238,221,17,207,110,49,22,251,196,250,218,35,197,4,77,
233,119,240,219,147,46,153,186,23,54,241,187,20,205,95,193,
249,24,101,90,226,92,239,33,129,28,60,66,139,1,142,79,
5,132,2,174,227,106,143,160,6,11,237,152,127,212,211,31,
235,52,44,81,234,200,72,171,242,42,104,162,253,58,206,204,
181,112,14,86,8,12,118,18,191,114,19,71,156,183,93,135,
21,161,150,41,16,123,154,199,243,145,120,111,157,158,178,177,
50,117,25,61,255,53,138,126,109,84,198,128,195,189,13,87,
223,245,36,169,62,168,67,201,215,121,214,246,124,34,185,3,
224,15,236,222,122,148,176,188,220,232,40,80,78,51,10,74,
167,151,96,115,30,0,98,68,26,184,56,130,100,159,38,65,
173,69,70,146,39,94,85,47,140,163,165,125,105,213,149,59,
7,88,179,64,134,172,29,247,48,55,107,228,136,217,231,137,
225,27,131,73,76,63,248,254,141,83,170,144,202,216,133,97,
32,113,103,164,45,43,9,91,203,155,37,208,190,229,108,82,
89,166,116,210,230,244,180,192,209,102,175,194,57,75,99,182,
};
unsigned char p(unsigned char x) {
return pi[x];
}
Що p
p
є складовою двох російських криптографічних стандартів, а саме хеш-функції Streebog та блок-шифру Кузнечика . У цій статті (і під час засідань ISO) дизайнери цих алгоритмів стверджували, що вони генерували масив pi
, вибираючи випадкові 8-бітні перестановки.
"Неможливі" реалізації
Є перестановки на 8 біт. Отже, для даної випадкової перестановки програмі, що реалізує її, не слід очікувати менше 1683 біт.
Однак ми знайшли кілька аномально невеликих реалізацій (які ми тут перераховуємо ), наприклад наступну програму C:
p(x){unsigned char*k="@`rFTDVbpPBvdtfR@\xacp?\xe2>4\xa6\xe9{z\xe3q5\xa7\xe8",l=0,b=17;while(--l&&x^1)x=2*x^x/128*285;return l%b?k[l%b]^k[b+l/b]^b:k[l/b]^188;}
який містить лише 158 символів і, таким чином, вміщує 1264 біт. Натисніть тут, щоб побачити, що це працює.
Ми говоримо про "неможливу" коротку реалізацію, оскільки, якби перестановка була результатом випадкового процесу (як стверджують його дизайнери), програми такої короткої програми не існувало ( детальну інформацію див. На цій сторінці ).
Довідкова реалізація
Більш читаною версією попереднього коду є:
unsigned char p(unsigned char x){
unsigned char
s[]={1,221,146,79,147,153,11,68,214,215,78,220,152,10,69},
k[]={0,32,50,6,20,4,22,34,48,16,2,54,36,52,38,18,0};
if(x != 0) {
unsigned char l=1, a=2;
while(a!=x) {
a=(a<<1)^(a>>7)*29;
l++;
}
unsigned char i = l % 17, j = l / 17;
if (i != 0) return 252^k[i]^s[j];
else return 252^k[j];
}
else return 252;
}
Таблиця k
така, що k[x] = L(16-x)
де L
лінійно в тому значенні L(x^y)==L(x)^L(y)
, і де, як і в С, ^
позначається XOR. Однак нам не вдалося скористатися цією властивістю, щоб скоротити реалізацію. Ми не знаємо жодної структури, s
яка могла б дозволити більш просту реалізацію --- однак її вихід завжди знаходиться в підполі, тобто де експоненція проводиться в кінцевому полі. Звичайно, ви абсолютно вільні у використанні більш простого виразу, якщо знайдете його!s
Цикл while відповідає оцінці дискретного логарифму в кінцевому полі з 256 елементами. Це працює за допомогою простого пошуку грубої сили: фіктивна змінна a
встановлюється як генератор кінцевого поля, і вона множиться на цей генератор, поки результат не дорівнює x
. У цьому випадку ми маємо, що l
це дискретний журнал x
. Ця функція не визначена в 0, звідси й окремий випадок, що відповідає if
висловлюванню.
Множення на генератор можна розглядати як множення на в яке потім зменшується за модулем на поліном . Роль модуля полягає в тому, щоб змінна залишалася на 8 бітах. В якості альтернативи ми можемо використовувати , і в цьому випадку це може бути (або будь-який інший цілий тип). З іншого боку, потрібно починати з того , що нам потрібно мати, коли дорівнює 1.unsigned char
a
a=(a<<1)^(a>>7)*(256^29)
a
int
l=1,a=2
l=255
x
Більш детально про властивості p
представлено в нашій роботі , з описом більшості наших оптимізацій для отримання попередньої короткої реалізації.
Правила
Запропонуйте програму, яка реалізує цю функцію p
менше 1683 біт. Чим коротша програма, тим вона більш ненормальна, для даної мови коротше - краще. Якщо у вашій мові є Кузнечик, Стрибог або p
як вбудований, ви не можете їх використовувати.
Коефіцієнт, який ми використовуємо для визначення найкращої реалізації, - це довжина програми в байтах. Ми використовуємо біт-довжину в своїй академічній роботі, але ми дотримуємося байтів тут для простоти.
Якщо ваша мова не має чіткого уявлення про функції, аргумент або виведення, кодування до вас , щоб визначити, але прийоми , такі як кодує значення , pi[x]
як x
, очевидно , заборонені.
Ми вже подали дослідницький документ з нашими висновками з цієї теми. Він доступний тут . Однак, якщо вона буде опублікована на науковому майданчику, ми з радістю визнаємо авторів найкращими реалізаціями.
До речі, дякую xnor за допомогу при складанні цього питання!
1683 bits at most
суворе обмеження [sic?] Чи мета?