Saya salah satu penulis Gimli. Kami sudah memiliki versi 2-tweet (280 karakter) di C tapi saya ingin melihat seberapa kecil itu bisa didapat.
Gimli ( kertas , situs web ) adalah kecepatan tinggi dengan desain permutasi kriptografi tingkat keamanan tinggi yang akan dipresentasikan pada Konferensi Perangkat Keras Kriptografi dan Sistem Tertanam (CHES) 2017 (25-28 September).
Tugas
Seperti biasa: untuk membuat implementasi Gimli yang dapat digunakan menjadi lebih kecil dalam bahasa pilihan Anda.
Seharusnya dapat mengambil 384 bit input (atau 48 byte, atau 12 int unsigned ...) dan mengembalikan (dapat memodifikasi di tempat jika Anda menggunakan pointer) hasil Gimli diterapkan pada 384 bit ini.
Konversi input dari desimal, heksadesimal, oktal atau biner diperbolehkan.
Kasing sudut potensial
Encoding integer diasumsikan sebagai little-endian (mis. Apa yang mungkin sudah Anda miliki).
Anda dapat mengubah nama Gimli
menjadi G
tetapi masih harus berupa panggilan fungsi.
Yang menang?
Ini adalah kode-golf sehingga jawaban tersingkat dalam byte menang! Aturan standar berlaku tentu saja.
Implementasi referensi disediakan di bawah ini.
Catatan
Beberapa keprihatinan telah dikemukakan:
"hei geng, tolong implementasikan program saya secara gratis dalam bahasa lain jadi saya tidak perlu" (thx to @jstnthms)
Jawaban saya adalah sebagai berikut:
Saya dapat dengan mudah melakukannya di Java, C #, JS, Ocaml ... Ini lebih untuk bersenang-senang. Saat ini Kami (tim Gimli) menerapkannya (dan dioptimalkan) pada AVR, Cortex-M0, Cortex-M3 / M4, Neon, SSE, SSE-unrolled, AVX, AVX2, VHDL dan Python3. :)
Tentang Gimli
Negara
Gimli menerapkan urutan putaran ke keadaan 384-bit. Negara direpresentasikan sebagai paralelepiped dengan dimensi 3 × 4 × 32 atau, setara, sebagai matriks 3 × 4 kata 32-bit.
Setiap putaran adalah urutan dari tiga operasi:
- lapisan non-linear, khususnya SP-box 96-bit yang diterapkan pada setiap kolom;
- di setiap putaran kedua, lapisan pencampuran linier;
- di setiap ronde keempat, tambahan konstan.
Lapisan non-linear.
Kotak-SP terdiri dari tiga sub-operasi: rotasi kata pertama dan kedua; fungsi-T non-linier 3-input; dan swap kata pertama dan ketiga.
Lapisan linier.
Lapisan linier terdiri dari dua operasi swap, yaitu Small-Swap dan Big-Swap. Small-Swap terjadi setiap 4 ronde mulai dari ronde 1. Big-Swap terjadi setiap 4 putaran mulai dari putaran ke-3.
Konstanta bulat.
Ada 24 putaran di Gimli, bernomor 24,23, ..., 1. Ketika bilangan bulat r adalah 24,20,16,12,8,4 kita XOR konstanta putaran (0x9e377900 XOR r) ke kata keadaan pertama.
sumber referensi dalam 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);
}
}
}
Versi Tweetable dalam C
Ini mungkin bukan implementasi terkecil yang dapat digunakan tetapi kami ingin memiliki versi standar C (sehingga tidak ada UB, dan "dapat digunakan" di perpustakaan).
#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);}
Tes vektor
Input berikut dihasilkan oleh
for (i = 0;i < 12;++i) x[i] = i * i * i + i * 0x9e3779b9;
dan nilai "dicetak" oleh
for (i = 0;i < 12;++i) {
printf("%08x ",x[i])
if (i % 4 == 3) printf("\n");
}
demikian:
00000000 9e3779ba 3c6ef37a daa66d46
78dde724 1715611a b54cdb2e 53845566
f1bbcfc8 8ff34a5a 2e2ac522 cc624026
harus kembali:
ba11c85a 91bad119 380ce880 d24c2c68
3eceffea 277a921c 4f73a0bd da5a9cd8
84b673f0 34e52ff7 9e2bef49 f41bb8d6
-round
bukan --round
berarti bahwa hal itu tidak pernah berakhir. Mengubah --
ke en dasbor mungkin tidak disarankan dalam kode :)