
Rolling Your Own Crypto - svenfaw
http://loup-vaillant.fr/articles/rolling-your-own-crypto
======
slindsey
Forget about creating your own crypto. I have had endless troubles just
_using_ crypto. Obscure options that aren't explained. Examples that don't
actually work.

C# had an option that I finally got to work but the documentation specifically
said not to use it; but the other choices didn't work.

I had to encrypt something in PHP then decrypt it in ColdFusion. Despite being
the same algorithm, key, etc, it didn't work. Strangely, the exact same data
in the other direction (CF->PHP) worked just fine.

I'd just like the libraries I use to have a simple choice: Encrypt(data,key)
and Decrypt(data,key) and be done.

~~~
wbond
I found the issue to be more insidious.

Don’t roll your own crypto. Ok, that makes sense.

Don’t implement existing crypto algorithms. Ok, arguments sound good.

This leaves the options of using existing libraries. Cool. So let’s go find an
existing library to deal with validating an SSL certificate chain in Python.

PyCrypto
([https://www.dlitz.net/software/pycrypto/api/current/](https://www.dlitz.net/software/pycrypto/api/current/))
- hmm, so basically the OpenSSL API, probably a minefield unless you are
really up on crypto.

M2Crypto
([https://gitlab.com/m2crypto/m2crypto](https://gitlab.com/m2crypto/m2crypto))
- umm, so no real docs. The recommendation is to go read a book about network
security with OpenSSL. So after reading a network security book, I should be
good to wire together some OpenSSL, right?

cryptography
([https://cryptography.io/en/latest/](https://cryptography.io/en/latest/)) -
sweet, we have docs! Hmm, so for humans we have Fernet and the ability to look
at X.509 certificates. But nothing about validating. Oh, but there is a
stalled PR
([https://github.com/pyca/cryptography/pull/2460](https://github.com/pyca/cryptography/pull/2460))
from 14 months ago, to verify a certificate signatures.

Which then leaves the typical programmer to – hack something together?

So it is (practically) 2017, and using one of the most popular programming
languages, you can’t verify an SSL certificate in a sane way without becoming
journeyman cryptographer.

I like crypto, but using cryptography to integrate with existing
protocols/standards sucks. Can we really not have an end-user focused
implementation of RFC 5280 with a few knobs to turn?

Perhaps people would stop "rolling their own" crypto if there were half-
decent, maintained, documented solutions out there. Maybe some day!

~~~
guitarbill
> Perhaps people would stop "rolling their own" crypto if there were half-
> decent, maintained, documented solutions out there. Maybe some day!

For transport security, HTTPS or SSH. Why go lower level?

Cert based stuff sucks, and cert management sucks. All of these suck harder
because of backwards compatibility. Slowly, people are coming round to the
fact you need to just deprecate stuff and get on with our lives. But the most
sucky thing is OpenSSL.

Sometimes, I think OpenSSL has actually done more damage than good. You accept
a shitty library because everybody uses it so it must be secure, right? Wrong.
And the API is so hostile, the docs are awful. Most things that use it or try
to replace it are awful (M2Crypto, PyCrypto, PyOpenSSL, even urllib3 [0]), as
if the awfulness of OpenSSL seeps into your thinking - I know it's happened to
me once or twice, just interfacing with OpenSSL. Even cryptography suffers
from being based on OpenSSL.

Every time I have to use OpenSSL on a new project, I can't wait to see it die.

[0]
[https://github.com/shazow/urllib3/blob/master/urllib3/util/s...](https://github.com/shazow/urllib3/blob/master/urllib3/util/ssl_.py)

~~~
wbond
I'm not going lower level – in fact, I'm not even dealing with a communication
protocol. Certificates are also used for document and executable signing.

~~~
guitarbill
Yeah, fair enough - it was more of a general assertion that it's easy to
forget that high-level solutions exist. It's NIH.

Does using certs still suck though? I get that it's a hard problem, but cert
revocation and distribution, that's really hard even for OSes.

------
pselbert
You have to applaud him for trying. Building _anything_ as a learning exercise
is an investment in yourself, and I'm encouraged when others are ambitious
about it.

We've all had "don't roll your own crypto" pounded into us, but nothing
teaches a lesson as soundly as trying something yourself. I've tried, failed
and learned a lesson from far less ambitions endeavors.

~~~
bisby
a great rule would be "try to roll your own crypto, but only as a learning
tool, don't try to use it"

~~~
stouset
Roll your own crypto, but for the love of god don't release it.

------
niftich
Quoting an older post of mine:

 _The 'don't roll your own crypto' argument is mostly just shorthand to 'defer
to the opinion of experts, use ready-made constructs when possible, and if
not, then exercise caution when hooking crypto primitives together in unproven
ways'._ [1]

Crypto code, like other library code, is question of trust.

Do I trust Daniel Bernstein? Do I trust Joan Daemen, who is half of the AES
team and a quarter of the Keccak team [2]? In practical matters, do I trust
tptacek [3]? Yes, I trust them, until people more educated in cryptography
than me cast enough doubt or prove it otherwise -- but you might have a
different model of who you trust. But ultimately, you're the one who answers
to your systems.

It's also a bit like science where we come up with a hypothesis (this seems to
work...) and then try very hard disprove it, so our knowledge evolves as we
go. It's important to understand that there was a time when it was _best
practice_ to use certain primitives that are now considered broken, and this
is okay -- assuming we all upgraded our systems since. For cases then that
assumption can't hold true, we need to account for that risk.

This is also why it's wise to go with cryptosystems that receive a good amount
of peer scrutiny. Your homegrown secret sauce might indeed be super secure,
but few will publish papers on how they can obtain collisions on a round-
reduced version. It's network effects, it's 'given enough eyes' all over
again.

[1]
[https://news.ycombinator.com/item?id=12400040](https://news.ycombinator.com/item?id=12400040)
[2]
[https://news.ycombinator.com/item?id=12766941](https://news.ycombinator.com/item?id=12766941)
[3]
[https://gist.github.com/tqbf/be58d2d39690c3b366ad](https://gist.github.com/tqbf/be58d2d39690c3b366ad)

~~~
halayli
you can trust their skills and ability, but trusting their intentions
shouldn't necessarily follow.

~~~
PeterisP
If I trust someones cryptographic abilities but don't trust their intentions,
then I should still use their cryptosystems over my own.

If I use e.g. Bernstein's cryptosystem and he's evil, then he and whoever
hires him can read my data.

If I use my own or your cryptosystem, then either the cryptosystem or
implementation definitely (with a much, much greater confidence than any trust
issues) is horribly broken due to some bug, oversight or side channel, and I
just haven't noticed yet. So the end result is that _everyone_ can read my
data - sticking with someone evil would have been more secure than rolling my
own.

------
ohyoutravel
I am interested enough where I would read a long form article on this kind of
stuff, and found this fascinating. But the end kind of left me feeling
dejected, as the article I guess is just a parody. Which is fine, but I
probably wouldn't have spent as much time trying to take in what I presumed
the article was trying to teach. I would really enjoy an article like this
that actually goes step-by-step so I could learn something like this start to
finish (though I would never implement).

From the article, "Last Step in Crypto:"

Get a PhD in cryptography. You need to be an expert yourself if you ever hope
to invent a primitive that works. Publish your shiny new primitive. It may
withstand the merciless assaults of cryptanalists, and be vetted by the
community. Wait. Your primitive needs to stand the test of time.

~~~
j2kun
This may only be sort of relevant, but I write a math/programming blog on
which I implemented a (very inefficient) elliptic curve crypto library from
first principles. This includes all the math background, and implementations
of a few working protocols. It might be a good starting point if you're
looking for resources like this (exposition-wise, not in terms of a practical
crypto solution).

[https://jeremykun.com/2014/02/08/introducing-elliptic-
curves...](https://jeremykun.com/2014/02/08/introducing-elliptic-curves/)

~~~
tptacek
I really like this series, as I do everything on your blog, but there are two
significant concerns I have with it that are relevant to the thread:

1\. It proposes that ECDH is secure, as a protocol, so long as the curve
parameter is carefully chosen. But this just isn't true, or at least, it's
true only given a technicality that moots the point. For instance: when
accepting a point from a counterparty in ECDH, you have to carefully validate
that the point is valid on the curve you expect to be working on, or else your
own computation might both be confined to an unexpectedly weak curve and
disclose information about the results. This is one of Sean's cryptopals set 8
challenges, and it's one of the better and more surprising exercises that
project came up with.

2\. It suggests that it's reasonable for people designing cryptography to come
up with their own curves. But in reality, nobody ever does this! We're
increasingly confident about the structure of curves we want to be using (you
want curves for which the math rules are consistent and don't require special
cases, for which it's easy to convert between equivalent curve structures for
signatures and key exchange, with prime structure that makes the curve math
fast). Once you find a good curve there (25519 is the best-known example, for
its security level), there's practically nothing to be gained from using any
other curve.

I get why you walk people through picking a new curve! It's a great exercise;
playing with very "small" curves in code is probably the best way to get a
feel for how elliptic curve works. But this is the kind of place where people
rolling their own stuff can get into a lot of trouble.

~~~
j2kun
Yup! My goal was more to explain the math than anything else. I was planning
to extend this for 25519 and discuss the alternate standard forms, but instead
I'm trying to finish up that darned book.

------
Exuma
[https://www.reddit.com/r/programming/comments/5iv1ti/rolling...](https://www.reddit.com/r/programming/comments/5iv1ti/rolling_your_own_crypto/dbbmwwo/)

~~~
shujito
yes, it says it in the very article

~~~
loup-vaillant
I had to admit I screwed up a little… I didn't expect merely writing _about_
crypto would be so hard. Good thing I put this up for peer review.

I have since revised my article. It should be less dangerous now.

------
danbruc
_Poly1305 is one of the few primitives out there that are provably secure._

That doesn't sound right. I guess this should read something like »is provably
as hard to break as the underlying block cipher« in the same way that that a
hash function built using the Merkle-Damgård construction is provably as hard
to break as the compression function used. The article easily gives the
impression that Poly1305 is provably secure in the same way as one-time pad.

~~~
loup-vaillant
I have thought about it and re-read the original paper. I stand by my claim.

The truth of the matter is, poly1305, while provably secure, is almost as
impractical as a one time pad: it relies on a shared random authentication
key. Where does that key is supposed to come from? In practice, you'd derive
it from a session key (and so rely on a symmetric cipher such as AES or
Chacha), or from a key exchange scheme such as Diffie-Hellman, and you rely on
_that_.

I left my phrasing as it was, because it is (I think) closer to the truth,
_and_ not dangerous. I do reckon the AEAD scheme I recommend only has a
_reduction_ proof, not a safety proof. I could be more precise, but I don't
like clutter.

------
ivanhoe
The only reason I'm aware of for rolling a custom crypto would be fighting
against automated attacks. Even ridiculously simple protection can prevent a
script from automatically collecting the data. If there's a lot of data
streams and each requires human interaction to decrypt it, it can
significantly raise the cost of breaking such data. In that case it's probably
best to make it just an additional layer over some well-tested method.

~~~
lvh
I'm not sure I understand the rationale. Automated attacks can't beat real
crypto either -- so why even bother rolling your own? (And automated attacks
can certainly see non-cryptographic encodings like Base64, Base32, ROT13...)

------
lvh
As one might expect[1], I have some thoughts.

There are a few "layers" of rolling your own crypto. Often, people think
they're not rolling their own crypto because they're using AES instead of some
hand-rolled bizarro cipher. This is not that: the primitives the post
references are solid (e.g. BLAKE2b, ChaCha20, X25519).

There are definitely challenges with explaining crypto to programmers in a way
that is non-scary and at the same time factually accurate; I walk that
tightrope constantly with Crypto 101. There are significant factual
inaccuracies in this post that matter and aren't just a temporary educational
tool so you can get a concept across quickly. Someone on Reddit[2] already
pointed out most of the ones that were glaring at me after a cursory review.
To the author's credit, he's put that link up by the start of the post.

There are at least two kinds of crypto education for programmers. One is
practical advice or libs to help people build better applications with crypto.
This means building better tools. Don't "pick Ed25519" \-- pick a library like
libsodium that did signatures right for you. Saying "compose ChaCha20 and
append a MAC" isn't the best level of advice we can strive for. Instead, "use
Fernet" and possibly "use libsodium's secretbox" is (although I think having
to specify a nonce may not be the greatest default -- I'm working on fixing
that). The other kind of crypto education for programmers is to help people
break things. That can help you become an expert, but I don't think we should
expect any meaningful percentage of programmers will spend a bunch of time
finishing all 8 sets of Cryptopals. [3] It is, however, a reasonable
assumption that a (super)majority of programmers will at some point touch some
crypto: the question is what they find when they do that. Will they have
secure password storage and not even notice because that was the right default
in the software they were using, or will they have to cobble together their
own? I for one am hoping it's the former.

Fundamentally, there are two reasons why you don't want to roll your own
crypto. One is because there's a good chance you'll mess it up. The other is
because that's effort, and you are not going to do better than the programmers
that already have done the hard work for you. This is sometimes true for
primitives (don't generate your own FFDH prime/implement your own FFDH -- you
will probably have small subgroups!), but especially true for high-level
recipes at varying levels of complexity from authenticated encryption (you
won't be better than OCB or secretbox) all the way to cryptographic ratchets.

Those reasons put together form my main criticism for this article. Sure, it
has fundamental inaccuracies, they're not trivial, and that's not OK. But even
if it was technically perfect, it doesn't help the next piece of software be
safer.

[1]: I am a cryptographer. I did
[https://www.crypto101.io](https://www.crypto101.io). I am Latacora's crypto
nerd.

[2]:
[https://www.reddit.com/r/programming/comments/5iv1ti/rolling...](https://www.reddit.com/r/programming/comments/5iv1ti/rolling_your_own_crypto/dbbmwwo/)

[3]: [http://cryptopals.com](http://cryptopals.com)

~~~
ooqr
Not rolling your own crypto makes sense given that one is unlikely to fully
comprehend the potential failures. But then does that not also mean that
rolling ones own crypto (with full intention to never use it on anything
'real') and learning at least a little more about potential failures will aid
understanding when using crypto?

For example, naive me once wanted to use BCrypt as a signature algorithm for a
web-based game when exchanging game state information, to prevent cheating by
allowing the server to verify game state transitions. For the purposes at
hand, it seemed like a strong enough cryptographic hash (the server handled
the signing between clients). The only problem was that BCrypt disregards
everything after the first 72 characters. So after headers, everything was
signed valid. Everything.

~~~
Ar-Curunir
Rolling own crypto for learning is different from rolling own crypto for
deployment. The former is good, the latter a most-definite no-no unless you
have training.

------
jackgavigan
I feel like no discussion of rolling one's own crypto is complete without a
link to Renaissance artist Pieter Bruegel the Elder's painting of the subject
(c. 1562):
[http://classicprogrammerpaintings.com/post/148027314949/we-r...](http://classicprogrammerpaintings.com/post/148027314949/we-
rolled-our-own-crypto-pieter-bruegel-the)

------
gioscarab
I Wrote my own crypto, here it is:
[https://github.com/gioblu/Cape](https://github.com/gioblu/Cape) can you brake
it? I do think it is necessary to write your own crypto to understand what
"crypto" is.

~~~
loup-vaillant
I'd have one objection: the Readme doesn't say anything about the underlying
primitives (are you using something standard or did you invent your own
cipher?), and doesn't say anything about external validation (are you alone so
far, or did your code get reviewed?). If it's a learning exercise, warning
wannabe users would be nice.

That said, your code looks too simple not to be easily breakable. I'm no
expert, but that piqued my interest. I'll take a look. If I break it, I'll
write an article about it.

~~~
loup-vaillant
Okay, I think I have cracked it. Haven't tested it, but a qualitative
reasoning should be enough to get you going.

I concentrated my efforts on your Cape::encrypt() method. Inlining
Cape::crypt() and simplifying the resulting code gives something like this (it
appears some computations cancelled each other):

    
    
      void Cape::encrypt(char *source, char *destination, uint8_t length)
      {
          uint8_t iv = this->generate_IV();
          char real_key[255];
          for (i = 0; i < _key_length; i++)
              real_key[i] = _key[(i ^ _reduced_key) % _key_length];
      
          for (i = 0; i < length; i++)
              destination[i] = source[i] ^ iv ^ i ^ real_key[i];
      
          destination[length] = iv ^ _reduced_key;
      };
    
    

Now the weaknesses of your algorithm are clear.

First, I don't believe your IV is truly randomly generated. I don't know of a
real CSPRNG on Arduino, so… probably not your fault.

Second, your IV is only one byte. You cannot securely send more than 256
messages with the same key.

Third, the attacker can get rid of the IV anyway: since it is given at the end
of the ciphertext, I can just XOR it with the rest of the ciphertext before
trying to crack it. This makes your IV irrelevant. You are now limited to
_one_ message per key. In practical terms, you don't do better than a one time
pad.

Fourth, the way you access the key in a weird order doesn't matter. It's the
same as using a different key. Assuming your key is properly unpredictable in
the first place, there is no need to access it in a weird order. I made this
clear by reordering the key in a _real_key_.

Fifth, XORing the message with the index doesn't buy you anything: the
attacker will just reverse it before trying to crack the rest.

Sixth, if your key is shorter than the message, you have a repeating key.
Repeating keys are shown to be broken since… a long time. The reason why is
because XORing parts of the ciphertext encoded with the same key reveals the
XOR of parts of the plaintext, and _that_ is easily broken in practice. So
you're forced to use keys as long as the message.

Conclusion: you have a fancy one time pad. It _is_ secure if your key is as
long as the message, _and_ you use it only once. I have to say your home-made
crypto is not _completely_ broken. But… a simple one time pad would have
achieved the same results more simply.

A word of (dangerous) advice: you won't accomplish much with XOR alone. Modern
ciphers tend to also to rearrange the order of the bits as well. If I may, we
have a real cryptographer here, and he has written a course:
[https://www.crypto101.io/](https://www.crypto101.io/)

------
lisper
SC4 is a PGP replacement designed to be simple and easy to use:

[https://github.com/Spark-Innovations/SC4](https://github.com/Spark-
Innovations/SC4)

Some (but not all) of the code has been audited. Based on DJB's TweetNaCl.

------
jwtadvice
I like how the author organizes 'levels' of rolling cryptography, and
generally agree with his assessment of how those strata should be organized.

------
nerdponx
The idea that anyone would even want to roll their own crypto makes no sense
to me. It would be like rolling your own linear algebra routines instead of
using BLAS, or rolling your own numeric optimizer instead of using BFGS (or
whatever other optimizer makes sense). Crypto is no less esoteric and no less
mathematical.

------
mlosapio
Rolling your own crypto - how about "don't"

------
rahrahrah
> Erratum: Apparently, I don't know what I'm doing either. I committed a
> number of approximations, misdirections, and even errors in there. Some of
> them where pointed out by /u/sacundim on Reddit. If you thought you could
> trust me, read that comment. It's sobering.

LOL brilliant. That was fast.

~~~
oconnore
A lot of those criticisms are sort of unfair. For example, pointing out length
extension attacks in a fabricated MAC construction not found in the article,
especially when the OP explicitly recommends blake2b, which is not vulnerable
to length extension (and also disclaims "How that magical MAC is built is
beyond the scope of this paragraph.").

Another example: criticizing that he mentions appending a MAC (you should
choose an AEAD!)... when later he recommends using an AEAD.

~~~
dom0
AEAD normally only means actual AEAD constructions (think AES-GCM/OCB,
Chacha20-Poly1305 - not combinations of primitives providing authentication
(=EtM, eg. first encrypt with AES-CTR then MAC with some HMAC).

But yeah, some of the criticism reads kinda nit-picky / "I'm going to find
false things in here". But on the other hand he provides good hints how the
article could be improved.

~~~
oconnore
The article recommends Chacha20 Poly1305, not some combination of primitives.

~~~
dom0
What do you mean by this then?

> Another example: criticizing that he mentions appending a MAC (you should
> choose an AEAD!)... when later he recommends using an AEAD.

~~~
oconnore
There is a section called "integrity: not optional", where he uses MACs (which
I would consider to be conceptually simpler to understand than AEADs) to
explain how integrity can be implemented.

Later, in a section called "Level 2: choosing crypto", he recommends using
ChaCha20 Poly1305.

Anyway, this isn't really my crusade, I just think that if you read the
informal blog post as an informal blog post, it's fine.

~~~
lvh
I think the criticism is still valid: combining a MAC and cipher into an AE
scheme (especially an AEAD scheme) is anything but trivial. For example, I
don't think it's reasonable to suggest someone would, given those two tools,
end up with the moral equivalent of secretbox but with ChaCha20 replacing
XSalsa20. (At least there's not a padding timing differential for MtE, but
still.)

------
edblarney
The four most dangerous words in CS.

But it's good that people look into it -> for _fun_ and _learning_. Just not
_for realsies_.

~~~
bkanber
There's serious pushback against rolling your own crypto. Your attitude
towards it is good, but the hivemind-y attitude is to never do it under any
circumstances. I'm sure that attitude prevents many people from experimenting
and becoming crypo experts in their own right.

Roll your own crypto, but be aware of the stakes, and be prepared to drop it
the second that the stakes become real.

~~~
pflats
>There's serious pushback against rolling your own crypto. Your attitude
towards it is good, but the hivemind-y attitude is to never do it under any
circumstances. I'm sure that attitude prevents many people from experimenting
and becoming crypo experts in their own right.

It's not a hivemind-y attitude, it's Software Engineering.

If you cannot show that a bridge will support a given weight, you do not build
the bridge. Period. You learn that in your first Engineering course, freshman
year. It's part of the responsibility of being an Engineer.

You can experiment with new bridge designs all you want, but until you can
prove mathematically that the bridge is sound, you do not build the bridge. If
you really want to roll your own bridge over the ditch in the your backyard,
go for it, but think three times before inviting your friend to drive their
truck over it, especially if you're not already an expert on bridges.

Cryptography is not a small or simple subject. If you are not an expert in the
field, it is incredibly unlikely that you will not know enough to critique
your own work. Instead of starting out by rolling your own, start by studying.

~~~
bkanber
That's a reductionist ("Period.") and a strawman position. It's unfortunate
that you invoked the responsibility of the engineer in your argument: I went
to engineering school. I have two degrees in mechanical engineering from a top
school, I've published peer reviewed papers, and have helped design hybrid
cars for companies you'd recognize. I qualify as an engineer under every
definition you can think of, understand firsthand the responsibilities of an
engineer, have gone through rigorous safety training in order to test drive
the cars that I've personally designed and built.

And yet I still say that nothing you said here is at odds with my statement:
know the stakes. _But play anyway._

You think engineers don't build wacky and dangerous shit for their friends to
play with? Prototypes that stretch the limits of design and would be
irresponsible to mass produce as-is? We do it all the time. It's part of the
learning process. I've been physically hurt, shocked, burnt both by heat and
chemicals, while working with other engineers' experiments. AND IT'S OK! It's
ok to try your own solutions on your friends and peers while the stakes are
low. Studying is only one half of learning. The other half is bringing
textbook knowledge to the real world by building and prototyping and getting
your peer group to throw hammers at it and see what happens. Engineering is
not theory. Engineering is theory applied to the real world. You can't be an
engineer if you don't have one foot on each side. Study on one side, build and
play on the other.

It definitely is a hivemind attitude, because the literal hundreds of other
engineers that I know -- people who design actual bridges, and buildings, and
medical devices, and cars, and oil rigs, and theater sets, things that
hundreds of millions of people rely on to be safe -- don't share this
attitude. Their attitude is: know the stakes. Most software projects go
nowhere and are usually only used by a handful of people close to the
developer. That's the definition of low stakes. And it's ok to experiment, and
to roll your own crypto, when the stakes are low. I think it's damaging, and
probably hubristic, to think that the stakes are high all the time. They're
not.

------
wfunction
Uhm, you _should_ roll your own crypto. Just make sure it's not the _only_
layer of crypto -- i.e., that there's a standard layer too.

Not going to rehash the arguments, but this was discussed recently:
[https://news.ycombinator.com/item?id=13199471](https://news.ycombinator.com/item?id=13199471)

~~~
Nomentatus
Yup. That's the answer - that's what XOR is for, so that you don't have to
encrypt twice (or more) serially, but in parallel. Note too, that encrypting a
pad can be done in advance, with spare cycles, at both ends, for many methods,
then XOR with the pad extremely quickly to communicate. In the Vietnam war the
North Vietnamese army used both a one-time pad layer and a book code layer.
But without computers it was too cumbersome a method and most messages
therefore went out in the clear.

~~~
wfunction
It's actually not what I was thinking of (I was in fact thinking of encrypting
sequentially and hashing+XOR in parallel), but that's a good point, that might
work too!

I'd need to think about it a bit more to convince myself it doesn't have any
significant downsides though; it's less obvious to me. For one thing,
requiring an OTP approach seems to constrain the set of encryption schemes you
can use. (e.g. imagine an algorithm that reverses all the bits of every block
before doing anything else.) Furthermore, if your custom encryption scheme
happens to leave any kind of "watermark" on the ciphertext that makes it
obvious it wasn't something standard like AES, applying the standard layer
last will prevent the attacker from realizing you have a custom layer at all,
until the standard layer is broken. Whereas if you use the OTP+XOR scheme, it
might become obvious something else is going on too.

That said, this approach might actually be stronger than the layered approach,
so it might actually be better. Need to think about it more :)

~~~
Nomentatus
I'll have to look back to see if I in fact have added to the fundamental
meaning of what others have called "layering." The pad doesn't absolutely have
to be an OTP, particularly when rolling your own layer, if the pad isn't the
only key, and the key can change. Watermarks are extinguished when XORed with
any genuinely decent (random-imitating, not frequency-bustable) encryption,
true. And you're right, at least one layer should not have a watermark. Order
doesn't matter though, there really isn't an order for the layers, they're
merged with one another. A not-very-good roll-your-own encryption scheme, if
it introduces a very large number of permutations (such as starting pad, key)
can be very helpful as a layer even though it would be a huge fail as stand-
alone encryption. Mechanisms to increase adjust the size (of all but one
layer, anyway) are advisable.

