Google Groups no longer supports new Usenet posts or subscriptions. Historical content remains viewable.
Dismiss

lightweight encryption of text file

227 views
Skip to first unread message

Daniel Fetchinson

unread,
Jan 8, 2010, 2:14:51 PM1/8/10
to Python
I have a plain text file which I would like to protect in a very
simple minded, yet for my purposes sufficient, way. I'd like to
encrypt/convert it into a binary file in such a way that possession of
a password allows anyone to convert it back into the original text
file while not possessing the password one would only see the
following with the standard linux utility 'file':

[fetchinson@fetch ~]$ file encrypted.data
encrypted.data: data

and the effort required to convert the file back to the original text
file without the password would be equivalent to guessing the
password.

I'm fully aware of the security implications of this loose
specification, but for my purposes this would be a good solution.

What would be the simplest way to achieve this using preferably stock
python without 3rd party modules? If a not too complex 3rd party
module made it really simple that would be acceptable too.

Cheers,
Daniel


--
Psss, psss, put it down! - http://www.cafepress.com/putitdown

Robert Kern

unread,
Jan 8, 2010, 2:51:47 PM1/8/10
to pytho...@python.org

Paul Rubin's p3.py algorithm is probably the most straightforward way to meet
these requirements. It's not a standard crypto algorithm by any means, but Paul
knows his stuff and has devised it with these deployment restrictions in mind.

http://www.nightsong.com/phr/crypto/p3.py

--
Robert Kern

"I have come to believe that the whole world is an enigma, a harmless enigma
that is made terrible by our own mad attempt to interpret it as though it had
an underlying truth."
-- Umberto Eco

Daniel Fetchinson

unread,
Jan 8, 2010, 4:39:39 PM1/8/10
to Python
>> I have a plain text file which I would like to protect in a very
>> simple minded, yet for my purposes sufficient, way. I'd like to
>> encrypt/convert it into a binary file in such a way that possession of
>> a password allows anyone to convert it back into the original text
>> file while not possessing the password one would only see the
>> following with the standard linux utility 'file':
>>
>> [fetchinson@fetch ~]$ file encrypted.data
>> encrypted.data: data
>>
>> and the effort required to convert the file back to the original text
>> file without the password would be equivalent to guessing the
>> password.
>>
>> I'm fully aware of the security implications of this loose
>> specification, but for my purposes this would be a good solution.
>>
>> What would be the simplest way to achieve this using preferably stock
>> python without 3rd party modules? If a not too complex 3rd party
>> module made it really simple that would be acceptable too.
>
> Paul Rubin's p3.py algorithm is probably the most straightforward way to
> meet
> these requirements. It's not a standard crypto algorithm by any means, but
> Paul
> knows his stuff and has devised it with these deployment restrictions in
> mind.
>
> http://www.nightsong.com/phr/crypto/p3.py

Thanks a lot, currently I'm having trouble using this code on python
2.6 but probably some small tweaking will fix it.

Daniel Fetchinson

unread,
Jan 8, 2010, 4:47:26 PM1/8/10
to Python

Actually, it also doesn't work with python 2.5 and currently I don't
have access to anything older. array.array raises a

ValueError: string length not a multiple of item size

Does anyone recall a change to array.array?

The full traceback is

Traceback (most recent call last):
File "p3.py", line 163, in <module>
_test()
File "p3.py", line 143, in _test
c1 = e(plain,key)
File "p3.py", line 69, in p3_encrypt
xkey = _expand_key(k_enc, n+4)
File "p3.py", line 41, in _expand_key
return array ('L', j)
ValueError: string length not a multiple of item size

Irmen de Jong

unread,
Jan 8, 2010, 5:02:00 PM1/8/10
to
On 8-1-2010 22:39, Daniel Fetchinson wrote:
>>
>> http://www.nightsong.com/phr/crypto/p3.py
>
> Thanks a lot, currently I'm having trouble using this code on python
> 2.6 but probably some small tweaking will fix it.

If you keep having issues with this module, maybe you can try this:

http://www.freenet.org.nz/ezPyCrypto/

It provides a very easy compact api on top of PyCrypto. So you'll need
to install that as well to be able to use this.

-irmen

Robert Kern

unread,
Jan 8, 2010, 5:09:27 PM1/8/10
to pytho...@python.org
On 2010-01-08 15:47 PM, Daniel Fetchinson wrote:
>>>> I have a plain text file which I would like to protect in a very
>>>> simple minded, yet for my purposes sufficient, way. I'd like to
>>>> encrypt/convert it into a binary file in such a way that possession of
>>>> a password allows anyone to convert it back into the original text
>>>> file while not possessing the password one would only see the
>>>> following with the standard linux utility 'file':
>>>>
>>>> [fetchinson@fetch ~]$ file encrypted.data
>>>> encrypted.data: data
>>>>
>>>> and the effort required to convert the file back to the original text
>>>> file without the password would be equivalent to guessing the
>>>> password.
>>>>
>>>> I'm fully aware of the security implications of this loose
>>>> specification, but for my purposes this would be a good solution.
>>>>
>>>> What would be the simplest way to achieve this using preferably stock
>>>> python without 3rd party modules? If a not too complex 3rd party
>>>> module made it really simple that would be acceptable too.
>>>
>>> Paul Rubin's p3.py algorithm is probably the most straightforward way to
>>> meet
>>> these requirements. It's not a standard crypto algorithm by any means,
>>> but
>>> Paul
>>> knows his stuff and has devised it with these deployment restrictions in
>>> mind.
>>>
>>> http://www.nightsong.com/phr/crypto/p3.py
>>
>> Thanks a lot, currently I'm having trouble using this code on python
>> 2.6 but probably some small tweaking will fix it.
>
> Actually, it also doesn't work with python 2.5 and currently I don't
> have access to anything older. array.array raises a
>
> ValueError: string length not a multiple of item size
>
> Does anyone recall a change to array.array?
>
> The full traceback is
>
> Traceback (most recent call last):
> File "p3.py", line 163, in<module>
> _test()
> File "p3.py", line 143, in _test
> c1 = e(plain,key)
> File "p3.py", line 69, in p3_encrypt
> xkey = _expand_key(k_enc, n+4)
> File "p3.py", line 41, in _expand_key
> return array ('L', j)
> ValueError: string length not a multiple of item size

Are you on a 64-bit platform? Unfortunately, array's integer typecodes are
platform-specific, but p3.py requires a 32-bit integer and was written on a
32-bit platform. It's reasonably straightforward to fix. Put this bit of
(untested) code at the top of the file and replace occurrences of 'L' with uint32:

# Find the typecode of a 32-bit unsigned integer.
for typecode in 'IL':
if len(array(typecode, [0]).tostring()) == 4:
uint32 = typecode
break
else:
raise RuntimeError("Neither 'I' nor 'L' are unsigned 32-bit integers.")

Steven D'Aprano

unread,
Jan 8, 2010, 8:50:59 PM1/8/10
to
On Fri, 08 Jan 2010 20:14:51 +0100, Daniel Fetchinson wrote:

> I have a plain text file which I would like to protect in a very simple
> minded, yet for my purposes sufficient, way. I'd like to encrypt/convert
> it into a binary file in such a way that possession of a password allows
> anyone to convert it back into the original text file while not
> possessing the password one would only see the following with the
> standard linux utility 'file':
>
> [fetchinson@fetch ~]$ file encrypted.data
> encrypted.data: data

If that is your sole requirement, then the addition of a single non-text
byte (say, a null) anywhere in the file would be sufficient to have file
identify it as data. You say "encrypt/convert" -- does this mean that you
don't care if people can read the text in a hex editor, so long as file
identifies it as data?

Would something like a binary Vigenere Cipher be sufficient?


# Untested
def encrypt(plaintext, password):
cipher = []
for i, c in enumerate(plaintext):
shift = password[i % len(password)]
shift = ord(shift)
cipher.append((ord(c) + shift) % 256)
return ''.join([chr(n) for n in cipher])

