In Applied Cryptography by Bruce Schneier (which I have been reading quite a lot recently), a protocol for splitting secrets is discussed. Here is a brief description:

  1. Trent generates a random byte string, R, the same length as the message, M.
  2. Trent XORS M with R to make S.
  3. He gives R to Alice and S to Bob.

Your task is to, given an input, split the input into two output files or print the split secret to STDOUT. One output/part of output should contain the random string; the other should contain the original input XOR'd with the random string. Input and output may be to/from files or to/from STDIN/STDOUT. Outputting to STDERR is also allowed.
There are a few restrictions, however:

  1. Your program must take 1 input (1 input filename & 2 outputs if doing file I/O), and output the random string and the original string XOR'd with that random string into the other.
  2. Your program must be cryptographically secure. All random number generators must be cryptographically secure. For example, /dev/random is fine, but the Mersenne Twister (usually randint(number,number) is not. Any random number generator must be explicitly cryptographically secure.
    • If you want to know anything more about what "cryptographically secure" means, check here.
  3. Standard rules and loopholes apply.

This is , so the code with the fewest bytes will win.
May the best coder prosper...

  • 6
    \$\begingroup\$ -1 for the cryptographically secure part. It doesn't add much to the challenge, other than making answers work around that restriction. It's not harder, just another step. \$\endgroup\$
    – Riker
    Mar 23, 2017 at 21:51
  • \$\begingroup\$ @Riker I felt like that adds to the challenge, personally, but I hear you. \$\endgroup\$
    – ckjbgames
    Mar 23, 2017 at 21:52
  • \$\begingroup\$ This is similar, but this isn't necessarily alphanumeric. \$\endgroup\$
    – ckjbgames
    Mar 23, 2017 at 21:54
  • \$\begingroup\$ "random string" String of bits, bytes, or printable ASCII chars? \$\endgroup\$ Mar 23, 2017 at 22:01
  • \$\begingroup\$ @ETHproductions If you aren't doing file I/O, these aren't needed. \$\endgroup\$
    – ckjbgames
    Mar 23, 2017 at 22:07

6 Answers 6


Bash + coreutils + openssl, 91 bytes

0000000: 63 3d 22 6f 70 65 6e 73 73 6c 20 65 6e 63 20 2d  c="openssl enc -
0000010: 61 65 73 2d 31 32 38 2d 63 74 72 20 2d 4b 20 24  aes-128-ctr -K $
0000020: 28 78 78 64 20 2d 70 73 20 2d 6c 20 31 36 20 2f  (xxd -ps -l 16 /
0000030: 64 65 76 2f 72 61 6e 64 6f 6d 29 20 2d 69 76 20  dev/random) -iv
0000040: 30 22 0a 24 63 3c 24 31 0a 74 72 20 01 2d ff 20  0".$c<$1.tr .-.
0000050: 5c 30 3c 24 31 7c 24 63 3e 26 32                 \0<$1|$c>&2

Takes a filename as argument and splits the secret to STDOUT and STDERR. Input and output are in raw binary format.

Sample run

$ cat input.txt
$ bash split input.txt 2> >(xxd -ps >& 2) | xxd -ps
$ printf %02x $[0xd5725c26aa3b ^ 0x97002945cf31] | xxd -r -ps

JavaScript (ES6), 77 76 bytes

let f =
M=>[R=crypto.getRandomValues(new Uint8Array(M.length)),M.map((c,i)=>c^R[i])]

let g = m => console.log(f([...m].map(c=>c.charCodeAt())).map(x=>`[${x.join(", ")}]`).join(",\n"))
g("Secret message")

I think this is what's being asked for. It takes in an array of bytes and outputs [random bytes, XORed message]. I'm assuming that crypto.getRandomValues is cryptographically secure (else I don't know why it exists), and that Math.random isn't. Otherwise I could save 28 bytes.

  • 1
    \$\begingroup\$ This is the kind of answer I wanted! \$\endgroup\$
    – ckjbgames
    Mar 23, 2017 at 22:36

Haskell, 178 Bytes

import System.Entropy
import qualified Data.ByteString as B
import Data.Bits
main|f<-B.init=do b<-B.getLine;r<-getEntropy.B.length$f b;B.putStrLn.pack.B.zipWith xor r$f b;print r

Unfortunately, I can't quite think of a way to do this without three big imports.

More readable version:

main=do b<-B.getLine
        r<-getEntropy . B.length $ B.init b
        B.putStrLn . pack . B.zipWith xor r $ f b
        print r

Basically, it reads a line from stdin, makes a random number with that length and then prints the xor'd version and the random number


Ruby, 88 76 bytes

Edit: I guess the outputs don't have to be strings strings?

p r=`head -c#{m.size}</dev/random`.bytes,m.zip(r).map{|a,b|a^b}

Python 3, 85 bytes

import os
print(list(k),[j^ord(i)for i,j in zip(k,s)])

The only part that might need explaining is the list comprehension ([j^ord...])

It combines the input with the random key (zip([1,2,3],[4,5,6])==[(1,4),(2,5),(3,6)]) and xors them together.


Java, 292 bytes

Not sure if 100% correct

enum e{;public static void main(String[]a){java.security.SecureRandom r=new java.security.SecureRandom();byte[]b=a[0].getBytes(),c=new byte[b.length],d=new byte[c.length];int i=-1;r.nextBytes(c);while(++i<b.length)d[i]=(byte)(b[i]^c[i]);System.out.println(new String(c)+"\n"+new String(d));}}

Takes the input as first argument, outputs key and XOR'ed string to STDOUT separated by newlines.

Ungolfed with comments:

enum e {

    public static void main(String[] a) {
        java.security.SecureRandom r = new java.security.SecureRandom();            // Secure random
        byte[] b = a[0].getBytes(), c = new byte[b.length], d = new byte[c.length]; // 3 arrays
        int i = -1;                                                                 // Index
        r.nextBytes(c);                                                             // Key
        while (++i < b.length) d[i] = (byte) (b[i] ^ c[i]);                         // XOR the input with key
        System.out.println(new String(c) + "\n" + new String(d));                   // Output key and XORed string
  • \$\begingroup\$ This is a perfectly acceptable answer. \$\endgroup\$
    – ckjbgames
    Mar 26, 2017 at 23:49
  • \$\begingroup\$ You could drop the java.security. as any modern IDE can auto-import that unambiguously. \$\endgroup\$ Sep 28, 2017 at 14:49

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge that you have read and understand our privacy policy and code of conduct.

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