CipherSaber şifrelemesi


11

Aşağıda açıklandığı gibi bir CipherSaber şifreleme programı uygulayın. Kuralları:

  • Bayt cinsinden en küçük giriş kazanır.
    • Bununla birlikte, normlarından ayrılırken, ciddi golf girişleri olmasa bile ilginç girişler yayınlayabilirsiniz.
  • Girdi, normalde düz metni standart girdiden alan bir programdır ve şifreli metni standart çıktıya yazar (anahtar tarafından (kullanıcı tarafından) tercih ettiğiniz şekilde yazar.
    • Ancak, bunu bir prosedür olarak uygulamak istiyorsanız, bu da iyidir.
  • IV, kriptografik olarak güvenli bir sözde sayı üreticisinden gelmelidir. Diliniz bunu desteklemiyorsa, farklı bir dil seçin. ;-)
  • Lütfen kriptoya özgü kitaplıklar, sistem çağrıları veya talimatlar kullanmayın (yukarıda belirtildiği gibi PRNG dışında). Tabii ki, jenerik düşük seviyeli bitsel operasyonlar iyidir.

CipherSaber, RC4 / Arcfour'un bir çeşididir, bu yüzden ikincisini tanımlayarak başlayacağım, daha sonra CipherSaber'ın yaptığı değişiklikler.

0. RC4 / Arcfour

Arcfour başka bir yerde tam olarak belirtilmiştir , ancak bütünlük için burada açıklayacağım. (İnternet taslağı ile bu açıklama arasında herhangi bir tutarsızlık olması durumunda, eski kural normatiftir.)

Anahtar kurulumu

Anahtarın ilk baytı ve sonuncusu olmak üzere iki diziyi Sve S2her ikisi de 256 uzunluğunu ayarlayın .k_1k_n

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

( S2256 baytın tümü dolana kadar anahtarın baytlarıyla tekrar tekrar doldurulur.)

Ardından, j0 olarak başlatın ve 256 kez karıştırın:

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

Bu tuş kurulumunu tamamlar. S2Dizi artık burada kullanılır ve temizlendi olabilir.

Şifre akışı oluşturma

Sıfırlayın ive j0'a gidin, ardından anahtar akışını aşağıdaki gibi oluşturun:

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

Verileri şifreleme / şifresini çözme

  • Şifrelemek için, anahtar akışı çıktısını düz metinle XOR yapın
  • Şifresini çözmek için, anahtar akışı çıktısını şifreleme metniyle XOR yapın

1. CipherSaber

CipherSaber (bu soruda uyguladığımız şey budur) RC4 / Arcfour'un iki şekilde bir varyasyonudur:

10 bayt IV / nonce

Bir mesaj şifrelenirken, via gibi 10 rastgele bayt alınmalı /dev/urandomve şifreli çıktının ilk 10 baytına yazılmalıdır. Bir mesajın şifresini çözerken, girişin ilk 10 baytı onu şifrelemek için kullanılan IV'tür.

RC4 / Arcfour anahtar kurulum aşaması, kullanıcı tarafından belirtilen parolanın yukarıda açıklandığı ve birleştirme passphrase || IVolduğu anahtar olarak çalıştırılır . Yani, "Merhaba dünya!" ve "supercalif" in bir IV'ü (ancak bu olası değildir: -P) "Merhaba dünya! supercalif" in bir anahtarıyla sonuçlanır.passphraseIV||

Tuş kurulumunun çoklu yinelemeleri

WEP şifrelemesini tamamen bozan güvenlik açığının önlenmesine yardımcı olmak için, RC4'ün anahtar kurulum aşamasının karıştırma döngüsü kullanıcı tarafından belirtilen sayıda çalıştırılır. Değeri jyinelemeler arasında tutulmalıdır.

2. Test vektörleri

İşte programlarınızı test etmek için kullanabileceğiniz bazı test vektörleri . Ayrıca, ossifrage sonuçlarınızı doğrulamak için kullanabileceğiniz bir CipherSaber şifreleme ve şifre çözme aracı oluşturdu.

