암호화 해시 골프


34

이 콘테스트는 끝났습니다.

도전 과제 의 특성으로 인해 관련 강도 도전에 대한 관심이 줄어들면 경찰 도전이 훨씬 쉬워집니다. 따라서 여전히 해시 함수를 게시 할 수 있지만 답변이 수락되지 않거나 리더 보드의 일부를 구성하지는 않습니다.

이 과제는 충돌에 강한 해시 함수 의 최단 구현을 검색 하는 것입니다 . 즉, 동일한 해시로 두 개의 다른 메시지를 찾을 수 없어야합니다.

경찰은 코드 크기와 충돌 내성 간의 최상의 절충안을 찾는 해시 함수를 발명하고 구현하려고합니다. 너무 많은 바이트를 사용하면 다른 경찰이 당신을 능가합니다!

강도로서, 경찰은 자신의 기능을 해독하여 부적합하다는 것을 증명함으로써 경찰의 ​​시도를 망가 뜨리려고합니다. 그러면 알고리즘을 강화하기 위해 더 많은 바이트를 사용하게됩니다!

경찰 도전

태스크

선택한 암호화 해시 함수 H : I-> O 를 구현하십시오. 여기서 I 는 2 2 30 미만 의 모든 음이 아닌 정수 세트 이고 O 는 2 128 미만의 모든 음이 아닌 정수 세트입니다 .

단일 정수, 정수 또는 정수 배열의 문자열 표현 또는 STDIN에서 읽고 기본 10 또는 16에서 STDOUT으로 인쇄하는 전체 프로그램을 받아들이고 리턴하는 실제 함수로 H 를 구현할 수 있습니다 .

채점

  • H 아래에 정의 된 강도 도전 에 저항 해야 합니다.

    강도가 게시 후 처음 168 시간 내에 제출을 물리 치면 금이 간 것으로 간주됩니다 .

  • H 의 구현은 가능한 한 짧아야합니다. 가장 짧은 무단 제출은 경찰 도전의 승자가 될 것입니다.

추가 규칙

  • H 를 함수로 구현하는 경우 위에서 설명한대로 동작하는 프로그램 내에서 함수를 실행할 래퍼를 제공하십시오.

  • 프로그램 또는 래퍼 (예 : 입력 및 해당 출력)에 대해 적어도 세 개의 테스트 벡터를 제공하십시오.

  • H 는 직접 구현하는 한 새로운 디자인 (선호) 또는 잘 알려진 알고리즘 일 수 있습니다. 내장 된 해시 함수, 압축 함수, 암호, PRNG 등을 사용하는 것은 금지되어 있습니다.

    해싱 함수 (예 : 기본 변환) 를 구현 하는 데 일반적으로 사용되는 모든 내장 게임은 공정한 게임입니다.

  • 프로그램 또는 함수의 출력은 결정적이어야합니다.

  • x86 또는 x64 플랫폼에서 또는 웹 브라우저 내에서 실행할 수있는 비어있는 컴파일러 / 인터프리터가 있어야합니다.

  • 귀하의 프로그램 또는 기능은 합리적으로 효율적 이어야하며 1 초 이내에 2 2 19 미만의 I 메시지를 해시해야합니다 .

    가장자리의 경우 내 컴퓨터 (Intel Core i7-3770, 16GiB RAM)에서 소요되는 (벽) 시간이 결정적입니다.

  • 이 과제의 특성상 출력 변경 여부에 관계없이 어떤 방식 으로든 답변 코드를 변경하는 것은 금지되어 있습니다.

    제출물에 금이 간 경우 (또는 그렇지 않은 경우에도) 추가 답변을 게시 할 수 있습니다.

    답변이 유효하지 않은 경우 (예 : I / O 사양을 준수하지 않는 경우) 삭제하십시오.

파이썬 2.7, 22 바이트

def H(M):
 return M%17

싸개

print H(int(input()))

강도 도전

태스크

'는 다음 사항을 게시하여 제출 경찰 어떠한 균열 스레드 강도' 개의 메시지 : MN을I 되도록 H (M) = H (N)M ≠ N .

채점

  • 각 경찰 제출물을 크래킹하면 1 ​​포인트가됩니다. 가장 많은 점수를 얻은 강도가 승리합니다.

    동점 인 경우, 가장 긴 제출을 금한 묶인 강도가 승리합니다.

