How good an encryption algorithm is this?

J

James Curran

Carl Daniel said:
You should never (or almost never) store passwords with reversible
encryption. Instead, store the username in plaintext and store the password
as a one-way hash. Typically MD5 or SHA(1) are used for this purpose.

I'd disagree with that. It's a nice theory, but in the real world,
where 80% of applications have no real need for strong security (*), and 99%
of user eventually forget their password, most users would prefer an "email
me my personally chosen and usually easy-to-remember password" option,
rather than an "email me a new string of random characters which I'm going
to lose before the next time I log in"

(*) e.g., a website forum needs a userid & password, but a security breach
would cause little harm.

--
Truth,
James Curran
[erstwhile VC++ MVP]
Home: www.noveltheory.com Work: www.njtheater.com
Blog: www.honestillusion.com Day Job: www.partsearch.com
 
J

Jon Skeet [C# MVP]

James Curran said:
I'd disagree with that. It's a nice theory, but in the real world,
where 80% of applications have no real need for strong security (*), and 99%
of user eventually forget their password, most users would prefer an "email
me my personally chosen and usually easy-to-remember password" option,
rather than an "email me a new string of random characters which I'm going
to lose before the next time I log in"

(*) e.g., a website forum needs a userid & password, but a security breach
would cause little harm.

A security breach might cause little harm in terms of the forum itself,
but knowing *one* password that someone uses could often easily lead to
knowing the *only* password that that person uses. I'm not as good at
using different passwords all over the place as I should be, although I
do do it to some extent - but I suspect many users just use the same
password everywhere. In that case, a security breach is potentially
*very* damaging.
 
S

Steve Friedl [MVP/Security]

Jon Skeet said:
A security breach might cause little harm in terms of the forum itself,
but knowing *one* password that someone uses could often easily lead to
knowing the *only* password that that person uses. I'm not as good at
using different passwords all over the place as I should be, although I
do do it to some extent - but I suspect many users just use the same
password everywhere. In that case, a security breach is potentially
*very* damaging.

Oh yes. Just after 9/11/2001, a major broadband support site set up a forum
for 9/11 discussions (to keep them all in one place), and after two weeks
they closed it down. Somebody else opened the "9/11 overflow forums", and
people flocked over there to continue the discussions. Of course, people
used the same username and password, and when that other site got hacked,
the major broadband site got a bit of unwanted attention. A few *moderators*
had their accounts expropriated this way, and it was a big hairy mess.

Generally I tell people that if they used their "main site" password on
another site, even for a few minutes, they have to change their *main* site
password immediately. The other site very well may keep logs, and changing
the other-site password immediately doesn't have the effect they imagine.

I don't use the same password for any two accounts *anywhere*.

Steve
 
I

Igor Tandetnik

Jon Skeet said:
I'm
not as good at using different passwords all over the place as I
should be, although I do do it to some extent

You might find Password Minder by Keith Brown useful:

http://www.pluralsight.com/tools.aspx

--
With best wishes,
Igor Tandetnik

With sufficient thrust, pigs fly just fine. However, this is not
necessarily a good idea. It is hard to be sure where they are going to
land, and it could be dangerous sitting under them as they fly
overhead. -- RFC 1925
 
I

Ian Griffiths [C# MVP]

You might find Password Minder by Keith Brown useful:

I just thought I'd point out that Keith's password minder is also free.

The way you worded your reply suggested that it wasn't...

Been using it for years, it stores *hundreds* of passwords.

And also, Keith's can store hundreds of passwords - again, you seem to be
suggesting that it can't.
 
J

Jerry Coffin

[ ... ]
So I decided to invent my own algorithm, and I just wanted anybody's opinion
on how secure this could be compared to the Win32 API version.
First, a C# program generates an array of 256 bytes, as such:

[ ... ]
This is run twice, so I have two arrays of 256 bytes, say key1 and key2.
These are then hardcoded into the C++ encryption algorithm.
Then, the C++ encryption algorithm goes as such:
It memcpys the _TCHAR array to a byte array, then loops round each byte of
this array.
For each byte, it gets the value of key1[n] (where n is the byte number),
and calls this 'b_current_indir' (the starting 'indirection level').
Then, it gets the value of key2[n] and calls this 'levels' - the number of
indirection levels.
Then, an inner loop runs 'levels' times - and on each loop the following
happens: the current byte of the data to be encrypted (dictated by the outer
loop) is XORed with key2[b_current_indir], and THEN, b_current_indir is
reassigned to take on the value of key2[b_current_indir].

[ ... ]
It seems to work to my eyes, but is it a pile of rubbish?

Yes, pretty much.

First you need to realize that repeated XORs have little real effect.
For the moment, let's assume that you XOR one particular input byte
with two other key bytes, calling the input A and the key bytes B and
C, giving: encrypted_byte = (A ^ B) ^ C. The associative property
says this is equivalent to encrypted_byte = A ^ (B ^ C).

If we chose to, we could do:
D = (B ^ C);
encrypted_byte = A ^ D;

Changing the number of times the inner loop executes only changes the
number of items on the right side of the first line that computes D,
meaning that whole inner loop is equivalent to XORing each input byte
with exactly ONE effective key byte (which is the result XORing
together all the key bytes you currently use).

Therefore, what you really have is just a slow and complex way of
producing the same output as XORing each input byte with one key
byte.

There are a number of ways of breaking this. Using a chosen
plaintext, the attack is downright simple: the attacker just gets you
to encrypt a bunch of zero bytes. Since the result of 0 XOR D is D,
this transmits your effective key. The result is that your attacker
gets the _effective_ key that even YOU don't know -- what you
transmit will look (to you) pretty much like random garbage (as you'd
expect for encrypted data) but is really the effective key.

The result of that is that the attacker can decrypt by XORing each
input byte with the effective key for that byte -- IOW, he can
actually decrypt your messages slightly FASTER than you can.

Using a known-plaintext attack is almost as easy: he simply XORs each
byte of the encrypted text with the original text that was encrypted
to (again) get the effective encryption key. Once again, he can
decrypt your messages faster than you can.

A ciphertext-only attack is a _little_ more difficult, but not much.
There are a couple of different typical methods. One is to look only
at the statistics of the encrypted text. You start separating the
text into two bins -- odd-numbered bytes in the first bin and even-
numbered bytes in the second. You then do three bins, four bins,
etc., until you find a length at which (almost by magic) there is a
substantial difference in the number of characters in each bin. At
that point, the attacker has just found your effective key length
(something you probably don't know).

From there his attack becomes fairly simple, based on the frequency
of various characters -- if you're using normal English input, the
space will typically be the most common character. Letters follow a
fairly consistent pattern -- 'e' the most common, 't' the second
most, etc. This will probably solve the encryption pretty easily,
but if he has any difficulty with it, he might also use digraphs and
trigraphs -- sets of two and three letters that do/don't occur
together (e.g. 'th' is common, 'q' is normally followed by 'u', 'jj'
is almost certainly a mistake, and so on).

The other basic approach to an attack requires two encrypted
messages. The attacker realizes (even if you don't) that each byte of
each message is A xor D, where A was the input byte and D and some
(effective) key byte. If he XORs together the bytes of the two
messages, he gets:

(A XOR D) XOR (A' XOR D)

Using the distributive property, this is:

(A xor A') XOR (D XOR D)

Since anything XOR'd with itself is zero, this is:

(A xor A') xor 0

XORing with zero is an identity operation, so this is equivalent to:

A xor A'

Now the attacker uses what are know as cribs -- he takes some guesses
at things that are likely to be in one message or the other. Just for
example, "the' is probably going to occur at least once in one of the
messages. Since he's now factored out the key, and just has the two
original messages XORd against each other, he'll simply take 'the'
and xor it with the combined message. At a place that one message
contained 'the' to start with, he'll get the plaintext of the other
message at the same spot as well. If he tries 'the' and gets 'qjv' as
the matching plaintext from the other message, he can easily guess
that he hasn't found a match. OTOH, if he gets 'his' there's a pretty
fair chance that he's just found a place that one of the original
messages contained 'the' and the other contained 'his'.

In a real attack, he might combine both approaches -- the first
approach is easy to automate, so he'd just let the computer crank
through that. Once he knows your effective key length, each match
with the crib solves more than just the few letters that match -- it
solves all the other characters where the same key byte would be
used.

With as simple of a scheme as you've devised, the cribs probably
wouldn't even come into use at all. The first approach would break
your cipher automatically in almost no time at all. Just for
comparison consider that years ago, WordPerfect would "encrypt"
documents with essentially this same scheme. On the 20 MHz 386 I used
back then, I could normally recover people's passwords for them
entirely automatically in about 10 seconds or so. On a current
machine, that would be reduced to a matter of milliseconds...
 
J

Jerry Coffin

[ ... ]
stream cipers are easier to beat than are block ciphers - byte 0 of stream
cipher can be decoded with NO other information from any other bytes in the
stream, byte 1 plaintext can be discovered using only byte 1 decoded and
byte 0 plaintext - consider block ciphers that have to be broken one block
at a time - typically 16 bytes at a time.

This really isn't true. It is true that stream ciphers have to be
used differently from block ciphers to provide secure results, but
with proper use a stream cipher provides security similar to a block
cipher.

In point of fact, block ciphers are often used to implement stream
ciphers -- just for example, output feedback and cipher feedback (OFB
and CFB) are two common ways of doing stream encryption with block
ciphers.
 
Top