def decrypt(ciphertext, password):
plain = []
for i, c in enumerate(ciphertext):
shift = password[i % len(password)]
shift = ord(shift)
plain.append((256 + ord(c) - shift) % 256)
return ''.join([chr(n) for n in plain])

(How times have changed... once upon a time, the Vigenere Cipher was
considered the gold-standard unbreakable encryption technology. Now it
merely qualifies as obfuscation.)

Is it acceptable if there is a chance (small, possibly vanishingly small)
that file will identify it as text? As far as I know, even the
heavyweight "serious" encryption algorithms don't *guarantee* that the
cipher text will include non-text bytes.


> and the effort required to convert the file back to the original text
> file without the password would be equivalent to guessing the password.

If you seriously mean that, then "lightweight encryption" won't do the
job, because it is vulnerable to frequency analysis, which is easier than
guessing the password. You need proper, heavy-weight encryption.


> I'm fully aware of the security implications of this loose
> specification, but for my purposes this would be a good solution.

Can you explain what your objection to real encryption is? Are you
concerned about the complex API? The memory requirements and processing
power required? (Neither of which are particularly high for small text
files on a modern PC, but perhaps you have to encrypt tens of millions of
huge files on an underpowered device...)


> What would be the simplest way to achieve this using preferably stock
> python without 3rd party modules? If a not too complex 3rd party module
> made it really simple that would be acceptable too.

The problem is that, as I see it, you've assumed a solution rather than
state what your requirements are. I'm *guessing* that you are more
concerned of having to learn to use a complex API, rather than actually
*requiring* a lightweight encryption algorithm. If that's the case, then
something serious like blowfish or similar would be perfectly acceptable
to you, so long as the API was simple.

(On the other hand, perhaps vulnerability to frequency analysis is a
feature, not a bug, in your use-case. If you forget the password, you
have a chance of recovering the text.)

--
Steven

Anthra Norell

unread,
Jan 9, 2010, 4:52:06 AM1/9/10
to pytho...@python.org
Daniel Fetchinson wrote:
> I have a plain text file which I would like to protect in a very
> simple minded, yet for my purposes sufficient, way. I'd like to
> encrypt/convert it into a binary file in such a way that possession of
> a password allows anyone to convert it back into the original text
> file while not possessing the password one would only see the
> following with the standard linux utility 'file':
>
> [fetchinson@fetch ~]$ file encrypted.data
> encrypted.data: data
>
> and the effort required to convert the file back to the original text
> file without the password would be equivalent to guessing the
> password.
>
> I'm fully aware of the security implications of this loose
> specification, but for my purposes this would be a good solution.
>
> What would be the simplest way to achieve this using preferably stock
> python without 3rd party modules? If a not too complex 3rd part
> module made it really simple that would be acceptable too.


Daniel,

Here's what looks like another thread veering off into package-ology,
leaving a stumped OP behind.

"Don't use a random generator for encryption purposes!" warns the
manual, of which fact I was reminded in no uncertain terms on this forum
a few years ago when I proposed the following little routine in response
to a post very similar to yours. One critic challenged me to encode my
credit card data and post it. Which I did. Upon which another critic
conjured up the horror vision of gigahertzes hacking my pathetic little
effort to pieces as I was reading his message. Of the well-meaning kind,
he urged me to put an immediate stop to this foolishness. I didn't.

No unplanned expenditures ensued.

Or to quote ... I forget who: Fools and innovators are people who don't
care much about what one is not supposed to do.

So, take or leave what follows for what it is worth or not worth, I am
confident it works and would serve your purpose, which, as I understand,
is not to write a text book on cryptology.

Regards

Frederic


##############################


import random


def crypt_string (string, key, floor = 0, size_of_set = 255):

# key is a number. The sign of that number controls which way the
process
# goes. If the number is positive, the result is an encryption. A
negative
# number orders a decryption.

if key == 0: return string # No processing

import random

MAX_CHUNK_SIZE = 32
MIN_CHUNK_SIZE = 16

def process_sequence (sequence):
s = ''
for c in sequence:
r = random.randint (0, size_of_set - 1)
s += chr (((ord (c) - floor + r * sign) % size_of_set) + floor)
return s

def shuffle_sequence (sequence):
random.shuffle (sequence)
return sequence

sign = (key > 0) * 2 - 1
random.seed (key * sign)

s = ''

if sign > 0: # forward

i = 0
while i < len (string):
random_size_of_chunk = random.randint (MIN_CHUNK_SIZE,
MAX_CHUNK_SIZE)
clear_chunk_shuffled = shuffle_sequence (list (string
[i:i+random_size_of_chunk]))
code_chunk_shuffled = process_sequence (clear_chunk_shuffled)
s += code_chunk_shuffled
i += len (code_chunk_shuffled)

else: # backward

i = 0
while i < len (string):
random_size_of_chunk = random.randint (MIN_CHUNK_SIZE,
MAX_CHUNK_SIZE)
code_chunk_shuffled = list (string [i:i+random_size_of_chunk])
real_size_of_chunk = len (code_chunk_shuffled)
unshuffling_template = shuffle_sequence (range
(real_size_of_chunk)) # 1. same ...
clear_chunk_shuffled = process_sequence
(code_chunk_shuffled) # 2. ... order
clear_chunk = real_size_of_chunk * [None]
for ii in range (real_size_of_chunk):
clear_chunk [unshuffling_template[ii]] =
clear_chunk_shuffled [ii]
s += ''.join (clear_chunk)
i += real_size_of_chunk

return s

def _crypt_file (in_file, out_file, key):

BUFFER_SIZE = 1024
while 1:
s = in_file.read (BUFFER_SIZE)
if s == '': break
out_file.write (crypt_string (s, key))


def crypt_file (in_file_name, out_file_name, key):

in_file = open (in_file_name, 'rb')
out_file = open (out_file_name, 'wb')
_crypt_file (in_file, out_file, key)
out_file.close ()

Daniel Fetchinson

unread,
Jan 9, 2010, 5:26:38 AM1/9/10
to Python
>>>>> I have a plain text file which I would like to protect in a very
>>>>> simple minded, yet for my purposes sufficient, way. I'd like to
>>>>> encrypt/convert it into a binary file in such a way that possession of
>>>>> a password allows anyone to convert it back into the original text
>>>>> file while not possessing the password one would only see the
>>>>> following with the standard linux utility 'file':
>>>>>
>>>>> [fetchinson@fetch ~]$ file encrypted.data
>>>>> encrypted.data: data
>>>>>
>>>>> and the effort required to convert the file back to the original text
>>>>> file without the password would be equivalent to guessing the
>>>>> password.
>>>>>
>>>>> I'm fully aware of the security implications of this loose
>>>>> specification, but for my purposes this would be a good solution.
>>>>>
>>>>> What would be the simplest way to achieve this using preferably stock
>>>>> python without 3rd party modules? If a not too complex 3rd party

>>>>> module made it really simple that would be acceptable too.
>>>>

Thanks!
That was exactly the problem, I'm on a 64 bit machine and your fix
seems to work indeed.

Daniel Fetchinson

unread,
Jan 9, 2010, 5:45:14 AM1/9/10
to Python
On 1/9/10, Steven D'Aprano <st...@remove-this-cybersource.com.au> wrote:
> On Fri, 08 Jan 2010 20:14:51 +0100, Daniel Fetchinson wrote:
>
>> I have a plain text file which I would like to protect in a very simple
>> minded, yet for my purposes sufficient, way. I'd like to encrypt/convert
>> it into a binary file in such a way that possession of a password allows
>> anyone to convert it back into the original text file while not
>> possessing the password one would only see the following with the
>> standard linux utility 'file':
>>
>> [fetchinson@fetch ~]$ file encrypted.data
>> encrypted.data: data
>
> If that is your sole requirement,

