Ben Gimli'nin yazarlarından biriyim. Şimdiden C içinde 2 tweet (280 karakter) sürümümüz var, ancak ne kadar küçük olabileceğini görmek istiyorum.
Gimli ( bildiri , web sitesi ), Şifreleme Donanımı ve Gömülü Sistemler Konferansı'nda (CHES) 2017 (25-28 Eylül ) sunulacak olan yüksek güvenlik seviyeli kriptografik permütasyon tasarımlı yüksek bir hızdır .
Görev
Her zamanki gibi: Gimli'nin tercih edilen dilde küçültülebilir kullanımını sağlamak.
Bu 384 bitlere uygulanan Gimli'nin sonucunu 384 bit (veya 48 bayt veya 12 işaretsiz int ...) girdi olarak alabilmeli ve geri döndürebilmeli (işaretçi kullanıyorsanız yerinde değişiklik yapabilir) .
Ondalık, onaltılık, sekizli veya ikiliden girdi dönüştürmeye izin verilir.
Potansiyel köşe kılıfları
Tamsayı kodlamanın az endian olduğu varsayılır (örneğin, muhtemelen zaten sahip olduğunuz).
Yeniden adlandırabilirsiniz Gimli
, G
ancak yine de bir işlev çağrısı olmalıdır.
Kim kazanır?
Bu kod-golf yani bayt cinsinden en kısa cevap kazanır! Standart kurallar elbette geçerlidir.
Aşağıda referans uygulaması verilmiştir.
Not
Bazı endişeler dile getirildi:
"hey gang, lütfen programımı diğer dillerde ücretsiz olarak uygulayın, böylece yapmak zorunda kalmam" (jstnthms için thx)
Cevabım aşağıdaki gibidir:
Java, C #, JS, Ocaml ile kolayca yapabilirim ... Eğlence için daha fazlası. Şu anda Biz (Gimli ekibi) AVR, Cortex-M0, Cortex-M3 / M4, Neon, SSE, SSE-kontrolsüz, AVX, AVX2, VHDL ve Python3 üzerinde uygulandı (ve optimize ettik). :)
Gimli hakkında
Eyalet
Gimli 384 bitlik duruma bir dizi tur uygular. Durum, 3 × 4 × 32 boyutlarıyla paralel olarak temsil edilir veya eşdeğerde, 3 × 4 matris olarak 32 bit kelimelik bir ifade ile gösterilir.
Her tur üç işlemden oluşan bir dizidir:
- doğrusal olmayan bir katman, özellikle her bir sütuna uygulanan 96 bitlik bir SP-box;
- her ikinci turda, doğrusal bir karıştırma katmanı;
- Her dördüncü turda, sabit bir ek.
Doğrusal olmayan katman.
SP-box üç alt işlemden oluşur: birinci ve ikinci kelimelerin rotasyonu; 3 girişli doğrusal olmayan bir T fonksiyonu; ve birinci ve üçüncü kelimelerin bir takas.
Doğrusal tabaka.
Doğrusal katman, Küçük Takas ve Büyük Takas olmak üzere iki takas işleminden oluşur. Küçük Takas, ilk turdan başlayarak her 4 turda bir gerçekleşir. Big-Swap 3. turdan başlayarak her 4 turda bir gerçekleşir.
Yuvarlak sabitler.
Gimli'de 24, 23, ..., 1 numaralı 24 tur var. R tur sayısı 24,20,16,12,8,4 olduğunda, tur sabitini (0x9e377900 XOR r) birinci durum kelimesine XOR yaparız.
C referans kaynağı
#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);
}
}
}
C de indirilebilir sürüm
Bu, en küçük kullanışlı uygulama olmayabilir, ancak C standart bir sürümüne sahip olmak istedik (bu nedenle UB değil ve bir kütüphanede "kullanılabilir").
#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);}
Test vektörü
Aşağıdaki girdi tarafından oluşturulan
for (i = 0;i < 12;++i) x[i] = i * i * i + i * 0x9e3779b9;
ve "yazdırılan" değerleri
for (i = 0;i < 12;++i) {
printf("%08x ",x[i])
if (i % 4 == 3) printf("\n");
}
Böylece:
00000000 9e3779ba 3c6ef37a daa66d46
78dde724 1715611a b54cdb2e 53845566
f1bbcfc8 8ff34a5a 2e2ac522 cc624026
dönmeli:
ba11c85a 91bad119 380ce880 d24c2c68
3eceffea 277a921c 4f73a0bd da5a9cd8
84b673f0 34e52ff7 9e2bef49 f41bb8d6
-round
yerine --round
o sonlandırır asla demektir. Dönüştürme --
bir tire muhtemelen :) kodunda önerilen değil