Code Golf: XOR Encryption

От : Encryption Co.
К : x $ * sj4 (это вы)

Ваша миссия, если вы решите принять он состоит в том, чтобы создать программу за кратчайшее количество нажатий клавиш, которая

  • принимает два параметра имени файла (либо командную строку, либо стандартный ввод), первый - это файл, содержащий ключ, а второй - какое-то сообщение. Оба файла будут в виде простого текста.

  • Применяет ключ к сообщению, используя шифрование XOR , перезаписывая файл.

Пример:

Входной файл:

StackOverflow is Cool

Ключ:

Code Golf

Шестнадцатеричный дамп зашифрованного выходного файла:

0000000: 101b 0506 4b08 1909 1425 030b 1200 2e1c  ....K....%......
0000010: 4c25 2c00 080d 0a                        L%,....

Для простоты предположим, что файлы могут уместиться в памяти


Это сообщение будет самошифровать в 5 ... 4 ... 3 ... 2 ... 1. ..

     #####
    #### _\_  ________
    ##=-[.].]| \      \
    #(    _\ |  |------|
     #   __| |  ||||||||
      \  _/  |  ||||||||
   .--'--'-. |  | ____ |
  / __      `|__|[o__o]|
_(____nm_______ /____\____ 

Шифрование XOR невозможно взломать, если размер ключа больше или равен размеру сообщения, и ключ генерируется беспристрастным случайным процессом. См .: Одноразовый блокнот . Так что никакого "плохого шифрования" здесь нет.

37
задан 4 revs, 3 users 60% 16 August 2010 в 07:44
поделиться

21 ответ

GolfScript, 28 символов

n.+/~:k;.,.)k.,@\/)*<{\(@^}%

Чтобы использовать, передайте файл сообщения, а затем новую строку, а затем файл ключа в стандартный ввод сценария:

$ (cat message-file ; echo ; cat key-file) | ruby golfscript.rb poorencrypt.gs

$ (echo StackOverflow is Cool;echo;echo Code Golf) | \
          ruby golfscript.rb poorencrypt.gs > encoded-file
$ (cat encoded-file;echo;echo Code Golf) | ruby golfscript.rb poorencrypt.gs
StackOverflow is Cool
8
ответ дан 27 November 2019 в 04:09
поделиться

Perl, 40 символов

Это немного хрупко.

print$/=!1,($_=<>)^substr<>x 1E4,0,y///c

Perl имеет встроенный строковый оператор xor. Чтобы решить эту проблему, сложнее всего добиться, чтобы две строки имели одинаковую длину.

$/=!1

Устанавливает «разделитель записей» на неопределенное значение и ничего не выводит на печать. С этой настройкой оператор строки чтения файла будет пролистывать весь файл.

$_=<>

Загружает весь первый файл (содержащий сообщение) в переменную $ _ .

substr <> x 1E4, 0, y///c

Создает другую строку из второго файла (ключа) и добавляет ее к себе 10 000 раз. Надеюсь, (1) эта действительно длинная строка будет длиннее, чем строка сообщения, и (2) она не будет настолько длинной, чтобы из-за нее программе не хватало памяти (вот почему это решение хрупкое). y /// c - это операция для подсчета количества символов в $ _ , и она на один символ короче, чем указанная длина . Это сокращает строку ключа до того же размера, что и строка сообщения.

22
ответ дан 27 November 2019 в 04:09
поделиться

Java, 319 313 310 символов


  • Обновление 1: заменено char [] c = r (a [0]) ; char [] k = r (a [1]); по char [] c = r (a [0]), k = r (a [1]); , сохранено 6 символы.

  • Обновление 2: заменено на (int i = 0; i на int i = 0; для (char p: c) c [i] ^ = k [i ++% k.length]; , сохранено 3 символа.


import java.io.*;class X{public static void main(String[]a)throws Exception{char[]c=r(a[0]),k=r(a[1]);int i=0;for(char p:c)c[i]^=k[i++%k.length];Writer w=new FileWriter(a[0]);w.write(c);w.close();}static char[]r(String a)throws Exception{return new BufferedReader(new FileReader(a)).readLine().toCharArray();}}

Более читаемая версия:

import java.io.*;
class X{
 public static void main(String[]a)throws Exception{
  char[]c=r(a[0]),k=r(a[1]);int i=0;for(char p:c)c[i]^=k[i++%k.length];
  Writer w=new FileWriter(a[0]);w.write(c);w.close();
 }
 static char[]r(String a)throws Exception{
  return new BufferedReader(new FileReader(a)).readLine().toCharArray();
 }
}

Java IO довольно многословен. При рефакторинге двух считываний file-to-char [] в метод сохраняются 4 символа. Да, закрытие (промывка) писателя абсолютно необходимо. В противном случае файл останется пустым. В противном случае это было бы 298 292 289 символов.

7
ответ дан 27 November 2019 в 04:09
поделиться

Python, 162 символа

m,r,o=map,raw_input,open
a,b=r(),r()
t,k=m(lambda x:list(o(x).read()[:-1]),[a,b])
o(a,'w').write(''.join(m(chr,m(lambda c:ord(c[0])^ord(c[1]),zip(t,len(t)*k)))))

Python 3, 143 символа

i,o=input,open
a,b=i(),i()
t,k=map(lambda x:list(o(x,'rb').read()[:-1]),[a,b])
o(a,'wb').write(bytes(map(lambda c:c[0]^c[1],zip(t,len(t)*k))))
8
ответ дан 27 November 2019 в 04:09
поделиться

C # 190 символов

using System.IO;class a{static void Main(string[] b){var c=File.ReadAllBytes(b[0]);var d=File.ReadAllBytes(b[1]);for(int e=0;e<c.Length;e++) c[e]^=d[e%d.Length];File.WriteAllBytes(b[0],c);}}
12
ответ дан 27 November 2019 в 04:09
поделиться

Repent, 13 7 символов (без поддержки файлов), 14 символов (с поддержкой файлов)

Repent - это мой собственный эзотерический игрушечный язык на основе стека, вдохновленный J, APL, Golfscript и Python. Вот короткое решение. Я объясню его, но уже очень поздно, и это занимает мою голову, поэтому я объясню его и выпущу интерпретатор Silverlight утром.

↓↷¦*⊕;€

Пояснение:

↓     Copies the message string back onto the stack
↷    Puts the extra message string to the bottom of stack
¦     Find length of message string
*     Multiply key array by last number - repeats key for at least as long as message
⊕;    Apply XOR between each element corresponding of message array and repeated 
      key array, pushing XOR encoded message to stack
€     Print encoded message string/(char array) as string.

Использовать как:

Repent "↓↷¦*⊕;€" "Code Golf" "StackOverflow is Cool" > output.txt

Выводить (большинство символов не отображается):

Ascii: K    % .L%, 
Hex:   10 1B 05 06 4B 08 19 09 14 25 03 0B 12 00 2E 1C 4C 25 2C 00 08 0D 0A

Использовать файлы это:

↓↶▲⇄▲↓3↔⇄¦*⊕;▼

Справочник по языку (незакончено)

Интерпретатор (незакончено)

25
ответ дан 27 November 2019 в 04:09
поделиться

F #, 168 символов

open System.IO
[<EntryPoint>]
let main a=
let k=File.ReadAllBytes a.[1]
let z i v=v^^^k.[i%k.Length]
File.WriteAllBytes(a.[0], Array.mapi z (File.ReadAllBytes a.[0]))
0

Примечание: в основном ввод-вывод, ключ - Array.mapi. Кроме того, какой-нибудь гуру F # наверняка выбьет из него черту это решение - я по профессии программист на C # и никогда не использовал F # ни для чего другого, кроме обучения для развлечения.

4
ответ дан 27 November 2019 в 04:09
поделиться

Ruby 72 62 символа

$<.inject{|k,l|l.each_byte{|b|$><<(b^(r=k.slice!0)).chr;k<<r}}

Я мог бы сэкономить 10 символов, если бы мне не пришлось убирать \ n из клавиша ввода с k = a.chomp; Продолжил и сделал это

Ограничения: обрабатывает только однострочные клавиши.

Как это работает:

$ < действует как массив, содержащий все строки всех входных файлов.

.inject выполняет итерацию по массиву

{| k, l | : на первом проходе аргументами являются ключевая строка и первая строка ввода.

l.each_byte {| b | принимает каждый символ из входных строк как int.

$> << означает «печать»

(b ^ (rkslice! 0) XOR 'b' с первым символом в ключе (который он отсекает и сохраняет в 'r '

.chr; преобразует целое число обратно в ascii

k << r поворачивает первый символ ключа до конца.

}} Блок возвращает обновленный k, который будет использоваться в качестве первого аргумента в следующем проходе для инъекции; второй аргумент будет следующей строкой ввода.

4
ответ дан 27 November 2019 в 04:09
поделиться

KSH93 - 152 символа

m=$(<$1)
k=$(<$2)
for ((e=0;e<${#m};e++)) 
do
out="$out$(printf "%02X" $(("'${m:$e:1}"^"'${k:${e}%${#k}:1}")))"
done
echo "${out}0d0a" | xxd -p -r >$1
0
ответ дан 27 November 2019 в 04:09
поделиться

Ruby - 158 символов

def a(b);File.readlines(b).join("\n").chomp;end;t=a($*[0]);k=a($*[1]);File.open($*[0],"w"){|f|0.upto(t.length-1){|i|f.putc((t[i]^k[i.modulo(k.length)]).chr)}}

Более красивая версия:

def a(b)
    File.readlines(b).join("\n").chomp
end

t = a($*[0])
k = a($*[1])

File.open($*[0],"w") {|f|
    0.upto(t.length - 1) {|i|
        f.putc((t[i] ^ k[i.modulo(k.length)]).chr)
    }
}

Это решение использует следующий аспект проблемы:

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

Это решение было написано на моем планшете с использованием распознавания рукописного ввода для ввода. При создании этого кода клавиши не нажимались. Таким образом, эта программа была разработана без нажатия клавиш. Игра окончена, я выигрываю!

2
ответ дан 27 November 2019 в 04:09
поделиться

q, 88 char

Реализовано с использованием q из http://kx.com/ , языка, написанного Артуром Уитни и вдохновленного APL и lisp.

a[0]1:"x"$2 sv'{(x|y)&not x&y}.'0b vs''flip{y:count[x]#y;(x;y)}.(read1')a:(hsym')`$'.z.x

