Code Golf: шифрование XOR
От: Encryption Co.
Кому: x $* sj4 (что вы)
Ваша миссия, если вы решите ее принять, заключается в создании программы в кратчайшем количестве нажатий клавиш, которые
-
Принимает два параметра имени файла (либо командной строки, либо stdin), первый - это файл, содержащий ключ, а второй - некоторое сообщение. Оба файла будут иметь простой текст.
-
Применяет ключ к сообщению с помощью XOR encryption, перезаписывая файл.
Пример:
Входной файл:
StackOverflow is Cool
Key:
Код Гольф
Hex дамп файла с зашифрованным выходом:
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 Шифрование невозможно взломать, если размер ключа больше или равен размеру сообщения, а ключ генерируется непредвзятым случайным процессом. См.: Одноразовая панель. Таким образом, здесь нет "плохого шифрования".
Ответы
Ответ 1
Показывать, 13 7 символов (без поддержки файлов), 14 char (с поддержкой файлов)
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↔⇄¦*⊕;▼
Языковая ссылка (незавершенная)
Интерпретатор (незавершенный)
Ответ 2
Perl, 40 char
Это немного хрупкий.
print$/=!1,($_=<>)^substr<>x 1E4,0,y///c
Perl имеет встроенный оператор string xor. Чтобы решить эту проблему, жесткая часть получает две строки с одинаковой длиной.
$/=!1
Устанавливает "разделитель записи" в значение undefined и не вызывает печати ничего. С помощью этого параметра оператор readline файла будет разбит на весь файл.
$_=<>
Загружает весь первый файл (содержащий сообщение) в переменную $_
.
substr <> x 1E4, 0, y///c
Создает другую строку из второго файла (ключ) и добавляет ее к себе 10 000 раз. Надеемся, что (1) эта очень длинная строка будет длиннее строки сообщения, и (2) она не будет так долго, что это приведет к тому, что у программы закончится нехватка памяти (что, как это решение является хрупким). y///c
- операция подсчета количества символов в $_
, и это на один символ короче, чем length
. Это сокращает строку ключа до того же размера, что и строка сообщения.
Ответ 3
С# 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);}}
Ответ 4
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))))
Ответ 5
GolfScript, 28 char
n.+/~:k;.,.)k.,@\/)*<{\(@^}%
Чтобы использовать, передайте файл сообщения, за которым следует новая строка, а затем файл ключа со стандартным входом script:
$ (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
Ответ 6
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: заменено for(int i=0;i<c.length;c[i]^=k[i++%k.length]);
на int i=0;for(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 довольно многословный. Рефакторинг двух файлов в char [] читает в метод, сохраненный 4 символа. Да, закрытие (промывка) писателя абсолютно необходимо. Кроме того, файл остается пустым. В противном случае было бы 298 292 289 символов.
Ответ 7
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)))
Ответ 8
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
Примечание. В основном IO ключом является Array.mapi. Кроме того, некоторые F # Guru, вероятно, выйдут из этого решения - я программист на С# по профессии и никогда не использовал F # для чего-либо еще, кроме обучения для удовольствия.
Ответ 9
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^(r.k.slice!0)
XORs 'b' с первым символом в ключе (который он срезает и сохраняет в 'r'
.chr;
преобразует целое число обратно в ascii
k<<r
вращает первый символ ключа до конца.
}}
Блок дает обновленный k, который будет использоваться в качестве первого аргумента в следующем проходе для инъекции; второй аргумент будет следующей строкой ввода.
Ответ 10
Другой
Решение 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
Привет
БВУ
Ответ 11
Haskell, 181 символ
I/O - сука при игре в гольф в 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
Ответ 12
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
.
Ответ 13
q, 88 char
Реализовано с помощью q из http://kx.com/, который является языком, написанным Артуром Уитни и вдохновленным APL и lisp.
a[0]1:"x"$2 sv'{(x|y)¬ 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)¬ 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
Ответ 14
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)
}
}
Это решение использует следующий аспект проблемы:
Ваша миссия, если вы решите принять его, - создать программу в кратчайшее количество нажатий клавиш что...
Это решение было написано на моем планшете, используя распознавание рукописного ввода для ввода. При создании этого кода не было поглажено никаких клавиш. Поэтому эта программа была разработана с нулевыми нажатиями клавиш. Игра окончена, я побеждаю!
Ответ 15
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)]
запись в stdout - 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))
Ответ 16
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 - лучший язык здесь...
Ответ 17
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)))
Ответ 18
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
Ответ 19
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)});
Ответ 20
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
Ответ 21
Java - 306 Chars
Использование решения BalusC Java в качестве базы:
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();
}
}
Я действительно не тестировал код, но я также ничего не изменил.
Ответ 22
C - 163 161 символ
Добавлен флеш и удален ненужный поиск.
golfed:
#include <stdio.h>
int*p,l;char*k;main(int c,char**v){FILE*f=fopen(*++v,"rb+");k=p=*++v;while(fgets(&l,2,f)){fseek(f,-1,1);putc(l^*k++,f);fflush(f);if(!*k)k=p;}}
ungolfed:
#include <stdio.h>
int*p,l;
char*k;
main(int c,char**v){
FILE*f=fopen(*++v,"rb+");
k=p=*++v;
while(fgets(&l,2,f)){
fseek(f,-1,1);
putc(l^*k++,f);
fflush(f);
if(!*k)k=p;
}
}
Ответ 23
С#, 168:
using System.IO;class a{static void Main(string[] b){File.WriteAllBytes(b[0],File.ReadAllBytes(b[0]).Select((x,i)=>x^File.ReadAllBytes(b[1])[i%d.Length]).ToArray());}}
Функциональное решение. Я сохранил переменные, введя в действие операцию чтения, которая заставляет ее выполняться снова и снова.