新的7级散列函数:Prvhash

2020-08-18 14:01:55

PRVHASH是生成从消息导出的伪随机数序列的散列函数。产生的散列非常接近于位频率的正态分布。PRVHASH在概念上类似于Keccak方案,但完全不同于该概念的实现。

PRVHASH可以生成32位到无限位的散列,从而产生与所选散列长度无关的粗略质量的散列。PRVHASH基于64位数学运算。超过256位的散列仍然需要广泛的测试,但是,例如,从512位或2048位产生的散列中提取的任何32位元素都与32位散列一样具有抗冲突能力。可以很容易地使用超过512位散列的函数,但必须进行统计测试。将哈希函数扩展到128位数学也很有效:这会以指数级增加属性。

PRVHASH完全基于蝴蝶效应,受到LCG伪随机数生成器的强烈启发。生成的散列具有良好的雪崩特性。为获得最佳结果,在创建HMAC时,应向散列函数提供随机种子,但这不是必需的。当集合中的每条消息都是随机种子时,这允许这样的集合的散列近似遵循正态分布。在没有种子的情况下,正态分布是以二阶效应实现的,内部随机数生成器(种子)具有强烈的向对数分布倾斜的分布。在实践中,InitLCG、InitSeed(而不是SeedXOR)和初始散列都可以是随机种子(参见prvhash42.h中的建议),添加有用的初始熵(LCG+种子+总熵的散列位)。

32位、64位、128位和256位PRVHASH散列通过所有SMHasher测试。其他散列长度没有完全测试,但可以进行推断。PRVHASH可能具有加密特性,但这一点还有待证明。此函数最适用于预压缩的最大熵数据。为了处理稀疏熵的情况,PRVHASH以不可能的字节尾部作为伪熵注入来结束消息的散列。在作者看来,此散列函数几乎肯定是不可逆的,因为它不使用固定素数,并且由于位截断引入的非线性。

通过创建一个简单的上下文结构,并将其初始化移到一个单独的函数中,可以很容易地将PRVHASH转换为流散列。它是一个固定时间的散列函数,仅依赖于消息长度。

有关实现的详细信息,请参阅prvhash42.h文件(prvhash.h和prvhash4.h是过时的版本)。Prvhash82.h文件实现相同的功能,但扩展到128位数学:使用某些编译器比prvhash42.h更快。

在大端体系结构(ARM)上,当在系统之间传输散列时,生成的散列的每个散列元素都应该进行字符顺序校正(字节交换)。

PRVHASH还可以用作一个非常有效的通用PRNG,带有外部熵源注入(就像/dev/urandom在Unix上的工作方式):64位散列值可以用作伪随机数,每轮拼接成8个输出字节:当8位真熵注入在8到2048个生成的随机字节之间(延迟也是通过熵源获得)时,这被测试得很好。Prvrng.h文件中实现了一个示例生成器:只需调用prvrng_test64()函数。Prvrng_test32()实现了相同的技术,但出于比较目的使用了32位散列。

另外,PRVHASH PRNG使用32位散列,没有外部熵注入:经过1.1万亿次迭代后,内部伪熵没有丢失。

下面是作者对核心散列函数如何工作的看法(实际上,提出这个解决方案需要大量的试验和错误)。

SEED*=lcg;//随机乘以随机。截断导致的非线性。uint32_t*const hc=(uint32_t*)&;Hash[hpos];//获取哈希字的地址。const uint64_t ph=*hc;//保存当前哈希字。*hc^=(Uint32_T)(seed>;>;32);//将内部熵添加到哈希字。seed^=ph^msg;//add。//将内部熵与";lcg";变量相加(均为随机变量)。截断是可能的。

在没有外部熵(消息)注入的情况下,函数可以长时间运行,生成伪熵而不需要太多重复。当引入外部熵(消息)时,函数不可预测地转变为无关状态。因此,可以说该函数在大量伪随机数生成器的空间内跳跃。Hashlength会影响这个生成器空间的大小,从而允许函数为任何所需的散列长度生成高质量的散列。

可以通过向INTC=(在PrvHash42中)和HL84(在PrvHash82中)添加额外的H142Term来最小化比特偏差。然而,这将增加较短消息的开销。