Código de Golf: XOR Encryption
code-golf (23)
F #, 168 caracteres
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
Nota: Mayormente IO, la clave es Array.mapi. Además, algunos F # Guru probablemente se vayan de la solución: soy un programador C # de oficio, y nunca usé F # para nada más que aprender por diversión.
De : Encryption Co.
Para : x $ * sj4 (ese eres tú)
Su misión, si decide aceptarla, es crear un programa en el menor número de teclas que
Toma dos parámetros de nombre de archivo (ya sea línea de comando o stdin), el primero es un archivo que contiene la clave y el segundo algún mensaje. Ambos archivos serán texto sin formato.
Aplica la clave del mensaje usando el cifrado XOR , sobrescribiendo el archivo.
Ejemplo:
Fichero de entrada:
StackOverflow es genial
Llave:
Código Golf
Hex dump del archivo de salida cifrado:
0000000: 101b 0506 4b08 1909 1425 030b 1200 2e1c ....K....%......
0000010: 4c25 2c00 080d 0a L%,....
Para simplificar, suponga que los archivos pueden caber en la memoria
Este mensaje se autocifrará en 5 ... 4 ... 3 ... 2 ... 1 ...
#####
#### _/_ ________
##=-[.].]| / /
#( _/ | |------|
# __| | ||||||||
/ _/ | ||||||||
.--''--''-. | | ____ |
/ __ `|__|[o__o]|
_(____nm_______ /____/____
El cifrado XOR es imposible de descifrar si el tamaño de la clave es mayor o igual al tamaño del mensaje y la clave se genera mediante un proceso aleatorio imparcial. Ver: almohadilla de una sola vez . Entonces no hay "Pobre Cifrado" aquí.
Haskell, 181 caracteres
I / O es una perra al jugar al golf en Haskell, y la E / S binaria doblemente. Esta solución probablemente puede mejorarse enormemente. ¡Sentirse libre!
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
Uso:
$ ghc --make encrypt.hs
$ echo -n ''Code Golf'' > key
$ echo -n '' is Cool'' > message
$ echo ''key message'' | ./encrypt
$ od -tx1 message
KSH93 - 152 caracteres
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
PowerShell, 125 115 caracteres
Hasta ahora, esta parece ser la respuesta más corta basada en .net:
$k=[char[]](gc $args[1]);$i=0;sc $args[0] ([byte[]]([char[]](gc $args[0])|%{$_ -bXor $k[$i++%$k.Length]})) -en byte
Versión bonita con abreviaturas de comando explicadas:
$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
Uso: powershell codegolf.ps1 message.txt key.txt
. Según lo solicitado, sobrescribe message.txt
.
Ruby - 158 caracteres
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)}}
Una versión más bonita:
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)
}
}
Esta solución aprovecha el siguiente aspecto del problema:
Su misión, si decide aceptarla, es crear un programa en el menor número de teclas que ...
Esta solución fue escrita en mi tableta utilizando el reconocimiento de escritura a mano como entrada. No se tocaron claves en la creación de este código. Por lo tanto, este programa se desarrolló en cero pulsaciones de teclas. Termina el juego, yo gano!
Arrepentirse, 13 7 caracteres (sin soporte de archivos), 14 caracteres (con soporte de archivos)
Repent es un lenguaje de juguete esotérico basado en stack, con inspiración de J, APL, Golfscript y Python. Aquí hay una solución corta. Lo explicaré, pero es muy tarde y me estoy metiendo de cabeza, así que lo explicaré y lanzaré un intérprete de Silverlight por la mañana.
↓↷¦*⊕;€
Explicación:
↓ 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.
Use como:
Repent "↓↷¦*⊕;€" "Code Golf" " is Cool" > output.txt
Salida (la mayoría de los caracteres no se muestran):
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
Usando archivos es:
↓↶▲⇄▲↓3↔⇄¦*⊕;▼
C - 163 161 caracteres
Se agregó color y se eliminó la búsqueda innecesaria.
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;}}
sin sentido:
#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;
}
}
F#, 147 146 caracteres
Esto se basa en gran medida en la solución de driis . Todo lo que hice fue agregar la sangría necesaria para que compilara, cambiara el orden de los parámetros de la línea de comando y ajustó las cosas. Sin embargo, no me sorprendería que todavía se pueda acortar un poco. Nota: recibirá una advertencia sobre coincidencias de patrones incompletos. Por lo general, yo sería el primero en quejarme de esto, pero creo que el código golf merece una excepción a las mejores prácticas habituales. :)
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 caracteres, más legible
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
GolfScript, 28 caracteres
n.+/~:k;.,.)k.,@//)*<{/(@^}%
Para usar, pase el archivo del mensaje, seguido de una nueva línea, seguido del archivo de la clave a la entrada estándar del guión:
$ (cat message-file ; echo ; cat key-file) | ruby golfscript.rb poorencrypt.gs
$ (echo 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 is Cool
Java, 336 316 405 caracteres
EDITAR: Olvidé que tenía que leer de un archivo. *suspiro
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;
}
}
}
Valió la pena intentarlo. Sin embargo, no creo que Java sea el mejor lenguaje aquí ...
Java, 319 313 310 caracteres
Actualización 1: reemplazado
char[]c=r(a[0]);char[]k=r(a[1]);
porchar[]c=r(a[0]),k=r(a[1]);
, guardado 6 caracteres.Actualización 2: reemplazada
for(int i=0;i<c.length;c[i]^=k[i++%k.length]);
porint i=0;for(char p:c)c[i]^=k[i++%k.length];
, guardado 3 caracteres.
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();}}
Versión más legible:
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 es bastante detallado. Refactorizando dos lecturas de archivo a char [] en un método guardado 4 caracteres. Sí, cerrar (enjuagar) al escritor es absolutamente necesario. De lo contrario, el archivo se deja en blanco. De lo contrario, habría sido 298 292 289 caracteres.
PHP, 142 141 caracteres
Edit 1: fputs()
lugar de 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)});
Bonita impresión:
$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)});
Perl, 40 caracteres
Es un poco frágil.
print$/=!1,($_=<>)^substr<>x 1E4,0,y///c
Perl tiene un operador de cadena xor incorporado. Para resolver este problema, la parte difícil es lograr que las dos cuerdas tengan la misma longitud.
$/=!1
Establece el "separador de registros" en el valor indefinido y no hace que se imprima nada. Con esta configuración, el operador de línea de lectura sorbirá en un archivo completo.
$_=<>
Carga todo el primer archivo (que contiene el mensaje) en la variable $_
.
substr <> x 1E4, 0, y///c
Crea otra cadena del segundo archivo (la clave) y la agrega a sí misma 10.000 veces. Afortunadamente, (1) esta cadena realmente larga será más larga que la cadena de mensaje, y (2) no será tan larga que hará que el programa se quede sin memoria (así es como esta solución es frágil). y///c
es una operación para contar el número de caracteres en $_
, y es un carácter más corto que decir length
. Esto acorta la cadena clave al mismo tamaño que la cadena del mensaje.
Python - 127 caracteres
utiliza parámetros de línea de comando para el archivo de clave y el archivo de datos
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)]
escribiendo en stdout - 109 caracteres
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))
Python3 - 114 caracteres
toma los parámetros de 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)))
q, 88 char
Implementado usando q desde http://kx.com/ que es un lenguaje escrito por Arthur Whitney e inspirado en APL y 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
Así que una pequeña explicación de lo que está sucediendo: (leer de derecha a izquierda)
a:(hsym'')`$''.z.x
Crea una lista de dos identificadores de archivo de una lista de argumentos de tiempo de ejecución y los guarda para su uso posterior en la variable "a".
(read1'')
Pasa el cursor por los dos archivos, léelos y devuelve una lista de bytes donde byte = 0x00..0xFF ((22 bytes), (10 bytes))
{y:count[x]#y;(x;y)}.
Forme la clave a la misma longitud que el mensaje. La clave se trunca si es demasiado larga y se repite si es demasiado corta. La lista ahora está bien formateada, 2x22.
flip
Transponer la lista y ahora es 22x2.
0b vs''''
Convierta cada elemento de la lista en tipo binario
{(x|y)¬ x&y}.''
El par XOR en todos los 22 elementos, devuelve una lista de 8 booleanos
"x"$2 sv''
Convierte 8 bits booleanos a byte.
a[0]1:
Escribir archivo, anulando el archivo de mensaje original.
Muestra de ejecución:
$ 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
Otro
Solución Perl, 59 (42) caracteres
(Conforme un trazador de líneas que parece funcionar hasta ahora :)
Programa (59 caracteres) con longitud de clave calculada:
$.-1?$_^=substr($k x((length)/length($k)+1),0,length):$k=$_
serán 42 caracteres si se usa el enfoque "frágil" de mobrule para la longitud de la clave:
$.-1?$_^=substr($k x 1e4,0,(length)):$k=$_
Línea de comando:
$> perl -i -0777 -pe''<insert above>'' keyfile messagefile
Esto reescribirá el mensaje en su forma xor-ed y volverá a su forma de texto claro:
$> cat keyfile ; cat messagefile
Code Golf
is Cool
Aplicar comando:
$> perl -i.bak -0777 -pe''<insert above>'' keyfile messagefile
$> cat keyfile ; cat messagefile
Code Golf
^P^[^E^FK^H^Y ^Tl/^@^SEI4O/ e/e
Aplicar de nuevo:
$> perl -i.bak -0777 -pe''<insert above>'' keyfile messagefile
$> cat keyfile ; cat messagefile
Code Golf
is Cool
Saludos
rbo
C # 190 caracteres
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);}}
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());}}
Una solución funcional. Guardé variables al subrayar la operación de lectura que hace que se ejecute una y otra vez.
Java - 306 Chars
Usando la solución Java de BalusC como base:
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();}}
Más legible
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();
}
}
En realidad, no probé el código, pero tampoco cambié nada drástico.
Python, 154 caracteres
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)))
Python, 162 caracteres
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 caracteres
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))))
Ruby 72 62 caracteres
$<.inject{|k,l|l.each_byte{|b|$><<(b^(r=k.slice!0)).chr;k<<r}}
Podría guardar 10 caracteres si no tuviera que quitar un Se adelantó y lo hizo /n
de la tecla de entrada con k=a.chomp;
Limitaciones: solo maneja claves de una sola línea.
Cómo funciona:
$<
actúa como una matriz que contiene todas las líneas de todos los archivos de entrada.
.inject
itera sobre la matriz,
{|k,l|
: en la primera pasada, los argumentos son la línea clave, y la primera línea de la entrada.
l.each_byte{|b|
toma cada carácter de las líneas de entrada como un int.
$><<
significa "imprimir"
(b^(rkslice!0)
XORs ''b'' con el primer caracter de la clave (que corta y almacena en ''r''
.chr;
convierte el entero a ASCII
k<<r
rota el primer carácter de la clave hasta el final.
}}
El bloque produce la k actualizada, que se usará como primer argumento en la siguiente pasada para inyectar; el segundo argumento será la siguiente línea de entrada.