Golf băm mật mã


34

Cuộc thi này đã kết thúc.

Do tính chất của các thử thách , thử thách cảnh sát trở nên dễ dàng hơn rất nhiều khi sự quan tâm đến thử thách cướp liên quan đã giảm đi. Do đó, trong khi bạn vẫn có thể đăng các hàm băm, câu trả lời của bạn sẽ không được chấp nhận hoặc tạo thành một phần của bảng xếp hạng.

Thách thức này là tìm kiếm cách thực hiện ngắn nhất của hàm bămkhả năng chống va chạm , nghĩa là không thể tìm thấy hai thông báo khác nhau có cùng hàm băm.

Là một cảnh sát, bạn cố gắng phát minh và thực hiện hàm băm để tìm ra sự thỏa hiệp tốt nhất giữa kích thước mã và khả năng chống va chạm. Sử dụng quá nhiều byte và một cảnh sát khác sẽ vượt qua bạn!

Là một tên cướp, bạn cố gắng ngăn chặn các nỗ lực của cảnh sát bằng cách phá vỡ các chức năng của chúng, chứng tỏ rằng chúng không phù hợp. Điều này sẽ buộc họ sử dụng nhiều byte hơn để củng cố thuật toán của họ!

Cảnh sát thách thức

Bài tập

Thực hiện hàm băm mật mã H: I -> O theo lựa chọn của bạn, trong đó I là tập hợp tất cả các số nguyên không âm dưới 2 2 30O là tập hợp của tất cả các số nguyên không âm dưới 2 128 .

Bạn có thể triển khai H như một hàm thực tế chấp nhận và trả về một số nguyên duy nhất, biểu diễn chuỗi của một số nguyên hoặc một mảng số nguyên hoặc một chương trình đầy đủ đọc từ STDIN và in ra STDOUT trong cơ sở 10 hoặc 16.

Chấm điểm

  • H rằng nó phải chống lại các thách thức cướp được xác định dưới đây.

    Nếu một tên cướp đánh bại trình của bạn trong 168 giờ đầu tiên sau khi đăng nó, nó được coi là bị bẻ khóa .

  • Việc thực hiện H nên càng ngắn càng tốt. Bài nộp ngắn nhất không bị theo dõi sẽ là người chiến thắng trong thử thách cảnh sát.

Quy tắc bổ sung

  • Nếu bạn triển khai H dưới dạng hàm, vui lòng cung cấp trình bao bọc để thực thi hàm từ bên trong chương trình hoạt động như đã giải thích ở trên.

  • Vui lòng cung cấp ít nhất ba vectơ kiểm tra cho chương trình hoặc trình bao bọc của bạn (ví dụ đầu vào và đầu ra tương ứng của chúng).

  • H có thể là thiết kế tiểu thuyết của bạn (ưa thích) hoặc một thuật toán nổi tiếng, miễn là bạn tự thực hiện nó. Nghiêm cấm sử dụng bất kỳ loại hàm băm dựng sẵn, hàm nén, mật mã, PRNG, v.v.

    Bất kỳ tích hợp thường được sử dụng để thực hiện các chức năng băm (ví dụ: chuyển đổi cơ sở) là trò chơi công bằng.

  • Đầu ra của chương trình hoặc chức năng của bạn phải có tính xác định.

  • Cần có một trình biên dịch / trình thông dịch miễn phí (như trong bia) có thể chạy trên nền tảng x86 hoặc x64 hoặc từ trong trình duyệt web.

  • Chương trình hoặc chức năng của bạn phải có hiệu quả hợp lý và phải băm bất kỳ tin nhắn nào trong I dưới 2 2 19 trong chưa đầy một giây.

    Đối với các trường hợp cạnh, thời gian (tường) dành cho máy của tôi (Intel Core i7-3770, 16 GiB RAM) sẽ là quyết định.

  • Do tính chất của thách thức này, không được phép thay đổi mã câu trả lời của bạn theo bất kỳ cách nào, cho dù nó có làm thay đổi đầu ra hay không.

    Nếu bài đăng của bạn đã bị bẻ khóa (hoặc thậm chí nếu không có), bạn có thể đăng câu trả lời bổ sung.

    Nếu câu trả lời của bạn không hợp lệ (ví dụ: nó không tuân thủ thông số I / O), vui lòng xóa nó.

Thí dụ

Python 2.7, 22 byte

def H(M):
 return M%17

