Enkripsi CipherSaber

11

Menerapkan program enkripsi CipherSaber , seperti yang dijelaskan di bawah ini. Pedoman:

  • Entri terkecil, dalam byte, menang.
    • Namun, dalam menyimpang dari norma norma , Anda dipersilakan untuk memposting entri yang menarik, bahkan jika itu bukan entri golf yang serius.
  • Entri biasanya berupa program yang mengambil plaintext dari input standar, dan menulis ciphertext ke output standar, dengan kunci yang ditentukan (oleh pengguna) dengan cara yang Anda inginkan.
    • Namun, jika Anda ingin menerapkan ini sebagai prosedur, itu juga baik-baik saja.
  • IV harus berasal dari generator nomor pseudorandom yang aman secara kriptografis. Jika bahasa Anda tidak mendukung itu, pilih yang lain. ;-)
  • Tolong jangan gunakan perpustakaan khusus crypto, panggilan sistem, atau instruksi (selain dari PRNG, sebagaimana ditentukan di atas). Tentu saja, operasi bitwise tingkat rendah umum tidak apa-apa.

CipherSaber adalah varian dari RC4 / Arcfour, jadi saya akan mulai dengan menjelaskan yang terakhir, lalu perubahan yang dilakukan oleh CipherSaber.

0. RC4 / Arcfour

Arcfour sepenuhnya ditentukan di tempat lain , tetapi untuk kelengkapan, saya akan menjelaskannya di sini. (Dalam hal terjadi perbedaan antara konsep Internet dan deskripsi ini, yang pertama adalah normatif.)

Pengaturan kunci

Siapkan dua array, Sdan S2, keduanya dengan panjang 256, di mana k_1byte pertama dari kunci, dan k_nyang terakhir.

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

( S2diisi dengan byte kunci, lagi dan lagi, sampai semua 256 byte diisi.)

Kemudian, inisialisasi jke 0, dan kocok 256 kali:

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

Ini menyelesaikan pengaturan kunci. The S2array tidak lagi digunakan di sini, dan dapat digosok.

Pembuatan stream cipher

Inisialisasi idan jke 0, lalu buat stream kunci sebagai berikut:

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

Mengenkripsi / mendekripsi data

  • Untuk mengenkripsi, XOR output keystream dengan plaintext
  • Untuk mendekripsi, XOR output keystream dengan ciphertext

1. CipherSaber

CipherSaber (yang kami implementasikan dalam pertanyaan ini) adalah variasi RC4 / Arcfour dalam dua cara:

10 byte IV / nonce

Saat mengenkripsi pesan, 10 byte acak harus diperoleh, seperti via /dev/urandom, dan dituliskan ke dalam 10 byte pertama dari output terenkripsi. Saat mendekripsi pesan, 10 byte pertama dari input adalah IV yang digunakan untuk mengenkripsi pesan.

Tahap pengaturan kunci RC4 / Arcfour dijalankan dengan passphrase || IVsebagai kunci, di mana passphrasefrasa sandi yang ditentukan pengguna, IVseperti yang dijelaskan di atas, dan ||digabungkan. Jadi, frasa sandi dari "Halo, dunia!" dan infus "supercalif" (namun tidak mungkin yaitu :-P) akan menghasilkan kunci "Halo, dunia! supercalif".

Beberapa iterasi pengaturan tombol

Untuk membantu mencegah kerentanan yang membuat enkripsi WEP benar-benar rusak, loop pengocokan pada tahap pengaturan kunci RC4 dijalankan beberapa kali sesuai yang ditentukan pengguna. Nilai jharus dipertahankan antara iterasi.

2. Tes vektor

Berikut adalah beberapa vektor uji yang dapat Anda gunakan untuk menguji program Anda. Selain itu, osif squeamish menciptakan alat enkripsi & dekripsi CipherSaber yang dapat Anda gunakan untuk memvalidasi hasil Anda.

Anda hanya perlu mengimplementasikan program enkripsi. Anda tidak perlu menyediakan program dekripsi, tetapi output program enkripsi Anda harus melakukan bolak-balik dengan benar ke input asli ketika diproses dengan program dekripsi yang diimplementasikan dengan benar menggunakan kunci yang benar.

