ギムリ、もっと短くしますか?


25

私はギムリの著者の一人です。Cにはすでに2ツイート(280文字)のバージョンがありますが、どれだけ小さくできるかを確認したいと思います。

Gimli(論文ウェブサイト)は、暗号化ハードウェアおよび組み込みシステムに関する会議(CHES)2017(9月25-28日)で発表される、高セキュリティレベルの暗号順列設計です。

タスク

いつものように:Gimliの小さく使用可能な実装を、選択した言語で作成します。

することができるはず、入力として384ビット取る(...または48バイト、または12 unsigned int型の)とリターン(あなたは、ポインタを使用する場合は所定の位置に変更することができる)ギムリの結果は、これらの384ビットに適用されます。

10進数、16進数、8進数、または2進数からの入力変換が許可されます。

潜在的なコーナーケース

整数エンコードは、リトルエンディアンであると想定されます(たとえば、既にあるもの)。

名前を変更するGimliGそれはまだ、関数呼び出しでなければなりません。

誰が勝ちますか?

これはコードゴルフなので、バイト単位の最短回答が勝ちです!もちろん、標準ルールが適用されます。

リファレンス実装を以下に示します。

注意

いくつかの懸念が提起されました。

「ギャングさん、私のプログラムを他の言語で無料で実装してください。そうする必要はありません」(thx to @jstnthms)

私の答えは次のとおりです。

Java、C#、JS、Ocamlで簡単に実行できます。現在、我々(Gimliチーム)は、AVR、Cortex-M0、Cortex-M3 / M4、Neon、SSE、SSE-unrolled、AVX、AVX2、VHDL、Python3に実装(および最適化)しています。:)


Gimliについて

状態

Gimliは、一連のラウンドを384ビット状態に適用します。状態は、次元3×4×32の平行六面体、または同等に、32ビットワードの3×4マトリックスとして表されます。

状態

各ラウンドは、3つの操作のシーケンスです。

  • 非線形層、具体的には各列に適用される96ビットSPボックス。
  • 2ラウンドごとに、線形混合層。
  • 4ラウンドごとに、一定の追加。

非線形レイヤー。

SPボックスは3つのサブ操作で構成されています。1番目と2番目の単語の回転。3入力の非線形T関数。そして、最初と3番目の単語の交換。

SP

線形レイヤー。

リニアレイヤーは、Small-SwapとBig-Swapの2つのスワップ操作で構成されます。スモールスワップは、1ラウンド目から4ラウンドごとに発生します。ビッグスワップは、3ラウンド目から4ラウンドごとに発生します。

リニア

ラウンド定数。

ギムリには24ラウンド、24、23、...、1の番号が付けられています。ラウンド数rが24,20,16,12,8,4の場合、ラウンド定数(0x9e377900 XOR r)を最初の状態ワードとXORします。

ここに画像の説明を入力してください

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);
    }
  }
}

Cでのツイート可能なバージョン

これは最小の使用可能な実装ではないかもしれませんが、C標準バージョンが必要でした(したがって、UBはなく、ライブラリで「使用可能」です)。

#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);}

テストベクトル

によって生成された次の入力

for (i = 0;i < 12;++i) x[i] = i * i * i + i * 0x9e3779b9;

および「印刷された」値

for (i = 0;i < 12;++i) {
  printf("%08x ",x[i])
  if (i % 4 == 3) printf("\n");
}

したがって:

00000000 9e3779ba 3c6ef37a daa66d46 
78dde724 1715611a b54cdb2e 53845566 
f1bbcfc8 8ff34a5a 2e2ac522 cc624026 

返す必要があります:

ba11c85a 91bad119 380ce880 d24c2c68 
3eceffea 277a921c 4f73a0bd da5a9cd8 
84b673f0 34e52ff7 9e2bef49 f41bb8d6 

3
つぶやきは140文字ではなく、280である
スタンストラム

1
私が知っている、それが2に収まる理由です;)twitter.com/TweetGimli
ビブ

10
「私はする必要はありませんので、ちょっとギャングが、他の言語で自由のための私のプログラムを実施してください」
jstnthms