Vỏ bánh

print H(int(input()))

Thử thách cướp

Bài tập

Crack bất kỳ cảnh sát đệ trình bằng cách đăng những điều sau đây trong tên cướp chủ đề : hai thông điệp MN trong tôi như vậy H (M) = H (N)M ≠ N .

Chấm điểm

  • Bẻ khóa mỗi bài nộp cảnh sát giúp bạn đạt được một điểm. Tên cướp có nhiều điểm nhất sẽ thắng.

    Trong trường hợp hòa, kẻ cướp bị trói đã bẻ khóa bài nộp dài nhất sẽ thắng.

Quy tắc bổ sung

  • Mỗi cảnh sát đệ trình chỉ có thể bị bẻ khóa một lần.

  • Nếu một đệ trình cảnh sát phụ thuộc vào hành vi được xác định thực hiện hoặc không xác định, bạn chỉ phải tìm một vết nứt hoạt động (có thể kiểm chứng) trên máy của bạn.

  • Mỗi vết nứt thuộc về một câu trả lời riêng trong chủ đề của bọn cướp.

  • Đăng một nỗ lực bẻ khóa không hợp lệ cấm bạn bẻ khóa đệ trình cụ thể đó trong 30 phút.

  • Bạn không thể bẻ khóa trình của riêng bạn.

Thí dụ

Python 2.7, 22 byte bởi người dùng8675309

1

18

Bảng xếp hạng

Đệ trình an toàn

  1. CJam, 21 byte bởi eBusiness
  2. C ++, 148 byte bởi tucuxi
  3. C ++, 233 (?) Byte bởi Vi.

Bài dự thi

Bạn có thể sử dụng Stack Snippet này để có được danh sách các câu trả lời chưa bị bẻ khóa.

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>


Nếu một hàm băm trả về sai số lớn hơn 2 ^ 128-1, điều đó có làm mất hiệu lực đệ trình không, hay chúng ta chỉ đơn giản là lấy kết quả modulo 2 ^ 128?
Martin Ender

@ MartinBüttner: Có, bạn phải lấy kết quả modulo 2 ^ 128.
Dennis

1
@Scimonster Không đáp ứng các yêu cầu (tối đa 2 ^ 30 bit đầu vào, 128 bit đầu ra)
CodeInChaos

1
Không cảnh sát và tên cướp thường đi theo cách khác?
haneefmubarak

2
Có lẽ chúng ta có thể có một quy tắc rằng các bài nộp phải bao gồm các băm ví dụ, khá khó chịu khi phải chạy các trình đệ trình đã chọn ngôn ngữ lập trình để có kết quả so sánh việc thực hiện bẻ khóa.
aaaaaaaaaaaa

Câu trả lời:


6

CJam, 21 byte

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

Lấy một chuỗi byte làm đầu vào.

Trong mã giả:

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

Ví dụ băm:

"" (chuỗi trống) -> 1
"Kiểm tra" -> 2607833638733409808360080023081587841
"kiểm tra" -> 363640467424586895504738713637444713

Có thể là một chút về mặt đơn giản, phạm vi đầu ra chỉ hơn 122 bit một chút, cường độ lặp ba lần đã bị hỏng một chút vì nó thực hiện chính xác cùng một lúc, vì vậy hãy nhập vào băm đầu tiên 1 lặp đi lặp lại sẽ là một nghỉ ngơi đầy đủ. Nhưng nó là ngắn, và không có niềm vui trong việc quá an toàn.


Có phiên bản C đi kèm như trong bài viết khác của CJam không?
Vi.

@Vi. Không, ít nhất là chưa. Tôi chưa bao giờ học hỏi về bigint trong C, có thư viện chuẩn nào không?
aaaaaaaaaaaa

GMP ?
Vi.


1
@ Agawa001 Bạn đang bị lẫn lộn thuật ngữ. Nó là một thuật toán băm hàm ba lần vượt qua. Mật mã Caesar là một thuật toán mã hóa cụ thể không có trạng thái bên trong.
aaaaaaaaaaaa

7

Python, 109 byte [ nứt , và một lần nữa ]

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

Tôi đã thử thực hiện chức năng một lần của Jenkins , với sự khác biệt duy nhất là hạt giống và số lượng bit.

Sự thật thú vị: Rõ ràng Perl đã sử dụng hàm băm của Jenkins tại một số điểm .

Vỏ bánh

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

Ví dụ

