CipherSaber暗号化


11

以下に説明するように、CipherSaber暗号化プログラムを実装します。ガイドライン:

  • バイト単位の最小のエントリが優先されます。
    • ただし、標準からの逸脱では、たとえ重要なゴルフエントリでなくても、興味深いエントリを投稿することを歓迎します。
  • 通常、エントリは、標準入力からプレーンテキストを取得し、暗号テキストを標準出力に書き込み、ユーザーが指定した方法でキーを(ユーザーが)指定するプログラムです。
    • ただし、これをプロシージャとして実装する場合は、それでも問題ありません。
  • IVは、暗号で保護された擬似乱数ジェネレータから取得する必要があります。お使いの言語がそれをサポートしていない場合は、別の言語を選択してください。;-)
  • 暗号固有のライブラリ、システムコール、または命令(上記で規定されているPRNG以外)は使用しないでください。もちろん、一般的な低レベルのビット単位操作は大丈夫です。

CipherSaberはRC4 / Arcfourの変形なので、後者について説明することから始め、CipherSaberがそれに対して行う変更について説明します。

0. RC4 / Arcfour

Arcfourは他の場所完全に指定されていますが完全を期すためにここで説明します。(インターネットドラフトとこの説明の間に矛盾がある場合、前者は規範的です。)

キー設定

2つの配列、Sおよびをセットアップします。S2両方とも長さ256です。ここk_1で、はキーの最初のバイトでk_n、最後はバイトです。

S = [0, ..., 255]
S2 = [k_1, ..., k_n, k_1, ...]

S2すべての256バイトがいっぱいになるまで、キーのバイトが何度も書き込まれます。)

次に、j0 に初期化し、256回シャッフルします。

j = 0
for i in (0 .. 255)
    j = (j + S[i] + S2[i]) mod 256
    swap S[i], S[j]
end

これでキーのセットアップが完了しました。S2配列は、もはやここで使用されていない、とスクラブすることができます。

暗号ストリーム生成

0に初期化iしてjから、次のようにキーストリームを生成します。

i = 0
j = 0
while true
    i = (i + 1) mod 256
    j = (j + S[i]) mod 256
    swap S[i], S[j]
    k = (S[i] + S[j]) mod 256
    yield S[k]
end

データの暗号化/復号化

  • 暗号化するには、キーストリーム出力をプレーンテキストでXORします
  • 復号化するには、キーストリーム出力と暗号文をXORします

1.サイファーセイバー

CipherSaber(この質問で実装しているもの)は、RC4 / Arcfourの2つの方法のバリエーションです。

10バイトIV /ノンス

メッセージを暗号化するときは、viaなど、ランダムな10バイトを取得し、/dev/urandom暗号化された出力の最初の10バイトに書き込む必要があります。メッセージを復号化するとき、入力の最初の10バイトは、暗号化に使用されるIVです。

RC4 / Arcfourキーセットアップステージはpassphrase || IVキーとして実行されます。ここpassphraseで、ユーザー指定のパスフレーズIVは上記のとおりで、||連結されています。「Hello、world!」のパスフレーズ そして、「supercalif」のIV(ただし、それは:-Pではありませんが)は、「Hello、world!supercalif」のキーになります。

キー設定の複数の反復

WEP暗号化が完全に壊れた脆弱性を防ぐために、RC4のキーセットアップステージのシャッフルループがユーザー指定の回数実行されます。の値はj反復間で保持する必要があります。

2.テストベクター

以下に、プログラムのテストに使用できるいくつかのテストベクトルを示します。さらに、squeamish ossifrageは、結果の検証に使用できるCipherSaber暗号化および復号化ツールを作成しました。

暗号化プログラムを実装するだけです。復号化プログラムを提供する必要はありませんが、正しいキーを使用して正しく実装された復号化プログラムで処理する場合、暗号化プログラムの出力は元の入力に正しく往復する必要があります。

回答:


7

Pyth、100バイト

$import os$KsM$os.urandom(10)$JuuXN@LN,T=+Z+@NT@+CMzKT)bGQU=b256=Z0sCM+K.exCb@=XJ=N@LJ,hk=+Z@Jhk)sNw

このスクリプトは、$Pythonコードの実行を許可するコマンドを使用します。サーバーで悪意のあるコードが実行されるのを防ぐために、オンラインコンパイラではthisコマンドが無効になっています。ここで見つけることができるオフラインコンパイラでそれを実行しなければなりません。

