Tujuan dari tantangan ini adalah untuk menemukan mustahil pelaksanaan singkat dari fungsi berikut p
, dalam bahasamu yang Anda pilih. Ini adalah kode C yang mengimplementasikannya (lihat
tautan TIO ini yang juga mencetak hasilnya) dan halaman wikipedia yang memuatnya .
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];
}
apa yang p
p
adalah komponen dari dua standar kriptografi Rusia, yaitu fungsi hash Streebog dan blok cipher Kuznyechik . Dalam artikel ini (dan selama pertemuan ISO), para desainer algoritma ini mengklaim bahwa mereka menghasilkan array pi
dengan memilih permutasi 8-bit acak.
Implementasi "Tidak Mungkin"
Ada permutasi pada 8 bit. Oleh karena itu, untuk permutasi acak yang diberikan, program yang mengimplementasikannya tidak diharapkan membutuhkan kurang dari 1683 bit.
Namun, kami telah menemukan beberapa implementasi kecil yang tidak normal (yang kami sebutkan di sini ), misalnya program C berikut:
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;}
yang hanya berisi 158 karakter dan dengan demikian cocok dalam 1264 bit. Klik di sini untuk melihat bahwa itu berfungsi.
Kami berbicara tentang implementasi pendek yang "tidak mungkin" karena, jika permutasi adalah output dari proses acak (seperti yang diklaim oleh perancang), maka program yang singkat ini tidak akan ada (lihat halaman ini untuk lebih jelasnya).
Implementasi referensi
Versi yang lebih mudah dibaca dari kode C sebelumnya adalah:
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;
}
Tabelnya k
sedemikian sehingga k[x] = L(16-x)
, di mana L
linear dalam arti itu L(x^y)==L(x)^L(y)
, dan di mana, seperti dalam C, ^
menunjukkan XOR. Namun, kami tidak berhasil memanfaatkan properti ini untuk mempersingkat implementasi kami. Kami tidak mengetahui adanya struktur di s
mana dapat memungkinkan implementasi yang lebih sederhana --- outputnya selalu di subfield, yaitu mana eksponensial dilakukan di bidang hingga. Tentu saja, Anda benar-benar bebas menggunakan ekspresi yang lebih sederhana jika Anda menemukannya!s
Loop sementara sesuai dengan evaluasi logaritma diskrit di bidang hingga dengan 256 elemen. Ini bekerja melalui pencarian brute-force sederhana: variabel dummy a
diatur untuk menjadi generator dari bidang yang terbatas, dan itu dikalikan dengan generator ini hingga hasilnya sama dengan x
. Ketika itu terjadi, kita memiliki itu l
adalah log diskrit x
. Fungsi ini tidak didefinisikan dalam 0, maka kasus khusus sesuai dengan if
pernyataan tersebut.
Perkalian oleh generator dapat dilihat sebagai perkalian oleh dalam yang kemudian direduksi modulo polinomial . Peran dari ini adalah untuk memastikan bahwa variabel tetap pada 8 bit. Atau, kita bisa menggunakan , dalam hal ini bisa menjadi (atau tipe integer lainnya). Di sisi lain, perlu untuk memulai karena kita perlu memiliki ketika sama dengan 1.unsigned char
a
a=(a<<1)^(a>>7)*(256^29)
a
int
l=1,a=2
l=255
x
Rincian lebih lanjut tentang sifat-sifat p
disajikan dalam makalah kami , dengan penulisan sebagian besar optimasi kami untuk mendapatkan implementasi singkat sebelumnya.
Aturan
Usulkan program yang mengimplementasikan fungsi p
dalam waktu kurang dari 1683 bit. Semakin pendek program, semakin abnormal, untuk bahasa tertentu, semakin pendek lebih baik. Jika bahasa Anda memiliki Kuznyechik, Streebog atau p
sebagai builtin, Anda tidak dapat menggunakannya.
Metrik yang kami gunakan untuk menentukan implementasi terbaik adalah panjang program dalam byte. Kami menggunakan bit-length dalam makalah akademis kami, tetapi kami tetap pada byte di sini demi kesederhanaan.
Jika bahasa Anda tidak memiliki gagasan yang jelas tentang fungsi, argumen, atau keluaran, penyandian terserah Anda untuk menentukan, tetapi trik seperti penyandian nilai pi[x]
seperti x
yang jelas-jelas dilarang.
Kami telah mengirimkan makalah penelitian dengan temuan kami tentang topik ini. Ini tersedia di sini . Namun, jika diterbitkan di tempat ilmiah, kami dengan senang hati akan mengakui penulis implementasi terbaik.
Omong-omong, terima kasih kepada xnor atas bantuannya saat menyusun pertanyaan ini!
1683 bits at most
pembatasan ketat atau tujuan?