Gimli, daha da kısaltır mı?


25

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, Gancak 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.

belirtmek, bildirmek

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.

SP

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.

Doğrusal

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.

görüntü tanımını buraya girin

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 

3
Bir tweet 140 karakter, 280 değil
Stan Strum

1
Biliyorum, bu yüzden 2'ye uyuyor;) twitter.com/TweetGimli .
Biv

10
"hey gang, lütfen programımı diğer dillerde ücretsiz olarak
uygula

hahaha Nah Python'da zaten var ve Java, C #, JS'de kolayca yapabilirim. Eğlence için daha fazla. :)
Biv

5
Referans kodu web sitesinde önemli bir hata var, -roundyerine --roundo sonlandırır asla demektir. Dönüştürme --bir tire muhtemelen :) kodunda önerilen değil
orlp

Yanıtlar:


3

CJam (114 karakter)

{24{[4/z{[8ZT].{8\#*G8#:Mmd+}__)2*\+.^W%\[_~;&8*\~@1$|2*@@&4*].^Mf%}%z([7TGT]R=4e!=\f=(2654435608R-_4%!*^\@]e_}fR}

Bu anonim bir bloktur (fonksiyon): adlandırmak istiyorsanız Gekleyiniz :G. CJam'da atanan isimler sadece tek büyük harfler olabilir. Bir yorum eklemek e# Gimli in CJamve karakterleri tek bir tweet'te bırakmak için boşluk var.

Çevrimiçi test

teşrih

{                                e# Define a block
  24{                            e# For R=0 to 23...
    [                            e#   Collect values in an array
      4/z                        e#     Transpose to columns
      {                          e#     Map over each column
        [8ZT].{8\#*G8#:Mmd+}     e#       Rotations, giving [x y z]
        __)2*\+.^W%\             e#       => [y^z x^y x^z*2] [x y z]
        [_~;&8*\~@1$|2*@@&4*].^  e#       => [x' y' z']
        Mf%                      e#       Map out any bits which overflowed
      }%
      z                          e#    Transpose to rows
      ([7TGT]R=4e!=\f=           e#    Permute first row
      (2654435608R-_4%!*^        e#    Apply round constant to first element
      \@                         e#    Put the parts in the right order
    ]e_                          e#  Finish collecting in array and flatten
  }fR
}

Bir an için çıkışın onaltılı olmadığı (çevrimiçi testte) olduğu için atıldım. :)
Biv

15

C (gcc), 237 bayt

#define P(a,l)x=a;a=S[c=l>>r%4*2&3];S[c]=x;
r,c,x,y,z;G(unsigned*S){
for(r=24;r;*S^=r--%4?0:0x9e377901+r){
for(c=4;c--;*S++=z^y^8*(x&y))
x=*S<<24|*S>>8,y=S[4]<<9|S[4]>>23,z=S[8],S[8]=x^2*z^4*(y&z),S[4]=y^x^2*(x|z);
S-=4;P(*S,33)P(S[3],222)}}

Muhtemelen takas yöntemimle bayt kazandım, ama kullanmamak çok şirin.


Kayıp mı Kazandınız mı?
HyperNeutrino

@HyperNeutrino Kazandı, beni kaybeden oldu :)
orlp

Ah tamam: P mantıklı: P: P
HyperNeutrino

Bu hala kesinlikle bir gelişmedir, ancak kullanmak unsignedyerine biraz aldatmak uint32_t(ve OP'nin kodu kullanmak biraz aldatmaktı long) çünkü şifrenin ardındaki fikir taşınabilir olması. (Aslında, bu temelde yalnızca 8 bayt tasarrufu sağlar).
Peter Taylor

1
@PeterTaylor Kodum benzer olsa da, OP koduna karşı gerçekten rekabet etmiyorum. En azından bir platformdaki bir uygulama ile çalışması gereken PPCG kuralları çerçevesinde çalışıyorum ve gcc32 bit veya 64 bit Intel CPU'larda (ve muhtemelen daha pek çoğu).
orlp

4

C, 268 karakter (268 bayt), uint32_t kullanarak

NB kod kullanımları orijinal yana <stdint.h>ve türleri Solarak uint32_t *, ben kullanımı düşünüyorum longkullanılmasının nedeni budur taşınabilirlik pahasına 280 karakter içine almak için bir dolandırıcı olduğunu uint32_tilk etapta. Karşılaştırmaların adil olması için tutarlı bir kullanım uint32_tve açık bir imza gerektiriyorsa void gimli(uint32_t *), orijinal kod gerçekten 284 karakterdir ve orlp kodu 276 karakterdir.

#include<stdint.h>
#define R(V)x=S[V],S[V]=S[V^y],S[V^y]=x,
void gimli(uint32_t*S){for(uint32_t r=24,x,y,z,*T;r--;y=72>>r%4*2&3,R(0)R(3)*S^=y&1?0x9e377901+r:0)for(T=S+4;T-->S;*T=z^y^8*(x&y),T[4]=y^x^2*(x|z),T[8]=x^2*z^4*(y&z))x=*T<<24|*T>>8,y=T[4]<<9|T[4]>>23,z=T[8];}

Bu, devam işaretleri ile iki tweet'e ayrılabilir.

#include<stdint.h>
#define R(V)x=S[V],S[V]=S[V^y],S[V^y]=x,
void gimli(uint32_t*S){for(uint32_t r=24,x,y,z,*T;r--;y=72>>r%4*2&3,R(0)R(3)// 1

ve

*S^=y&1?0x9e377901+r:0)for(T=S+4;T-->S;*T=z^y^8*(x&y),T[4]=y^x^2*(x|z),T[8]=x^2*z^4*(y&z))x=*T<<24|*T>>8,y=T[4]<<9|T[4]>>23,z=T[8];}// 2/2

Kullanımı longiçinde zaman versiyonu (taşınabilirlik bakımından), kasa (aksine uzun bir minimum boyut standardı ile 32 bit çünkü int). Atamadaki dökümden önce yapılan rotasyonlar yapılır xve güvenli hale getirilir (işaretli değerdeki doğru kayma CC'ye bağımlı olduğu için). Geri dönerken alçı üst bitlerden kurtulur ve bizi doğru duruma getirir :). ylonguint32_t* S
Biv

2

Java (OpenJDK 8) , 351 343 339 320 318 247 + 56 bayt

Golfe başlamak için sadece referansın 1: 1 portu yakınında.

void f(int[]x,int y,int z){int q=x[y];x[y]=x[z];x[z]=q;}

s->{for(int r=24,c,x,y,z;r>0;--r){for(c=0;c<4;x=s[c]<<24|s[c]>>>8,y=s[4+c]<<9|s[4+c]>>>23,z=s[8+c],s[8+c]=x^z<<1^(y&z)<<2,s[4+c]=y^x^(x|z)<<1,s[c++]=z^y^(x&y)<<3);if((r&3)==2){f(s,0,2);f(s,1,3);}if((r&3)<1){f(s,0,1);f(s,2,3);s[0]^=0x9e377900|r;}}}

Çevrimiçi deneyin!


1
Neden Integerhiç kullanmıyorsun ? o_O Herhangi bir Integeryöntem kullanmadığınız için , burada kullanmamaya gerek yok int...
Olivier Grégoire

@ OlivierGrégoire Integer.divideUnsigned'i denemekten benden kalan bir kalıntı olduğunu düşünüyorum ama >>>
Roberto Graham

s[0]^=(0x9e377900|r);(en sonunda) - fazladan parantezleri düşüremez misiniz?
Clashsoft

İle aynı s[4+c]>>>(23).
Clashsoft

1
Çok daha az değişiklik yapabilir ve 300: alabilirsiniz void P(int[]S,int a,int b){int x=S[a];S[a]=S[b];S[b]=x;}void gimli(int[]S){for(int r=24,c,x,y,z;r>0;S[0]^=y<1?0x9e377901+r:0){for(c=4;c-->0;){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);}y=r%4;if(--r%2>0){P(S,0,1+y/2);P(S,3,2-y/2);}}}. Temelde derlemesi için gereken minimum değişiklikleri yaptım. Java'nın öncelik kuralları C'lerden farklı değildir.
Peter Taylor

2

JavaScript (ES6), 231 bayt

s=>{for(r=25;--r;[a,b,c,d,...e]=s,s=r&1?s:r&2?[c,d,a,b,...e]:[b,a,d,c,...e],s[0]^=r&3?0:0x9e377900|r)for(c=4;c--;x=s[c]<<24|s[c]>>>8,y=s[j=c+4]<<9|s[j]>>>23,z=s[c+8],s[c+8]=x^z*2^(y&z)*4,s[j]=y^x^(x|z)*2,s[c]=z^y^(x&y)*8);return s}

gösteri


0

32 bit x86 birleştirici (112 bayt)

(__cdecl arama kuralı)

            pusha
            mov     ecx, 9E377918h
    loc_6:  mov     esi, [esp+24h]
            push    esi
            push    4
            pop     ebx
    loc_E:  lodsd
            ror     eax, 8
            mov     ebp, [esi+0Ch]
            rol     ebp, 9
            mov     edx, [esi+1Ch]
            push    eax
            push    ebp
            lea     edi, [edx+edx]
            and     ebp, edx
            shl     ebp, 2
            xor     edi, ebp
            xor     eax, edi
            mov     [esi+1Ch], eax
            pop     ebp
            pop     eax
            push    eax
            push    ebp
            xor     ebp, eax
            or      eax, edx
            shl     eax, 1
            xor     ebp, eax
            mov     [esi+0Ch], ebp
            pop     ebp
            pop     eax
            xor     edx, ebp
            and     eax, ebp
            shl     eax, 3
            xor     edx, eax
            push    edx
            dec     ebx
            jnz     short loc_E
            pop     esi
            pop     ebp
            pop     ebx
            pop     eax
            pop     edi
            mov     dl, cl
            and     dl, 3
            jnz     short loc_5B
            xchg    eax, ebx
            xchg    esi, ebp
            xor     eax, ecx
    loc_5B: cmp     dl, 2
            jnz     short loc_63
            xchg    eax, ebp
            xchg    esi, ebx
    loc_63: stosd
            xchg    eax, ebx
            stosd
            xchg    eax, ebp
            stosd
            xchg    eax, esi
            stosd
            dec     cl
            jnz     short loc_6
            popa
            retn

Eğilebilir versiyon (z85 formatındaki Base85 kodlaması)

v7vb1h> C} HbQuA91y51A:? oWYw48G) Ben H = /] rGf9Na> sA.DWu06 {6f # TEC ^ CM: # IEA-cstx7:!> VfVf # u * YB & mP (tuCl * + 7eENBP) $ :) Lh k } t $ ^ wM51j% LDF $ HMAg2bB ^ MQP
Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.