Is this secure?

M

mk

It might be helpful if you could say what your application does, or
anyway give an idea of what its actual security requirements are.
Generating and emailing someone a random password is a fairly standard
method for (e.g.) web forums to verify that the person has supplied a
working email address, basically as a first level spam filter. Your
scheme is probably ok for that. If you're doing something with more
demanding security requirements, then as mentioned before, there is a
whole lot of stuff you have to pay attention to, and focusing narrowly
on password generation isn't that useful.

OK some data:

1. I'm going to probably use HTTPS (I meant HTTP over SSL, but wrote
HTTP instead of being precise)

2. The app will have GUI and it will be locally installed; it's not
going to be web app, it will just be online in the sense of downloading
data frequently from the net.

3. I can't disclose the details on what the app will be doing, but it's
not going to be terribly security-critical, medium-level at most - what
happens in the app itself is not _directly_ related to money.

4. The app will be based on subscription model, costing $10-$20 per
month. It's not really doing online banking or smth like that.

5. The worst thing that can happen when security of some account is
compromised is that the user will have to reset the password, resending
it to predefined email (I don't really see the way of organizing it in a
different manner).

I'm thinking about optionally passphrase-securing the password saved in
GUI. In that case 'diceware' approach would be helpful.

I certainly do not want to focus narrowly on password generation: the
entire security model will have to be worked out, but the project didn't
get to that stage yet, it's all still in planning stages. I just wanted
to have this one part (password generation) researched before I get to
other stages so I don't have to implement this later in haste and do
smth wrong.

Regards,
mk
 
R

Robert Kern

2. The app will have GUI and it will be locally installed; it's not
going to be web app, it will just be online in the sense of downloading
data frequently from the net.

If you are storing the password instead of making your user remember it, most
platforms have some kind of keychain secure password storage. I recommend
reading up on the APIs available on your targeted platforms.

--
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
 
S

Steven D'Aprano

Yes. There's no way around this, short of forcing them to use hardware
key, which is an overkill for this application.

Of course there is. Why don't you find out how applications with real
security work, instead of making up amateur insecure schemes or worrying
about insignificant deviations from uniformity in your password generator?

You can't get hold of a user's login password in Linux or Windows by
grabbing the copy-and-paste buffer, or by looking in the password file.
No hardware key required.

Today, you say that your application only needs weak security because the
value of the accounts are low. (If they're that low, why do you need a
password at all?) But tomorrow, your application will be bigger, better,
new and improved, with remote logins over the Internet and much more
value -- and it will still be using the same crappy weak security that it
has now, I guarantee it.

If you are storing the password, instead of a hash, you fail.

If you are storing a hash without a salt, you fail.

Yes, an awful lot of software do these things. They shouldn't, even for
supposed "low value passwords".

http://blog.moertel.com/articles/2006/12/15/never-store-passwords-in-a-database

http://www.codinghorror.com/blog/2007/09/youre-probably-storing-passwords-incorrectly.html

The app is not that critical, it's about quarterly subscription to the
service, and the users will be able to reset the password anyway.

And when users realise that they don't need to buy a subscription, they
just need to steal a password from somebody else, what does that do to
your business model?
 
P

Peter Pearson

I will repeat my advice to just use random.SystemRandom.choice() instead
of trying to interpret the bytes from /dev/urandom directly.

Out of curiosity:

def gen_rand_string(length):
prng = random.SystemRandom()
chars = []
for i in range(length):
chars.append(prng.choice('abcdefghijklmnopqrstuvwxyz'))
return ''.join(chars)

if __name__ == "__main__":
chardict = {}
for i in range(10000):
## w = gen_rand_word(10)
w = gen_rand_string(10)
count_chars(chardict, w)
counts = list(chardict.items())
counts.sort(key = operator.itemgetter(1), reverse = True)
for char, count in counts:
print char, count


s 3966
d 3912
g 3909
h 3905
a 3901
u 3900
q 3891
m 3888
k 3884
b 3878
x 3875
v 3867
w 3864
y 3851
l 3825
z 3821
c 3819
e 3819
r 3816
n 3808
o 3797
f 3795
t 3784
p 3765
j 3730
i 3704

Better, although still not perfect.

What would be perfect? Surely one shouldn't be happy if all the
tallies come out exactly equal: that would be a blatant indication
of something very nonrandom going on.

The tallies given above give a chi-squared value smack in the
middle of the range expected for random sampling of a uniform
distribution (p = 0.505). So the chi-squared metric of
goodness-of-fit to a unifom distribution says you're doing fine.
 
P

Peter Pearson

rand_str_SystemRandom_seeding
mean 3845.15384615 std dev 46.2016419186
l 3926 1.75 std devs away from mean
y 3916 1.53 std devs away from mean
d 3909 1.38 std devs away from mean
a 3898 1.14 std devs away from mean
p 3898 1.14 std devs away from mean
c 3889 0.95 std devs away from mean
u 3884 0.84 std devs away from mean
j 3873 0.60 std devs away from mean
n 3873 0.60 std devs away from mean
w 3866 0.45 std devs away from mean
x 3863 0.39 std devs away from mean
r 3855 0.21 std devs away from mean
m 3852 0.15 std devs away from mean
b 3841 -0.09 std devs away from mean
t 3835 -0.22 std devs away from mean
o 3829 -0.35 std devs away from mean
k 3827 -0.39 std devs away from mean
i 3821 -0.52 std devs away from mean
s 3812 -0.72 std devs away from mean
q 3806 -0.85 std devs away from mean
v 3803 -0.91 std devs away from mean
g 3799 -1.00 std devs away from mean
h 3793 -1.13 std devs away from mean
e 3782 -1.37 std devs away from mean
f 3766 -1.71 std devs away from mean
z 3758 -1.89 std devs away from mean

Chi2 = 14.43, 25 d.f., prob = 0.046362.
The observed distribution is SIGNIFICANTLY CLOSER
to the uniform distribution than reasonable by chance.
rand_str_SystemRandom_noseeding
mean 3845.15384615 std dev 55.670522726
i 3961 2.08 std devs away from mean
r 3911 1.18 std devs away from mean
e 3910 1.16 std devs away from mean
m 3905 1.08 std devs away from mean
a 3901 1.00 std devs away from mean
u 3893 0.86 std devs away from mean
t 3882 0.66 std devs away from mean
w 3872 0.48 std devs away from mean
s 3870 0.45 std devs away from mean
c 3868 0.41 std devs away from mean
n 3866 0.37 std devs away from mean
q 3865 0.36 std devs away from mean
k 3863 0.32 std devs away from mean
y 3848 0.05 std devs away from mean
j 3836 -0.16 std devs away from mean
v 3830 -0.27 std devs away from mean
f 3829 -0.29 std devs away from mean
z 3829 -0.29 std devs away from mean
g 3827 -0.33 std devs away from mean
l 3818 -0.49 std devs away from mean
b 3803 -0.76 std devs away from mean
d 3803 -0.76 std devs away from mean
p 3756 -1.60 std devs away from mean
x 3755 -1.62 std devs away from mean
h 3744 -1.82 std devs away from mean
o 3729 -2.09 std devs away from mean

Chi2 = 20.96, 25 d.f., prob = 0.304944.
The observed distribution is not significantly different
from the uniform distribution.
rand_str_custom
mean 3517.15384615 std dev 40.7541336343
i 3586 1.69 std devs away from mean
a 3578 1.49 std devs away from mean
e 3575 1.42 std devs away from mean
m 3570 1.30 std devs away from mean
q 3562 1.10 std devs away from mean
c 3555 0.93 std devs away from mean
g 3552 0.86 std devs away from mean
w 3542 0.61 std devs away from mean
p 3536 0.46 std devs away from mean
x 3533 0.39 std devs away from mean
s 3528 0.27 std devs away from mean
o 3524 0.17 std devs away from mean
d 3516 -0.03 std devs away from mean
t 3515 -0.05 std devs away from mean
h 3511 -0.15 std devs away from mean
v 3502 -0.37 std devs away from mean
z 3502 -0.37 std devs away from mean
b 3500 -0.42 std devs away from mean
f 3496 -0.52 std devs away from mean
u 3492 -0.62 std devs away from mean
l 3486 -0.76 std devs away from mean
r 3478 -0.96 std devs away from mean
n 3476 -1.01 std devs away from mean
j 3451 -1.62 std devs away from mean
k 3450 -1.65 std devs away from mean
y 3430 -2.14 std devs away from mean

Chi2 = 12.28, 25 d.f., prob = 0.015815.
The observed distribution is SIGNIFICANTLY CLOSER
to the uniform distribution than reasonable by chance.
It would appear that SystemRandom().choice is indeed best (in terms of
how much the counts stray from mean in std devs), but only after seeding
it with os.urandom.

I don't see any reason to worry about any of the three, except
perhaps that the first and last are surprisingly uniform.
 
A

Aahz

If you are storing the password instead of making your user remember
it, most platforms have some kind of keychain secure password
storage. I recommend reading up on the APIs available on your targeted
platforms.

Are you sure? I haven't done a lot of research, but my impression was
that Windows didn't have anything built in.
--
Aahz ([email protected]) <*> http://www.pythoncraft.com/

"Many customs in this life persist because they ease friction and promote
productivity as a result of universal agreement, and whether they are
precisely the optimal choices is much less important." --Henry Spencer
 
P

Paul Rubin

Are you sure? I haven't done a lot of research, but my impression was
that Windows didn't have anything built in.

I don't know much about the windows but there is the CAPI and then
there is all the TCPA (i.e. DRM) stuff. Maybe it can be used somehow.
 
R

Robert Kern

Are you sure? I haven't done a lot of research, but my impression was
that Windows didn't have anything built in.

You're right, not built-in, but Windows does provide enough crypto services for
a cross-platform Python implementation to be built:

http://pypi.python.org/pypi/keyring

--
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
 
A

Aahz

You're right, not built-in, but Windows does provide enough crypto
services for a cross-platform Python implementation to be built:

http://pypi.python.org/pypi/keyring

Thanks you! That's a big help!
--
Aahz ([email protected]) <*> http://www.pythoncraft.com/

"Many customs in this life persist because they ease friction and promote
productivity as a result of universal agreement, and whether they are
precisely the optimal choices is much less important." --Henry Spencer
 
L

Lie Ryan

I will repeat my advice to just use random.SystemRandom.choice() instead
of trying to interpret the bytes from /dev/urandom directly.

Out of curiosity:

def gen_rand_string(length):
prng = random.SystemRandom()
chars = []
for i in range(length):
chars.append(prng.choice('abcdefghijklmnopqrstuvwxyz'))
return ''.join(chars)

if __name__ == "__main__":
chardict = {}
for i in range(10000):
## w = gen_rand_word(10)
w = gen_rand_string(10)
count_chars(chardict, w)
counts = list(chardict.items())
counts.sort(key = operator.itemgetter(1), reverse = True)
for char, count in counts:
print char, count


s 3966
d 3912
g 3909
h 3905
a 3901
u 3900
q 3891
m 3888
k 3884
b 3878
x 3875
v 3867
w 3864
y 3851
l 3825
z 3821
c 3819
e 3819
r 3816
n 3808
o 3797
f 3795
t 3784
p 3765
j 3730
i 3704

Better, although still not perfect.

I give you this:

I give you this:

import itertools
def gen():
valid_chars = 'abcdefghijklmnopqrstuvwxyz'
for char in itertools.repeat(valid_chars):
yield char

gen = gen()
def gen_rand_string(length):
chars = (next(gen) for i in range(length))
return ''.join(chars)

since it gives me a perfect distribution of letters, it must be a very
secure random password generation scheme.
 
M

Michael Rudolf

Am 03.03.2010 04:51, schrieb Lie Ryan:
import itertools
def gen():
valid_chars = 'abcdefghijklmnopqrstuvwxyz'
for char in itertools.repeat(valid_chars):
yield char

gen = gen()
def gen_rand_string(length):
chars = (next(gen) for i in range(length))
return ''.join(chars)

since it gives me a perfect distribution of letters,

It does not. Only if not (length(valid_chars) % length)

Regards,
Michael
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Members online

Forum statistics

Threads
474,176
Messages
2,570,950
Members
47,500
Latest member
ArianneJsb

Latest Threads

Top