ハハハNah私はすでにPythonでそれを持っています、そして私は簡単にJava、C#、JSでそれをすることができます。それは楽しみのためです。:)
ビブ

5
Webサイトの参照コードには、終了しないという意味では-roundなく、重大なエラーが--roundあります。--エンダッシュに変換することは、おそらくコードでは推奨されていません:)
orlp

回答:


3

CJam(114文字)

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

これは匿名ブロック(関数)です。名前を付けたい場合はG、appendを追加します:G。CJamでは、割り当てられる名前は単一の大文字のみです。コメントを追加e# Gimli in CJamして、1つのツイートに文字を残すスペースがあります。

オンラインテスト

解剖

{                                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
}

しばらくの間、(オンラインテストで)出力が16進数ではなかったという事実に私は投げ捨てられました。:)
ビブ

15

C(gcc)、237バイト

#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)}}

スワッピング方法でバイトを得たのかもしれませんが、使用するには可愛すぎます。


失ったか得た?
ハイパーニュートリノ

@HyperNeutrino獲得、私を敗者にします:)
orlp

ああ大丈夫:P理にかなっています:P:P
HyperNeutrino

これはまだ間違いなく改善されていますが、暗号の背後にあるアイデアは移植性が高いということなので、unsigned代わりに使用するのは多少不正ですuint32_t(そしてOPのコードは使用するのは多少不正ですlong)。(実際、基本的にこれはわずか8バイトを節約します)。
ピーターテイラー

1
@PeterTaylor私のコードは似ていますが、OPのコードと実際には競合していません。私はPPCGのルールの下で働いています。PPCGは少なくともプラットフォーム上の実装で動作する必要がありgcc、32ビットまたは64ビットのIntel CPU(およびおそらくそれ以上)で動作します。
orlp

4

C、uint32_tを使用した268文字(268バイト)

NB元のコードはを使用し<stdint.h>Sとしてタイプしているため、の使用は、そもそも使用する理由である移植性を犠牲にして280文字に入るためのチートuint32_t *だと思います。比較の公平性のために、明示的な署名の一貫した使用が必要な場合、元のコードは実際には284文字であり、orlpのコードは276文字です。longuint32_tuint32_tvoid gimli(uint32_t *)

#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];}

これは、継続マーカー付きの2つのツイートに分割できます。

#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

そして

*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

私のバージョンlongでの使用は、longの最小サイズが標準では32ビットであるため(移植性に関して)安全です。のローテーションおよび割り当ては、割り当てにキャストする前に行われ、安全になります(符号付き値の右シフトはCCに依存するため)。)に戻ったときのキャストは、上位ビットを取り除き、適切な状態にします:)。intxylonguint32_t* S
ビブ

2

Java(OpenJDK 8)351 343 339 320 318 247 + 56バイト

ゴルフを開始するための参照のちょうど1:1のポート。

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;}}}

オンラインでお試しください!


1
なぜ使用Integerするのですか?あなたが任意の使用していないのでO_O Integer方法を使用していない理由はありませんint...ここでsは
オリヴィエ・グレゴワール

@OlivierGrégoire私はInteger.divideUnsignedを試してみただけの残党だと思いますが、私は持っていることができることに気付きました>>>
ロベルト・グラハム

s[0]^=(0x9e377900|r);(最後に)-余分な括弧を削除できませんか?
クラッシュソフト

と同じs[4+c]>>>(23)
Clashsoft

1
変更をはるかに少なくして300を取得できます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);}}}。基本的に、コンパイルするために必要な最小限の変更を行いました。Javaの優先規則は、Cの規則とそれほど変わりません。
ピーターテイラー

2

JavaScript(ES6)、231バイト

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}

デモ


0

32ビットx86アセンブラー(112バイト)

(__cdecl呼び出し規約)

            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

ツイート可能バージョン(z85形式のBase85エンコード):

v7vb1h> C} HbQuA91y51A:oWYw48G)?I = H /] rGf9Na> sA.DWu06 {6f#TEC ^ CM:#IeA-cstx7:>!VfVf#u * YB&mP(tuCl * + 7eENBP)$ :) Lh!k } t $ ^ wM51j%LDf $ HMAg2bB ^ MQP
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.