GolfScript, 60 karakter
{[[0 1{.283{1$2*.255>@*^}:r~^}255*].@?~)={257r}4*99]{^}*}:S;
Kode ini mendefinisikan fungsi bernama S
yang mengambil dalam byte dan menerapkan Rijndael S-box untuk itu. (Ini juga menggunakan fungsi pembantu internal bernama r
untuk menyimpan beberapa karakter.)
Implementasi ini menggunakan tabel logaritma untuk menghitung invers GF (2 8 ), seperti yang disarankan oleh Thomas Pornin . Untuk menyimpan beberapa karakter, seluruh tabel logaritma dihitung ulang untuk setiap byte input; Meski begitu, dan meskipun GolfScript menjadi bahasa yang sangat lambat secara umum, kode ini hanya membutuhkan sekitar 10 ms untuk memproses byte pada laptop lama saya. Pra-perhitungan tabel logaritma (as L
) mempercepatnya hingga sekitar 0,5 ms per byte, dengan biaya sederhana dari tiga karakter lagi:
[0 1{.283{1$2*.255>@*^}:r~^}255*]:L;{[L?~)L={257r}4*99]{^}*}:S;
Untuk kenyamanan, berikut ini adalah test harness sederhana yang memanggil fungsi S
, sebagaimana didefinisikan di atas, untuk menghitung dan mencetak seluruh S-box dalam hex seperti di Wikipedia :
"0123456789abcdef"1/:h; 256, {S .16/h= \16%h= " "++ }% 16/ n*
Coba kode ini secara online.
(Demo online menghitung ulang tabel logaritma untuk menghindari mengambil terlalu banyak waktu. Meski begitu, situs GolfScript online kadang-kadang secara acak waktu habis; ini adalah masalah yang diketahui dengan situs, dan memuat ulang biasanya memperbaikinya.)
Penjelasan:
Mari kita mulai dengan perhitungan tabel logaritma, dan secara khusus dengan fungsi helper r
:
{1$2*.255>@*^}:r
Fungsi ini mengambil dua input pada stack: satu byte dan bitmask reduksi (sebuah konstanta antara 256 dan 511). Ini menggandakan byte input, mengalikan salinan dengan 2 dan, jika hasilnya melebihi 255, XOR dengan bitmask untuk mengembalikannya di bawah 256.
Di dalam kode penghasil log-tabel, fungsinya r
disebut dengan bitmask reduksi 283 = 0x11b (yang sesuai dengan Rijndael GF (2 8 ) polinomial reduksi x 8 + x 4 + x 3 + x + 1), dan hasilnya XORed dengan byte asli, secara efektif mengalikannya dengan 3 (= x + 1, sebagai polinomial) dalam bidang hingga Rijndael. Perkalian ini diulang 255 kali, mulai dari byte 1, dan hasilnya (ditambah byte nol awal) dikumpulkan ke dalam array 257-elemen L
yang terlihat seperti ini (bagian tengah dihilangkan):
[0 1 3 5 15 17 51 85 255 26 46 ... 180 199 82 246 1]
Alasan mengapa ada 257 elemen adalah bahwa, dengan 0 yang diawali dan dengan 1 terjadi dua kali, kita dapat menemukan invers modular dari byte yang diberikan hanya dengan melihat indeks (berbasis-nol) dalam array ini, meniadakannya, dan mencari naik byte pada indeks yang dinegasikan dalam array yang sama. (Dalam GolfScript, seperti dalam banyak bahasa pemrograman lainnya, indeks array negatif dihitung mundur dari akhir array.) Memang, inilah yang dilakukan oleh kode L?~)L=
pada awal fungsi S
.
Sisa kode memanggil fungsi helper r
empat kali dengan bitmask reduksi 257 = 2 8 + 1 untuk membuat empat bit-rotated copy dari byte input terbalik. Ini semua dikumpulkan ke dalam array, bersama dengan konstanta 99 = 0x63, dan XOR bersama-sama untuk menghasilkan hasil akhir.