Tôi là một trong những tác giả của Gimli. Chúng tôi đã có phiên bản 2 tweet (280 ký tự) trong C nhưng tôi muốn xem nó có thể nhỏ đến mức nào.
Gimli ( giấy , trang web ) là một tốc độ cao với thiết kế hoán vị mật mã cấp độ bảo mật cao sẽ được trình bày tại Hội nghị về Phần cứng và Hệ thống nhúng mã hóa (CHES) 2017 (25-28 / 9).
Nhiệm vụ
Như thường lệ: để thực hiện Gimli nhỏ có thể sử dụng được bằng ngôn ngữ bạn chọn.
Nó có thể lấy 384 bit đầu vào (hoặc 48 byte hoặc 12 không dấu int ...) và trả về (có thể sửa đổi tại chỗ nếu bạn sử dụng con trỏ) kết quả của Gimli được áp dụng trên 384 bit này.
Chuyển đổi đầu vào từ thập phân, thập lục phân, bát phân hoặc nhị phân được cho phép.
Trường hợp góc tiềm năng
Mã hóa số nguyên được coi là ít endian (ví dụ như những gì bạn có thể đã có).
Bạn có thể đổi tên Gimli
thành G
nhưng nó vẫn phải là một hàm gọi.
Ai thắng?
Đây là môn đánh gôn, vì vậy câu trả lời ngắn nhất bằng byte sẽ thắng! Quy tắc tiêu chuẩn áp dụng tất nhiên.
Một triển khai tham khảo được cung cấp dưới đây.
chú thích
Một số lo ngại đã được nêu ra:
"Này các bạn, vui lòng triển khai chương trình của tôi miễn phí bằng các ngôn ngữ khác để tôi không phải" (thx to @jstnthms)
Câu trả lời của tôi như sau:
Tôi có thể dễ dàng làm điều đó trong Java, C #, JS, Ocaml ... Đó là nhiều hơn cho vui. Hiện tại, chúng tôi (nhóm Gimli) đã triển khai (và tối ưu hóa) trên AVR, Cortex-M0, Cortex-M3 / M4, Neon, SSE, SSE-unrolled, AVX, AVX2, VHDL và Python3. :)
Về Gimli
Nhà nước
Gimli áp dụng một chuỗi các vòng cho trạng thái 384 bit. Trạng thái được biểu diễn dưới dạng song song với kích thước 3 × 4 × 32 hoặc tương ứng là ma trận 3 × 4 của các từ 32 bit.
Mỗi vòng là một chuỗi gồm ba thao tác:
- một lớp phi tuyến tính, cụ thể là hộp SP 96 bit được áp dụng cho mỗi cột;
- trong mỗi vòng thứ hai, một lớp trộn tuyến tính;
- trong mỗi vòng thứ tư, một sự bổ sung liên tục.
Lớp phi tuyến tính.
Hộp SP bao gồm ba thao tác phụ: xoay các từ thứ nhất và thứ hai; một hàm T phi tuyến 3 đầu vào; và hoán đổi từ thứ nhất và từ thứ ba.
Lớp tuyến tính.
Lớp tuyến tính bao gồm hai hoạt động hoán đổi, cụ thể là Hoán đổi nhỏ và Hoán đổi lớn. Hoán đổi nhỏ xảy ra cứ sau 4 vòng bắt đầu từ vòng 1. Big-Swap xảy ra cứ sau 4 vòng bắt đầu từ vòng 3.
Các hằng số tròn.
Có 24 vòng ở Gimli, được đánh số 24,23, ..., 1. Khi số vòng r là 24,20,16,12,8,4, chúng tôi XOR hằng số vòng (0x9e377900 XOR r) cho từ trạng thái đầu tiên.
nguồn tham khảo trong C
#include <stdint.h>
uint32_t rotate(uint32_t x, int bits)
{
if (bits == 0) return x;
return (x << bits) | (x >> (32 - bits));
}
extern void gimli(uint32_t *state)
{
int round;
int column;
uint32_t x;
uint32_t y;
uint32_t z;
for (round = 24; round > 0; --round)
{
for (column = 0; column < 4; ++column)
{
x = rotate(state[ column], 24);
y = rotate(state[4 + column], 9);
z = state[8 + column];
state[8 + column] = x ^ (z << 1) ^ ((y&z) << 2);
state[4 + column] = y ^ x ^ ((x|z) << 1);
state[column] = z ^ y ^ ((x&y) << 3);
}
if ((round & 3) == 0) { // small swap: pattern s...s...s... etc.
x = state[0];
state[0] = state[1];
state[1] = x;
x = state[2];
state[2] = state[3];
state[3] = x;
}
if ((round & 3) == 2) { // big swap: pattern ..S...S...S. etc.
x = state[0];
state[0] = state[2];
state[2] = x;
x = state[1];
state[1] = state[3];
state[3] = x;
}
if ((round & 3) == 0) { // add constant: pattern c...c...c... etc.
state[0] ^= (0x9e377900 | round);
}
}
}
Phiên bản có thể Tweet trong C
Đây có thể không phải là triển khai có thể sử dụng nhỏ nhất nhưng chúng tôi muốn có phiên bản tiêu chuẩn C (do đó không có UB và "có thể sử dụng" trong thư viện).
#include<stdint.h>
#define P(V,W)x=V,V=W,W=x
void gimli(uint32_t*S){for(long r=24,c,x,y,z;r;--r%2?P(*S,S[1+y/2]),P(S[3],S[2-y/2]):0,*S^=y?0:0x9e377901+r)for(c=4;c--;y=r%4)x=S[c]<<24|S[c]>>8,y=S[c+4]<<9|S[c+4]>>23,z=S[c+8],S[c]=z^y^8*(x&y),S[c+4]=y^x^2*(x|z),S[c+8]=x^2*z^4*(y&z);}
Vectơ kiểm tra
Các đầu vào sau được tạo bởi
for (i = 0;i < 12;++i) x[i] = i * i * i + i * 0x9e3779b9;
và "in" giá trị bởi
for (i = 0;i < 12;++i) {
printf("%08x ",x[i])
if (i % 4 == 3) printf("\n");
}
do đó:
00000000 9e3779ba 3c6ef37a daa66d46
78dde724 1715611a b54cdb2e 53845566
f1bbcfc8 8ff34a5a 2e2ac522 cc624026
nên trả lại:
ba11c85a 91bad119 380ce880 d24c2c68
3eceffea 277a921c 4f73a0bd da5a9cd8
84b673f0 34e52ff7 9e2bef49 f41bb8d6
-round
thay vì --round
phương tiện mà nó không bao giờ chấm dứt. Chuyển đổi --
sang dấu gạch ngang có lẽ không được đề xuất trong mã :)