Show HN: Write (almost) perfect encryption in an hour
github.com
github.com
(a) This isn't a one-time pad at all, because the keystream comes from /dev/random. This is, instead, a simple stream cipher keyed from the /dev/random CSPRNG. Since /dev/random is difficult in practice to seed and run deterministically, the only mode you can run it in is "one time pad mode". How close to an actual OTP it is depends on your environment.
(b) One-time pads don't work well in practice. Enthusiasts fixate on the "unbreakable" point without having a full mental model of how a cryptosystem works. That robs them of the insight that (i) only a small part of the cryptosystem is "theoretically unbreakable" with an OTP, and (ii) that part is, in the history of cryptanalysis, the least risky component of the system. In exchange for hardening what was already the strongest component of any cryptosystem, OTP crypto makes grave sacrifices in other parts of the system that are routinely and profitably exploited. It's a terrible tradeoff.
Seconding the (pragmatic) skeptical comments in this thread. Don't use anything like this to encrypt real data. You are safer with any modern block or stream cipher than you are with a ad-hoc stream cipher, which is what this is in practice.
As a learning experience, though: keep at it! This isn't a bad start at all.
If you like/grok how this cipher works, a great next step towards practical cryptography is to learn Salsa20, which is a very simple algorithmic keystream generator that is fast and highly regarded by cryptographers.
But I think practical crypto engineering is a bad next step. The better next step is to take this knowledge and apply it to practical cryptanalysis. Trust me: if you're just getting started with crypto and you're a programmer, you will get 1000x more insight from learning to break systems than you will from building random systems. Here's a bunch of exercises that start in a place that is very compatible with this XOR code:
One-time pads are fetishized because they are the only theoretical silver bullet to cryptanalysis, but they have a bunch of problems that prevent them from being serious solutions to real cryptography needs.
1. They are just about the worst compromise between security and utility. The one-time pad digest must be at least as long as the message, and any communication is going to be more or less stateless because you need to generate a new one-time pad for every message (by design) to prevent cryptanalysis. This is great for an ivory tower exercise, not so great for typical use cases.
2. One-time pads have a terrible ideal to implementation ratio: they look great theoretically and are almost never implemented securely. Among other things, it is very difficult to seed them properly.
3. They do not solve the problem of key exchange whatsoever, which is arguably a much larger vulnerability in practice. A one-time pad is alluring for its standalone strength, but in practice it won't help you elsewhere.
Practically speaking, one-time pads don't solve any real problem in cryptography in a meaningful way, and using them practically tends to attract the sort of programmer that goes into cryptography with a dangerously inaccurate belief from the outset: that you can really develop a silver-bullet to cryptanalysis in real-world cryptosystems.
Other than that, completely agree that it's good practice, but there needs to be a README disclosing that this is unsafe crypto (like just about every other repository anywhere).
from random.c
srand(time(NULL));// seed
Here goes your security. All one needs to know is when you generated your keyfile. srand() and rand() ARE NOT secure for crypto applications.This.
I wish people dabbling in crypto wouldn't be using phrases like "With this project you can be perfectly sure" or "[...]this encryption is unbreakable even in theory."
Now, that isn't to say that we should actually use this library (as-is). You know, don't roll your own crypto for real use. With this particular algorithm, you're putting a lot of faith in the RNG, and it's easy to miss that you need a huge key (or lots of small ones).
Finally, the claim that it's "unbreakable, even in theory" (which comes from the Wikipedia article) to me seems a bit misleading -- isn't the theory usually stronger than any particular implementation? (The word "even" throws me off.)
The name says "one-time," because if a key is used to encrypt two different plaintexts, information will leak.
In this implementation, the results of two encryptions may be based on the same bytes from the key file; not for all bytes, but for some. This is because it chooses bytes from the file (function generate_random_offsets() at https://github.com/pannous/xipher/blob/master/encrypt.c), then writes both the address of those bytes and the XOR'd value to the result of the encryption.
There is no provision to avoid picking the same offsets/key-bytes from one encryption-run to the next, except that they are chosen at random. Because the format of the encrypted messages is very simple, it can be easily determined for two encrypted messages, which key-bytes they share. Remedies: store between runs, remove 00 from file,define chunks in the file?
It's not too difficult to avoid sharing the secrets between two encryption runs; it is not even necessary to chose the key-bytes from the file at random. One could just use the key-bytes in sequence, send the address of the first key-byte, and store the next available key-byte for the next run. When the shared key-file doesn't have enough random bytes, because it has been used for encrypting too many message, it can error out -- which it should, but this implementation will never do that.
> NOTE: You can increase security significantly if you xor/encrypt zipped files, as they already contain very little structure!
> If your key is too small or if you are using it too often, you may be reducing security.
I hope it goes without saying that this thing should not be taken at all seriously.
If num_bytes << num_cypher_bytes (and even more if we know the key length) then the encryption leaks information. https://en.wikipedia.org/wiki/XOR_cipher Otherwise this is a stream cipher and it is really secure but it's inconvenient :)
But it is a good starting point for anybody who's interested in crypto.
Also, weak RNG. Use arc4random. (And /dev/urandom isn't insecure, either.)
The paper mentions the inconvenience of sending the keys:
>Another common argument is that unlike symmetric PSKs, OTP keys also eventually run out and users need to exchange another keyfile. The messages of TFC only consume 420 bytes of key material. The drop in the price of storage space has made the issue negligible: A $10 microSD card can store 4GB of keyfiles to encrypt more than 9 million messages, which is in most cases enough for several years or decades.
If the key size is at least as large as the plaintext AND the key is truly random then it actually is a perfect encryption, because every single bit in the output is going to be random. It is called 'one time pad' -- https://en.wikipedia.org/wiki/One-time_pad
It's a real encryption, much-much better than basically anything before because it's really unbreakable.
For example, you generating a 1TB key before leaving on a trip you could imagine a VPN set up that encrypted 1TB of traffic in a way that was theoretically unbreakable by someone sniffing the traffic only.
It's not useful or practical in many situations that we associate with cryptography over the internet, but it certainly has its applications.
Almost every other cryptographic scheme exists in order to increase convenience, at the expense of some security. The one time pad method is "perfectly" secure (assuming the key is securely generated, and kept safe), everything else is less than perfect (although computationally improbable).
If you can generate a secure keystream (for instance, from pure random data well in advance of your message encryption), you can use just XOR and nothing else, and that system will be difficult to attack mathematically.
XOR as a concept gets an unjustified bad rap amongst generalist engineers because of all the terrible Rube Goldberg XOR schemes other developers have come up with. It's authentically essential to strong cryptography, but very easy to misuse in weak crypto.