加密哈希高尔夫


34

比赛结束了。

由于挑战的性质,当对相关强盗挑战的兴趣减少时,警察挑战变得容易得多。因此,尽管您仍然可以发布哈希函数,但是您的答案将不会被接受或成为排行榜的一部分。

这个挑战是最短实施的搜索哈希函数抗碰撞,也就是说,它应该是不可能找到相同的哈希两个不同的消息。

作为警察,您尝试发明并实现一个哈希函数,以在代码大小和抗冲突性之间找到最佳折衷方案。使用太多字节,另一位警察将使您失望!

作为强盗,您尝试通过破坏警察的职能来挫败他们的尝试,证明它们不合适。这将迫使他们使用更多字节来增强算法!

警察挑战

任务

实现加密散列函数H:我- > 0您选择,其中在2以下的集合中的所有非负整数的2 30Ø低于2集的所有非负整数的128

您可以将H实现为实际函数,该函数接受并返回单个整数,整数或整数数组的字符串表示形式,或者从STDIN读取并以10或16为基数打印到STDOUT的完整程序。

计分

  • H必须抵抗下面定义的强盗挑战

    如果强盗在发布后的168小时内将您提交的内容拒之门外,则认为该文件已被破解

  • H的实现应尽可能短。最短的不打扰的提交将是警察挑战赛的获胜者。

附加规则

  • 如果将H实现为函数,请提供一个包装程序,以从行为如上所述的程序中执行该函数。

  • 请为您的程序或包装器至少提供三个测试向量(示例输入及其相应的输出)。

  • H可以是您的新颖设计(首选)或众所周知的算法,只要您自己实现即可。禁止使用任何类型的内置哈希函数,压缩函数,密码,PRNG等。

    通常用于实现哈希函数(例如,基本转换)的任何内置方法都是公平的游戏。

  • 程序或函数的输出必须是确定性的。

  • 应该有一个免费的(如在啤酒中)编译器/解释器,可以在x86或x64平台上或从Web浏览器中运行。

  • 您的程序或函数应该相当高效,并且必须在不到2秒的时间内对I 2 2 19以下的消息进行哈希处理。

    对于边缘情况,在我的计算机(Intel Core i7-3770,16 GiB RAM)上花费的(墙)时间将是决定性的。

  • 考虑到这一挑战的性质,无论是否更改输出,都禁止以任何方式更改答案的代码。

    如果您提交的内容被破解(甚至没有被破解),则可以发布其他答案。

    如果您的答案无效(例如,它不符合I / O规范),请删除它。

Python 2.7,22个字节

def H(M):
 return M%17

包装纸

print H(int(input()))

强盗挑战

任务

通过在强盗的线程中张贴以下内容来破解任何警察的提交:I中的两个消息MN,使得H(M)= H(N)M≠N

计分

  • 破解每个警察提交的内容可以使您获得1分。得分最高的强盗获胜。

    如果是平局,则破解最长提交的并列强盗获胜。

附加规则

  • 每次提交的警察只能被破解一次。

  • 如果警察提交依赖于实现定义的行为或未定义的行为,则只需找到在计算机上可验证的破解即可。

  • 每个破解都属于强盗线程中的一个单独答案。

  • 发布无效的破解尝试会禁止您破解特定的提交文件30分钟。

  • 您可能不会破解自己的提交。

Python 2.7,user8675309的22个字节

1

18

排行榜

安全提交

  1. CJam,由eBusiness提供的21个字节
  2. C ++,tucuxi 148字节
  3. C ++,Vi的233(?)字节。

完整的作品

您可以使用此堆栈片段获取尚未破解的答案的列表。