추가 규칙

  • 모든 경찰 제출은 한 번만 해킹 할 수 있습니다.

  • 경찰 제출이 구현 정의 또는 정의되지 않은 동작에 의존하는 경우 시스템에서 (확인 가능) 작동하는 균열 만 찾으면됩니다.

  • 각 균열은 강도 실에서 별도의 답변에 속합니다.

  • 잘못된 크래킹 시도를 게시하면 30 분 동안 해당 특정 크래킹이 크래킹되지 않습니다.

  • 당신은 당신 자신의 제출물을 해독 할 수 없습니다.

Python 2.7, 사용자 별 22 바이트

1

18

리더 보드

안전한 제출

  1. CJAM, eBusiness에서 21 바이트
  2. C ++, 148 바이트 (tucuxi)
  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을 가져와야합니다.
Dennis

1
@Scimonster가 요구 사항을 충족하지 못함 (최대 2 ^ 30 비트 입력, 128 비트 출력)
CodeInChaos

1
경찰과 강도는 대개 반대 방향으로 가지 않습니까?
haneefmubarak 2018 년

2
아마도 우리는 제출물에 예제 해시를 포함해야한다는 규칙을 가지고있을 수 있습니다. 구현 자와 크래킹을 비교하는 결과를 얻기 위해 제출자가 선택한 프로그래밍 언어를 실행해야한다는 것은 매우 성가신 일입니다.
aaaaaaaaaaaa

답변:


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
"테스트"-> 2607833638733409808360080023081587841
"test"-> 363640467424586895504738713637444713

그것은 간단한면에 약간있을 수 있으며, 출력 범위는 122 비트 이상이며, 트리플 반복 강화는 매번 똑같은 일을하기 때문에 이미 약간 깨졌습니다. 반복은 완전히 중단됩니다. 그러나 짧고 너무 안전하다는 재미는 없습니다.


다른 CJam 게시물과 같은 C 버전이 있습니까?
Vi.

@Vi. 아니요, 아직은 아닙니다. 나는 C에서 bigint를 다루지 않았다. 표준 라이브러리가 있습니까?
aaaaaaaaaaaa

GMP ?
Vi.


1
@ Agawa001 용어가 섞여 있습니다. 트리플 패스 스펀지 함수 해시 알고리즘입니다. 시저 암호는 내부 상태가없는 하나의 특정 암호화 알고리즘입니다.
aaaaaaaaaaaa

7

파이썬, 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은 어느 시점에서 Jenkins의 해시를 사용했습니다 .

