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 байтов не будут заполнены.)

Затем инициализируйте jдо 0 и перемешайте 256 раз:

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

На этом настройка ключа завершена. Не S2массив больше не используется здесь, и может быть извлечен.

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

Инициализируйте iи равным j0, затем сгенерируйте поток ключей следующим образом:

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 / nonce

При шифровании сообщения необходимо получить 10 случайных байтов, например, через /dev/urandom, и записать их в первые 10 байтов зашифрованного вывода. При дешифровании сообщения первые 10 байтов ввода - это IV, используемый для его шифрования.

Этап настройки ключа RC4 / Arcfour запускается с passphrase || IVключом, в котором passphraseзаданная пользователем парольная фраза IVсоответствует описанной выше и ||представляет собой конкатенацию. Итак, фраза «Привет, мир!» и IV "supercalif" (хотя маловероятно, что это :-P) приведет к ключу "Hello, world! supercalif".

Несколько итераций настройки ключа

Чтобы предотвратить уязвимость, из-за которой шифрование 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 Encryption & Decryption Tool , вы можете использовать следующий код, который преобразует строку в последовательность шестнадцатеричных цифр.

$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's / 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
Jakube
источник
По-видимому, встроенные функции Pyth не имеют криптографически безопасных псевдослучайных чисел . Вы можете оставить свою запись как есть, и она не будет претендовать на зеленую галочку, или вы можете создать версию, которая использует urandom(которая может быть отдельной записью, если хотите), если вы хотите «выиграть». :-)
Крис Шут-Янг
@ ChrisJester-Young К сожалению об этом. Я не думал, что генератор случайных чисел в Python настолько небезопасен. Исправил это до стоимости 25 байт.
Якуб,
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)
Maltysen
источник
Вам нужно только написать программу шифрования. Таким образом, вы можете удалить else:v,d=d[:10],d[10:]часть.
Якуб
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}
gnibbler
источник
2

C, 312 байтов

Принимает количество итераций ключа и ключа в командной строке, а затем шифрует все данные с stdin на stdout. При этом используется библиотечная функция BSD / Darwin 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]);}}

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
r3mainer
источник
1

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

Это мой ответ Python на оригинальный вопрос о стекаповороте еще в 2010 году! Это кодер и декодер все в одной программе

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

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

Эта версия пытается объединить 2 цикла 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]))
gnibbler
источник