No, that was not my sole requirement, I also wrote:

"""
and the effort required to convert the file back to the original text
file without the password would be equivalent to guessing the
password.
"""

> then the addition of a single non-text


> byte (say, a null) anywhere in the file would be sufficient to have file
> identify it as data.

Yes, but this would not satisfy the other requirement quoted above.
One could read the file without an effort that is equivalent to
guessing a random password.

> You say "encrypt/convert" -- does this mean that you
> don't care if people can read the text in a hex editor, so long as file
> identifies it as data?

I do care. See the quote above :)

> Would something like a binary Vigenere Cipher be sufficient?
>
>
> # Untested
> def encrypt(plaintext, password):
> cipher = []
> for i, c in enumerate(plaintext):
> shift = password[i % len(password)]
> shift = ord(shift)
> cipher.append((ord(c) + shift) % 256)
> return ''.join([chr(n) for n in cipher])
>
> def decrypt(ciphertext, password):
> plain = []
> for i, c in enumerate(ciphertext):
> shift = password[i % len(password)]
> shift = ord(shift)
> plain.append((256 + ord(c) - shift) % 256)
> return ''.join([chr(n) for n in plain])

Thanks, this looks simple enough and probably sufficient for my purposes!
I'll see if I'll use this or Paul Rubin's p3.py.

> Is it acceptable if there is a chance (small, possibly vanishingly small)
> that file will identify it as text? As far as I know, even the
> heavyweight "serious" encryption algorithms don't *guarantee* that the
> cipher text will include non-text bytes.

Hmmm, that's a good point, but actually it doesn't matter if 'file'
identifies it as text with a very small probability.

>> and the effort required to convert the file back to the original text
>> file without the password would be equivalent to guessing the password.
>
> If you seriously mean that, then "lightweight encryption" won't do the
> job, because it is vulnerable to frequency analysis, which is easier than
> guessing the password. You need proper, heavy-weight encryption.

Well, probably you are right and I should have been more clear. What
typically people call obfuscation is sufficient for me, as long as the
obfuscation involves a password, something that your solution seems to
do.


>> I'm fully aware of the security implications of this loose
>> specification, but for my purposes this would be a good solution.
>
> Can you explain what your objection to real encryption is?

Not much really, I simply don't want to overkill, that's all. First
and foremost I wouldn't want to introduce a dependency on a 3rd party
module and also wouldn't want to read documentation of a complex API
when all I need are two functions: encrypt( text, password) and
decrypt( text, password ). I really like your solution because that's
all it does.

> The problem is that, as I see it, you've assumed a solution rather than
> state what your requirements are. I'm *guessing* that you are more
> concerned of having to learn to use a complex API,

Well, that's sort of true about learning a complex API :) But it's
also true that I'm not storing anything really valuable in the file
but still wouldn't want to leave it lying around in plain text. In
case I lose the laptop with the file I seriously doubt anybody who
finds it will go through each and every file and try to find what's in
it, even though they look like data files and there is no hint what so
ever that any one of them contains encrypted info. If they see a text
file, well, that can give them ideas, so let's encrypt a little bit.
So basically that's the story, granted, it's not a full specification
or anything like that, it's a description of a vague situation but
that's really all I have :)

Cheers,
Daniel

Daniel Fetchinson

unread,
Jan 9, 2010, 5:49:38 AM1/9/10
to Python
> > I have a plain text file which I would like to protect in a very
> > simple minded, yet for my purposes sufficient, way. I'd like to
> > encrypt/convert it into a binary file in such a way that possession of
> > a password allows anyone to convert it back into the original text
> > file while not possessing the password one would only see the
> > following with the standard linux utility 'file':
> >
> > [fetchinson@fetch ~]$ file encrypted.data
> > encrypted.data: data
> >
> > and the effort required to convert the file back to the original text
> > file without the password would be equivalent to guessing the
> > password.
> >
> > I'm fully aware of the security implications of this loose
> > specification, but for my purposes this would be a good solution.
> >
> > What would be the simplest way to achieve this using preferably stock
> > python without 3rd party modules? If a not too complex 3rd part
> > module made it really simple that would be acceptable too.
>
>
>
>

Thanks a lot!

Your description is a good fit for my purposes, indeed I don't plan on
writing a text book on encryption :) Also, I don't plan on encrypting
credit card numbers either, all I need is that a file doesn't look
obviously full of ascii characters but something that is generic data.
And since it will not be an entire system, with lots of files of this
type, only we are talking about a single file, there is no incentive
to decipher my algorithm.

I'll take a look at your code, thanks a lot,

Dave Angel

unread,
Jan 9, 2010, 6:05:05 AM1/9/10
to Anthra Norell, pytho...@python.org

Anthra Norell wrote:
> <div class="moz-text-flowed" style="font-family: -moz-fixed">Daniel

> <snip>
The problem I'd have with this approach (not studied in detail), is that
there's no reason that next year's Python must use the same random
number generator, or the same shuffle algorithm. So in order to assure
that "encrypted" archives will be recoverable, one should store with
them the CPython implementation, in source form, just in case that's
needed to reconstruct things.

DaveA

Arnaud Delobelle

unread,
Jan 9, 2010, 7:54:11 AM1/9/10
to
Daniel Fetchinson <fetch...@googlemail.com> writes:

> I have a plain text file which I would like to protect in a very
> simple minded, yet for my purposes sufficient, way. I'd like to
> encrypt/convert it into a binary file in such a way that possession of
> a password allows anyone to convert it back into the original text
> file while not possessing the password one would only see the
> following with the standard linux utility 'file':
>
> [fetchinson@fetch ~]$ file encrypted.data
> encrypted.data: data

[...]

This is probably not what you want, but it is very simple and doesn't
import any module:) I am not qualified to say how easy it is to discover
the message without the password.

def str2int(txt):
return reduce(lambda n, c: n*255 + ord(c), txt, 0)

def int2str(n):
chars = []
while n:
n, o = divmod(n, 255)
chars.append(chr(o))
return ''.join(reversed(chars))

def encrypt(txt, pwd):
return int2str(str2int(txt)*str2int(pwd))

def decrypt(txt, pwd):
return int2str(str2int(txt)/str2int(pwd))

def test(txt, pwd):
encrypted_txt = encrypt(txt, pwd)
decrypted_txt = decrypt(encrypted_txt, pwd)
print "text:%r" % txt
print "encrypted:%r" % encrypted_txt
print "decrypted:%r" % decrypted_txt


>>> test("This encryption scheme is definitely unbreakable.", "secret")
text:'This encryption scheme is definitely unbreakable.'
encrypted:'&2\xa5\xd4\x17i+E\x01k\xfa\x94\xf80\xa8\x8f\xea.w\x128\xf1\xd9\x0f9\xf2t\xc9\r`\x90%\xd6\xf3~\x1f\x00%u&\x8a\xe4\xe0\xa7\xb8\xb0ec)S>\xcb\xf2>\xec'
decrypted:'This encryption scheme is definitely unbreakable.'

--
Arnaud

Daniel Fetchinson

unread,
Jan 9, 2010, 2:01:33 PM1/9/10
to Python

Thanks, this looks pretty simple too, I will go with either Steven's
or with your solution.

Paul Rubin

unread,
Jan 9, 2010, 3:03:16 PM1/9/10
to
Daniel Fetchinson <fetch...@googlemail.com> writes:
> I have a plain text file which I would like to protect in a very
> simple minded, yet for my purposes sufficient, way.

For encrypting strings, use this module:

http://nightsong.com/phr/crypto/p3.py

Obviously this is limited to strings that fit in memory, which
might be a problem with large files. Some day I might get
around to adding a streaming interface to it.

The "file" command will not recognize the ciphertext as encrypted
data. It will just say "data".

If you want to be more serious, use pgp or gpg with the -c option
(password-based encryption). I think "file" does recognize the pgp
file format as encrypted data (RFC 2440).

