GolfScript, 60 ký tự
{[[0 1{.283{1$2*.255>@*^}:r~^}255*].@?~)={257r}4*99]{^}*}:S;
Mã này định nghĩa một hàm có tên S
là byte và áp dụng hộp S Rijndael cho nó. (Nó cũng sử dụng chức năng trợ giúp nội bộ có tên r
để lưu một vài ký tự.)
Việc triển khai này sử dụng bảng logarit để tính toán nghịch đảo của GF (2 8 ), theo đề xuất của Thomas Pornin . Để lưu một vài ký tự, toàn bộ bảng logarit được tính toán lại cho mỗi byte đầu vào; mặc dù vậy, và mặc dù GolfScript là một ngôn ngữ rất chậm nói chung, mã này chỉ mất khoảng 10 ms để xử lý một byte trên máy tính xách tay cũ của tôi. Tính toán trước bảng logarit (as L
) tăng tốc lên tới khoảng 0,5 ms mỗi byte, với chi phí khiêm tốn của ba ký tự khác:
[0 1{.283{1$2*.255>@*^}:r~^}255*]:L;{[L?~)L={257r}4*99]{^}*}:S;
Để thuận tiện, đây là một khai thác thử nghiệm đơn giản gọi hàm S
, như được định nghĩa ở trên, để tính toán và in ra toàn bộ hộp chữ S trong hex như trên Wikipedia :
"0123456789abcdef"1/:h; 256, {S .16/h= \16%h= " "++ }% 16/ n*
Hãy thử mã này trực tuyến.
(Bản demo trực tuyến định trước bảng logarit để tránh mất quá nhiều thời gian. Mặc dù vậy, trang web GolfScript trực tuyến đôi khi có thể hết thời gian ngẫu nhiên; đây là sự cố đã biết với trang web và tải lại thường khắc phục nó.)
Giải trình:
Hãy bắt đầu với tính toán bảng logarit và cụ thể là với hàm trợ giúp r
:
{1$2*.255>@*^}:r
Hàm này có hai đầu vào trên ngăn xếp: một byte và bitmask giảm (hằng số nằm trong khoảng từ 256 đến 511). Nó nhân đôi byte đầu vào, nhân số sao chép lên 2 và, nếu kết quả vượt quá 255, XOR sẽ tạo bit với bitmask để đưa nó trở lại dưới 256.
Trong mã tạo bảng nhật ký, hàm r
được gọi với bitmask khử 283 = 0x11b (tương ứng với đa thức khử Rijndael GF (2 8 ) x 8 + x 4 + x 3 + x + 1) và kết quả là XORed với byte gốc, nhân nó một cách hiệu quả với 3 (= x + 1, dưới dạng đa thức) trong trường hữu hạn Rijndael. Phép nhân này được lặp lại 255 lần, bắt đầu từ byte 1 và kết quả (cộng với một byte số 0 ban đầu) được thu thập vào một mảng gồm 256 phần tử L
trông như thế này (bỏ qua phần giữa):
[0 1 3 5 15 17 51 85 255 26 46 ... 180 199 82 246 1]
Lý do tại sao có tới 256 phần tử là vì, với 0 được đặt trước và với 1 xảy ra hai lần, chúng ta có thể tìm thấy nghịch đảo mô-đun của bất kỳ byte đã cho nào chỉ bằng cách tra cứu chỉ số (dựa trên không) của nó trong mảng này, phủ nhận nó và tìm kiếm lên byte tại chỉ mục phủ định trong cùng một mảng. (Trong GolfScript, như trong nhiều ngôn ngữ lập trình khác, các chỉ mục mảng âm tính ngược từ cuối mảng.) Thật vậy, đây chính xác là những gì mã L?~)L=
ở đầu hàm S
thực hiện.
Phần còn lại của mã gọi hàm trợ giúp r
bốn lần với bitmask khử 256 = 2 8 + 1 để tạo bốn bản sao xoay bit của byte đầu vào đảo ngược. Tất cả đều được thu thập thành một mảng, cùng với hằng số 99 = 0x63 và XOR cùng nhau để tạo ra đầu ra cuối cùng.