Thực hiện thuật toán băm SHA-1


15

Mục tiêu của môn đánh gôn này là tạo ra một chương trình lấy một chuỗi làm đầu vào và bạn phải xuất giá trị băm SHA-1 dưới dạng số thập lục phân. Bạn có thể tìm mã giả cho SHA-1 tại đây

Các quy tắc khác:

  1. Không có quyền truy cập mạng
  2. Bạn không được phép chạy các chương trình bên ngoài
  3. Bạn không được phép sử dụng các phương thức tích hợp để băm đầu vào
  4. Mã ngắn nhất sẽ thắng
  5. Chỉ cần xử lý đầu vào ASCII
  6. Đầu ra có thể là chữ thường hoặc chữ hoa
  7. Đầu vào có thể được cung cấp bằng cách sử dụng:

    1. Nhắc nhở cho đầu vào
    2. Sử dụng đối số dòng lệnh
    3. Sử dụng STDIN

Các trường hợp thử nghiệm:

Input: The quick brown fox jumps over the lazy dog
Output: 2fd4e1c67a2d28fced849ee1bb76e7391b93eb12
----------------------------------------------------------
Input: The quick brown fox jumps right over the lazy dog
Output: 1c3aff41d97ada6a25ae62f9522e4abd358d741f
------------------------------------------------------------
Input: This is a code golf challenge
Output: f52ff9edd95d98e707bd16a7dead459cb8db8693

Câu trả lời:


5

GolfScript, 374 322 ký tự