Paul Rubin

unread,
Jan 9, 2010, 3:04:40 PM1/9/10
to
Daniel Fetchinson <fetch...@googlemail.com> writes:
>> http://www.nightsong.com/phr/crypto/p3.py
>
> Thanks a lot, currently I'm having trouble using this code on python
> 2.6 but probably some small tweaking will fix it.

Yikes, this is the first I've heard of such a problem. I will
look into it. Thanks. (Also thanks to Robert for the recommendation).

Paul Rubin

unread,
Jan 9, 2010, 3:18:33 PM1/9/10
to
Robert Kern <rober...@gmail.com> writes:
> Are you on a 64-bit platform? Unfortunately, array's integer typecodes
> are platform-specific, but p3.py requires a 32-bit integer ...

Oh yes, thanks, I never did get around to dealing with 64 bit platforms.
I also notice that some of the unit test functions use print statements,
which won't compile under Python 3.0. I will try to release a version
in the next few days with fixes for both of these issues.

Nobody

unread,
Jan 10, 2010, 3:33:42 AM1/10/10
to
On Fri, 08 Jan 2010 20:14:51 +0100, Daniel Fetchinson wrote:

> I have a plain text file which I would like to protect in a very
> simple minded, yet for my purposes sufficient, way. I'd like to
> encrypt/convert it into a binary file in such a way that possession of
> a password allows anyone to convert it back into the original text
> file while not possessing the password one would only see the
> following with the standard linux utility 'file':

> What would be the simplest way to achieve this using preferably stock


> python without 3rd party modules? If a not too complex 3rd party
> module made it really simple that would be acceptable too.

RC4 (aka ArcFour) is quite trivial to implement, and better than inventing
your own cipher or using a Vignere:

import itertools

class arcfour:
def __init__(self, key):
self.s = range(256)
self.schedule(map(ord, key))
self.pad = self.prng()

def swap(self, i, j):
self.s[i], self.s[j] = self.s[j], self.s[i]

def schedule(self, key):
j = 0
for i, c in zip(xrange(256), itertools.cycle(key)):
j = (j + self.s[i] + c) % 256
self.swap(i, j)

def prng(self):
i = j = 0
while True:
i = (i + 1) % 256
j = (j + self.s[i]) % 256
self.swap(i, j)
yield self.s[(self.s[i] + self.s[j]) % 256]

def crypt(self, string):
chars = (chr(c ^ r) for c, r in zip(map(ord, string), self.pad))
return ''.join(chars)

I suggest that you don't use the password itself as the key, unless you're
sure that a low-entropy string won't be used. Instead, create an SHA hash
(see the sha and hashlib modules) of the password and use that.

Daniel Fetchinson

unread,
Jan 10, 2010, 3:59:31 AM1/10/10
to pytho...@python.org

Thanks, this looks very simple too, but where is the decryption code?
Wikipedia seems to suggest that encryption and decryption are both the
same but running crypt on the output of crypt doesn't give back the
original string. So probably I'm misunderstanding something.

Steven D'Aprano

unread,
Jan 10, 2010, 10:30:12 AM1/10/10
to
On Sun, 10 Jan 2010 09:59:31 +0100, Daniel Fetchinson wrote:

> Thanks, this looks very simple too, but where is the decryption code?
> Wikipedia seems to suggest that encryption and decryption are both the
> same but running crypt on the output of crypt doesn't give back the
> original string. So probably I'm misunderstanding something.

Yes, the nature of a stream cipher :)

What you're probably doing is what I did, before I had my Aha!!! moment:


>>> arc = arcfour("password")
>>> plaintext = "attack at dawn"
>>> ciphertext = arc.crypt(plaintext)
>>> print plaintext; print ciphertext.encode("hex").upper()
attack at dawn
6371736C6E7C3F495C185629210B
>>> x = arc.crypt(ciphertext)
>>> assert x == plaintext


Traceback (most recent call last):

File "<stdin>", line 1, in <module>
AssertionError
>>> x
'\x16\xf7\xf1\xcc\xda\xb5\xe0\xbf\x0b\x13 bF\x8f'


So what's going on? Consider:

Because Arcfour uses xor for the encryption step, decryption is exactly
the same. So you only need one method to do both.

But because Arcfour stores state, calling it twice in a row doesn't give
the same result:

>>> arc.crypt("hello").encode("hex").upper()
'CAA48DE953'
>>> arc.crypt("hello").encode("hex").upper()
'03405412CA'


Arcfour is a stream cipher. When you call it twice on two different
strings, that is logically equivalent to calling it once on a single long
string made up of concatenating the two strings together. Each time you
encrypt a single character, the internal state ("self.s") changes. To
undo the change, you need the same state. The easiest way to do this is
by creating a new instance:


>>> encrypter = arcfour("password")
>>> decrypter = arcfour("password")
>>> plaintext = "attack at dawn"
>>> ciphertext = encrypter.crypt(plaintext)
>>> assert decrypter.crypt(ciphertext) == plaintext
>>>


So long as the two instances stay in lock-step (every time you use up a
byte from the keystream in one, you do the same in the other) you can use
one to decrypt the output of the other. It doesn't even really matter
which one you use:

>>> x = decrypter.crypt("Nobody expects the Spanish Inquisition!!!")
>>> encrypter.crypt(x)
'Nobody expects the Spanish Inquisition!!!'


In summary: use the arcfour class to create a stream. If you are just
encrypting, or just decrypting, you can use one stream, or as many
streams as you like, using different keys. But to do both, you need two
streams, initiated with the same key, and kept in lockstep.

The advantage of a stream cipher is that you can encrypt a text without
needing all the text at once, and then decrypt it the same way:

>>> output = []
>>> output.append(encrypt.crypt("abcdefghi"))
>>> output.append(encrypt.crypt("jklmno"))
>>> output.append(encrypt.crypt("p"))
>>> output.append(encrypt.crypt("qrstuvwxyz"))
>>> output = ''.join(output)
>>>
>>> plain = []
>>> plain.append(decrypt.crypt(output[0:20]))
>>> plain.append(decrypt.crypt(output[20:24]))
>>> plain.append(decrypt.crypt(output[24:]))
>>> ''.join(plain)
'abcdefghijklmnopqrstuvwxyz'

--
Steven

Nobody

unread,
Jan 10, 2010, 11:20:45 AM1/10/10
to
On Sun, 10 Jan 2010 09:59:31 +0100, Daniel Fetchinson wrote:

> Thanks, this looks very simple too, but where is the decryption code?
> Wikipedia seems to suggest that encryption and decryption are both the
> same but running crypt on the output of crypt doesn't give back the
> original string. So probably I'm misunderstanding something.

The encryption is stateful (it wouldn't be very good if it wasn't), so you
need to create and initialise a new arcfour instance for decryption; you
can't re-use the existing instance.

Nobody

unread,
Jan 10, 2010, 11:24:53 AM1/10/10
to
On Sun, 10 Jan 2010 15:30:12 +0000, Steven D'Aprano wrote:

>> Thanks, this looks very simple too, but where is the decryption code?
>> Wikipedia seems to suggest that encryption and decryption are both the
>> same but running crypt on the output of crypt doesn't give back the
>> original string. So probably I'm misunderstanding something.
>
> Yes, the nature of a stream cipher :)

It isn't limited to stream ciphers. You would have the same issue for
a block cipher with chaining (i.e. *not* ECB mode).


Daniel Fetchinson

unread,
Jan 10, 2010, 11:48:02 AM1/10/10
to Python


Thanks Steven, this was very helpful!

Paul Rubin

unread,
Jan 10, 2010, 11:54:51 AM1/10/10
to
Nobody <nob...@nowhere.com> writes:
> RC4 (aka ArcFour) is quite trivial to implement, and better than inventing
> your own cipher or using a Vignere: ...

