5

How is it possible, from bash or standard linux command-line tools, to XOR a file against a key? Something like:

cat my1GBfile | xor my1MB.key > my1GBfile.encrypted

Off-topic: I know the encryption is quite weak with this example, but I was just wondering if this is available from bash or standard linux command-line tools (or even better: from bash and cygwin, because I use both Linux and Windows).

  • 1
    What exactly are you looking to do? I'm asking because XORing 1GB with 1MB is not possible. Would you like the key to be repeated until it is 1GB and then XOR? – PawkyPenguin Oct 16 '17 at 20:35
  • @PawkyPenguin Yes, the key should be repeated / looped. I'm trying to do a very weak encryption (I know it, I want to test how weak it is with various tests + other things). – Basj Oct 16 '17 at 20:38
5

bash can't deal with ASCII NUL characters, so you won't be doing this with shell functions, you need a small program for it. This can be done in just about any language, but it seems easiest to do it in C, perhaps like this:

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

(this needs some more error checking, but oh well).

Compile the above with:

cc -o xor xor.c

then run it like this:

./xor my1MB.key <my1GBfile >my1GBfile.encrypted
  • Thanks for this answer! I'm going to use this right now! When I said bash, I meant bash + standard linux command-line tools. Isn't there any standard command-line tool allowing to do this? Thanks again for this code! – Basj Oct 16 '17 at 21:08
  • Isn't there any standard command-line tool allowing to do this? - Not really. You can probably concoct something by decoding the input first, doing the XOR, and then encoding it back, but it's going to be a lot uglier and a lot more fragile. – Satō Katsura Oct 16 '17 at 21:18
2

With GNU tools, you can do:

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

You need a shell (like the GNU shell) with process substitution support, a od with support for the -w option (like GNU od), and GNU awk for xor() (and the ability to output the NUL byte which not all awks do).

  • Thanks for your answer! I'll try this asap. Just being curious, what is the thing about NUL byte in command-line (also mentioned in the other answer), why is this a problem? (maybe do you have reference to another question about this?) – Basj Oct 17 '17 at 7:28
  • @Basj, historically, tools written in C tend to use NUL delimited strings. In puts(var), puts() outputs the content of var up to the first NUL character. Those APIs can't be used if you want to support the NUL character in your strings, you need to represent strings some other way than by using a NUL terminator. – Stéphane Chazelas Oct 17 '17 at 7:36

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.