싸개

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 해시 (각 a16 진수의 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선언되어 있습니까? 아니면 o입니다 output?
Vi.

에 대해서도 동일합니다 n. 실제로 "제거되지 않은"코드가 실행되도록 확인 했습니까?
Vi.

무차별 범을 시작 ...
Vi.

3 라운드 버전조차 쉽지 않습니다.
Vi.

@Vi. 수정되지 않은 버전 수정-더 이상 확인하지 않아서 죄송합니다. 나는 그 내부 루프를 자랑스럽게 생각합니다. U i=81;i-=3런타임 비용이 많이 들지 않으면 서 훨씬 더 사악했을 수 있습니다.
tucuxi

5

CJam, 44 바이트 [ 크랙 ]

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

입력은 10 진입니다.

CJam은 느립니다. 일부 컴퓨터에서 1 초 안에 실행되기를 바랍니다.

설명

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

@orlp 편집 ...
jimmy23013 2016 년

내 컴퓨터에서 0.4 초가 걸리므로 허용 범위 내에 있습니다.
Dennis

A, B, C 등은 무엇입니까? 일부 매트릭스? 어느 치수? C로 쉽게 구현할 수 있습니까?
Vi.

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, 골프 다운 함수 선언에서 문자를 세었습니다.
Vi.

출력 해시는 무엇입니까? 나는 그것이 ((h << 64) | j)라고 가정합니다.
tucuxi 2016 년

예. 또는 한 쌍의 64 비트 숫자입니다. 나는 __uint128_t이것을 구현 한 후에 만 알았습니다 .
Vi.

1
@Dennis, Done.󠀠
Vi.

4

피시스, 8 금이

sv_`.lhQ

온라인으로 사용해보십시오

어리석은 대답은 대부분의 사람들이 Pyth를 읽을 수 없기 때문에 어떻게 작동하는지 설명하겠습니다. 이것은 1의 자연 로그에 입력을 더한 다음 문자열로 변환합니다. 해당 문자열을 반대로 한 다음 평가 한 다음 정수로 변환합니다.

파이썬 번역은 다음과 같습니다.

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

사양과의 비 호환성으로 인해 적어도 하나의 사소한 취약점에 대해 생각할 수 있지만, 이것이 최소한 무차별적인 증거라고 생각합니다. 다른 것들 중에서도 처음 천만개의 해시를 확인했습니다.

골프 측면에서 이것은 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을 통한 이진 입력을 허용하고 16 진 해시를 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입니다.


예 :

선행 0을 무시합니다.

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

'aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa'와 'aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa'와 'aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa'는 어떻게 행동합니까?
Ismael Miguel

1
foo|(d5c9bef71d4f5d1b) 및 foo\(d5c9bef71d4f5d1b)는 매우 유사한 해시를 생성 합니다.
Ismael Miguel

1
파산 !!! \x00그리고 \x00\x00!
Ismael Miguel

1
채팅 댓글을 바탕으로 아직 이것이 크랙되지 않았다고 생각합니까? upvoted 의견은 깨지지 않은 해시를 감추고있는 사람들에게는 혼란 스러울 수 있으므로 두 번 확인하십시오.
Sp3000


3

J-39 바이트- 금이 간

문자열을 입력으로 받아서 정수 <2 128을 반환하는 함수 . 함수의 이름을 유효하게 지정해야한다고 가정하므로 익명 함수를 제출할 수 있으면 다른 3자를 삭제하십시오.

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

상형 문자를 읽지 않는 사람들을 위해 여기 내가하는 일에 대한 요약이 있습니다.

  • a=.(2^128x)&|@^/@이것은 서브 루틴 *으로 숫자 배열을 취한 다음 지수를 전력 타워로 취급합니다. 여기서 지수는 mod 2 128 입니다. "파워 타워"는 입력 3 4 5 6을 주면 계산 한다는 의미 3 ^ (4 ^ (5 ^ 6))입니다.
  • (".p:@+5,9:)a이 함수는 문자열을 가져 와서 숫자 N으로 변환 한 다음 ( n +5) 번째 및 ( n +9) 번째 소수를 계산 한 다음 a이전부터 시작합니다. 즉 우리가 찾을 수있다 p(n+5) ^ p(n+9)2 모드 128p(k)은 IS k번째 수상.
  • H=:_8...\(a...)]입력의 8 문자 서브 블록에 대해 위 기능을 수행 한 다음 a모든 결과를 함께 수행하고 결과 해시 함수를 호출하십시오 H. J의 " k-th prime"기능이 p(k)> 2 31을 초과 할 때 ( 즉 k=105097564, 가장 큰 안전) 8 문자를 사용 합니다 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

파이썬 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

@ feersum base-10 문자열은 내가 테스트 한 것입니다. 그것은 아무것도 사용하지 않지만 ord(c)그래도, 그래서 정말 :) 할 것입니다 문자열 (NUL 문자 같은 것들을 제외하고, 나는 정말 쉽게 그 메이크업 해시 충돌을 생각 그래서 스틱을 0-9 문자열..)
tomsmeding

1
그것을 깨뜨렸다 : codegolf.stackexchange.com/a/51160/41288 . "10000"및 "20000"과 같은 문자열은 매우 가까운 해시를 생성 함을 관찰함으로써 시작됩니다. 점점 더 많은 제로를 가지고 놀기 시작했으며, 128 정도가 지나면 모든 숫자 + k * 4 제로 반복은 k에 관계없이 동일한 해시를 반환합니다.
tucuxi 2016 년

@tucuxi는 이미 벌하지한다고 생각 너무 열심히; 사소한 것이 아니지만 누군가 어쨌든 그것을 깨뜨린 것이 기쁘다. 잘 했어.
tomsmed

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 %입니다. 2 ^ 32 시도는 현대 PC에는 그다지 중요하지 않습니다.
tucuxi 2016 년

래퍼에는 헤더가 포함되어 있지 않으며 일반적으로 많은 해시로 이어집니다.
Vi.

해시 샘플을 제공하십시오. 나를 위해 "3"과 "33"은 481c27f26cba06cf (이 래퍼 사용)로 이어집니다.
Vi.

금 : codegolf.stackexchange.com/a/51215/41288 . @Vi 직전에 의심됩니다. 왜 그렇게 많은 해시가 같은지 알아 냈습니다.
tucuxi 2016 년

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. bruteforcer는 여기서 다른 64 비트 해시와 비교하여 충돌이 훨씬 빠릅니다.
Vi.

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에서 일부 연산을 수행 한 다음 결과 modulo 2 128 을 가져옵니다 .


이것을 어떻게 실행합니까? Ideone은 컴파일을 거부합니다.
마틴 엔더

1
클래스 이름을 "Main"으로 바꾸거나 첫 번째 "public"키워드 (두 번째 키워드는 아님)를 제거하여 Ideone에서이를 실행할 수 있습니다. 어느 쪽이든 작동합니다.
SuperJedi224


1
@ SuperJedi224 왜 첫 번째 public문자를 제거하여 7 자를 저장 하지 않겠습니까 ?
user253751 2018 년

@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 비트 해시를 생성하기에 충분한 햄스터 휠이 있습니다.

코드의 4 가지 주요 상수는 다음과 같습니다.

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

이전과 마찬가지로이 프로그램은 래퍼가 필요없는 완전한 프로그램입니다. 정수 I 은 원시 이진 데이터 (big-endian)로 stdin을 통해 입력되며 해시 O 는 16 진으로 stdout에 인쇄됩니다. I의 선행 0 은 무시됩니다.

예 :

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은 모두 0과 같으므로 동일한 출력을 생성합니다.
squeamish ossifrage

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 및 변수 스와핑. 무엇을 사랑하지거야?

여기에 놀 수있는 ungolf'd 버전이 있습니다.

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. 나는 대형으로 숫자를 시도했습니다
출력은 2 내 것 같았다 128 범위.


register_globals지시문 때문에 PHP 4.1이 필요 합니다.

세션, POST, GET, REQUEST 및 쿠키에서 로컬 변수를 자동으로 생성하여 작동합니다.

키를 사용합니다 a. (EG :을 통해 액세스 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

파이썬 2.X-139 바이트 [[ Cracked ]]

이것은 다른 모든 (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

래퍼 (16 진수라고도하는 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 2016 년

당신은 절대적으로 맞습니다. 분명히 더 큰 입력 타이밍을 테스트해야합니다. 또한 해당 근무 시간이 추가 된 후 자체 테스트를 실행하는 것을 잊어 버린 것 같습니다. 원래 버전 (게시하기 전에) 변화 선수 그리고 테스트 "처음 100000 개 정수에 더 충돌"내 전달되지 않았다 : /
의아해

1

파이썬 2.7-161 바이트 [[ Cracked ]]

글을 게시하기 전에 첫 번째 해시 함수를 쓸모없는 버전으로 변경 했으므로 비슷한 구조의 다른 버전을 게시 할 것이라고 생각합니다. 이번에는 사소한 충돌에 대해 테스트했으며 가능한 대부분의 입력 크기를 테스트했습니다.

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()

실행 예 (입력은 항상 16 진수) :

$ 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


잘 했어 지미 :)
의아해

1

루비, 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

질문에 필요한 래퍼를 제공해 주시겠습니까?
Dennis

입력 형식은 무엇입니까? 나는 숫자로 시도했지만 말한다 comparison of String with 255 failed (ArgumentError).
jimmy23013

H는 문자열을 가져오고 Build string은 OP에 필요한 수를 가져 와서 문자열로 변환합니다.
MegaTom

gets.to_i래퍼에 필요하다고 생각합니다 .
jimmy23013 2016 년


0

Mathematica, 89 바이트, 금이 간

Last@CellularAutomaton[(a=Mod)[#^2,256],{#~IntegerDigits~2,0},{#~a~99,128}]~FromDigits~2&

최단이 아닙니다.


3
Mathematica없이 어떻게 이것을 실행합니까? "x86 또는 x64 플랫폼에서 또는 웹 브라우저에서 실행할 수있는 비어있는 컴파일러 / 인터프리터가 있어야합니다."
Martin Ender



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
해시의 출력 값은 부동 소수점으로 보입니다. 그리고 3000000000000000000000000000000000000000000001과 3000000000000000000000000000000000000000000000에 대해서도 동일합니다
.

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 패딩에 결함이있는 것 외에 이것은 암호화 해시가 아니며이를 해독 할 수있는 방법이 너무 많습니다.
aaaaaaaaaaaa

0

파이썬 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에 십진 해시 값을 인쇄하는 완전한 프로그램입니다. 여분의 선행 0은 다른 해시 값을 초래하므로 입력에 아무것도 없다고 가정합니다.

이것은 모듈 식 지수를 통해 197 자리의 입력 숫자 청크를 채워서 작동합니다. 일부 언어와 달리이 int()함수는 항상 기본 10이 기본이므로 int('077')63이 아닌 77입니다.

샘플 출력 :

$ 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

어. 나는 줄 :-(
squeamish ossifrage
당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.