That's a cute implementation, but it has no authentication and doesn't
include any randomness, which means if you use the same key for two
inputs, there is a security failure (xor'ing the two ciphertexts reveals
the xor of the plaintexts). It also looks rather slow. I don't make
any guarantees about p3.py, but it has been reviewed by several experts
and appears to be reasonably sound for the type of casual use being
discussed here, and it is tuned for speed (given the implementation
constraints). For more demanding purposes, you should use a more
serious library like one of the OpenSSL wrappers.

geremy condra

unread,
Jan 10, 2010, 2:59:52 PM1/10/10
to Daniel Fetchinson, Python
Not sure why in the world you would homebrew something like this- a
small dependency isn't that bad, and aes can be pretty simple to use.
Might as well go for the industrial strength approach.

Geremy Condra

Paul Rubin

unread,
Jan 10, 2010, 3:26:05 PM1/10/10
to

In my experience, 1) small dependencies ARE that bad, since they mean
you have to develop and test on every platform that you want your code
to run on; 2) using a serious library requires quite a bit of knowledge
and decision-making which not everyone is equipped to do. "AES" is not
so simple to use unless you know what you're doing in terms of modes,
nonces, etc. Having supported this kind of package in a commercial
setting in the past, IMO, for the sort of (common) application in
question, it's best to keep things as simple as possible and supply a
single interface that provides encryption, authentication, and random
initialization all in one call. The cost is a little bit of ciphertext
bloat, but it prevents all kinds of security failures frequently
overlooked by novices.

I'd like it a lot if the Python stdlib could include a serious
cryptography module. That was rejected for regulatory reasons several
years ago, but maybe things are changing enough that the issue can be
revisited sometime.

Nobody

unread,
Jan 10, 2010, 10:36:17 PM1/10/10
to
On Sun, 10 Jan 2010 08:54:51 -0800, Paul Rubin wrote:

> Nobody <nob...@nowhere.com> writes:
>> RC4 (aka ArcFour) is quite trivial to implement, and better than inventing
>> your own cipher or using a Vignere: ...
>
> That's a cute implementation, but it has no authentication and doesn't
> include any randomness, which means if you use the same key for two
> inputs, there is a security failure (xor'ing the two ciphertexts reveals
> the xor of the plaintexts).

Right. RC4 is a cipher, not a cryptosystem.

But, yeah, the OP needs to be aware of the difference (and probably isn't,
yet). So to take that a step further ...

The key passed to arcfour.schedule() shouldn't be re-used. If you need to
encrypt multiple files, use a different key for each. If you want to
encrypt multiple files with the same "password", generate a unique key by
hashing a combination of the password and a random salt (e.g. from
/dev/random), and prepend the salt to the beginning of the stream. To
decrypt, extract the salt from the stream to generate the key.

If you need to verify the data, append a hash of the ciphertext (a hash
of the plaintext would allow an attacker to confirm a guessed plaintext
or to confirm that two files contain the same plaintext). Stream ciphers
are vulnerable to replacement attacks:

(p1 xor r) xor (p1 xor p2) == (p2 xor r)

So if you can guess any part of the plaintext p1, you can replace it with
alternative plaintext p2 without needing to decrypt/encrypt or knowing
anything about the pad r.

Also, if this is for something important, I'd be concerned about how to
protect the key. That's hard enough to do in C, let alone in Python.

> It also looks rather slow.

Any kind of bulk binary data processing in pure Python is slow. The code
was written mainly for simplicity, e.g. using generators means that you
don't have to deal with buffer sizes. Replacing " % 256" with " & 255"
might be worthwhile.

> I don't make
> any guarantees about p3.py, but it has been reviewed by several experts
> and appears to be reasonably sound for the type of casual use being
> discussed here, and it is tuned for speed (given the implementation
> constraints). For more demanding purposes, you should use a more
> serious library like one of the OpenSSL wrappers.

The OP specifically wanted to avoid third-party libraries.

Nobody

unread,
Jan 10, 2010, 10:44:26 PM1/10/10
to
On Sun, 10 Jan 2010 12:26:05 -0800, Paul Rubin wrote:

> I'd like it a lot if the Python stdlib could include a serious
> cryptography module.

And I'd like a truckload of gold ;)

Right now, even asking for HTTPS support is too much to ask. Heck,
even asking for the fake HTTPS support to be identified as such is too
much, apparently.

Steve Holden

unread,
Jan 10, 2010, 10:52:24 PM1/10/10
to pytho...@python.org
No, Paul, nobody will complain if you *ask* ...

A question I've been asking myself quite a lot recently is how the PSF
could, were funding to be available, direct the development of Python in
specific directions, and what those directions should be. Unfortunately
there are probably as many answers as Python programmers in terms of the
priorities to be adopted.

regards
Steve
--
Steve Holden +1 571 484 6266 +1 800 494 3119
PyCon is coming! Atlanta, Feb 2010 http://us.pycon.org/
Holden Web LLC http://www.holdenweb.com/
UPCOMING EVENTS: http://holdenweb.eventbrite.com/

Paul Rubin

unread,
Jan 10, 2010, 11:22:50 PM1/10/10
to
Steve Holden <st...@holdenweb.com> writes:
>> Right now, even asking for HTTPS support is too much to ask. Heck,
>> even asking for the fake HTTPS support to be identified as such is too
>> much, apparently.
>>
> No, Paul, nobody will complain if you *ask* ...

Er, that wasn't me...

> A question I've been asking myself quite a lot recently is how the PSF
> could, were funding to be available, direct the development of Python in

> specific directions,...

Crypto in the stdlib is not a matter of funding or (technical)
priorities. It's a policy issue; the maintainers were (at least as of a
few years ago) concerned about legal restrictions on crypto in some
jurisdictions causing problems with distributing Python if it included
crypto. I know that other systems (Java, Mozilla, etc) include crypto
but they may have had to jump through some hoops for that purpose.

Paul Rubin

unread,
Jan 10, 2010, 11:27:55 PM1/10/10
to
Nobody <nob...@nowhere.com> writes:

> But, yeah, the OP needs to be aware of the difference (and probably isn't,
> yet). So to take that a step further ...

> The key passed to arcfour.schedule() shouldn't be re-used....
> If you need to verify the data, append a hash of the ciphertext ...


> If you want to encrypt multiple files with the same "password",
> generate a unique key by hashing a combination of the password and a

> random salt (e.g. from /dev/random)...

Yep, a whole lot of stuff that's easy to get wrong if it's left to the
user (for example, you mean "a MAC of the ciphertext", not "a hash of
the ciphertext"), and a lot of extra work even if the user gets it
right. It's simplest for the library to provide a single interface that
does all of it.

>> It also looks rather slow.
>
> Any kind of bulk binary data processing in pure Python is slow.

Well, slow is a relative term, but p3.py is about 5x faster than the
fastest pure-Python rc4 implementation that I compared it to. Its
heavy lifting is done by the SHA and array modules, that are written in C.

Steve Holden

unread,
Jan 10, 2010, 11:57:41 PM1/10/10
to pytho...@python.org
Paul Rubin wrote:
> Steve Holden <st...@holdenweb.com> writes:
>>> Right now, even asking for HTTPS support is too much to ask. Heck,
>>> even asking for the fake HTTPS support to be identified as such is too
>>> much, apparently.
>>>
>> No, Paul, nobody will complain if you *ask* ...
>
> Er, that wasn't me...
>
Oh sorry, no more it was.

>> A question I've been asking myself quite a lot recently is how the PSF
>> could, were funding to be available, direct the development of Python in
>> specific directions,...
>
> Crypto in the stdlib is not a matter of funding or (technical)
> priorities. It's a policy issue; the maintainers were (at least as of a
> few years ago) concerned about legal restrictions on crypto in some
> jurisdictions causing problems with distributing Python if it included
> crypto. I know that other systems (Java, Mozilla, etc) include crypto
> but they may have had to jump through some hoops for that purpose.
>