入力の形式は次のとおりです。

secret key
5 (number of repeats)
secret message

プログラムは暗号化された文字列を出力しますが、これには印刷できない文字が含まれている場合があります。CipherSaber Encryption&Decryption Toolを使用して検証する場合は、次のコードを使用して、文字列を一連の16進数に変換できます。

$import os$KsM$os.urandom(10)$JuuXN@LN,T=+Z+@NT@+CMzKT)bGQU=b256=Z0         
jdm.[2.HCd`0
sCM+K.exCb@=XJ=N@LJ,hk=+Z@Jhk)sNw

Pythは暗号的に安全な擬似乱数をサポートしておらず、Pythonからそれらをインポートするには25バイトかかります。Pyth / Pythonの標準の疑似乱数ジェネレーターを使用し、オンラインコンパイラーでも機能する短いコードは次のとおりです。

KmO=b256TJuuXN@LN,T=+Z+@NT@+CMzKT)bGQUb=Z0sCM+K.exCb@=XJ=N@LJ,hk=+Z@Jhk)sNw

オンラインで試す:文字列または一連の16進数を返す

コードは特別なものではありません。大量のダーティな割り当てと計算結果の即時再利用、およびリストスワップトリックの2倍の適用。

説明:

                                  implicit: z = 1st input (= key string)
                                  Q = 2nd input (number of repetitions)
$import os$KsM$os.urandom(10)$
$import os$                       import Python's os module
              $os.urandom(10)$    create 10 cryptographically secure 
                                  pseudo-random bytes
            sM                    convert them to ints
           K                      store them in K

JuuXN@LN,T=+Z+@NT@+CMzKT)bGQU=b256
                             =b256assign b with 256
 u                         QUb    start with G = [0, 1, ..., 255], 
                                  evaluate the following expression Q times and
                                  update G with the result each time:
  u                      bG         start with N = G, 
                                    for each T in [0, 1, ..., 255] evaluate the
                                    following expression and update N each time:
                   CMz                convert key to list of ints
                  +   K               extend it with K
                 @     T              take the Tth element (modulo length)
              @NT                     take the Tth element of N
             +                        add these two values
           +Z                         add Z (with is initially 0)
          =                           and update Z with the result
        ,T  Z                         make the pair of indices [T, Z] 
     @LN                              look-up their values in N
   XN                   )             and switch these two values in N
J                                 assign the result (the key setup) to J

=Z0                               set Z to 0

sCM+K.exCb@=XJ=N@LJ,hk=+Z@Jhk)sNw 
                                w read a string from input (message)
     .e                           map each index k, char b in message to:
                         @Jhk       look-up the (k+1)th element in J
                      =+Z           add it to Z and update Z
                   ,hk  Z           make the pair of indices [k+1,Z]
                @LJ                 look-up their values in J
              =N                    assign the result to N
            XJ N             )      swap these values in J
           =                        and update J with the result
          @  J                sN    take the sum(N)th element of J
        Cb                          convert b to int
       x                            bitwise xor of these two elements
   +K                             insert K at the beginning
 CM                               convert each element to char
s                                 sum them (generate a string)
                                  implicitly print

どうやら、組み込みのPyth関数には暗号的に安全な擬似乱数がありません。エントリをそのままにしておくと、緑色のチェックマークの対象になりません。または、urandom「勝つ」ことを気にする場合は(必要に応じて別のエントリにすることもできます)を使用するバージョンを作成できます。:-)
クリスジェスターヤング

@ ChrisJester-Youngそれについてすみません。Pythonの乱数ジェネレーターがそれほど安全であるとは思っていませんでした。25バイトのコストに修正しました。
ジャクベ

4

Pythonの2 - 373の 350 326 317バイト

恐らく後で来るパイス。1つの関数を定義しc(p,d,r,m)ます。パスフレーズとデータのバイトリスト、繰り返しのint、1のときに暗号化して0のときに復号化するintを受け取ります。これは、IVの処理のみが異なるためです。バイトリストを返します。

import os
B=256
def c(p,d,r,m):
    if m:v=map(ord,os.urandom(10))
    else:v,d=d[:10],d[10:]
    p+=v;S=range(B);T=(p*B)[:B];j=0;exec"for i in range(B):j=(j+S[i]+T[i])%B;S[i],S[j]=S[j],S[i]\n"*r;o=[];i=j=0
    for b in d:i=-~i%B;j=(j+S[i])%B;S[i],S[j]=S[j],S[i];k=(S[i]+S[j])%B;o+=[S[k]^b]
    return v+o if m else o

テストコード/ヘルパー関数は次のとおりです。

phrase = "hello"
text = "Mary had a little lamb, little lamb, little lamb"
N = 5

def make_bytes(string):
    return map(ord, string)

def make_string(bytes):
    return "".join(map(chr, bytes))

def make_hex(bytes):
    return " ".join("%02x" % i for i in bytes)

def from_hex(hex_str):
    return [int(i, 16) for i in hex_str.split()]

cipher = c(make_bytes(phrase), make_bytes(text), N, 1)
print make_hex(cipher)
plain = c(make_bytes(phrase), cipher, N, 0)
print make_string(plain)

暗号化プログラムを作成するだけです。そのため、else:v,d=d[:10],d[10:]部品を削除できます。
ジャクベ

3

ルビー-263文字

これは、2010年のstackoverflowに関する元の質問に対する私のRubyの回答です!それはすべて1つのプログラムのエンコーダーとデコーダーです

パラメータは次のとおりです
。eまたはd(エンコードまたはデコード用)
キー
の回数

$ ruby saber.rb e gnibbler 10 < in.txt | ruby saber.rb d gnibbler 10

o,k,l=ARGV;print o<'e'?(v=STDIN.read(10))*0:v=(0..9).map{rand(256).chr}.join;j=0;E=255
S=Array 0..255;(S*l.to_i).each{|i|j=j+S[i]+((k+v)*E)[i].ord&E;S[i],S[j]=S[j],S[i]};i=j=0
STDIN.each_byte{|c|i=i+1&E;j=j+S[i]&E;S[i],S[j]=S[j],S[i];print (c^S[S[i]+S[j]&E]).chr}

2

C、312バイト

コマンドラインでキーとキーの混合反復カウントを受け入れ、stdinのすべてをstdoutに暗号化します。これは、arc4random()RC4に基づいたPRNGであるBSD / Darwinライブラリ関数を使用します。自動的にシードされるため、結果は毎回異なります。

unsigned char n,i,j,q,x,t,s[256],k[256];main(int c,char**v){for(strcpy(k,v[1]),n=strlen(k);x<10;x++)putchar(k[n++]=arc4random());do{s[i]=i;}while(++i);for(x=atoi(v[2]);x--;)do{t=s[i];s[i]=s[j+=s[i]+k[i%n]];s[j]=t;}while(++i);for(;(c=getchar())>0;){q+=s[++i];t=s[i];s[i]=s[q];s[q]=t;t=s[i]+s[q];putchar(c^s[t]);}}

Tidierバージョン:

unsigned char n,i,j,q,x,t,s[256],k[256];
main(int c,char**v) {
  for (strcpy(k,v[1]),n=strlen(k);x<10;x++) putchar(k[n++]=arc4random());
  do {
    s[i]=i;
  }
  while(++i);
  for (x=atoi(v[2]);x--;) do {
    t=s[i];
    s[i]=s[j+=s[i]+k[i%n]];
    s[j]=t;
  }
  while (++i);
  for (;(c=getchar())>0;) {
    q+=s[++i];
    t=s[i];
    s[i]=s[q];
    s[q]=t;
    t=s[i]+s[q];
    putchar(c^s[t]);
  }
}

例:

$ echo -n 'Ciphersaber' | ./csgolf 'hello' 20 | xxd -p
0f6257c330e5e01c3eab07bc9cb4ee4c3eaa514a85

1

Python-266文字

これは、2010年のstackoverflowに関する元の質問に対する私のPythonの答えです!それはすべて1つのプログラムのエンコーダーとデコーダーです

パラメータは次のとおりです
。eまたはd(エンコードまたはデコード用)
キー
の回数

$ python saber.py e gnibbler 10 < in.txt | python saber.py d gnibbler 10

このバージョンは、rc4の2つのループを1つにマージしようとします(これまでのところ11バイトを保存しています...)

import os,sys;X,Y=sys.stdin.read,os.write;_,o,k,l=sys.argv;p='d'<o
V=(X,os.urandom)[p](10);Y(1,V*p);E,S=255,range(256)
for q in S*int(l),X():
 t=q<'';j=0;i=-t
 for c in q:i=i+1&E;j=j+S[i]+t*ord(((k+V)*E)[i])&E;S[i],S[j]=S[j],S[i];t or Y(1,chr(ord(c)^S[S[i]+S[j]&E]))
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.