desarrollo-web-br-bd.com

XOR un archivo contra una clave

¿Cómo es posible, desde bash o herramientas de línea de comandos estándar de Linux, XOR un archivo contra una clave? Algo así como:

cat my1GBfile | xor my1MB.key > my1GBfile.encrypted

Fuera de tema: Sé que el cifrado es bastante débil con este ejemplo, pero me preguntaba si está disponible en bash o en las herramientas estándar de línea de comandos de Linux (o incluso mejor: de bash y cygwin, porque uso Linux y Windows ).

6
Basj

bash no puede tratar con caracteres ASCII NUL, por lo que no hará esto con las funciones de Shell, necesita un pequeño programa para ello. Esto se puede hacer en casi cualquier lenguaje, pero parece más fácil hacerlo en C, tal vez así:

#include <stdio.h>                                                                                                              
#include <stdlib.h>

int
main(int argc, char *argv[])
{
    FILE *kf;
    size_t ks, n, i;
    long pos;
    unsigned char *key, *buf;

    if (argc != 2) {
        fprintf (stderr, "Usage: %s <key>\a\n", argv[0]);
        exit(1);
    }
    if ((kf = fopen(argv[1], "rb")) == NULL) {
        perror("fopen");
        exit(1);
    }

    if (fseek(kf, 0L, SEEK_END)) {
        perror("fseek");
        exit(1);
    }
    if ((pos = ftell(kf)) < 0) {
        perror("ftell");
        exit(1);
    }
    ks = (size_t) pos;
    if (fseek(kf, 0L, SEEK_SET)) {
        perror("fseek");
        exit(1);
    }
    if ((key = (unsigned char *) malloc(ks)) == NULL) {
        fputs("out of memory", stderr);
        exit(1);
    }
    if ((buf = (unsigned char *) malloc(ks)) == NULL) {
        fputs("out of memory", stderr);
        exit(1);
    }

    if (fread(key, 1, ks, kf) != ks) {
        perror("fread");
        exit(1);
    }

    if (fclose(kf)) {
        perror("fclose");
        exit(1);
    }

    freopen(NULL, "rb", stdin);
    freopen(NULL, "wb", stdout);

    while ((n = fread(buf, 1, ks, stdin)) != 0L) {
        for (i = 0; i < n; i++)
            buf[i] ^= key[i];
        if (fwrite(buf, 1, n, stdout) != n) {
            perror("fwrite");
            exit(1);
        }
    }

    free(buf);
    free(key);

    exit(0);
}

(Esto necesita más comprobación de errores, pero bueno).

Compile lo anterior con:

cc -o xor xor.c

luego ejecútelo así:

./xor my1MB.key <my1GBfile >my1GBfile.encrypted
6
Satō Katsura

Con las herramientas GNU), puede hacer:

paste <(od -An -vtu1 -w1 file) <(while :; do od -An -vtu1 -w1 key; done) |
  awk 'NF!=2{exit}; {printf "%c", xor($1, $2)}'

Necesita un Shell (como el GNU Shell) con soporte de sustitución de procesos, un od con soporte para la opción -w (Como GNU od), y GNU awk para xor() (y la capacidad de generar el byte NUL que no todos awks do).

3
Stéphane Chazelas