这一挑战的目标是找到一个不可能短期实现以下功能p
,在您选择的langage。这是实现它的C代码(请参阅
此TIO链接,也将输出其输出)和包含该代码的Wikipedia页面。
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和块密码Kuznyechik。在本文中(以及在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位。单击此处查看它是否有效。
我们谈论“不可能”的简短实现是因为,如果排列是随机过程的输出(如其设计者所声称的那样),那么这种简短的程序将不存在(有关更多详细信息,请参见本页)。
参考实施
以前的C代码的可读性更高的版本是:
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)
,并且像C中一样,^
表示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位实现该功能。程序越短,对于给定的语言,越短越好。如果您的语言碰巧具有Kuznyechik,Streebog或p
作为内置语言,则不能使用它们。
我们用来确定最佳实现的度量标准是程序长度(以字节为单位)。我们在学术论文中使用位长,但是为了简单起见,我们在这里坚持使用字节长。
如果你的语言不具备的功能,参数或输出一个清晰的概念,编码是由你来定义,但像编码值招数pi[x]
作为x
显然是禁止的。
我们已经提交了一份有关此主题研究结果的研究论文。在这里可用。但是,如果要在科学的地点发表,我们将很高兴地向您推荐最佳实现的作者。
顺便说一句,感谢xnor在起草这个问题时所提供的帮助!
1683 bits at most
严格的限制还是“目标”?