[128]+.,.~55+64%1,*\(8*2
32?:?.*+256{base}:B~1>++"!Vi9y BRQ+@phoKD5Vj=]30z0"{96@32-*+}*?B\64/{4/{256B}%{0'=820'{64-
2$=^}/2*.?/+?%+}64*1$'&4$?(^3$&|1518500249{++[]@+@+@?*4/.?/+?%+2$+\@32*.?/++@(@+?%@-1%+}:Y~
^2$^1859775393Y
&4$3$&|3$3$&|2400959708Y
^2$^3395469782Y'n/{'~3$3$'\+20*~}/+]zip{~+?%}%}/{?+16B{.9>7*+48+}%1>}%''+

Điều này dựa trên việc triển khai chính xác mã giả trong GolfScript cộng với một số mã hóa nhỏ để rút ngắn mã (thử trực tuyến ). Đầu vào sẽ được đọc từ STDIN.


Đây là GolfScript dài nhất tôi từng thấy: P
Doorknob

5

Python 3 - 645 ký tự

h=0x67452301,0xEFCDAB89,0x98BADCFE,0x10325476,0xC3D2E1F0
L=lambda v,s:(v<<s|v>>B-s)%2**B
B=32
R=range
m=input().encode()
l=len(m)
m+=b'\x80'+bytes((55-l)%64)+m.fromhex(hex(2**64+l*8)[3:])
for C in [m[i:i+64]for i in R(0,len(m),64)]:
 w=[sum(C[i+j]<<8*(3-j)for j in R(4))for i in R(0,64,4)];a,b,c,d,e=h
 for i in R(16,80):w+=[L(w[i-3]^w[i-8]^w[i-14]^w[i-16],1)]
 for i in R(80):f=[b&c|~b&d,b^c^d,b&c|b&d|c&d,b^c^d][i//20];k=[0x5A827999,0x6ED9EBA1,0x8F1BBCDC,0xCA62C1D6][i//20];t=L(a,5)+f+e+k+w[i];e=d;d=c;c=L(b,30);b=a;a=t%2**32
 g=a,b,c,d,e;h=[(h[i]+g[i])%2**32for i in R(5)]
B=160
print('%x'%(L(h[0],128)|L(h[1],96)|L(h[2],64)|L(h[3],32)|h[4]))

Chỉ là một phiên bản golf của mã giả.


utf = u8 trong python3?
BẠN

1
@YOU Vâng, điều đó cũng làm việc. Tôi vừa kiểm tra và hóa ra .encode()sử dụng UTF-8 theo mặc định, thậm chí còn ngắn hơn.
grc

2

D (759 ký tự)

Phiên bản thực thi trực tuyến: http://dpaste.dzfl.pl/f0c8508f

import std.range,std.algorithm,std.bitmanip,std.stdio:g=writef;
void main(char[][]x){
    auto m=cast(ubyte[])x[1];
    uint a=0x67452301,b=0xEFCDAB89,i,t,f,k;
    uint[5]h=[a,b,~a,~b,0xC3D2E1F0],s;
    uint[80]w;
    auto r=(uint u,uint b)=>u<<b|u>>32-b;
    auto u=(uint i)=>[r(s[0],5)+f+s[4]+k+w[i],s[0],r(s[1],30),s[2],s[3]];
    ubyte[64]p;
    p[0]=128;
    m~=p[0..64-(m.length+8)%64]~nativeToBigEndian(8*m.length);
    foreach(ch;m.chunks(64)){
        16.iota.map!(i=>w[i]=ch[i*4..$][0..4].bigEndianToNative!uint).array;
        iota(16,80).map!(i=>w[i]=r(w[i-3]^w[i-8]^w[i-14]^w[i-16],1)).array;
        s=h;
        80.iota.map!(i=>(i<20?f=s[3]^s[1]&(s[2]^s[3]),k=0x5A827999:i<40?f=s[1]^s[2]^s[3],k=0x6ED9EBA1:i<60?f=s[1]&s[2]|s[3]&(s[1]|s[2]),k=0x8F1BBCDC:(f=s[1]^s[2]^s[3],k=0xCA62C1D6),s[]=u(i)[])).array;
        h[]+=s[];
    }
    g("%(%08x%)",h);
}

2

C, 546 ký tự

Chương trình tính toán SHA-1 của nội dung đầu vào tiêu chuẩn của nó.

unsigned b[16],k[]={1732584193,0xEFCDAB89,0,271733878,0xC3D2E1F0},i,j,n,p,t,u,v,w,x;
char*d=b;a(c){for(d[p++^3]=c,c=0,t=*k,u=k[1],v=k[2],w=k[3],x=k[4];
c>79?*k+=t,k[1]+=u,k[2]+=v,k[3]+=w,k[4]+=x,p=0:p>63;x=w,w=v,v=u<<30|u/4,u=t,t=i)
i=b[c-3&15]^b[c+8&15]^b[c+2&15]^b[j=c&15],c++>15?b[j]=i*2|i>>31:0,i=u^v^w,
i=(t<<5|t>>27)+x+b[j]+(c<21?(w^u&(v^w))+1518500249:c<41?i+1859775393:
c<61?(u&v|w&(u|v))-1894007588:i-899497514);}
main(){for(k[2]=~*k;i=~getchar();++n)a(~i);for(a(128);p-56;a(0));
for(;p<20?printf("%02x",(d=k)[p^3]&255):p>55;a(n*8L>>504-p*8));}

Một vài lưu ý:

  1. Chương trình này giả định rằng intchính xác là 32 bit. Đối với các nền tảng không phải là trường hợp này, unsignedkhai báo ngay từ đầu nên được thay thế bằng loại 32 bit không dấu của nền tảng. ( uint32_tsẽ là sự lựa chọn rõ ràng, nếu nó không yêu cầu #include <stdint.h>.)
  2. Chương trình này giả định một nền tảng endian nhỏ. Đối với một nền tảng lớn, chỉ cần loại bỏ hai lần xuất hiện ^3trong chương trình và thay thế việc khởi tạo k[]bằng khối sau : {19088743,0x89ABCDEF,0,1985229328,0xF0E1D2C3}, với kích thước 541 ký tự.
  3. Đối với các triển khai charkhông được ký theo mặc định, người ta có thể xóa &255cái xuất hiện trên dòng cuối cùng để lưu thêm bốn ký tự.

Lợi nhuận này be417768b5c3c5c1d9bcb2e7c119196dd76b5570cho The quick brown fox jumps over the lazy dognhưng nó phải trở lại2fd4e1c67a2d28fced849ee1bb76e7391b93eb12
ProgramFOX

@ProgramFOX Giá trị băm đó dành cho chuỗi cộng với một dòng mới kết thúc. Các giá trị SHA-1 thử nghiệm được trích dẫn trong phần mô tả là dành cho các chuỗi mà không chấm dứt các dòng mới, vì vậy đừng nối thêm một dòng mới vào đầu vào nếu bạn muốn kiểm tra các chuỗi đó.
hộp bánh mì

1

Mã python của tôi dài hơn một chút nhưng nó hoạt động hoàn toàn.

data="hello world"
bytes = ""
h0,h1,h2,h3,h4=0x67452301,0xEFCDAB89,0x98BADCFE,0x10325476,0xC3D2E1F0
for n in range(len(data)):bytes+='{0:08b}'.format(ord(data[n]))
bits=bytes+"1"
pBits=bits
while len(pBits)%512!=448:pBits+="0"
pBits+='{0:064b}'.format(len(bits)-1)
def chunks(l,n):return[l[i:i+n]for i in range(0,len(l),n)]
def rol(n,b):return((n<<b)|(n>>(32-b)))&0xffffffff 
for c in chunks(pBits,4512):
    words=chunks(c,32)
    w=[0]*80
    for n in range(0,16):w[n]=int(words[n],2)
    for i in range(16,80):w[i]=rol((w[i-3]^w[i-8]^w[i-14]^w[i-16]),1)
    a,b,c,d,e=h0,h1,h2,h3,h4
    for i in range(0,80):
        if 0<=i<=19:f=(b&c)|((~b)&d);k=0x5A827999
        elif 20<=i<=39:f=b^c^d;k=0x6ED9EBA1
        elif 40<=i<=59:f=(b&c)|(b&d)|(c&d);k=0x8F1BBCDC
        elif 60<=i<=79:f=b^c^d;k=0xCA62C1D6
        temp=rol(a,5)+f+e+k+w[i]&0xffffffff
        e,d,c,b,a=d,c,rol(b,30),a,temp 
    h0+=a
    h1+=b
    h2+=c
    h3+=d
    h4+=e 
print '%08x%08x%08x%08x%08x'%(h0,h1,h2,h3,h4)

Vui lòng chỉ định ngôn ngữ trong câu trả lời. Ngoài ra, vì đây là môn đánh gôn, ít nhất bạn nên thử thu nhỏ. Tên biến một char, loại bỏ khoảng trắng không cần thiết, bỏ các hằng số đắt tiền ( 0xffffffff) vào các biến (cũng, sẽ-1 đủ không?) ...
John Dvorak

có vẻ như phython với tôi :)
Owais Qureshi

@JanDvorak Tôi đã sửa đổi mã của mình.
kyle k

h0..h4 vẫn là hai chữ cái ;-)
John Dvorak

Tôi gặp lỗi cú pháp ở dòng 29.
Chương trìnhFOX
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.