There are administrative hoops to jump through still in the US to export
cryptographic code. Further, if the standard distribution were to
include it then the requirements of the US government do still come into
play, and it would be a pain to have to have people downloading the
software certify (for example) that they weren't intending to re-export
it to a "prohibited" country.

We can get around some of these issues by retaining the hosting on
mainland Europe rather than in the USA, but these issues do demand
careful study which apparently nobody really has time for at present.

Carl Banks

unread,
Jan 11, 2010, 12:21:14 AM1/11/10
to
On Jan 8, 11:14 am, Daniel Fetchinson <fetchin...@googlemail.com>
wrote:

> I have a plain text file which I would like to protect in a very
> simple minded, yet for my purposes sufficient, way. I'd like to
> encrypt/convert it into a binary file in such a way that possession of
> a password allows anyone to convert it back into the original text
> file while not possessing the password one would only see the
> following with the standard linux utility 'file':
>
> [fetchinson@fetch ~]$ file encrypted.data
> encrypted.data: data
>
> and the effort required to convert the file back to the original text
> file without the password would be equivalent to guessing the
> password.


gpg -c simpletextfile.txt -o simpletextfile.gpg

But I guess you can't depend on users to have gpg installed so you
have to roll out some unvetted Python tool.


Carl Banks

geremy condra

unread,
Jan 11, 2010, 12:31:23 AM1/11/10
to pytho...@python.org
On Sun, Jan 10, 2010 at 3:26 PM, Paul Rubin <no.e...@nospam.invalid> wrote:
> geremy condra <deba...@gmail.com> writes:
>> Not sure why in the world you would homebrew something like this- a
>> small dependency isn't that bad, and aes can be pretty simple to use.
>> Might as well go for the industrial strength approach.
>
> In my experience, 1) small dependencies ARE that bad, since they mean
> you have to develop and test on every platform that you want your code
> to run on;

And having no dependencies frees you from the burden of testing
where your software will be deployed? I don't think so.

> 2) using a serious library requires quite a bit of knowledge
> and decision-making which not everyone is equipped to do.

Homebrewing is not a good solution to the problem of being
ignorant of modern cryptography.

> "AES" is not so simple to use unless you know what you're doing in
> terms of modes, nonces, etc.

Seems pretty simple to me- use AES 192, don't use ECB mode, and
use your library of choice's key strengthening utilities. Even blatantly
ignoring that advice would still probably give you better results than
homebrewing though, so I don't really see the issue here.

> Having supported this kind of package in a commercial
> setting in the past, IMO, for the sort of (common) application in
> question, it's best to keep things as simple as possible and supply a
> single interface that provides encryption, authentication, and random
> initialization all in one call.  The cost is a little bit of ciphertext
> bloat, but it prevents all kinds of security failures frequently
> overlooked by novices.
>
> I'd like it a lot if the Python stdlib could include a serious
> cryptography module.  That was rejected for regulatory reasons several
> years ago, but maybe things are changing enough that the issue can be
> revisited sometime.

I agree. I inquired about it not too long ago on python-ideas; little
serious discussion ensued.

Geremy Condra

Steve Holden

unread,
Jan 11, 2010, 12:54:04 AM1/11/10
to pytho...@python.org
The OP's statement of requirements would be pretty much satisfied by the
"crypt" utility. He can even run it under Cygwin on Windows if
necessary. Cryptographic sophistication (or even cryptographic security)
was not requested (and would not be provided anyway by most of the
suggested solutions).

If any real protection is required then an ad-hoc program is definitely
not the way to provide it.

Paul Rubin

unread,
Jan 11, 2010, 4:56:36 AM1/11/10
to
geremy condra <deba...@gmail.com> writes:
> And having no dependencies frees you from the burden of testing
> where your software will be deployed? I don't think so.

If you just use the stdlib and are a bit careful about OS dependent
features, your code can run pretty much everywhere. More to the point,
if (say) you develop a pure Python app on Linux and a Windows user
reports a problem, you can probably straighten it out without having to
actually use a Windows development system. If you need C extensions you
need Windows compilers.

>> 2) using a serious library requires quite a bit of knowledge
>> and decision-making which not everyone is equipped to do.
>
> Homebrewing is not a good solution to the problem of being
> ignorant of modern cryptography.

Not sure what you're getting at. If you're referring to p3.py as a
homebrew algorithm designed by someone ignorant, I don't think that is
accurate. I've been a fulltime crypto developer, and p3.py was reviewed
by several experts on sci.crypt who all felt that its design is sound.
I don't claim it's suitable for high-value data (stick with something
standards-conformant for that) but it was designed as a replacement for
the now-defunct rotor module, and is just about certainly better in
every regard. Its only cryptographic assumption is that SHA1(key+X) is
a pseudorandom function for fixed length X. That is not a certified
characteristic of SHA1, but the HMAC standard (RFC 2104) is based on the
same assumption (see Krawczyk's paper cited in the RFC). I'd go as far
as to say that it is just about certainly better than RC4, which has
well-known distinguishers of quite low complexity.

>> "AES" is not so simple to use unless you know what you're doing in
>> terms of modes, nonces, etc.
>
> Seems pretty simple to me- use AES 192, don't use ECB mode, and
> use your library of choice's key strengthening utilities.

That does not address any questions of authentication, ciphertext
malleability, IV generation, etc. p3.py handles all of that with no
fuss imposed on the user. Really, p3.py was written because the same
basic desire (simple, pure-Python encryption) kept coming up over and
over in my own code and others', and it really seems to address the
constraints about as well as anything I've been able to think of.

Robert Kern

unread,
Jan 11, 2010, 11:44:10 AM1/11/10
to pytho...@python.org
On 2010-01-09 03:52 AM, Anthra Norell wrote:

> Daniel Fetchinson wrote:
> > I have a plain text file which I would like to protect in a very
> > simple minded, yet for my purposes sufficient, way. I'd like to
> > encrypt/convert it into a binary file in such a way that possession of
> > a password allows anyone to convert it back into the original text
> > file while not possessing the password one would only see the
> > following with the standard linux utility 'file':
> >
> > [fetchinson@fetch ~]$ file encrypted.data
> > encrypted.data: data
> >
> > and the effort required to convert the file back to the original text
> > file without the password would be equivalent to guessing the
> > password.
> >
> > I'm fully aware of the security implications of this loose
> > specification, but for my purposes this would be a good solution.
> >
> > What would be the simplest way to achieve this using preferably stock
> > python without 3rd party modules? If a not too complex 3rd part
> > module made it really simple that would be acceptable too.
>
> Daniel,
>
> Here's what looks like another thread veering off into package-ology,
> leaving a stumped OP behind.
>
> "Don't use a random generator for encryption purposes!" warns the
> manual, of which fact I was reminded in no uncertain terms on this forum
> a few years ago when I proposed the following little routine in response
> to a post very similar to yours. One critic challenged me to encode my
> credit card data and post it. Which I did.

Actually, you just "encrypted" your credit card number and challenged
comp.lang.python to crack it. No one challenged you to do anything of the sort.
Fortunately, the ever-watchful eye of Google was upon us that day:

http://groups.google.com/group/comp.lang.python/browse_thread/thread/5fb9ffada975bae9?pli=1

> Upon which another critic
> conjured up the horror vision of gigahertzes hacking my pathetic little
> effort to pieces as I was reading his message. Of the well-meaning kind,
> he urged me to put an immediate stop to this foolishness. I didn't.
>
> No unplanned expenditures ensued.

That's because comp.lang.python is not full of thieves, not because your
algorithm is worth a damn.

p3.py imposes no more overhead than this, but it has some real security
properties. To quote Paul Rubin from that previous thread:

"""
Since good encryption schemes that don't have significant performance
penalties are widely available, why mess with a crap scheme EVER? Why
use a solution that "might or might not be adequate" when you can use
one that's definitely ok?
"""

--
Robert Kern

"I have come to believe that the whole world is an enigma, a harmless enigma
that is made terrible by our own mad attempt to interpret it as though it had
an underlying truth."
-- Umberto Eco

Anthra Norell

unread,
Jan 11, 2010, 3:09:43 PM1/11/10
to pytho...@python.org
My dear Robert. Thank you for the clarification. You are right. The
thread recorded by Google doesn't mention the credit card detail. I
remember it distinctly, though. I also remember that it wasn't my idea.
And I recall being urged by another, well-mannered, member of this group
to call it off right away. He wrote--I pretty much quote: "...there must
be a number of machines out there grinding away at your code right
now!"

>> Upon which another critic
>> conjured up the horror vision of gigahertzes hacking my pathetic little
>> effort to pieces as I was reading his message. Of the well-meaning kind,
>> he urged me to put an immediate stop to this foolishness. I didn't.
>>
>> No unplanned expenditures ensued.
>
> That's because comp.lang.python is not full of thieves, not because
> your algorithm is worth a damn.

You're right about the thieves. You have a point about my algorithm,
although you might express it in a fashion that lives up to its merits.
My algorithm would not resist a brute-force attack that iterates through
all possible keys and analyzes the outcome for non-randomness. I knew
that then and so I posted a second-level encryption, that is, an
encryption of an encryption. Thus the brute-force attack wouldn't find
anything non-random. By not disclosing the detail I may have breached
some formal rule of the craft. If I had disclosed it, I have my doubts
that the processing power available at a sensible cost would have done
the job. The keys I said I used were long integers. There are roughly
4.3 billion of them. Cycling through all of them would surely take a
considerable number of hours on a PC. If each one of the 4.3 billion
top-level decryptions required another bottom-level run many hours long,
the chances of cracking the code before dying of old age are very, very,
very remote.
I may be wrong about that. If you know better, your knowledge
would serve the community a lot better than your ill temper.


>
> p3.py imposes no more overhead than this, but it has some real
> security properties. To quote Paul Rubin from that previous thread:
>
> """
> Since good encryption schemes that don't have significant performance
> penalties are widely available, why mess with a crap scheme EVER? Why
> use a solution that "might or might not be adequate" when you can use
> one that's definitely ok?
> """
>

Excellent point!

Why EVER make anything yourself when you can buy it?

Another excellent point!


Cheers

Frederic

Paul Rubin

unread,
Jan 11, 2010, 3:28:08 PM1/11/10
to
Anthra Norell <anthra...@bluewin.ch> writes:
> Why EVER make anything yourself when you can buy it?

http://en.wikipedia.org/wiki/Dunning-Kruger_effect

John Bokma

unread,
Jan 11, 2010, 4:30:44 PM1/11/10
to
Anthra Norell <anthra...@bluewin.ch> writes:

> Why EVER make anything yourself when you can buy it?

Do you make your own processors? Your own hard disk drives?
Why not?

--
John Bokma

Read my blog: http://johnbokma.com/
Hire me (Perl/Python): http://castleamber.com/

Robert Kern

unread,
Jan 11, 2010, 5:49:30 PM1/11/10
to pytho...@python.org
On 2010-01-11 14:09 PM, Anthra Norell wrote:
> Robert Kern wrote:
>> On 2010-01-09 03:52 AM, Anthra Norell wrote:

>>> "Don't use a random generator for encryption purposes!" warns the
>>> manual, of which fact I was reminded in no uncertain terms on this forum
>>> a few years ago when I proposed the following little routine in response
>>> to a post very similar to yours. One critic challenged me to encode my
>>> credit card data and post it. Which I did.
>>
>> Actually, you just "encrypted" your credit card number and challenged
>> comp.lang.python to crack it. No one challenged you to do anything of
>> the sort. Fortunately, the ever-watchful eye of Google was upon us
>> that day:
>>
>> http://groups.google.com/group/comp.lang.python/browse_thread/thread/5fb9ffada975bae9?pli=1
>>
> My dear Robert. Thank you for the clarification. You are right. The
> thread recorded by Google doesn't mention the credit card detail. I
> remember it distinctly, though. I also remember that it wasn't my idea.
> And I recall being urged by another, well-mannered, member of this group
> to call it off right away. He wrote--I pretty much quote: "...there must
> be a number of machines out there grinding away at your code right now!"

You are probably remembering James Stroud's post, but it came in response to
your challenge.

http://www.opensubscriber.com/message/pytho...@python.org/1393006.html

>>> Upon which another critic
>>> conjured up the horror vision of gigahertzes hacking my pathetic little
>>> effort to pieces as I was reading his message. Of the well-meaning kind,
>>> he urged me to put an immediate stop to this foolishness. I didn't.
>>>
>>> No unplanned expenditures ensued.
>>
>> That's because comp.lang.python is not full of thieves, not because
>> your algorithm is worth a damn.
>
> You're right about the thieves. You have a point about my algorithm,
> although you might express it in a fashion that lives up to its merits.
> My algorithm would not resist a brute-force attack that iterates through
> all possible keys and analyzes the outcome for non-randomness. I knew
> that then and so I posted a second-level encryption, that is, an
> encryption of an encryption. Thus the brute-force attack wouldn't find
> anything non-random. By not disclosing the detail I may have breached
> some formal rule of the craft.

So, you're saying that you lied about the encryption algorithm used in your
challenge. USENET has no (or very few) formal rules for you to breach, but lying
certainly isn't ethical behavior. Honestly, it's okay to not be a good
cryptographer. I'm not. But it is very much not okay to be a liar.

Paul Rubin

unread,
Jan 11, 2010, 6:00:44 PM1/11/10
to
John Bokma <jo...@castleamber.com> writes:
>> Why EVER make anything yourself when you can buy it?
>
> Do you make your own processors? Your own hard disk drives?
> Why not?

Well, if you try to make your own processors or hard drives, worst
normal outcome is they don't work and you try something else instead.
This is more like making your own cancer drugs.

John Bokma

unread,
Jan 11, 2010, 6:19:11 PM1/11/10
to
Paul Rubin <no.e...@nospam.invalid> writes:

As someone who has made his own processor /upgrade/ [1] I can assure you
that can get hurt (or others) by doing so (exploding tantalum
capacitor) ;-)

[1] ARM 3 upgrade for an Archimedes A310.

Anthra Norell

unread,
Jan 12, 2010, 6:59:04 AM1/12/10
to pytho...@python.org
I am not a bad cryptographer. I am not a cryptographer. A liar? Your
judgment is evidence of a commendable broad-mindedness that complements
computer science with psychology, even ethics, as fields of interest. If
I may suggest, take your fields of interest other than computer science
to the more responsive audiences of respective interest groups. You may
try www.justrage.com for a starter. Also find some reference reading at
http://www.cnn.com/2008/TECH/11/03/angry.internet/index.html and at
http://www.recovery-man.com/abusive/rage_vs_anger.htm. On my part I
would offer you this quote by...I forget whom: You can't sling mud
without soiling yourself. And if you sling at someone out of range,
you're the only one getting dirty.
Isn't it unfortunate that Robert Kern the ethicist takes the stage
with a contribution totally irrelevant on this forum, let alone to the
OP's question, and thus crowds out Robert Kern the cryptographer who
could comment on a much more relevant matter, namely my--possibly rash,
so what?--conjecture that any brute-force key-guessing attack can be
foiled by stacking a number of encryptions sufficient to keep the
fastest super computer busy until the sun goes out five billion years
from now. It doesn't take all that many. The way I understand it the
encoding time, the keyed decoding time and the size of the key data grow
linearly with the number of encryption levels, whereas the
brute-force-decoding time grows exponentially. Right?
I finally would point out that my proposals have always been
attempts to solve the posted problem, no less, no more. I therefore
consider any criticism to miss the point if it judges the proposal by
criteria that transcend the posted problem. You'll recall that the
problem is now, and was then, a simple encryption scheme for private
use. Private use excludes malicious attacks and so immunity against them
is not an applicable quality criterion.

Regards

Frederic

Robert Kern

unread,
Jan 12, 2010, 11:09:33 AM1/12/10
to pytho...@python.org

Yes, being ethical is an interest of mine. It should be yours, too.

> Isn't it unfortunate that Robert Kern the ethicist takes the stage with
> a contribution totally irrelevant on this forum, let alone to the OP's
> question, and thus crowds out Robert Kern the cryptographer who could
> comment on a much more relevant matter, namely my--possibly rash, so
> what?--conjecture that any brute-force key-guessing attack can be foiled
> by stacking a number of encryptions sufficient to keep the fastest super
> computer busy until the sun goes out five billion years from now. It
> doesn't take all that many. The way I understand it the encoding time,
> the keyed decoding time and the size of the key data grow linearly with
> the number of encryption levels, whereas the brute-force-decoding time
> grows exponentially. Right?

This is uncontroversial. It is one reason why the DES algorithm was repeated
thrice to make the algorithm 3DES. However, it is not especially relevant. The
point is that you are claiming this group's nonresponse to your challenge as
evidence that it is strong. What's more, it turns out that you lied about the
algorithm you used in the challenge. That undermines your claim drastically.
Since your claim is targeted at convincing the OP to choose your algorithm over
other choices that are better in every way, refuting your claim is necessarily
on-topic. I didn't want to discredit you by calling you a liar, but you exposed
yourself as one.

However, brute force key searching isn't why we think your algorithm is weak (or
rather, the low key size from your originally stated algorithm was one reason,
but it was hardly the most striking reason). You are using a linear random
number generator in a mode that is susceptible to a number of standard attacks.
It fails to have a number of properties that are necessary in an encryption
system. One can break your algorithm with less computation than is necessary for
brute force search. Repeating the algorithm many times will not increase the
time necessary to break your repeated algorithm exponentially.

It is important that the OP understands this, and that your claims do not go
unchallenged.

> I finally would point out that my proposals have always been attempts to
> solve the posted problem, no less, no more. I therefore consider any
> criticism to miss the point if it judges the proposal by criteria that
> transcend the posted problem. You'll recall that the problem is now, and
> was then, a simple encryption scheme for private use. Private use
> excludes malicious attacks and so immunity against them is not an
> applicable quality criterion.

Encryption is *always* about preventing malicious attacks. If you had called
your algorithm a "no-security obfuscation algorithm", I wouldn't have much
problem with it (although a real encryption algorithm like p3.py is also
strictly better for obfuscation, too). I do have a problem with people claiming
"unbreakable encryption" when it has been demonstrated to be false.

Words have meanings, and your words claim far too much. It's possible that you
do not mean to claim so much, but you would then need to change your language.
The reason that this is so important is that the OP necessarily cannot give you
all of the information about his use case in a short post to comp.lang.python.
How do you know that he won't be subject to malicious attacks? You cannot make
this judgment for him. But you can describe your algorithm correctly. Calling an
algorithm an "unbroken encryption algorithm" (let's ignore your claim of
"unbreakable" for now) means a whole bunch of things, the most important of
which is that attacks on the algorithm don't take less time than searching the
entire key space.

If the OP uses a real encryption algorithm, he can rely on the fact that he can
use the algorithm for large files or for plaintexts that a malicious agent might
choose even if he did not communicate (or even know about!) those needs at the
time. He cannot rely on those features with your algorithm, but you do not
reveal those limitations of your algorithm. You simply assumed that the OP could
deal with those limitations, and that does him a disservice.

Steve Holden

unread,
Jan 12, 2010, 12:53:42 PM1/12/10
to pytho...@python.org
Robert Kern wrote:
> On 2010-01-12 05:59 AM, Anthra Norell wrote:
[ping, pong, ping, pong]

> If the OP uses a real encryption algorithm, he can rely on the fact that
> he can use the algorithm for large files or for plaintexts that a
> malicious agent might choose even if he did not communicate (or even
> know about!) those needs at the time. He cannot rely on those features
> with your algorithm, but you do not reveal those limitations of your
> algorithm. You simply assumed that the OP could deal with those
> limitations, and that does him a disservice.
>
The fact that much hogwash is spoken about encryption through ignorance
is underlined today by the reactions to reports that a team of German
computer scientists have cracked a message encrypted with RSA using a
768-bit key.

http://www.out-law.com//default.aspx?page=10659

The general tenor of these ill-informed responses is along the lines of
"we will soon have to use biometrics or PINs as an additional layer of
protection". This is baloney, pure and simple. If no cryptographic
weaknesses have been demonstrated in the algorithms then the simple
solution (and one that Moore's Law and the rise of multiprocessor
hardware adequately supports) is to use longer keys. 2,048-bit RSA will
be secure at least for my lifetime, unless startling developments come
along in quantum computing.

Biometric and PIN-based access control systems are demonstrably easier
to break than 768-bit encryption, which has just been done for a single
message in something like two years with the aid of a large number of
computers and a brute-force attack. They can also be subverted, which is
rather more difficult for a cryptosystem with properly-protected private
keys.

Just the same, people continue to make exaggerated claims for "crypto"
systems that have not been subjected to cryptanalysis. This behavior is
unlikely to change, so you will probably be happier allowing such
people (who are legion) their delusions.

Anthra Norell

unread,
Jan 12, 2010, 5:38:31 PM1/12/10
to pytho...@python.org
Robert Kern wrote:
> On 2010-01-12 05:59 AM, Anthra Norell wrote:

> If the OP uses a real encryption algorithm, he can rely on the fact
> that he can use the algorithm for large files or for plaintexts that a
> malicious agent might choose even if he did not communicate (or even
> know about!) those needs at the time. He cannot rely on those features
> with your algorithm, but you do not reveal those limitations of your
> algorithm. You simply assumed that the OP could deal with those
> limitations, and that does him a disservice.
>

Robert,
let's stop this nonsense. If you don't, I certainly will. You take me
to the task for intentions you invent for the purpose, like claiming
this or that. I don't claim anything, least of all the supremacy of my
proposal. The idea of it! If someone else makes a better proposal I'd be
the idiot you crave to make me look if I denied the fact. This is an
interest group, not a religion with a clergy devoted to keeping heresies
at bay. In my perception of an interest group, everyone's contribution
is welcome and the common benefit results from the discussions of those
contributions, absolutely none of which comes with a warranty, as
absolutely no poster deems himself infallible and no OP expects it. Your
accusation I was abusing the confidence of an OP by representing a sham
as the ultimate solution is so utterly ludicrous that I can let it pass
and that concludes the matter as far as I am concerned.

Frederic

Ethan Furman

unread,
Jan 12, 2010, 11:59:17 AM1/12/10
to pytho...@python.org
Anthra Norell wrote:

> I consider the encryption unbreakable [...] (from previous thread)

> I am not a cryptographer. (from this thread)

Then you shouldn't be making claims about your encryption algorithms.


~Ethan~

Aahz

unread,
Jan 18, 2010, 2:45:59 PM1/18/10
to
In article <mailman.691.12630339...@python.org>,
Daniel Fetchinson <fetch...@googlemail.com> wrote:
>
>Well, that's sort of true about learning a complex API :) But it's
>also true that I'm not storing anything really valuable in the file
>but still wouldn't want to leave it lying around in plain text. In
>case I lose the laptop with the file I seriously doubt anybody who
>finds it will go through each and every file and try to find what's in
>it, even though they look like data files and there is no hint what so
>ever that any one of them contains encrypted info. If they see a text
>file, well, that can give them ideas, so let's encrypt a little bit.

One reason I like OSX is that it's dirt-simple to encrypt my home dir.
--
Aahz (aa...@pythoncraft.com) <*> http://www.pythoncraft.com/

"If you think it's expensive to hire a professional to do the job, wait
until you hire an amateur." --Red Adair

0 new messages