>>> 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 byte

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 là tiện ích mở rộng GCC và hoạt động như mong đợi. Hàm băm dựa trên hàm băm lặp FNV (tôi đã mượn số nguyên tố của chúng, mặc dù alà các chữ số đầu tiên của Pi trong hex) với phép quay giống như sha1 khi bắt đầu mỗi lần lặp. Quá trình biên dịch -O3, băm một tệp 10 MB mất dưới 2 giây, do đó, vẫn có biên độ để tăng các lần lặp trong vòng lặp bên trong - nhưng hôm nay tôi cảm thấy hào phóng.

Khử nhiễu (thay đổi tên biến, thêm nhận xét, khoảng trắng và một cặp dấu ngoặc) cho niềm vui bẻ khóa của bạn:

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
}

Đề xuất chơi gôn được hoan nghênh (ngay cả khi tôi không cải thiện mã dựa trên chúng).

chỉnh sửa: lỗi chính tả trong mã khử lỗi (phiên bản golf vẫn không thay đổi).


odường như chưa được khởi tạo Khai outputbáo ở đâu? Hoặc có thể ooutput?
Vi.

Tương tự cho n. Bạn đã thực sự kiểm tra mã "khử xấu" để chạy chưa?
Vi.

Bắt đầu bruteforcer ...
Vi.

Ngay cả phiên bản 3 vòng cũng không dễ.
Vi.

@Vi. Đã sửa lỗi phiên bản khử xấu - xin lỗi vì đã không kiểm tra nó tốt hơn. Tôi tự hào về vòng lặp bên trong đó; U i=81;i-=3thậm chí có thể còn tệ hơn, mà không có chi phí thời gian chạy đáng kể.
tucuxi

5

CJam, 44 byte [ đã bẻ khóa ]

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

Đầu vào là trong cơ sở 10.

CJam chậm. Tôi hy vọng nó chạy trong 1 giây trong một số máy tính ...

Giải thích

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.

Chà, hai thứ dường như là một điểm yếu ... Nó được dự định để làm cho một số tính toán chậm nhanh hơn lúc ban đầu. Nhưng nó không thể chạy trong một giây bất kể tôi làm gì, vì vậy cuối cùng tôi đã xóa mã chậm.

Nó cũng sẽ tốt hơn nếu tôi đã sử dụng các bit nhị phân và các cơ sở cao hơn.

Phiên bản 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);
}

Bạn có thể vui lòng thêm một mô tả? Không phải ai cũng biết đến CJam.
orlp

@orlp Đã chỉnh sửa ...
jimmy23013

Điều này mất 0,4 giây trên máy tính của tôi, vì vậy nó cũng nằm trong phạm vi cho phép.
Dennis

A, B, C là gì? Một số ma trận? Những kích thước nào? Nó có thể dễ dàng thực hiện trong C?
Vi.

1
Nứt , tôi tin.
Sp3000

5

C ++, 182 ký tự (+ khoảng 51 ký tự của mẫu soạn sẵn)

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;}

Bản mẫu:

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
}

Chương trình có thể chạy được với chức năng đánh gôn

#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
Tôi nghĩ rằng khai báo hàm vv tính vào số lượng ký tự.
Ypnypn

@Ypnypn, đếm các ký tự trong khai báo hàm xuống.
Vi.

Băm đầu ra là gì? Tôi giả sử nó là ((h << 64) | j).
tuc lửa

Vâng. Hoặc chỉ là một cặp số 64 bit. Tôi phát hiện ra __uint128_tchỉ sau khi thực hiện điều này.
Vi.

1
@Dennis, Xong.󠀠
Vi.

4

Pyth, 8 nứt

