37

From : Encryption Co.
To : x$*sj4 (that's you)

你的任务,如果你选择接受它,是用最少的击键次数创建一个程序,

  • 采用两个文件名参数(命令行或标准输入),第一个是包含密钥的文件,第二个是一些消息。这两个文件都是纯文本。

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

例子:

输入文件:

StackOverflow 很酷

钥匙:

代码高尔夫

加密输出文件的十六进制转储:

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 加密是不可能破解的。请参阅:一次性垫。所以这里没有“加密不良”。

4

23 回答 23

25

Repent, 13 7 chars (无文件支持), 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↔⇄¦*⊕;▼

语言参考(未完成)

口译员(未完成)

于 2010-08-14T00:15:26.957 回答
22

Perl,40 个字符

它有点脆弱。

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

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

$/=!1

将“记录分隔符”设置为未定义的值,并且不会打印任何内容。使用此设置,文件读取行运算符将在整个文件中啜饮。

$_=<>

将整个第一个文件(包含消息)加载到变量$_中。

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

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

于 2010-08-13T19:10:04.087 回答
12

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);}}
于 2010-08-13T17:37:17.227 回答
8

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))))
于 2010-08-13T18:52:15.690 回答
8

GolfScript,28 个字符

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

要使用,请将消息文件、新行和密钥文件传递到脚本的标准输入:

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

$ (echo StackOverflow 很酷;echo;echo Code Golf) | \
          ruby golfscript.rb poorencrypt.gs > 编码文件
$ (cat 编码文件;echo;echo Code Golf) | ruby golfscript.rb 差加密.gs
StackOverflow 很酷
于 2010-08-13T20:42:34.037 回答
7

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 相当冗长。将两个 file-to-char[] 重构为保存 4 个字符的方法。是的,关闭(冲洗)作者是绝对必要的。否则文件为空。否则它将是298 292 289 个字符。

于 2010-08-14T04:25:51.860 回答
6

Python3 - 114 个字符

从标准输入获取参数

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)))
于 2010-08-14T07:37:06.217 回答
4

其他

Perl 解决方案,59 (42) 个字符

(符合目前看来可行的单线:)

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

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

如果使用mobrule 的“脆弱”方法来处理密钥长度,则为 42 个字符:

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

命令行:

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

会将消息重写为其异或形式并返回到它的明文形式:

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

于 2010-08-14T15:43:25.273 回答
4

红宝石 72 62 个字符

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

如果我不必\n从输入键中删除 a ,我可以节省 10 个字符k=a.chomp; 继续前进并做到了

限制:仅处理单行键。

这个怎么运作:

$<就像一个包含所有输入文件的所有行的数组。

.inject遍历数组,

{|k,l| :在第一遍中,参数是关键行和输入的第一行。

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

$><<"印刷"是什么意思

(b^(r.k.slice!0)异或 'b' 与键中的第一个字符(它切掉并存储在 'r'

.chr;将整数转换回 ascii

k<<r将键的第一个字符旋转到末尾。

}}该块产生更新后的 k,它将用作下一次注入的第一个参数;第二个参数将是下一行输入。

于 2010-08-13T23:48:52.603 回答
4

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 可能会从这个解决方案中脱颖而出——我是一名 C# 程序员,除了为了好玩而学习之外,从未将 F# 用于其他任何事情。

于 2010-08-13T17:19:52.300 回答
3

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.

于 2010-08-14T13:17:50.550 回答
3

Haskell,181 个字符

在 Haskell 中打高尔夫球时,I/O 很糟糕,二进制 I/O 更是如此。这个解决方案可能会得到很大的改进。随意!

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
于 2010-08-13T21:24:36.717 回答
3

q, 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')`$'.z.x

所以稍微解释一下发生了什么:(从右到左阅读)

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

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

(read1')

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

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

将密钥塑造成与消息相同的长度。如果太长则截断密钥,如果太短则重复。该列表现在格式正确,2x22。

flip

转置列表,现在是 22x2。

0b vs''

将列表的每个元素转换为二进制类型

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

对所有 22 个元素进行 XOR 对,返回一个包含 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
于 2010-08-14T17:01:55.693 回答
2

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))
于 2010-08-14T07:08:01.760 回答
2

红宝石 - 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)
    }
}

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

如果您选择接受它,您的任务是用最少的击键次数创建一个程序 ...

这个解决方案是在我的平板电脑上使用手写识别输入的。在创建此代码时没有敲击任何键。因此,该程序是在零键击中开发的。游戏结束,我赢了!

于 2010-08-13T22:47:22.460 回答
1

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

于 2010-08-14T03:20:30.697 回答
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)});
于 2010-08-14T01:29:12.727 回答
0

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)))
于 2010-08-13T19:06:14.207 回答
0

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
于 2010-08-14T18:04:30.123 回答
0

F#,147146 个字符

这在很大程度上基于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
于 2010-08-14T00:19:13.263 回答
0

Java - 306 个字符

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

我实际上并没有测试代码,但我也没有改变任何剧烈的东西。

于 2010-08-20T17:40:56.370 回答
0

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

功能性解决方案。我通过内联读取操作来保存变量,这会导致它一遍又一遍地执行。

于 2012-04-11T23:28:16.867 回答
0

C - 163 161 个字符

添加了刷新并删除了不必要的搜索。

打高尔夫球:

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

未打高尔夫球:

#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;
    }
}
于 2010-12-08T03:01:51.590 回答