Шифрування CipherSaber


11

Реалізуйте програму шифрування CipherSaber , як описано нижче. Правила:

  • Найменший запис у байтах виграє.
    • Однак, відходячи від норм , ви можете розміщувати цікаві записи, навіть якщо вони не є серйозними.
  • Запис, як правило, являє собою програму, яка бере звичайний текст зі стандартного вводу і записує шифротекст до стандартного виводу з ключем, визначеним (користувачем) у певному варіанті.
    • Однак якщо ви хочете реалізувати це як процедуру, це теж добре.
  • IV повинен походити від криптографічно захищеного генератора псевдовипадкових чисел. Якщо ваша мова не підтримує це, виберіть іншу. ;-)
  • Будь ласка, не використовуйте криптоспецифічні бібліотеки, системні дзвінки чи інструкції (крім PRNG, як зазначено вище). Звичайно, загальні бітові операції низького рівня добре.

CipherSaber - це варіант RC4 / Arcfour, тому я почну з опису останнього, потім зміни, які CipherSaber вносить до них.

0. RC4 / Arcfour

Arcfour повністю вказаний в іншому місці , але для повноти я опишу це тут. (У випадку будь-яких розбіжностей між Інтернетом-проектом та цим описом, перший є нормативним.)

Налаштування ключів

Встановіть два масиви, 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масив більше не використовується тут, і може бути витягнутий.

Генерація потоку шифрів

Ініціалізуйте iі jдо 0, а потім генеруйте ключовий потік наступним чином:

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

CipherSaber (що саме ми реалізуємо в цьому питанні) є варіантом RC4 / Arcfour двома способами:

10-байт IV / ні

Під час шифрування повідомлення повинно бути отримано 10 випадкових байтів, таких як via /dev/urandom, і записати їх у перші 10 байт зашифрованого виводу. При розшифровці повідомлення першими 10 байтами вводу є IV, який використовується для його шифрування.

Етап налаштування ключа RC4 / Arcfour виконується passphrase || IVяк ключ, де passphraseвказана користувачем парольна фраза, IVяк описано вище, і ||є конкатенацією. Отже, фразу "Привіт, світ!" І IV "суперкаліф" (однак малоймовірно, що це :-P) призведе до ключа "Привіт, світ! суперкаліф".

Кілька ітерацій налаштування ключів

Для того, щоб запобігти вразливості, яка зробила шифрування WEP повністю порушеним, цикл переміщення на етапі налаштування ключа RC4 виконує вказану користувачем кількість разів. Значення jмає зберігатися між ітераціями.

2. Тестові вектори

Ось кілька тестових векторів, які ви можете використовувати для тестування своїх програм. Крім того, гидливо гриф створив шифрування і дешифрування інструменту 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. Щоб запобігти виконанню шкідливого коду на сервері, ця команда відключена в онлайн-компіляторі. Ви повинні запустити його за допомогою офлайн-компілятора, який ви можете знайти тут .

Вхід у форматі:

secret key
5 (number of repeats)
secret message

Програма виводить зашифрований рядок, який може містити недруковані символи. Якщо ви хочете перевірити це за допомогою інструменту шифрування та розшифровки CipherSaber , ви можете використовувати наступний код, який перетворює рядок у ряд шістнадцяткових цифр.

$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

Спробуйте в режимі он-лайн: повернення рядка або серії шістнадцяткових цифр

Код - нічого особливого. Просто багато брудних завдань та негайне повторне використання обчислених результатів та двічі застосування трюку заміни списку .

Пояснення:

                                  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 байт.
Jakube

4

Python 2 - 373 350 326 317 байт

Піт, можливо, пізніше. Визначає одну функцію, c(p,d,r,m)яка приймає байтові списки для парольної фрази та даних та int для повторень та режим, який шифрується при 1 та розшифровує при 0. Це тому, що єдиною різницею в них є стосунок до 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:]деталь.
Jakube

3

Рубін - 263 ч

Це моя відповідь Ruby на початкове запитання щодо stackoverflow ще в 2010 році! Це кодер і декодер в одній програмі

Параметри є:
е або г (для кодування або декодування)
ключове
число раз

$ 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. Для цього використовується функція бібліотеки BSD / Дарвіна arc4random(), яка є PRNG на базі RC4. Він автоматично висіває, тому результати будуть щоразу різні.

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

Тид'є версія:

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

Пітон - 266 символів

Це моя відповідь Python на початкове запитання щодо stackoverflow ще в 2010 році! Це кодер і декодер в одній програмі

Параметри є:
е або г (для кодування або декодування)
ключове
число раз

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

Ця версія намагається об'єднати дві петлі rc4 в одну (поки що зберігає 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]))
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.