diff --git a/N-of-N-Seed-Splitting,-Theory-and-Practice.md b/N-of-N-Seed-Splitting,-Theory-and-Practice.md
new file mode 100644
index 0000000..ed47ab2
--- /dev/null
+++ b/N-of-N-Seed-Splitting,-Theory-and-Practice.md
@@ -0,0 +1,119 @@
+### Contents
++ [N-of-N Seed Splitting: A Theoretical Introduction](#a_nn)
++ [Seed Splitting with MMGen](#a_ss)
+
+#### N-of-N Seed Splitting: A Theoretical Introduction
+
+The bitwise exclusive-or operation (usually denoted as `XOR`, or “![⊕]”)
+has interesting properties that make it very useful in cryptography.
+
+Suppose we have two bytes, *a* and *b*:
+
+![]["a: 1 0 0 1 0 1 0 0"]
+
+![]["b: 0 1 0 1 1 1 1 0"]
+
+To XOR the two bytes, we compare each of their bits. If the bit is the same for
+both *a* and *b,* the corresponding bit of the result is 0. If it differs, the
+result is 1:
+
+![]["a ⊖ b: 1 1 0 0 1 0 1 0"]
+
+Thus XOR can be thought of logically as “one or the other but not both”, or
+arithmetically as addition [modulo][wm] 2 without carry, since 1 plus 1 equals 0
+in base-2 arithmetic.
+
+As is clear from our above example, switching the order of *a* and *b* has no
+effect on the result. So XOR, like addition, is commutative:
+
+![]["a ⊕ b = b ⊕ a"]
+
+And like addition, grouping has no effect on the result. XOR is associative:
+
+![]["a ⊕ (b ⊕ c) = (a ⊕ b) ⊕ c"]
+
+But unlike addition, XOR has an extra property: *invertibility.* The result can
+be switched with any of the operands, making XOR sort of like addition and
+subtraction rolled into one. Thus, if
+
+![]["a ⊕ b = c"]
+
+then
+
+![]["c ⊕ a = b"]
+
+![]["b ⊕ c = a"]
+
+and so forth.
+
+This last property makes XOR very handy for encryption and decryption. Given
+a plaintext *P* and a random value *r* with the same bit length as *P*, we
+encrypt *P* by XOR’ing it with *r* to obtain the ciphertext *C:*
+
+![]["P ⊕ r = C"]
+
+To decrypt, we just XOR the ciphertext with *r* to recover the plaintext:
+
+![]["C ⊕ r = P"]
+
+The randomness of the ciphertext is guaranteed to be no less than that of the
+random value. Thus if *r* is perfectly random, then *C* is perfectly
+undecipherable without knowledge of *r.* This is the principle underlying the
+[one-time pads][otp] used by spies and diplomats before the computer age, as
+well as modern [stream ciphers][sc].
+
+To demonstrate how this can be used for seed splitting, all we do is change
+the names of the variables:
+
+![]["seed ⊕ share1 = share2"]
+
+Here *seed* is analogous to *P* in the previous example, *share1* is
+a random value with the same bit length as *seed,* and *share2* is
+the resulting “ciphertext”. Just as the ciphertext reveals nothing about the
+plaintext in the previous example, *share2* reveals nothing about
+*seed* without knowledge of *share1.* And *share1,* of
+course, being a random value, reveals nothing about *seed* either. To recover
+the seed, we just XOR the two shares. Since XOR is commutative, the order in
+which we combine them isn’t important:
+
+![]["share2 ⊕ share1 = seed"]
+
+Thanks to XOR’s associativity, splits of arbitrary length can be created by
+using an arbitrary number of random shares:
+
+Perform an *n*-way split:
+
+![]["seed ⊕ share1 ⊕ share2 ... ⊕ shareN-1 = shareN"]
+
+Recover the seed:
+
+![]["share1 ⊕ share2 ... ⊕ shareN = seed"]
+
+Knowledge of anything less than *n* shares reveals nothing about the seed.
+
+#### Seed Splitting with MMGen
+
+The MMGen wallet implements seed-splitting functionality via the commands
+`mmgen-seedsplit` and `mmgen-seedjoin`.
+
+TBD
+
+[⊕]: https://mmgen.github.io/images/ss/o_xor.svg "⊕"
+["a: 1 0 0 1 0 1 0 0"]: https://mmgen.github.io/images/ss/byte_a.svg "a: 1 0 0 1 0 1 0 0"
+["b: 0 1 0 1 1 1 1 0"]: https://mmgen.github.io/images/ss/byte_b.svg "b: 0 1 0 1 1 1 1 0"
+["a ⊖ b: 1 1 0 0 1 0 1 0"]: https://mmgen.github.io/images/ss/byte_ab.svg "a ⊖ b: 1 1 0 0 1 0 1 0"
+["a ⊕ b = b ⊕ a"]: https://mmgen.github.io/images/ss/ab-ba.svg "a ⊕ b = b ⊕ a"
+["a ⊕ (b ⊕ c) = (a ⊕ b) ⊕ c"]: https://mmgen.github.io/images/ss/abc.svg "a ⊕ (b ⊕ c) = (a ⊕ b) ⊕ c"
+["a ⊕ b = c"]: https://mmgen.github.io/images/ss/ab-c.svg "a ⊕ b = c"
+["c ⊕ a = b"]: https://mmgen.github.io/images/ss/ca-b.svg "c ⊕ a = b"
+["b ⊕ c = a"]: https://mmgen.github.io/images/ss/bc-a.svg "b ⊕ c = a"
+["P ⊕ r = C"]: https://mmgen.github.io/images/ss/Pr-C.svg "P ⊕ r = C"
+["C ⊕ r = P"]: https://mmgen.github.io/images/ss/Cr-P.svg "C ⊕ r = P"
+["seed ⊕ share1 = share2"]: https://mmgen.github.io/images/ss/ss-enc.svg "seed ⊕ share1 = share2"
+["share2 ⊕ share1 = seed"]: https://mmgen.github.io/images/ss/ss-dec.svg "share2 ⊕ share1 = seed"
+["seed ⊕ share1 ⊕ share2 ... ⊕ shareN-1 = shareN"]: https://mmgen.github.io/images/ss/ssN-enc.svg "seed ⊕ share1 ⊕ share2 ... ⊕ shareN-1 = shareN"
+["share1 ⊕ share2 ... ⊕ shareN = seed"]: https://mmgen.github.io/images/ss/ssN-dec.svg "share1 ⊕ share2 ... ⊕ shareN = seed"
+
+[wm]: https://en.wikipedia.org/wiki/Modular_arithmetic
+[otp]: https://en.wikipedia.org/wiki/One-time_pad
+[sc]: https://en.wikipedia.org/wiki/Stream_cipher