Waktunya minum teh!

8

pengantar

Beberapa waktu yang lalu saya menemukan algoritma enkripsi kecil ( TEA ) dan sejak itu saya merekomendasikannya setiap kali sifat keamanan kriptografi khusus tidak diperlukan dan implementasi mandiri adalah persyaratan.
Sekarang hari ini, kami ingin menggunakan algoritma enkripsi nama * tiny * secara harfiah dan tugas Anda adalah mengimplementasikan algoritma enkripsi terkecil !

Spesifikasi

Memasukkan

Input adalah daftar 8 byte (atau setara bahasa Anda), ini adalah plaintext , dan daftar 16 byte (atau setara bahasa Anda), inilah kuncinya .
Konversi input dari desimal, heksadesimal, oktal atau biner diperbolehkan.
Membaca 1 bilangan bulat 64-bit, 2 32-bit atau 4 16-bit sebagai output (opsional sebagai daftar) diperbolehkan (untuk plaintext, gandakan angka untuk kunci)

Keluaran

Outputnya adalah daftar 8 byte (atau setara bahasa Anda), ini adalah ciphertext .
Konversi keluaran ke desimal, heksadesimal, oktal atau biner diperbolehkan, tetapi tidak wajib.
Penulisan 1 bilangan bulat 64-bit, 2 32-bit atau 4 16-bit sebagai output (opsional sebagai daftar) diperbolehkan.

Apa yang harus dilakukan?

Tugas Anda adalah mengimplementasikan arah enkripsi dari algoritma enkripsi kecil ( TEA ), perhatikan XTEA dan XXTEA adalah algoritma lainnya.
Wikipedia memiliki contoh kode-C dan daftar referensi untuk beberapa implementasi dalam bahasa lain, ini adalah deskripsi asli (PDF) .

Lebih formal:

Let k1, k2, k3, k4, v1, v2, sum be unsigned 32-bit integers.
(k1,k2,k3,k4) <- key input
(v1,v2) <- plaintext input
sum <- 0
repeat 32 times:
    sum <- ( sum + 0x9e3779b9 ) mod 2^32
    v0  <- ( v0 + ( ((v1 << 4) + k0) XOR (v1 + sum) XOR ((v1 >> 5) + k1) ) ) mod 2^32
    v1  <- ( v1 + ( ((v0 << 4) + k2) XOR (v0 + sum) XOR ((v0 >> 5) + k3) ) ) mod 2^32
output <- (v0,v1)

where 0x9e3779b9 is a hexadecimal constant and
"<<" denotes logical left shift and ">>" denotes logical right shift.

Kasing sudut potensial

\0adalah karakter yang valid dan Anda tidak dapat mempersingkat input atau output Anda.
Pengkodean integer diasumsikan sebagai little-endian (mis. Apa yang mungkin sudah Anda miliki).

Yang menang?

Ini adalah kode-golf sehingga jawaban tersingkat dalam byte menang!
Aturan standar berlaku tentu saja.

Kasus uji

Vektor uji dibuat menggunakan contoh kode Wikipedia C.

Key: all zero (16x \0)
Plaintext -> Ciphertext (all values as two 32-bit hexadecimal words)
00000000 00000000 -> 41ea3a0a 94baa940
3778001e 2bf2226f -> 96269d3e 82680480
48da9c6a fbcbe120 -> 2cc31f2e 228ad143
9bf3ceb8 1e076ffd -> 4931fc15 22550a01
ac6dd615 9c593455 -> 392eabb4 505e0755
ebad4b59 7b962f3c -> b0dbe165 cfdba177
ca2d9099 a18d3188 -> d4641d84 a4bccce6
b495318a 23a1d131 -> 39f73ca0 bda2d96c
bd7ce8da b69267bf -> e80efb71 84336af3
235eaa32 c670cdcf -> 80e59ecd 6944f065
762f9c23 f767ea2c -> 3f370ca2 23def34c

Berikut adalah beberapa vektor uji yang dibuat sendiri dengan kunci bukan nol:

format: ( 4x 32-bit word key , 2x 32-bit word plaintext ) -> ( 2x 32-bit word ciphertext )
(all in hexadecimal)

( 4300e123 e39877ae 7c4d7a3c 98335923 , a9afc671 79dcdb73 ) -> ( 5d357799 2ac30c80 )
( 4332fe8f 3a127ee4 a9ca9de9 dad404ad , d1fe145a c84694ee ) -> ( a70b1d53 e7a9c00e )
( 7f62ac9b 2a0771f4 647db7f8 62619859 , 618f1ac2 67c3e795 ) -> ( 0780b34d 2ca7d378 )
( 0462183a ce7edfc6 27abbd9a a634d96e , 887a585d a3f83ef2 ) -> ( d246366c 81b87462 )
( 34c7b65d 78aa9068 599d1582 c42b7e33 , 4e81fa1b 3d22ecd8 ) -> ( 9d5ecc3b 947fa620 )
( f36c977a 0606b8a0 9e3fe947 6e46237b , 5d8e0fbe 2d3b259a ) -> ( f974c6b3 67e2decf )
( cd4b3820 b2f1e5a2 485dc7b3 843690d0 , 48db41bb 5ad77d7a ) -> ( b4add44a 0c401e70 )
( ee2744ac ef5f53ec 7dab871d d58b3f70 , 70c94e92 802f6c66 ) -> ( 61e14e3f 89408981 )
( 58fda015 c4ce0afb 49c71f9c 7e0a16f0 , 6ecdfbfa a705a912 ) -> ( 8c2a9f0c 2f56c18e )
( 87132255 41623986 bcc3fb61 7e6142ce , 9d0eff09 55ac6631 ) -> ( 8919ea55 c7d430c6 )
SEJPM
sumber
1
Ketika saya mencoba kode Wikipedia C, menggunakan tombol nol dan plaintext, saya mendapatkan baris kedua dari plaintext Anda sebagai ciphertext saya ...
Neil
Nah, dua yang pertama lakukan sekarang; Saya terlalu malas untuk mencoba sisanya.
Neil
@Neil, itu hal yang menyenangkan tentang crypto: Peluangnya tinggi, bahwa jika sepele (berbasis 0) dan testvector pass nontrivial, semua vektor tes akan berlalu :)
SEJPM
2
Saya sarankan Anda menambahkan beberapa test case dengan kunci bukan nol.
Dennis
@ Dennis itu sekarang dapat ditemukan di bagian bawah pertanyaan :)
SEJPM