function g(p){$.getJSON('//api.stackexchange.com/2.2/questions/51068/answers?page='+p+'&pagesize=100&order=desc&sort=creation&site=codegolf&filter=!.Fjs-H6J36w0DtV5A_ZMzR7bRqt1e',function(s){s.items.map(function(a){var h=$('<div/>').html(a.body).children().first().text();if(!/cracked/i.test(h)&&(typeof a.comments=='undefined'||a.comments.filter(function(b){var c=$('<div/>').html(b.body);return /^cracked/i.test(c.text())||c.find('a').filter(function(){return /cracked/i.test($(this).text())}).length>0}).length==0)){var m=/^\s*((?:[^,(\s]|\s+[^-,(\s])+)\s*(?:[,(]|\s-).*?([0-9]+)/.exec(h);$('<tr/>').append($('<td/>').append($('<a/>').text(m?m[1]:h).attr('href',a.link)),$('<td class="score"/>').text(m?m[2]:'?'),$('<td/>').append($('<a/>').text(a.owner.display_name).attr('href',a.owner.link))).appendTo('#listcontent');}});if(s.length==100)g(p+1);});}g(1);
table th, table td {padding: 5px} th {text-align: left} .score {text-align: right} table a {display:block}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script><link rel="stylesheet" type="text/css" href="//cdn.sstatic.net/codegolf/all.css?v=83c949450c8b"><table><tr><th>Language</th><th class="score">Length</th><th>User</th></tr><tbody id="listcontent"></tbody></table>


如果哈希函数错误地返回大于2 ^ 128-1的数字,这会使提交无效,还是我们将结果取模2 ^ 128?
马丁·恩德

@MartinBüttner:是的,您必须将结果取模2 ^ 128。
丹尼斯

1
@Scimonster不满足要求(最多2 ^ 30位输入,128位输出)
CodesInChaos 2015年

1
警察和强盗通常不会反方向走吗?
haneefmubarak

2
也许我们可能有一条规则,即提交必须包含示例散列,必须运行提交者选择的编程语言才能获得结果,以比较那些破解实现的对象。
aaaaaaaaaaaaaa 2015年

Answers:


6

CJam,21个字节

1q3*{i+_E_#*^26_#)%}/

接受一串字节作为输入。

用伪代码:

hash = 1
3 times:
    for i in input:
        hash = hash + i
        hash = hash xor hash * 14^14
        hash = hash mod (26^26 + 1)
output hash

哈希示例:

“”(空字符串)-> 1
“ Test”-> 2607833638733409808360080023081587841
“ test”-> 363640467424586895504738713637444713

可能只是简单一点,输出范围仅比122位略多一点,三重迭代加强已经有点破了,因为每次都做完全相同的事情,因此在第一个中将哈希输入1迭代将是一个完整的休息。但这很短,太安全也没什么好玩的。


是否有与其他CJam帖子一样的随附C版本?
六。

@Vi。不,至少还没有。我从没涉足过bigint的C语言,是否有一个标准库?
aaaaaaaaaaaaaa 2015年

GMP
六。


1
@ Agawa001您正在弄混您的术语。它是三遍海绵函数哈希算法。凯撒密码是一种没有内部状态的特定加密算法。
aaaaaaaaaaaaaa

7

Python中,109个字节[ 破解并再次 ]

def f(n,h=42,m=2**128):
 while n:h+=n&~-m;n>>=128;h+=h<<10;h^=h>>6;h%=m
 h+=h<<3;h^=h>>11;h+=h<<15;return h%m

我尝试按原样实现Jenkins的一次性函数,唯一的区别是种子和位数。

有趣的事实:显然,Perl在某个时候使用了詹金斯的哈希

包装纸

print(f(int(input())))

例子

>>> f(0)
12386682
>>> f(1)
13184902071
>>> f(2**128-1)
132946164914354994014709093274101144634
>>> f(2**128)
13002544814292
>>> f(2**128+1)
13337372262951
>>> f(2**(2**20))
290510273231835581372700072767153076167



6

C ++,148字节

typedef __uint128_t U;U h(char*b,U n,U&o){U a=0x243f6a8885a308d,p=0x100000001b3;for(o=a;n--;)for(U i=27;--i;){o=(o<<i)|(o>>(128-i));o*=p;o^=b[n];}}

__uint128_t是GCC扩展名,可以正常使用。哈希基于迭代FNV哈希(我借用了它们的质数,尽管a是Pi的第一个数字以十六进制表示),并且在每次迭代开始时都具有类似sha1的旋转。使用进行编译-O3,对10MB的文件进行哈希处理需要不到2秒的时间,因此在内部循环中仍有迭代的余地-但是我今天感到很慷慨。

去丑化(更改变量名,添加注释,空格和大括号),以助您开启乐趣:

typedef __uint128_t U;
U h(char* input, U inputLength, U &output){
    U a=0x243f6a8885a308d,p=0x100000001b3;    
    for(output=a;inputLength--;) {   // initialize output, consume input
        for(U i=27;--i;) {                          // evil inner loop
            output = (output<<i)|(output>>(128-i)); // variable roll 
            output *= p;                            // FNV hash steps
            output ^= input[inputLength];        
        }
    }
    // computed hash now available in output
}

欢迎提供打高尔夫球的建议(即使我不能根据这些建议改进代码)。

编辑:修正了取消拼写的代码中的错别字(高尔夫版本保持不变)。


o似乎尚未初始化。output声明在哪里?也许ooutput
六。

相同n。您是否实际检查过“去粉刺”代码以运行?
六。

开始暴力破解...
Vi。

甚至3轮版本也不容易。
六。

@Vi。修复了不符合规定的版本-很抱歉无法更好地对其进行检查。我为这种内在循环感到自豪;U i=81;i-=3没有大量的运行时成本,本来可以变得更加邪恶。
tucuxi

5

CJam,44个字节[ 破解 ]

lW%600/_z]{JfbDbGK#%GC#[md\]}%z~Bb4G#%\+GC#b

输入以10为底。

CJam很慢。我希望它可以在一秒钟内在某些计算机上运行...

说明

lW%600/            e# Reverse, and split into chunks with size 600.
_z                 e# Duplicate and swap the two dimensions.
]{                 e# For both versions or the array:
    JfbDb          e# Sum of S[i][j]*13^i*19^j, where S is the character values,
                   e# and the indices are from right to left, starting at 0.
    GK#%GC#[md\]   e# Get the last 32+48 bits.
}%
z~                 e# Say the results are A, B, C, D, where A and C are 32 bits.
Bb4G#%             e# E = the last 32 bits of A * 11 + C.
\+GC#b             e# Output E, B, D concatenated in binary.

好吧,二维事物似乎是一个弱点...最初是为了更快地进行一些缓慢的计算。但是无论如何我都无法立即运行,因此我最终删除了慢速代码。

如果我使用了二进制位和更高的基数,也应该更好。

C版

__uint128_t hash(unsigned char* s){
    __uint128_t a=0,b=0;
    __uint128_t ar=0;
    __uint128_t v[600];
    int l=0,j=strlen(s);
    memset(v,0,sizeof v);
    for(int i=0;i<j;i++){
        if(i%600)
            ar*=19;
        else{
            a=(a+ar)*13;
            ar=0;
        }
        if(i%600>l)
            l=i%600;
        v[i%600]=v[i%600]*19+s[j-i-1];
        ar+=s[j-i-1];
    }
    for(int i=0;i<=l;i++)
        b=b*13+v[i];
    a+=ar;
    return (((a>>48)*11+(b>>48))<<96)
        +((a&0xffffffffffffull)<<48)
        +(b&0xffffffffffffull);
}

能否请您添加说明?并非所有人都知道CJam。
orlp 2015年

@orlp编辑...
jimmy23013 2015年

这在我的计算机上需要0.4 s,所以它在允许的范围内。
丹尼斯

什么是A,B,C等?一些矩阵?哪个尺寸?可以在C中轻松实现吗?
六。

1
我相信它会破裂
Sp3000

5

C ++,182个字符(+约51个字符的样板)

h=0xC0CC3051F486B191;j=0x9A318B5A176B8125;char q=0;for(int i=0;i<l;++i){char w=buf[i];h+=((w<<27)*257);j^=(h+0x5233);h+=0xAA02129953CC12C3*(j>>32);j^=(w+0x134)*(q-0x16C552F34);q=w;}

样板:

void hash(const unsigned char* buf, size_t len, unsigned long long *hash1, unsigned long long *hash2)
{
    unsigned long long &h=*hash1;
    unsigned long long &j=*hash2;
    size_t l = len;
    const unsigned char* b = buf;

    // code here
}

具有高尔夫功能的可运行程序

#include <stdio.h>

// The next line is 227 characters long
int hash(char*b,int l,long long&h,long long&j){h=0xC0CC3051F486B191;j=0x9A318B5A176B8125;char q=0;for(int i=0;i<l;++i){char w=b[i];h+=((w<<27)*257);j^=(h+0x5233);h+=0xAA02129953CC12C3*(j>>32);j^=(w+0x134)*(q-0x16C552F34);q=w;}}

int main() {
    char buf[1024];
    int l  = fread(buf, 1, 1024, stdin);
    long long q, w;
    hash(buf, l, q, w);
    printf("%016llX%016llX\n", q, w);
}

2
我认为函数声明等都计入字符数。
Ypnypn

@Ypnypn,在golfing down函数声明中计数的字符。
六。

什么是输出哈希?我假设它是((h << 64)| j)。
tucuxi 2015年

是。或者只是一对64位数字。我__uint128_t只有实现了才发现。
六。

1
@Dennis,Done.󠀠
六。

4

Pyth,8 破裂

sv_`.lhQ

在线尝试

有点愚蠢的答案,我将解释它的工作原理,因为大多数人看不懂Pyth。这将自然对数加一个输入,然后将其转换为字符串。该字符串被反转,然后求值,然后转换为整数。

python翻译如下所示:

import math
n = eval(input()) + 1
rev = str(math.log(n))[::-1]
print(int(eval(rev)))


4

Python 3,216个字节[ 破解 ]

def f(m):
 h=1;p=[2]+[n for n in range(2,102)if 2**n%n==2];l=len(bin(m))-2;*b,=map(int,bin((l<<(l+25)//26*26)+m)[2:])
 while b:
  h*=h
  for P in p:
   if b:h=h*P**b.pop()%0xb6ee45a9012d1718f626305a971e6a21
 return h

由于与规范不兼容,我可以想到至少一个轻微的漏洞,但除此之外,我认为这至少是蛮力的证明。除其他外,我已经检查了前1000万个哈希。

在高尔夫方面,这在Python 2中会更短一些,但我牺牲了一些字节来提高效率(因为无论如何它都不会取胜)。

编辑:这是我尝试实现Very Smooth Hash的尝试,但是不幸的是128位太小了。

包装纸

print(f(int(input())))

例子

>>> f(0)
2
>>> f(123456789)
228513724611896947508835241717884330242
>>> f(2**(2**19)-1)
186113086034861070379984115740337348649
>>> f(2**(2**19))
1336078

代码说明

def f(m):
 h=1                                             # Start hash at 1
 p=[2]+[n for n in range(2,102)if 2**n%n==2]     # p = primes from 2 to 101
 l=len(bin(m))-2                                 # l = bit-length of m (input)
 *b,=map(int,bin((l<<(l+25)//26*26)+m)[2:])      # Convert bits to list, padding to
                                                 # a multiple of 26 then adding the
                                                 # bit-length at the front

 while b:                                        # For each round
  h*=h                                           # Square the hash
  for P in p:                                    # For each prime in 2 ... 101
   if b:h=(h*P**b.pop()                          # Multiply by prime^bit, popping
                                                 # the bit from the back of the list
           %0xb6ee45a9012d1718f626305a971e6a21)  # Take mod large number

 return h                                        # Return hash

填充的示例f(6)

[1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 0]

(len 3)(------------------ 23 zeroes for padding -------------------------)(input 6)
       (---------------------------- length 26 total ------------------------------)


4

C,87字节[ 破解 ]

这是完整的程序;无需包装。通过stdin接受二进制输入,并将十六进制哈希输出到stdout。

c;p;q;main(){while((c=getchar())+1)p=p*'foo+'+q+c,q=q*'bar/'+p;printf("%08x%08x",p,q);}

这仅计算64位哈希,因此我在这里进行了一些赌博。

如果有人想知道,则两个常数'foo+''bar/'是质数1718578987和1650553391。


例子:

忽略前导零:

echo -ne '\x00\x00\x00\x00' |./hash
0000000000000000

单字节输入:

echo -ne '\x01' |./hash
0000000100000001
echo -ne '\xff' |./hash
000000ff000000ff

多字节输入:

echo -ne '\x01\x01' |./hash
666f6f2dc8d0e15c
echo -ne 'Hello, World' |./hash
04f1a7412b17b86c

它是如何将与“aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa”和“aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa”行为?
Ismael Miguel

1
foo|(d5c9bef71d4f5d1b)和foo\(d5c9bef71d4f5d1b)会产生非常相似的哈希值。
Ismael Miguel

1
打破它!!!\x00\x00\x00
Ismael Miguel 2015年

1
根据聊天评论,我相信这还没有破解吗?只是仔细检查一下,因为被批评的评论可能会使那些浏览未破解哈希的人感到困惑。
Sp3000


3

J-39个字节- 破解

以字符串作为输入并返回整数<2 128的函数。我假设我们必须将函数命名为有效,因此如果可以提交匿名函数,则从计数中再减去3个字符。

H=:_8(".p:@+5,9:)a\(a=.(2^128x)&|@^/@)]

对于那些不阅读象形文字的人,以下是我正在做的事情的简要介绍。

  • a=.(2^128x)&|@^/@这是一个子例程*,它接受一个数字数组,然后将其视为电力塔,其中幂取值取值模2 128。所谓“电力塔”,是指如果您给它输入信息3 4 5 6,它将进行计算3 ^ (4 ^ (5 ^ 6))
  • (".p:@+5,9:)a此函数接受一个字符串,将其转换为数字N,然后计算第(n +5)个和第(n +9)个质数,然后将afrom放在其上。也就是说,我们发现p(n+5) ^ p(n+9)MOD 2 128这里p(k)k个素数。
  • H=:_8...\(a...)]对输入的8个字符的子块执行上述功能,然后将a所有结果汇总在一起,并调用结果哈希函数H。我使用8个字符,因为kp(k)> 2 31时,J的“ -th素数”函数失败,即k=105097564是最大的安全k

有一些示例输出。您可以在tryj.tk上在线尝试此操作,但是我真的建议您从Jsoftware下载解释器,在家中进行操作

   H=:_8(".p:@+5,9:)a\(a=.(2^128x)&|@^/@)]
   H '88'
278718804776827770823441490977679256075
   H '0'
201538126434611150798503956371773
   H '1'
139288917338851014461418017489467720433
   H '2'
286827977638262502014244740270529967555
   H '3'
295470173585320512295453937212042446551
   30$'0123456789'  NB. a 30 character string
012345678901234567890123456789
   H 30$'0123456789'
75387099856019963684383893584499026337
   H 80$'0123456789'
268423413606061336240992836334135810465

*从技术上讲,它本身并不是一个函数,它会附加到其他函数并对其输出起作用。但这是J的语义问题,而不是概念上的区别:程序流程如上所述。



2

Python 3,118个字节[ 破解 ]

def H(I):
    o=0;n=3;M=1<<128
    for c in I:i=ord(c);o=(o<<i^o^i^n^0x9bb90058bcf52d3276a7bf07bcb279b7)%M;n=n*n%M
    return o

缩进是一个选项卡。简单的哈希,还没有真正对其进行彻底的测试。

调用如下:

print(H("123456789"))

结果: 73117705077050518159191803746489514685


如何将输入整数转换为字符串以在算法中使用?
feersum 2015年

@feersum base-10字符串是我测试过的。它不使用任何东西,ord(c)但是,实际上,任何字符串都可以:)(除了nul chars之类的东西,我认为那些使哈希冲突非常容易。所以坚持使用0-9字符串。)
tomsmeding

1
打破它: codegolf.stackexchange.com/a/51160/41288。首先观察“ 10000”和“ 20000”之类的字符串会产生非常接近的哈希值。开始使用越来越多的零,并且在128个左右之后,任何数字+ k * 4个零重复都会返回相同的哈希值,而与k无关。
tucuxi

@tucuxi已经认为它不应该费劲;很高兴那不是小事,但有人反正把它弄坏了。辛苦了
tomsmeding

2

C ++,239个字节

我的第一个代码高尔夫![ 请保持温柔 ]

#define r(a,b) ((a<<b)|(a>>(64-b)))
typedef uint64_t I;I f(I*q, I n, I&h){h=0;for(I i=n;--i;)h=r(h^(r(q[i]*0x87c37b91114253d5,31)*0x4cf5ad432745937f),31)*5+0x52dce729;h^=(h>>33)*0xff51afd7ed558ccd;h^=(h>>33)*0xc4ceb9fe1a85ec53;h^=(h>>33);}

非高尔夫版本:

I f(I* q, I n, I& h) // input, length and output
{
    h = 0; // initialize hashes
    for (I i=n;--i;)
    {
        q[i] *= 0x87c37b91114253d5;
        q[i]  = rotl(q[i], 31);
        q[i] *= 0x4cf5ad432745937f;

        h ^= q[i]; // merge the block with hash

        h *= rotl(h, 31);
        h = h * 5 + 0x52dce729;
    }
    h ^= h>>33;
    h *= 0xff51afd7ed558ccd;
    h ^= h>>33;
    h *= 0xc4ceb9fe1a85ec53; // avalanche!
    h ^= h>>33;
}

不是最好的哈希,而且绝对不是现有的最短代码。接受高尔夫技巧并希望有所提高!

包装纸

可能不是世界上最好的,但仍然是包装纸

I input[500];

int main()
{
    string s;
    getline(cin, s);
    memcpy(input, s.c_str(), s.length());
    I output;
    f(input, 500, output);
    cout << hex << output << endl;
}

2
看起来很坚固,但有64位,可能会受到蛮力攻击。在〜sqrt(n)测试中(从n个总输出中)发现冲突的机率大约为50%;对于现代PC,2 ^ 32次尝试并不多。
tucuxi

包装程序缺少标头包含,通常会导致许多相等的哈希。
六。

提供一些哈希样本。对我来说,“ 3”和“ 33”都指向481c27f26cba06cf(使用此包装器)。
六。

破解:codegolf.stackexchange.com/a/51215/41288。我怀疑@Vi之前。找出为什么这么多哈希是相等的。
tucuxi

1
正确的碰撞(不使用错误):printf '33333333\x40\xF3\x32\xD6\x56\x91\xCA\x66' | ./hash7_-> a4baea17243177fd; printf '33333333\x77\x39\xF3\x82\x93\xDE\xA7\x2F' | ./hash7_-> a4baea17243177fd。与此处的其他64位哈希相比,暴力破解者在此处发现冲突的速度要快得多。
六。

2

Java中,299个 291 282字节,破获。

import java.math.*;class H{public static void main(String[]a){BigInteger i=new java.util.Scanner(System.in).nextBigInteger();System.out.print(BigInteger.valueOf(i.bitCount()*i.bitLength()+1).add(i.mod(BigInteger.valueOf(Long.MAX_VALUE))).modPow(i,BigInteger.valueOf(2).pow(128)));}}

对BigIntegers进行一些运算,然后取结果为2 128模。


我该如何运行?Ideone拒绝对其进行编译。
马丁·恩德

1
通过将类重命名为“ Main”或删除第一个“ public”关键字(而不是第二个关键字),可以在Ideone上运行它。任一个都会起作用。
SuperJedi224


1
@ SuperJedi224为什么不删除public自己的第一个字符,节省7个字符?
user253751

@immibis因为那之后我认为它在Eclipse上无法正常工作。我会尝试的。编辑:我想是的。真是令人惊讶
SuperJedi224

2

C,128字节[ 破解 ]

p;q;r;s;main(c){while((c=getchar())+1)p=p*'foo+'+s^c,q=q*'bar/'+p,r=r*'qux3'^q,s=s*'zipO'+p;printf("%08x%08x%08x%08x",p,q,r,s);}

该算法与我上次尝试 (由Vi。破解)大致相同,但是现在具有足够的仓鼠轮来生成适当的128位哈希。

代码中的四个素常数如下:

'foo+' = 1718578987
'bar/' = 1650553391
'qux3' = 1903523891
'zipO' = 2053730383

和以前一样,这是一个无需包装的完整程序。整数I通过stdin作为原始二进制数据(big-endian)输入,并且哈希O以十六进制打印到stdout。I中的前导零被忽略。

例子:

echo -ne '\x00' |./hash
00000000000000000000000000000000
echo -ne '\x00\x00' |./hash
00000000000000000000000000000000
echo -ne '\x01' |./hash
00000001000000010000000100000001
echo -ne 'A' |./hash
00000041000000410000004100000041
echo -ne '\x01\x01' |./hash
666f6f2dc8d0e15cb9a5996fe0d8df7c
echo -ne 'Hello, World' |./hash
da0ba2857116440a9bee5bb70d58cd6a


您的示例没有在此处显示碰撞(前两个)吗?
mbomb007

@ mbomb007编号。输入是0到2 ^(2 ^ 30)之间的数字。0x00和0x0000都等于零,因此它们产生相同的输出。
吱吱作响的ossifrage,2015年

2

C,122字节[ 破解 ]

long long x,y,p;main(c){for(c=9;c|p%97;c=getchar()+1)for(++p;c--;)x=x*'[3QQ'+p,y^=x^=y^=c*x;printf("%016llx%016llx",x,y);}

嵌套循环,半确定的LCG和变量交换。不去爱的种种?

这是一个非高尔夫版本可以使用:

long long x,y,p;

int main(int c){
    // Start with a small number of iterations to
    //   get the state hashes good and mixed because initializing takes space
    // Then, until we reach the end of input (EOF+1 == 0)
    //   and a position that's a multiple of 97
    for (c=9;c|p%97;c=getchar()+1) {

        // For each input c(haracter) ASCII value, iterate down to zero
        for (++p;c--;) {

            // x will act like a LCG with a prime multiple
            //   partially affected by the current input position
            // The string '[3QQ' is the prime number 0x5B335151
            x=x*'[3QQ'+p;

            // Mix the result of x with the decrementing character
            y^=c*x;

            // Swap the x and y buffers
            y^=x^=y;
        }
    }

    // Full 128-bit output
    printf("%016llx%016llx",x,y);
    return 0;
}

这是一个完全自包含的程序,可从STDIN读取并打印到STDOUT。

例:

> echo -n "Hello world" | ./golfhash
b3faef341f70c5ad6eed4c33e1b55ca7

> echo -n "" | ./golfhash
69c761806803f70154a7f816eb3835fb

> echo -n "a" | ./golfhash
5f0e7e5303cfcc5ecb644cddc90547ed

> echo -n "c" | ./golfhash
e64e173ed4415f7dae81aae0137c47e5

在一些简单的基准测试中,它的哈希值约为3MB / s的文本数据。哈希速度取决于输入数据本身,因此应该考虑在内。



1

PHP 4.1,66字节[ 破解 ]

我只是在热身。

希望您能体会到这一点。

<?for($l=strlen($b.=$a*1);$i<40;$o.=+$b[+$i]^"$a"/$a,$i++);echo$o;

我尝试过使用最大为999999999999999999999999999
的数字。输出似乎在2128范围内。


由于该register_globals指令,需要PHP 4.1 。

它通过从会话,POST,GET,REQUEST和cookie自动创建局部变量来工作。

它使用密钥a。(例如:访问http://localhost/file.php?a=<number>)。

如果要使用PHP 4.2和更高版本进行测试,请尝试以下操作:

<?for($l=strlen($b.=$a=$_REQUEST['a']*1);$i<40;$o.=+$b[+$i]^"$a"/$a,$i++);echo$o;

此版本仅适用于POST和GET。


输出示例:

0 -> 0000000000000000000000000000000000000000
9 -> 8111111111111111111111111111111111111111
9999 -> 8888111111111111111111111111111111111111
1234567890 -> 0325476981111111111111111111111111111111
99999999999999999999999999999999999999999999999999999999999999999999999999999999 -> 0111191111111111111111111111111111111111

(我向您保证,有些数字会产生相同的哈希值)。



1

C,134字节,已破解

这是完整的C程序。

long long i=0,a=0,e=1,v,r;main(){for(;i++<323228500;r=(e?(scanf("%c",&v),e=v>'/'&&v<':',v):(a=(a+1)*7)*(7+r)));printf("0x%llx\n", r);}

它的作用:想法是将输入作为字节数组,并在末尾附加伪随机(但确定性)字节,以使长度等于大约2 2 30(多一点)。该实现逐字节读取输入,并在找到第一个非数字字符时开始使用伪随机数据。

由于不允许内置PRNG,因此我自己实现了它。

有一个未定义/实现定义的行为会使代码更短(最终值应为无符号,对于不同的值,我应使用不同的类型)。而且我不能在C中使用128位值。

long long i = 0, prand = 0, notEndOfInput = 1, in, hash;

main() {
    for (; i++ < 323228500;) {
        if (notEndOfInput) {
            scanf("%c", &in);
            notEndOfInput = in >= '0' && in <= '9';
            hash = in;
        } else {
            prand = (prand + 1)*7;
            hash = prand*(7 + hash);
        }
    }
    printf("0x%llx\n", hash);
}


1

Python 2.X-139字节 [[ 破解 ]]

这与所有其他哈希(LOOP,XOR,SHIFT,ADD)非常相似。来吧,抢劫点吧;)解决这个问题后,我会再努力一点。

M=2**128
def H(I):
 A=[1337,8917,14491,71917];O=M-I%M
 for z in range(73):
  O^=A[z%4]**(9+I%9);O>>=3;O+=9+I**(A[z%4]%A[O%4]);O%=M
 return O

包装器(期望base-16中的一个参数也称为十六进制):

import sys
if __name__ == '__main__':
 print hex(H(long(sys.argv[1], 16)))[2:][:-1].upper()


1
另外,我不确定该条目是否符合OP的规格,因为在我的机器上,该功能在大型输入上需要花费几秒钟的时间。例如,H(2**(2**10))花费了大约8或9秒,而H(2**(2**12))花费了大约29秒并且H(2**(2**14))花费了2分钟以上。
mathmandan

您完全正确,我显然应该测试较大输入的时序。另外,在添加该班次后,我似乎忘记了运行自己的测试。原始版本没有变化(发布之前),并且通过了我的“前100000个整数中无冲突”测试:/
困惑的2015年

1

Python 2.7-161字节[[ 破解 ]]

好吧,因为在发布之前我设法将第一个哈希函数更改为无用的版本,所以我想我将发布具有类似结构的另一个版本。这次我对它进行了微不足道的碰撞测试,并测试了大多数可能的输入幅度的速度。

A=2**128;B=[3,5,7,11,13,17,19]
def H(i):
 o=i/A
 for r in range(9+B[i%7]):
  v=B[i%7];i=(i+o)/2;o=o>>v|o<<128-v;o+=(9+o%6)**B[r%6];o^=i%(B[r%6]*v);o%=A
 return o

包装器(不计入字节数)

import sys
if __name__ == '__main__':
 arg = long(sys.argv[1].strip(), 16)
 print hex(H(arg))[2:][:-1].upper()

运行示例(输入始终为十六进制数):

$ python crypt2.py 1
3984F42BC8371703DB8614A78581A167
$ python crypt2.py 10
589F1156882C1EA197597C9BF95B9D78
$ python crypt2.py 100
335920C70837FAF2905657F85CBC6FEA
$ python crypt2.py 1000
B2686CA7CAD9FC323ABF9BD695E8B013
$ python crypt2.py 1000AAAA
8B8959B3DB0906CE440CD44CC62B52DB


做得好吉米:)
2015年

1

Ruby,90字节

def H(s);i=823542;s.each_byte{|x|i=(i*(x+1)+s.length).to_s.reverse.to_i%(2**128)};i;end

我编写了一个高度随机的哈希算法,没有看任何真实的哈希值……不知道它是否好。它需要一个字符串作为输入。

包装器:

def buildString(i)
  if(i>255)
    buildString(i/256)+(i%256).chr
  else
    i.chr
  end
end 
puts H buildString gets

您能否提供问题所需的包装纸?
丹尼斯

输入格式是什么?我尝试了一个数字,但是上面写着comparison of String with 255 failed (ArgumentError)
jimmy23013 2015年

H接受一个字符串,Build字符串接受OP所需的数字并将其转换为字符串。
MegaTom 2015年

我认为您需要gets.to_i包装纸。
jimmy23013 2015年



0

PHP,79字节(破裂。带有注释):

echo (('.'.str_replace('.',M_E*$i,$i/pi()))*substr(pi(),2,$i%20))+deg2rad($i);

这会通过php中的类型转换来做很多令人恐惧的事情,这使得很难预测;)(或者至少我希望如此)。但是,这不是最短或最不可读的答案。

要运行它,您可以使用PHP4并注册全局变量(?i = 123)或使用命令行:

php -r "$i = 123.45; echo (('.'.str_replace('.',M_E*$i,$i/pi()))*substr(pi(),2,$i%20))+deg2rad($i);"

5
哈希的输出值看起来是浮点数。
Vi。

0

C#-393个字节已破解

using System;class P{static void Main(string[]a){int l=a[0].Length;l=l%8==0?l/8:l/8+1;var b=new byte[l][];for(int i=0;i<l;i++){b[i]=new byte[8];};int j=l-1,k=7;for(int i=0;i<a[0].Length;i++){b[j][k]=Convert.ToByte(""+a[0][i],16);k--;if((i+1)%8==0){j--;k=7;}}var c=0xcbf29ce484222325;for(int i=0;i<l;i++){for(int o=0;o<8;o++){c^=b[i][o];c*=0x100000001b3;}}Console.WriteLine(c.ToString("X"));}}

取消高尔夫:

using System;
class P
{
    static void Main(string[]a)
    {
      int l = a[0].Length;
      l = l % 8 == 0 ? l / 8 : l / 8 + 1;
      var b = new byte[l][];
      for (int i = 0; i < l; i++) { b[i] = new byte[8]; };
      int j = l-1, k = 7;
      for (int i = 0; i < a[0].Length; i++)
      {
        b[j][k] = Convert.ToByte(""+a[0][i], 16);
        k--;
        if((i+1) % 8 == 0)
        {
          j--;
          k = 7;
        }
      }
      var c = 0xcbf29ce484222325;
      for (int i = 0; i < l; i++)
      {
        for (int o = 0; o < 8; o++)
        {
          c ^= b[i][o];
          c *= 0x100000001b3;
        }
      }
      Console.WriteLine(c.ToString("X"));
    }
}

我一生中从未接触过密码学或哈希算法,所以要格外:)

这是FNV-1a哈希的简单实现,其中一些数组以输入为中心。我相信有更好的方法可以做到这一点,但这是我所能做的最好的。

长输入可能会占用一点内存。


破解:codegolf.stackexchange.com/a/51277/101除了错误的填充之外,这不是加密哈希,有很多破解它的方法。
aaaaaaaaaaaaaa 2015年

0

Python 2,115字节[ 已经破解!]

好,这是我最后的努力。仅115个字节,因为不需要最后的换行符。

h,m,s=1,0,raw_input()
for c in[9+int(s[x:x+197])for x in range(0,len(s),197)]:h+=pow(c,257,99**99+52)
print h%4**64

这是一个完整的程序,在stdin上输入一个十进制整数,并在stdout上打印一个十进制哈希值。额外的前导零将导致不同的哈希值,因此我仅假设输入中没有任何值。

这是通过模幂填充197位数字的输入数字的块。与某些语言不同,该int()函数始终默认默认为10,而int('077')不是63。

样本输出:

$ python hash.py <<<"0"
340076608891873865874583117084537586383

$ python hash.py <<<"1"
113151740989667135385395820806955292270

$ python hash.py <<<"2"
306634563913148482696255393435459032089

$ python hash.py <<<"42"
321865481646913829448911631298776772679

$ time python hash.py <<<`python <<<"print 2**(2**19)"`
233526113491758434358093601138224122227

real    0m0.890s   <-- (Close, but fast enough)
user    0m0.860s
sys     0m0.027s

1
它没有使用块的顺序... Cracked
jimmy23013 2015年

啊。我接受:-(
吱吱作响的ossifrage
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.