sv_`.lhQ

Dùng thử trực tuyến

Một câu trả lời ngớ ngẩn, tôi sẽ giải thích cách nó hoạt động vì hầu hết mọi người không thể đọc Pyth. Điều này lấy nhật ký tự nhiên của một cộng với đầu vào, và sau đó chuyển đổi nó thành một chuỗi. Chuỗi đó được đảo ngược, và sau đó được ước tính và sau đó được chuyển đổi thành một số nguyên.

Một bản dịch python sẽ trông như:

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


4

Python 3, 216 byte [ đã bẻ khóa ]

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

Do không tương thích với thông số kỹ thuật, tôi có thể nghĩ về ít nhất một lỗ hổng nhỏ , nhưng khác hơn là tôi nghĩ rằng điều này ít nhất là bằng chứng vũ phu. Tôi đã kiểm tra 10 triệu băm đầu tiên, trong số những thứ khác.

Về mặt golf, nó sẽ ngắn hơn trong Python 2, nhưng tôi đã hy sinh một số byte để đạt hiệu quả (vì dù sao nó có thể sẽ không giành chiến thắng).

Chỉnh sửa: Đây là nỗ lực của tôi trong việc triển khai Very Smooth Hash , nhưng tiếc là 128 bit quá nhỏ.

Vỏ bánh

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

Ví dụ

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

Giải thích mã

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

Một ví dụ về phần đệm cho 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 byte [ đã bẻ khóa ]

Đây là chương trình hoàn chỉnh; không cần bọc Chấp nhận đầu vào nhị phân thông qua stdin và đưa ra hàm băm thập lục phân cho thiết bị xuất chuẩn.

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

Điều này chỉ tính toán một hàm băm 64 bit, vì vậy tôi đang tham gia một chút đánh bạc ở đây.

Trong trường hợp bất cứ ai thắc mắc, hai hằng số 'foo+''bar/'là số nguyên tố 1718578987 và 1650553391.


Ví dụ:

Bỏ qua các số 0 hàng đầu:

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

Đầu vào một byte:

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

Đầu vào nhiều byte:

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

Nó sẽ cư xử như thế nào với 'aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa
Ismael Miguel

1
foo|(d5c9bef71d4f5d1b) và foo\(d5c9bef71d4f5d1b) tạo ra các giá trị băm tương tự RẤT .
Ismael Miguel

1
Đã phá vỡ nó!!! \x00\x00\x00!
Ismael Miguel

1
Dựa trên các bình luận trò chuyện, tôi tin rằng điều này vẫn chưa bị bẻ khóa? Chỉ cần kiểm tra lại, bởi vì nhận xét được nâng cấp có thể gây nhầm lẫn cho những người đang lướt qua các băm không bị bẻ khóa.
Sp3000


3

J - 39 byte - bị bẻ khóa

Hàm lấy một chuỗi làm đầu vào và trả về một số nguyên <2 128 . Tôi giả sử rằng chúng ta phải đặt tên cho hàm của mình là hợp lệ, vì vậy hãy bỏ 3 ký tự khác khỏi số đếm nếu chúng ta có thể gửi các hàm ẩn danh.

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

Đối với những người không đọc chữ tượng hình, đây là danh sách những gì tôi đang làm.

  • a=.(2^128x)&|@^/@Đây là một chương trình con * lấy một dãy số, và sau đó coi nó như một tháp năng lượng, trong đó phép lũy thừa được lấy theo mod 2 128 . Theo "tháp năng lượng", ý tôi là nếu bạn cho nó đầu vào 3 4 5 6, nó sẽ tính toán 3 ^ (4 ^ (5 ^ 6)).
  • (".p:@+5,9:)aHàm này lấy một chuỗi, chuyển đổi nó thành số N và sau đó tính toán ( n +5) -th và ( n số nguyên tố thứ +9), sau đó ném atừ trước lên trên nó. Đó là, chúng tôi tìm thấy p(n+5) ^ p(n+9)mod 2 128 trong đó p(k)là số knguyên tố thứ.
  • H=:_8...\(a...)]Thực hiện chức năng trên trên các khóa con 8 ký tự của đầu vào, sau đó atất cả các kết quả cùng nhau và gọi hàm băm kết quả H. Tôi sử dụng 8 ký tự vì "k chức năng -th Prime" không thành công khi p(k)> 2 31 , tức k=105097564là an toàn lớn nhất k.

Có một số đầu ra mẫu. Bạn có thể thử trực tuyến tại tryj.tk , nhưng tôi thực sự khuyên bạn nên làm điều này ở nhà bằng cách tải xuống trình thông dịch từ 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

* Về mặt kỹ thuật, bản thân nó không phải là một chức năng, nó gắn với các chức năng khác và hoạt động trên đầu ra của chúng. Nhưng đây là một vấn đề ngữ nghĩa của J, không phải là một sự khác biệt về khái niệm: dòng chương trình như tôi đã mô tả ở trên.



2

Python 3, 118 byte [ bị bẻ khóa ]

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

Lõm là một tab duy nhất. Băm đơn giản, chưa thực sự kiểm tra nó kỹ lưỡng.

Gọi như sau:

print(H("123456789"))

kết quả: 73117705077050518159191803746489514685


Làm thế nào số nguyên đầu vào nên được chuyển đổi thành một chuỗi để sử dụng trong thuật toán của bạn?
frageum

@feersum chuỗi cơ sở 10 là những gì tôi đã thử nghiệm. ord(c)Mặc dù vậy, nó không sử dụng bất cứ thứ gì, nhưng thực sự, bất kỳ chuỗi nào cũng sẽ làm được :) (ngoại trừ những thứ như ký tự không, tôi nghĩ rằng chúng tạo ra các va chạm băm thực sự dễ dàng. Vì vậy, hãy gắn bó với chuỗi 0-9.)
tomsmeding

1
Đã phá vỡ nó: codegolf.stackexchange.com/a/51160/41288 . Bắt đầu bằng cách quan sát rằng các chuỗi như "10000" và "20000" tạo ra các giá trị băm rất gần. Bắt đầu chơi xung quanh với ngày càng nhiều số 0 và sau 128 hoặc hơn, mọi số 0 + k * 4 số lặp lại sẽ trả về cùng một hàm băm bất kể k.
tucuxi

@tucuxi Đã nghĩ rằng nó không nên quá khó; vui vì điều đó không tầm thường nhưng dù sao cũng có người phá vỡ nó. Làm tốt lắm.
tomsmeding

2

C ++, 239 byte

Golf mã đầu tiên của tôi! [ Xin hãy nhẹ nhàng ]

#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);}

Phiên bản bị đánh cắp:

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;
}

Không phải là hàm băm tốt nhất và chắc chắn không phải là mã ngắn nhất trong sự tồn tại. Chấp nhận lời khuyên chơi golf và hy vọng cải thiện!

Vỏ bánh

Có lẽ không phải là tốt nhất trên thế giới, nhưng dù sao cũng là một trình bao bọc

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
Trông chắc chắn, nhưng với 64 bit, nó có thể bị ép buộc. Có khoảng 50% cơ hội tìm thấy sự va chạm trong các thử nghiệm ~ sqrt (n) (trong số n tổng sản lượng); 2 ^ 32 lần thử là không nhiều đối với một máy tính hiện đại.
tucuxi

Wrapper thiếu bao gồm tiêu đề và nói chung dẫn đến nhiều băm bằng nhau.
Vi.

Cung cấp một số mẫu băm. Đối với tôi cả "3" và "33" đều dẫn đến 481c27f26cba06cf (sử dụng trình bao bọc này).
Vi.

Nứt: codegolf.stackexchange.com/a/51215/41288 . Tôi nghi ngờ ngay trước @Vi. tìm ra lý do tại sao rất nhiều băm là như nhau.
tuc lửa

1
Va chạm đúng cách (không có lỗi sử dụng): 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 tìm thấy sự va chạm ở đây nhanh hơn nhiều so với trong băm 64 bit khác ở đây.
Vi.

2

Java, 299 291 282 byte, bị bẻ khóa.

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)));}}

Có một số hoạt động trên BigIntegers, sau đó lấy kết quả modulo 2 128 .


Làm thế nào để tôi chạy cái này? Ideone từ chối biên dịch nó.
Martin Ender

1
Bạn có thể chạy nó trên Ideone bằng cách đổi tên lớp thành "Chính" hoặc xóa từ khóa "công khai" đầu tiên (nhưng KHÔNG phải từ khóa thứ hai). Một trong hai sẽ làm việc.
SuperJedi224


1
@ SuperJedi224 Tại sao không tự xóa cái đầu tiên public, tiết kiệm 7 ký tự?
dùng253751

@immibis Bởi vì sau đó tôi không nghĩ rằng nó sẽ hoạt động tốt trên Eclipse. Tôi sẽ thử nó mặc dù. EDIT: Tôi đoán nó làm. Đó là một bất ngờ.
SuperJedi224

2

C, 128 byte [ bị bẻ khóa ]

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);}

Đây ít nhiều là thuật toán giống như nỗ lực cuối cùng của tôi (đã bị bẻ khóa bởi Vi.) , Nhưng giờ đây đã có đủ bánh xe hamster để tạo ra các giá trị băm 128 bit thích hợp.

Bốn hằng số nguyên tố trong mã như sau:

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

Như trước đây, đây là một chương trình hoàn chỉnh không cần trình bao bọc. Số nguyên I được nhập qua stdin dưới dạng dữ liệu nhị phân thô (big-endian) và hàm băm O được in ở dạng hex đến stdout. Số không hàng đầu trong tôi được bỏ qua.

Ví dụ:

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


Chẳng phải ví dụ của bạn cho thấy một vụ va chạm ngay tại đó (hai cái đầu tiên) sao?
mbomb007

@ mbomb007 Số Đầu vào là một số trong khoảng từ 0 đến 2 ^ (2 ^ 30). 0x00 và 0x0000 đều bằng 0, do đó chúng tạo ra cùng một đầu ra.
squossish ossifrage

2

C, 122 byte [ đã bẻ khóa ]

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);}

Các vòng lặp lồng nhau, LCG nửa khẳng định và hoán đổi biến. Không yêu là gì?

Đây là một phiên bản ungolf'd để chơi xung quanh:

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;
}

Đây là một chương trình hoàn toàn tự chứa, đọc từ STDIN và in ra STDOUT.

Thí dụ:

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

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

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

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

Trong một số điểm chuẩn đơn giản, nó băm khoảng 3MB / s dữ liệu văn bản. Tốc độ băm phụ thuộc vào chính dữ liệu đầu vào, do đó có lẽ nên được xem xét.



1

PHP 4.1, 66 byte [ đã bẻ khóa ]

Tôi chỉ ấm lên.

Tôi hy vọng bạn tìm thấy điều này.

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

Tôi đã thử số lượng lớn như 999999999999999999999999999.
Sản lượng dường như nằm trong phạm vi 2 128 .


PHP 4.1 là bắt buộc vì register_globalschỉ thị.

Nó hoạt động bằng cách tự động tạo các biến cục bộ từ phiên, POST, GET, REQUEST và cookie.

Nó sử dụng chìa khóa a. (EG: truy cập qua http://localhost/file.php?a=<number>).

Nếu bạn muốn thử nghiệm nó với PHP 4.2 trở lên, hãy thử điều này:

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

Phiên bản này chỉ hoạt động với POST và GET.


Ví dụ đầu ra:

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

(Tôi đảm bảo với bạn rằng có những con số tạo ra cùng một hàm băm).



1

C, 134 byte, Cracked

Đây là chương trình C hoàn chỉnh.

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);}

Những gì nó làm: Ý ​​tưởng là lấy đầu vào dưới dạng mảng byte và nối các byte giả ngẫu nhiên (nhưng xác định) ở cuối để tạo độ dài bằng khoảng 2 2 30 (thêm một chút). Việc thực hiện đọc từng byte đầu vào theo byte và bắt đầu sử dụng dữ liệu giả ngẫu nhiên khi nó tìm thấy ký tự đầu tiên không phải là một chữ số.

Vì PRNG dựng sẵn không cho phép tôi tự thực hiện.

Có hành vi được xác định / thực hiện được xác định làm cho mã ngắn hơn (giá trị cuối cùng không được ký và tôi nên sử dụng các loại khác nhau cho các giá trị khác nhau). Và tôi không thể sử dụng các giá trị 128 bit trong C. Phiên bản ít bị xáo trộn hơn:

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 byte [[ Cracked ]]

Điều này khá giống với tất cả các băm khác (LOOP, XOR, SHIFT, ADD) ở đây. Hãy đến lấy điểm của bạn;) Tôi sẽ làm khó hơn sau khi giải quyết vấn đề này.

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

Wrapper (mong đợi một đối số trong cơ sở-16 còn được gọi là thập lục phân):

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


1
Ngoài ra, tôi không chắc chắn rằng mục nhập này đáp ứng thông số kỹ thuật của OP, vì trên máy của tôi, chức năng này mất nhiều giây trên các đầu vào lớn. Ví dụ: H(2**(2**10))mất khoảng 8 hoặc 9 giây, trong khi H(2**(2**12))mất khoảng 29 giây và H(2**(2**14))mất hơn hai phút.
mathmandan

Bạn hoàn toàn đúng, rõ ràng tôi nên kiểm tra thời gian cho các đầu vào lớn hơn. Ngoài ra, tôi dường như đã quên chạy thử nghiệm của riêng mình sau khi sự thay đổi đó được thêm vào. Phiên bản gốc không có sự thay đổi (trước khi đăng) và nó đã vượt qua bài kiểm tra "không va chạm trong 100000 số nguyên đầu tiên" của tôi: /
Bối rối

1

Python 2.7 - 161 byte [[ Cracked ]]

Vì tôi đã thay đổi hàm băm đầu tiên của mình thành một phiên bản vô dụng trước khi đăng nó, tôi nghĩ rằng tôi sẽ đăng một phiên bản khác có cấu trúc tương tự. Lần này tôi đã thử nó chống lại các va chạm tầm thường và tôi đã thử nghiệm hầu hết các cường độ đầu vào có thể cho tốc độ.

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

Wrapper (không được tính bằng bytecount)

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

Chạy ví dụ (đầu vào luôn là số thập lục phân):

$ 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


Làm tốt lắm jimmy :)
Bối rối

1

Ruby, 90 byte

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

Một thuật toán băm rất ngẫu nhiên tôi đã tạo ra mà không cần nhìn vào bất kỳ giá trị băm thực sự nào ... không biết nó có tốt không. nó lấy một chuỗi làm đầu vào.

Vỏ bánh:

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

Bạn có thể vui lòng cung cấp trình bao bọc câu hỏi yêu cầu?
Dennis

Định dạng đầu vào là gì? Tôi đã thử với một số nhưng nó nói comparison of String with 255 failed (ArgumentError).
jimmy23013

H lấy một chuỗi, Chuỗi xây dựng lấy số theo yêu cầu của OP và biến nó thành chuỗi.
MegaTom

Tôi nghĩ rằng bạn cần một gets.to_itrong bọc.
jimmy23013


0

Mathicala, 89 byte, đã bị bẻ khóa

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

Không phải là ngắn nhất.


3
Làm thế nào để bạn chạy này mà không có Mathicala? "Cần có một trình biên dịch / trình thông dịch miễn phí (như trong bia) có thể chạy trên nền tảng x86 hoặc x64 hoặc từ trong trình duyệt web."
Martin Ender



0

PHP, 79 Byte (đã bị bẻ khóa. Với một bình luận):

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

Điều này không có nhiều thứ đáng sợ thông qua chuyển đổi loại trong php, điều này làm cho nó khó dự đoán;) (hoặc ít nhất là tôi hy vọng vậy). Tuy nhiên, đây không phải là câu trả lời ngắn nhất hoặc khó đọc nhất.

Để chạy nó, bạn có thể sử dụng PHP4 và đăng ký toàn cầu (với? I = 123) hoặc sử dụng dòng lệnh:

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

5
Giá trị đầu ra của hàm băm trông nổi điểm. Và nó giống nhau cho 3000000000000000000000000000000000000000000001 và 30000000000000000000000000000000000000000000000.
Vi.

0

C # - 393 byte bị bẻ khóa

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"));}}

Ung dung:

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"));
    }
}

Tôi chưa bao giờ chạm vào mật mã hoặc băm trong đời, vì vậy hãy nhẹ nhàng :)

Đó là một thực hiện đơn giản của một hàm băm FNV-1a với một số trục xoay trên đầu vào. Tôi chắc chắn có một cách tốt hơn để làm điều này nhưng đây là cách tốt nhất tôi có thể làm.

Nó có thể sử dụng một chút bộ nhớ trên các đầu vào dài.


Cracked: codegolf.stackexchange.com/a/51277/101 Trên đầu trang có phần đệm bị lỗi, đây không phải là một hàm băm mật mã, có rất nhiều cách để phá vỡ nó.
aaaaaaaaaaaa

0

Python 2, 115 byte [Đã bẻ khóa!]

OK, đây là nỗ lực cuối cùng của tôi. Chỉ 115 byte vì dòng mới cuối cùng không bắt buộc.

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

Đây là một chương trình hoàn chỉnh nhập số nguyên thập phân trên stdin và in giá trị băm thập phân trên thiết bị xuất chuẩn. Các số 0 đứng đầu sẽ dẫn đến các giá trị băm khác nhau, vì vậy tôi sẽ giả sử rằng đầu vào không có giá trị nào.

Điều này hoạt động bằng cách nhồi các khối 197 chữ số của số đầu vào thông qua lũy thừa mô-đun. Không giống như một số ngôn ngữ, int()hàm luôn mặc định là cơ sở 10, vì vậy int('077')là 77 chứ không phải 63.

Đầu ra mẫu:

$ 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
Nó không sử dụng thứ tự các khối ... Cracked .
jimmy23013

Ừ Tôi nhượng bộ :-(
squossish ossifrage
Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.