Jawaban:

5

JavaScript (ES6), 122 118 114 113 byte

f=
(v,w,k,l,m,n)=>{for(s=0;s<84e9;v+=w*16+k^w+s^(w>>>5)+l,w+=v*16+m^v+s^(v>>>5)+n)s+=0x9e3779b9;return[v>>>0,w>>>0]}
;
<div oninput="[r0.value,r1.value]=f(...[v0,v1,k0,k1,k2,k3].map(i=>parseInt(i.value,16))).map(i=>(i+(1<<30)*4).toString(16).slice(1))">
Plain 0: <input id=v0><br>
Plain 1: <input id=v1><br>
Key 0: <input id=k0><br>
Key 1: <input id=k1><br>
Key 2: <input id=k2><br>
Key 3: <input id=k3><br>
</div>
Cipher 0: <input id=r0 readonly><br>
Cipher 1: <input id=r1 readonly><br>

Catatan: Menggunakan aritmatika little-endian. Menerima dan mengembalikan nilai integer 32-bit yang tidak ditandatangani. Sunting: Disimpan 4 byte dengan menggunakan perkalian alih-alih shift kiri. Disimpan 4 byte dengan menguji ssehingga menghindari variabel loop terpisah. Disimpan 1 byte dengan memindahkan +=s di dalam for.

Neil
sumber
Mengapa tidak menggunakan eval dengan return implisit alih-alih return?
Downgoat
Mengganti {return}dengan eval('')tidak menghemat byte apa pun
Neil
Oh baiklah. Pikir itu menghemat beberapa byte :(
Downgoat
4

Ruby, 114 113 106 byte

Karena Ruby tidak memiliki aritmatika 32-bit, operasi mod tambahan menyebabkannya hampir menyatu dengan Javascript meskipun ada operasi penghematan byte lain yang dimiliki Ruby ...

  • (-1 byte dari titik koma ekstra)
  • (-7 byte dari memangkas operasi mod yang tidak perlu dan memindahkan barang di sekitar)

Cobalah online!

->v,w,a,b,c,d{s=0
32.times{s+=0x9e3779b9;v+=w*16+a^w+s^w/32+b;v%=m=2**32;w+=v*16+c^v+s^v/32+d;w%=m}
[v,w]}
Nilai Tinta
sumber
2

C, 116 byte

T(v,w,k,l,m,n,s)unsigned*v,*w;{for(s=0;s+957401312;*v+=*w*16+k^*w+s^*w/32+l,*w+=*v*16+m^*v+s^*v/32+n)s+=2654435769;}

Mengambil plaintext sebagai v dan w ; kunci sebagai k , l , m , dan n ; dan menyimpan ciphertext di v dan w .

Uji di Ideone .

Dennis
sumber
2

J, 149 byte

4 :0
'u v'=.y
s=.0
m=.2x^32
for.i.32
do.s=.m|s+2654435769
u=.m|u+(22 b.)/(s+v),(2{.x)+4 _5(33 b.)v
v=.m|v+(22 b.)/(s+u),(2}.x)+4 _5(33 b.)u
end.u,v
)

Yay! eksplisit (Boo!) J! Saya pikir ada cara untuk melakukan ini secara diam-diam, tetapi mungkin itu akan menjadi tidak dapat dibaca.

Pemakaian

Mengambil kunci sebagai empat bilangan bulat 32-bit pada LHS dan plaintext sebagai dua bilangan bulat 32-bit pada RHS. Awalan 16bsetara dengan 0xdalam bahasa lain dan mewakili nilai hex. Builtin hfdmemformat output menjadi string hex untuk kemudahan dalam pengujian.

    f =: 4 :0
'u v'=.y
s=.0
m=.2x^32
for.i.32
do.s=.m|s+2654435769
u=.m|u+(22 b.)/(s+v),(2{.x)+4 _5(33 b.)v
v=.m|v+(22 b.)/(s+u),(2}.x)+4 _5(33 b.)u
end.u,v
)
   hfd 0 0 0 0 f 0 0
41ea3a0a
94baa940
   hfd 0 0 0 0 f 16b3778001e 16b2bf2226f
96269d3e
82680480
   hfd 16b4300e123 16be39877ae 16b7c4d7a3c 16b98335923 f 16ba9afc671 16b79dcdb73 
5d357799
2ac30c80
mil
sumber