Chris Jester-Young
sumber

Jawaban:

7

Pyth, 100 byte

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

Script ini menggunakan $perintah, yang memungkinkan mengeksekusi kode Python. Untuk mencegah eksekusi kode berbahaya di server, perintah ini dinonaktifkan di kompiler online. Anda harus menjalankannya dengan kompiler offline yang dapat Anda temukan di sini .

Input dalam format:

secret key
5 (number of repeats)
secret message

Program mengeluarkan string terenkripsi, yang mungkin berisi karakter yang tidak diinginkan. Jika Anda ingin memverifikasinya menggunakan Alat Enkripsi & Dekripsi CipherSaber , Anda dapat menggunakan kode berikut, yang mengubah string menjadi serangkaian angka heksadesimal.

$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 tidak mendukung nomor pseudorandom yang aman secara kriptografis dan mengimpornya dari Python menghabiskan biaya 25 byte. Kode yang lebih pendek, yang menggunakan generator nomor-pseudorandom-acak Pyth / Python dan juga berfungsi di kompiler online adalah:

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

Cobalah online: mengembalikan string atau serangkaian digit heksadesimal

Kode ini tidak istimewa. Hanya banyak tugas kotor dan penggunaan kembali segera hasil yang dihitung dan menerapkan dua kali trik daftar-swap .

Penjelasan:

                                  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
Jakube
sumber
Tampaknya, fungsi Pyth bawaan tidak memiliki nomor pseudorandom yang aman secara kriptografis . Anda dapat menyimpan entri Anda apa adanya, dan itu tidak akan memenuhi syarat untuk centang hijau, atau Anda dapat membuat versi yang menggunakan urandom(yang bisa menjadi entri terpisah jika Anda mau) jika Anda peduli tentang "menang". :-)
Chris Jester-Young
@ ChrisJester-Young Maaf tentang itu. Saya tidak berpikir bahwa generator nomor acak Python sangat tidak aman. Memperbaikinya dengan biaya 25 byte.
Jakube
4

Python 2 - 373 350 326 317 byte

Pyth mungkin akan datang nanti. Menentukan satu fungsi, c(p,d,r,m)yang mengambil daftar byte untuk frasa sandi dan data, dan int untuk pengulangan dan mode yang mengenkripsi ketika 1 dan mendekripsi ketika 0. Ini karena satu-satunya perbedaan di dalamnya adalah berurusan dengan IV. Mengembalikan daftar byte.

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

Berikut ini beberapa kode uji / fungsi Pembantu:

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)
Maltysen
sumber
Anda hanya perlu menulis program enkripsi. Jadi Anda bisa menghapus else:v,d=d[:10],d[10:]bagian itu.
Jakube
3

Ruby - 263 karakter

Ini adalah jawaban Ruby saya untuk pertanyaan asli tentang stackoverflow pada tahun 2010! Ini adalah encoder dan decoder semua dalam satu program

Parameternya adalah:
e atau d (untuk enkode atau decode) beberapa kali
kunci

$ 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}
gnibbler
sumber
2

C, 312 byte

Menerima kunci dan kunci pencampuran dihitung pada baris perintah, kemudian mengenkripsi semuanya di stdin ke stdout. Ini menggunakan fungsi perpustakaan BSD / Darwin arc4random(), yang merupakan PRNG berdasarkan RC4. Secara otomatis benih itu sendiri, sehingga hasilnya akan berbeda setiap saat.

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

Versi lebih rapi:

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

Contoh:

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

Python - 266 karakter

Ini adalah jawaban Python saya untuk pertanyaan asli tentang stackoverflow pada tahun 2010! Ini adalah encoder dan decoder semua dalam satu program

Parameternya adalah:
e atau d (untuk enkode atau decode) beberapa kali
kunci

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

Versi ini mencoba untuk menggabungkan 2 loop dari rc4 menjadi satu (menyimpan sejauh 11 byte ...)

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]))
gnibbler
sumber