Yalnızca şifreleme programını uygulamanız gerekir. Şifre çözme programını sağlamanız gerekmez, ancak doğru anahtarı kullanarak doğru şekilde uygulanan bir şifre çözme programı ile işlendiğinde şifreleme programınızın çıktısı orijinal girdiye doğru şekilde geri dönmelidir.

Yanıtlar:


7

Pyth, 100 bayt

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

Bu komut dosyası, $Python kodunun yürütülmesine izin veren komutu kullanır . Sunucuda kötü amaçlı kod yürütülmesini önlemek için, bu komut çevrimiçi derleyicide devre dışı bırakılır. Burada bulabileceğiniz çevrimdışı derleyici ile çalıştırmanız gerekiyor .

Giriş şu biçimde:

secret key
5 (number of repeats)
secret message

Program, yazdırılamayan karakterler içerebilen şifrelenmiş dizeyi çıkarır. CipherSaber Şifreleme ve Şifre Çözme Aracı'nı kullanarak doğrulamak istiyorsanız , dizeyi onaltılık sayı dizisine dönüştüren aşağıdaki kodu kullanabilirsiniz.

$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, kriptografik olarak güvenli sahte raund sayılarını desteklemez ve bunları Python'dan içe aktarmanın 25 bayt maliyeti. Pyth's / Python'un normar sözde sayı üretecini kullanan ve aynı zamanda çevrimiçi derleyicide çalışan daha kısa bir kod:

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

Çevrimiçi deneyin: bir dize veya onaltılık basamak dizisi döndürme

Kod özel bir şey değil. Sadece çok fazla kirli görevler ve hesaplanan sonuçların hemen yeniden kullanılması ve iki kez liste değiştirme hilesi uygulanması.

Açıklama:

                                  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

Görünüşe göre, yerleşik Pyth işlevlerinin şifreli olarak güvenli sahte sayılar yok . Girişinizi olduğu gibi tutabilirsiniz ve yeşil onay için uygun olmaz veya urandom"kazanmayı" önemsiyorsanız , (isterseniz ayrı bir giriş olabilir) bir sürüm yapabilirsiniz. :-)
Chris Jester-Young

@ ChrisJester-Young Bunun için üzgünüm. Python'un rasgele sayı üretecinin çok güvensiz olduğunu düşünmemiştim. 25 baytlık bir maliyetle düzeltildi.
Jakube

4

Piton 2 - 373 350 326 317 bayt

Pyth muhtemelen daha sonra geliyor. c(p,d,r,m)Parola ve veri için bayt listelerini alan bir işlev ve 1 olduğunda şifreleyen ve 0 olduğunda şifresini çözen yineleme ve mod için int tanımlar. Çünkü bunların içindeki tek fark IV ile ilgilidir. Bayt listesini döndürür.

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

İşte bazı test kodu / Yardımcı fonksiyonları:

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)

Yalnızca bir şifreleme programı yazmanız gerekir. Böylece else:v,d=d[:10],d[10:]parçayı kaldırabilirsiniz .
Jakube

3

Yakut - 263 karakter

Bu, 2010'da stackoverflow hakkındaki orijinal soruya Ruby cevabım! Tek bir programda bir kodlayıcı ve kod çözücüdür

Parametreler şunlardır:
e veya d (kodlama veya kod çözme için)
tuş
sayısı

$ 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 bayt

Komut satırında bir anahtar ve anahtar karıştırma yineleme sayısını kabul eder, daha sonra stdin'deki her şeyi stdout'a şifreler. Bu arc4random(), RC4 tabanlı bir PRNG olan BSD / Darwin kütüphane işlevini kullanır . Otomatik olarak kendini tohumlar, böylece sonuçlar her seferinde farklı olacaktır.

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

Düzenli sürüm:

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

Misal:

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

1

Python - 266 karakter

Bu 2010 yılında stackoverflow hakkındaki orijinal soruya Python cevabım! Tek bir programda bir kodlayıcı ve kod çözücüdür

Parametreler şunlardır:
e veya d (kodlama veya kod çözme için)
tuş
sayısı

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

Bu sürüm, rc4'ün 2 döngüsünü bir araya getirmeye çalışır (şimdiye kadar 11 bayt kaydeder ...)

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]))
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.