Итак, небольшое объяснение того, что происходит: (читайте справа налево)

a:(hsym')`$'.z.x

Создает список из двух дескрипторов файлов из списка аргументов времени выполнения и сохраняет его для дальнейшего использования в переменной «a».

(read1')

Переберите два файла, прочтите их и верните список со списком байтов, где byte = 0x00..0xFF ((22 байта), (10 байтов))

{y:count[x]#y;(x;y)}.

Сформируйте ключ такой же длины, как и сообщение. Ключ обрезается, если он слишком длинный, и повторяется, если он слишком короткий. Список теперь хорошо отформатирован, 2x22.

flip

Переместите список, и теперь он 22x2.

0b vs''

Преобразование каждого элемента списка в двоичный тип

{(x|y)&not x&y}.'

Попарное XOR для всех 22 элементов, возвращает список из 8 логических

"x"$2 sv'

Преобразование 8 логических битов в байт.

a[0]1:

Записать файл, заменив исходный файл сообщения.

Пример выполнения:

$ cp message.txt message.txt.bk
$ q g.q message.txt key.txt    
$ diff -s message.txt message.txt.bk0
Binary files message.txt and message.txt.bk0 differ
$ q g.q message.txt key.txt          
$ diff -s message.txt message.txt.bk0
Files message.txt and message.txt.bk0 are identical
3
ответ дан 27 November 2019 в 04:09
поделиться

Другое

решение Perl, 59 (42) символов

(соответствует однострочному тексту, который пока работает :)

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

 $.-1?$_^=substr($k x((length)/length($k)+1),0,length):$k=$_

будет 42 символа, если использовать "хрупкий" подход mobrule к длине ключа:

 $.-1?$_^=substr($k x 1e4,0,(length)):$k=$_

Командная строка:

 $> perl -i -0777 -pe'<insert above>' keyfile messagefile

Этот перепишет сообщение на свое xor-ed и обратно в текстовую форму:

 $> cat keyfile ; cat messagefile

 Code Golf
 StackOverflow is Cool

Применить команду:

 $> perl -i.bak -0777 -pe'<insert above>' keyfile messagefile
 $> cat keyfile ; cat messagefile

 Code Golf
 ^P^[^E^FK^H^Y   ^Tl/^@^SEI4O/   e/e

Применить снова:

 $> perl -i.bak -0777 -pe'<insert above>' keyfile messagefile
 $> cat keyfile ; cat messagefile

 Code Golf
 StackOverflow is Cool

С уважением

rbo

4
ответ дан 27 November 2019 в 04:09
поделиться

Python3 - 114 символов

принимает параметры из stdin

a=input().split()
k,t=[open(x,"rb").read()for x in a]
open(a[1],"wb").write(bytes(x^y for x,y in zip(k*len(t),t)))
6
ответ дан 27 November 2019 в 04:09
поделиться

PowerShell, 125 115 символов

На данный момент это самый короткий ответ на основе .net:

$k=[char[]](gc $args[1]);$i=0;sc $args[0] ([byte[]]([char[]](gc $args[0])|%{$_ -bXor $k[$i++%$k.Length]})) -en byte

Симпатичная версия с сокращениями команд прописано:

$k=[char[]](get-content $args[1])
$i=0
set-content `
   $args[0] `
   ([byte[]] ([char[]] (get-content $args[0]) `
              | foreach {$_ -bXor $k[$i++ % $k.Length]})) `
   -encoding byte

Использование: PowerShell codegolf.ps1 message.txt key.txt . По запросу он перезаписывает message.txt .

3
ответ дан 27 November 2019 в 04:09
поделиться

Python, 154 символа

import sys,struct;_,f,k=sys.argv
open(f,'r+b').write(''.join(struct.pack('B',ord(a)^ord(b))for a,b in zip(open(f,'r+b').read(),open(k,'rb').read()*1000)))
0
ответ дан 27 November 2019 в 04:09
поделиться

PHP, 142 141 символ

Редактировать 1: fputs () вместо fwrite () .

$t=fopen($argv[1],'r+');$s=fgets($t);rewind($t);$k=fgets(fopen($argv[2],'r'));for($i=0;$i<strlen($s);$i++)fputs($t,$s{$i}^$k{$i%strlen($k)});

Красивый шрифт:

$t = fopen($argv[1],'r+');
$s = fgets($t);
rewind($t);
$k = fgets(fopen($argv[2],'r'));
for($i=0; $i<strlen($s); $i++)
  fputs($t, $s{$i} ^ $k{$i % strlen($k)});
0
ответ дан 27 November 2019 в 04:09
поделиться

F#, 147 146 символов

Это в значительной степени основано на решении driis'а. Все, что я сделал, это добавил необходимые отступы для компиляции, изменил порядок параметров командной строки и подтянул все. Я не удивлюсь, если его можно еще немного сократить. Примечание: Вы получите предупреждение о неполном совпадении шаблонов. Обычно я бы первым пожаловался на это, но я думаю, что кодовый гольф заслуживает исключения из обычной лучшей практики. :)

open System.IO[<EntryPoint>]let m[|a;b|]=File.ReadAllBytes|>fun r->r a|>fun k->File.WriteAllBytes(b,Array.mapi(fun i->(^^^)k.[i%k.Length])(r b));0

F#, 147 символов, более читабельно

open System.IO
let r=File.ReadAllBytes
[<EntryPoint>]
let m[|a;b|]=
 let k=r a
 File.WriteAllBytes(b,Array.mapi(fun i->(^^^)k.[i%k.Length])(r b));0
0
ответ дан 27 November 2019 в 04:09
поделиться

Java, 336 316 405 символов

РЕДАКТИРОВАТЬ: Забыл, что нужно было читать из файла. * вздох

public class A {
public static void main(String[] a) throws Throwable {
    char[] p = new BufferedReader(new FileReader(a[1])).readLine().toCharArray();
    char[] t = new BufferedReader(new FileReader(a[0])).readLine().toCharArray();
    int u = t.length;
    int k = 0;
    for (int i = 0; i < u; i++) {
        new FileOutputStream (a[0]).write((char) ((int) t[i] ^ (int) p[k]));
        k = k = ++k % p.length;
    }
}
}

Стоило попробовать. Однако я не думаю, что Java здесь лучший язык ...

1
ответ дан 27 November 2019 в 04:09
поделиться

Python - 127 символов

использует параметры командной строки для ключевого файла, а файл данных

import sys
a=sys.argv
_,k,t=[open(x).read()for x in a]
s=open(a[2],"w").write
[s(chr(ord(x)^ord(y)))for x,y in zip(k*len(t),t)]

записывает в стандартный вывод - 109 символов

import sys
_,k,t=[open(x).read()for x in sys.argv]
print"".join(chr(ord(x)^ord(y))for x,y in zip(k*len(t),t))
2
ответ дан 27 November 2019 в 04:09
поделиться

Haskell, 181 символ

Ввод-вывод - это сука при игре в гольф на Haskell, а двоичный ввод-вывод - вдвойне. Это решение, вероятно, можно значительно улучшить. Не стесняйтесь!

import Data.Bits
import Data.ByteString as B
u=unpack
g o[l,n]=o$pack$Prelude.zipWith xor(u n)(cycle$u l)
f x=mapM B.readFile x>>=g(B.writeFile$x!!1)
main=Prelude.getLine>>=f.words

Использование:

$ ghc --make encrypt.hs
$ echo -n 'Code Golf' > key
$ echo -n 'StackOverflow is Cool' > message
$ echo 'key message' | ./encrypt
$ od -tx1 message
3
ответ дан 27 November 2019 в 04:09
поделиться

Java - 306 символов

Использование Java-решения BalusC в качестве основы:

import java.io.*;class X{public static void main(String[]a)throws Exception{final char[]c=r(a[0]),k=r(a[1]);int i=0;for(int p:c)c[i]^=k[i++%k.length];new FileWriter(a[0]){{write(c);}}.close();}static char[]r(String a)throws Exception{return new BufferedReader(new FileReader(a)).readLine().toCharArray();}}

Более читабельное:

import java.io.*;
class X{
 public static void main(String[]a)throws Exception{
  final char[]c=r(a[0]),k=r(a[1]);int i=0;for(int p:c)c[i]^=k[i++%k.length];
  new FileWriter(a[0]){{write(c);}}.close();
 }
 static char[]r(String a)throws Exception{
  return new BufferedReader(new FileReader(a)).readLine().toCharArray();
 }
}

Я фактически не тестировал код, но и не изменил ничего радикального.

0
ответ дан 27 November 2019 в 04:09
поделиться
Другие вопросы по тегам:

Похожие вопросы: