代码高尔夫:XORencryption

来自 :Encryption Co.
:x $ * sj4(就是你)

你的任务,如果你select接受它,就是用最短的击键次数创build一个程序

  • 接受两个文件名参数(命令行或标准input),第一个是包含密钥和第二个消息的文件。 这两个文件将是纯文本。

  • 使用XORencryption将密钥应用于消息,覆盖该文件。

例:

input文件:

StackOverflow很酷

键:

代码高尔夫

encryption输出文件的hex转储:

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

为了简单起见,假定文件可以放在内存中


此消息将自我encryption在5 … 4 … 3 … 2 … 1 …

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

如果密钥的大小大于或等于消息的大小,并且密钥由无偏的随机过程生成,则XORencryption不可能破解。 请参阅: 一次性垫 。 所以这里没有“糟糕的encryption”。

悔改, 13 7个字符(没有文件支持),14个字符(有文件支持)

Repent是我自己的一个深奥的基于堆栈的玩具语言,灵感来自J,APL,Golfscript和Python。 这是一个简短的解决scheme。 我会解释一下,但是已经很晚了,而且这是我的头脑,所以我会解释它,并在早上释放一个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↔⇄¦*⊕;▼ 

语言参考(未完成)

口译员(未完成)

Perl,40个字符

这有点脆弱。

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

Perl有一个内置的string异或运算符。 为了解决这个问题,困难的部分是让两个string具有相同的长度。

 $/=!1 

将“logging分隔符”设置为未定义的值,并不会导致打印任何内容。 使用此设置,文件readline运算符将在整个文件中啜泣。

 $_=<> 

将整个第一个文件(包含消息)加载到variables$_

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

从第二个文件(键)创build另一个string,并将其自身添加到10,000次。 希望(1)这个真正长的string比消息string长,(2)不会太长,导致程序内存不足(这就是这个解决scheme是脆弱的)。 y///c是计算$_中字符个数的操作,它比说length短一个字符。 这将密钥string缩短为与消息string相同的大小。

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

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

GolfScript,28个字符

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

要使用,传递消息文件,然后传递一个新行,然后将密钥文件传递给脚本的标准input:

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

 $(回声StackOverflow很酷;回声;回声代码高尔夫)|  \
           ruby golfscript.rb poorencrypt.gs>编码文件
 $(猫编码文件;回声;回声代码高尔夫)|  ruby golfscript.rb poorencrypt.gs
 StackOverflow很酷

Java, 319 313 310字符


  • 更新1:replacechar[]c=r(a[0]);char[]k=r(a[1]);char[]c=r(a[0]),k=r(a[1]); ,保存了6个字符。

  • 更新2:replacefor(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个字符。 是的,closures(冲洗)作者是绝对必要的。 否则该文件留空。 否则本来是298 292 289个字符。

Python3 – 114个字符

从标准input参数

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

F#,168个字符

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

注:大多数IO,关键是Array.mapi。 此外,一些F#Guru可能会打败这个解决scheme – 我是一个C#程序员的交易,从来没有使用F#除了学习的乐趣。

Ruby 72 62个字符

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

我可以保存10个字符,如果我不必从input键中删除\nk=a.chomp; 走在前面,做到了

限制:只能处理单行键。

怎么运行的:

$<就像包含所有input文件的所有行一样的数组。

.inject遍历数组,

{|k,l| :在第一遍时,参数是关键线,并且是input的第一行。

l.each_byte{|b| 将input行中的每个字符作为int。

$><<表示“打印”

(b^(rkslice!0)与键中的第一个字符“异或”(将其切下并存储在“r”

.chr; 将整数转换回ascii

k<<r将键的第一个字符旋转到最后。

}}块生成更新后的k,它将在下一次传递中用作第一个参数注入; 第二个参数将是下一行input。

另一个

Perl解决scheme,59(42)个字符

(符合似乎工作到目前为止的一个class轮:)

计算密钥长度的程序(59个字符):

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

如果使用密码长度为“脆弱”的方法 ,将会是42个字符:

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

命令行:

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

重写消息到它的异或forms,并回到它的明文forms:

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

Haskell,181个字符

在Haskell打高尔夫时,I / O是个婊子,而二进制I / O则是双重的。 这个解决scheme可能会大大改善。 随意!

 import Data.Bits import Data.ByteString as B u=unpack go[l,n]=o$pack$Prelude.zipWith xor(un)(cycle$ul) fx=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 

PowerShell, 125 115个字符

到目前为止,这似乎是最短的基于networking的答案:

 $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

88个字符

使用http://kx.com/中的q实现,这是Arthur Whitney编写的一种语言,受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')`$'.zx 

因此,对正在发生的事情作一点解释:(从右到左)

 a:(hsym')`$'.zx 

从运行时参数列表创build两个文件句柄的列表,并将其保存以便稍后在variables“a”中使用。

 (read1') 

循环两个文件,读取它们并返回字节列表,其中字节= 0x00..0xFF((22字节),(10字节))

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

将密钥形成与消息相同的长度。 如果太长,则会将其截断,如果太短则会重复。 该列performance在格式化很好,2 x 22。

 flip 

调换列表,现在是22×2。

 0b vs'' 

将列表中的每个元素转换为二进制types

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

在所有22个元素中XOR配对明智,返回一个8布尔列表的列表

 "x"$2 sv' 

将8个布尔位转换为字节。

 a[0]1: 

写入文件,覆盖原来的消息文件。

样品运行:

 $ cp message.txt message.txt.bk $ q gq message.txt key.txt $ diff -s message.txt message.txt.bk0 Binary files message.txt and message.txt.bk0 differ $ q gq message.txt key.txt $ diff -s message.txt message.txt.bk0 Files message.txt and message.txt.bk0 are identical 

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

该解决scheme利用了以下方面的问题:

你的任务,如果你select接受它,是创build一个程序在最短的击键次数

此解决scheme是使用手写识别input写在我的平板电脑上的。 在创build这个代码时没有任何键被触动。 因此,这个程序是在零击键中开发的。 游戏结束,我赢了!

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

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是这里最好的语言…

F#, 147 146个字符

这主要是基于driis的解决scheme 。 我所做的只是添加必要的缩进,以便编译,切换命令行参数的顺序,并收紧。 尽pipe如此,如果它能缩短一点,我也不会感到惊讶。 注意:您会收到关于不完整模式匹配的警告。 通常我会第一个抱怨,但我认为代码高尔夫应该是一个例外,通常的最佳做法。 🙂

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

F#,147个字符,更具可读性

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

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

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 

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

Java – 306个字符

以BalusC的Java解决scheme为基础:

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

我没有真正testing代码,但我也没有改变任何激烈的。

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

C#,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());}} 

function性解决scheme 我通过内联读取操作来保存variables,从而导致它被反复执行。