Groups | Search | Server Info | Keyboard shortcuts | Login | Register [http] [https] [nntp] [nntps]


Groups > comp.lang.python > #32660 > unrolled thread

How to generate account number?

Started byAndriy Kornatskyy <andriy.kornatskyy@live.com>
First post2012-11-03 00:13 +0300
Last post2012-11-03 11:42 +0300
Articles 9 — 5 participants

Back to article view | Back to comp.lang.python


Contents

  How to generate account number? Andriy Kornatskyy <andriy.kornatskyy@live.com> - 2012-11-03 00:13 +0300
    Re: How to generate account number? GangGreene <GangGreene@example.com> - 2012-11-02 18:02 -0400
      RE: How to generate account number? Andriy Kornatskyy <andriy.kornatskyy@live.com> - 2012-11-03 11:38 +0300
        Re: How to generate account number? Roy Smith <roy@panix.com> - 2012-11-03 09:22 -0400
          Re: How to generate account number? Tim Chase <python.list@tim.thechases.com> - 2012-11-03 10:34 -0500
          RE: How to generate account number? Andriy Kornatskyy <andriy.kornatskyy@live.com> - 2012-11-03 19:18 +0300
          RE: How to generate account number? Andriy Kornatskyy <andriy.kornatskyy@live.com> - 2012-11-03 19:23 +0300
    Re: How to generate account number? Steven D'Aprano <steve+comp.lang.python@pearwood.info> - 2012-11-02 22:39 +0000
      RE: How to generate account number? Andriy Kornatskyy <andriy.kornatskyy@live.com> - 2012-11-03 11:42 +0300

#32660 — How to generate account number?

FromAndriy Kornatskyy <andriy.kornatskyy@live.com>
Date2012-11-03 00:13 +0300
SubjectHow to generate account number?
Message-ID<mailman.3220.1351890866.27098.python-list@python.org>
Requirements for `account number` generator:

1. Issue pseudo random consistent number (must be unique for dozen millions of records)
2. Easy check validity (without a need to make a database call)

Interested? Read more here:

http://mindref.blogspot.com/2012/11/generate-account-number.html

Comments or suggestions are welcome.

Thanks.

Andriy Kornatskyy
 		 	   		  

[toc] | [next] | [standalone]


#32667

FromGangGreene <GangGreene@example.com>
Date2012-11-02 18:02 -0400
Message-ID<1gsdm9-r2c.ln1@crazy-horse.bildanet.com>
In reply to#32660
On Sat, 03 Nov 2012 00:13:19 +0300, Andriy Kornatskyy wrote:

> Requirements for `account number` generator:
> 
> 1. Issue pseudo random consistent number (must be unique for dozen
> millions of records)
> 2. Easy check validity (without a need to make a database call)
> 
> Interested? Read more here:
> 
> http://mindref.blogspot.com/2012/11/generate-account-number.html
> 
> Comments or suggestions are welcome.
> 
> Thanks.
> 
> Andriy Kornatskyy

generate sha1sum on the ((key database record(s))+date+timeofday)
Should be unique for billions/trillions of records.

[toc] | [prev] | [next] | [standalone]


#32687

FromAndriy Kornatskyy <andriy.kornatskyy@live.com>
Date2012-11-03 11:38 +0300
Message-ID<mailman.3234.1351931985.27098.python-list@python.org>
In reply to#32667
>>> from hashlib import sha1
>>> sha1('GangGreene-20120203-1012').hexdigest()
'ef764a2fe44532008dc9a99c391c70cd85ec9d82'

It is too long and not verifiable.

>>> from uuid import uuid4

>>> uuid4()

UUID('2c14484b-5a0c-4f4b-b7bc-8187548b4888')

Pretty much the same what you suggest but simpler and shorter. Not quite elegant for humans.

Here are examples per this post:
http://mindref.blogspot.com/2012/11/generate-account-number.html

>>> account_number(1)
'Z05738521581'
>>> account_number(2)
'Z17888279480'
>>> account_number(3)
'Z07395350007'

Short, human readable and satisfy original requirements.

Andriy


----------------------------------------
> From: GangGreene@example.com
> Subject: Re: How to generate account number?
> Date: Fri, 2 Nov 2012 18:02:09 -0400
> To: python-list@python.org
>
> On Sat, 03 Nov 2012 00:13:19 +0300, Andriy Kornatskyy wrote:
>
>> Requirements for `account number` generator:
>>
>> 1. Issue pseudo random consistent number (must be unique for dozen
>> millions of records)
>> 2. Easy check validity (without a need to make a database call)
>>
>> Interested? Read more here:
>>
>> http://mindref.blogspot.com/2012/11/generate-account-number.html
>>
>> Comments or suggestions are welcome.
>>
>> Thanks.
>>
>> Andriy Kornatskyy
>
> generate sha1sum on the ((key database record(s))+date+timeofday)
> Should be unique for billions/trillions of records.
> --
> http://mail.python.org/mailman/listinfo/python-list
 		 	   		  

[toc] | [prev] | [next] | [standalone]


#32695

FromRoy Smith <roy@panix.com>
Date2012-11-03 09:22 -0400
Message-ID<roy-1E6B33.09225503112012@news.panix.com>
In reply to#32687
In article <mailman.3234.1351931985.27098.python-list@python.org>,
 Andriy Kornatskyy <andriy.kornatskyy@live.com> wrote:

> 'Z05738521581'
> 'Z17888279480'
> 'Z07395350007'
> 
> Short, human readable and satisfy original requirements.
> 
> Andriy

If you really want human readable, it's better to chunk the data up into 
3 or 4 digit groups.  So, instead of Z05738521581, maybe 
Z05-738-521-581.  Or perhaps even better, Z05-7385-21-581 (just a hunch, 
but I suspect varying the length of the groups makes it easier to read).

Even better might be base-32 encoding the value.  Strings of digits have 
an information density of about 3.2 bits/char. Base-32 is just about as 
readable, but gives you 5 bits/char, so you end up with a few less 
characters (which you still want to chunk into 3 or 4 character groups).

[toc] | [prev] | [next] | [standalone]


#32699

FromTim Chase <python.list@tim.thechases.com>
Date2012-11-03 10:34 -0500
Message-ID<mailman.3242.1351956818.27098.python-list@python.org>
In reply to#32695
On 11/03/12 08:22, Roy Smith wrote:
> Even better might be base-32 encoding the value.  Strings of
> digits have an information density of about 3.2 bits/char.
> Base-32 is just about as readable, but gives you 5 bits/char, so
> you end up with a few less characters (which you still want to
> chunk into 3 or 4 character groups).

For things that will be read off a screen/paper, I recommend
omitting several letters that are easy to mistake visually:  i/I/l/1
and O/0 in particular.  The VIN (vehicle identification number) on
all US cars avoids these characters[*], making it easier to read
them back without concern for "is that a zero or an oh; and is that
an ell, a one, a lowercase eye, or a capital eye?"  As an encoding
advantage,

>>> print len(''.join(c for c in (string.ascii_uppercase +
string.digits) if c not in "O0iIl1"))
32

the number 32 is pretty handy when dealing with binary :-)

-tkc


[*]
The VIN avoids "Q" too and does use the digits 0/1, but the idea
holds.  Make it easy to ready back.

[toc] | [prev] | [next] | [standalone]


#32702

FromAndriy Kornatskyy <andriy.kornatskyy@live.com>
Date2012-11-03 19:18 +0300
Message-ID<mailman.3244.1351959557.27098.python-list@python.org>
In reply to#32695
Roy,

Per your advise:

>>> from base64 import b32encode
>>> human_format = lambda n: 'Z%s-%s' % (b32encode(chr((n >> 24) & 255) + chr((n >> 16) & 255))[:4], b32encode(chr((n >> 8) & 255) + chr(n & 255))[:4])
>>> human_format(5738521581)
'ZKYFA-4PWQ'
>>> human_format(17888279480)
'ZFI4Q-PO4A'
>>> human_format(7395350007)
'ZXDGA-CX3Q'

Side by side:

Z05738521581 = ZKYFA-4PWQ
Z17888279480 = ZFI4Q-PO4A
Z07395350007 = ZXDGA-CX3Q

Thanks.

Andriy


----------------------------------------
> From: roy@panix.com
> Subject: Re: How to generate account number?
> Date: Sat, 3 Nov 2012 09:22:55 -0400
> To: python-list@python.org
>
> In article <mailman.3234.1351931985.27098.python-list@python.org>,
> Andriy Kornatskyy <andriy.kornatskyy@live.com> wrote:
>
> > 'Z05738521581'
> > 'Z17888279480'
> > 'Z07395350007'
> >
> > Short, human readable and satisfy original requirements.
> >
> > Andriy
>
> If you really want human readable, it's better to chunk the data up into
> 3 or 4 digit groups. So, instead of Z05738521581, maybe
> Z05-738-521-581. Or perhaps even better, Z05-7385-21-581 (just a hunch,
> but I suspect varying the length of the groups makes it easier to read).
>
> Even better might be base-32 encoding the value. Strings of digits have
> an information density of about 3.2 bits/char. Base-32 is just about as
> readable, but gives you 5 bits/char, so you end up with a few less
> characters (which you still want to chunk into 3 or 4 character groups).
> --
> http://mail.python.org/mailman/listinfo/python-list
 		 	   		  

[toc] | [prev] | [next] | [standalone]


#32703

FromAndriy Kornatskyy <andriy.kornatskyy@live.com>
Date2012-11-03 19:23 +0300
Message-ID<mailman.3245.1351959884.27098.python-list@python.org>
In reply to#32695
Tim,

Good point. b32decode seems to be capable to understand such common mistakes (see map01 argument to b32decode), I haven't tried:

http://docs.python.org/2/library/base64.html

Thanks.

Andriy

----------------------------------------
> Date: Sat, 3 Nov 2012 10:34:26 -0500
> From: python.list@tim.thechases.com
> To: roy@panix.com
> Subject: Re: How to generate account number?
> CC: python-list@python.org
>
> On 11/03/12 08:22, Roy Smith wrote:
> > Even better might be base-32 encoding the value. Strings of
> > digits have an information density of about 3.2 bits/char.
> > Base-32 is just about as readable, but gives you 5 bits/char, so
> > you end up with a few less characters (which you still want to
> > chunk into 3 or 4 character groups).
>
> For things that will be read off a screen/paper, I recommend
> omitting several letters that are easy to mistake visually: i/I/l/1
> and O/0 in particular. The VIN (vehicle identification number) on
> all US cars avoids these characters[*], making it easier to read
> them back without concern for "is that a zero or an oh; and is that
> an ell, a one, a lowercase eye, or a capital eye?" As an encoding
> advantage,
>
> >>> print len(''.join(c for c in (string.ascii_uppercase +
> string.digits) if c not in "O0iIl1"))
> 32
>
> the number 32 is pretty handy when dealing with binary :-)
>
> -tkc
>
>
> [*]
> The VIN avoids "Q" too and does use the digits 0/1, but the idea
> holds. Make it easy to ready back.
> --
> http://mail.python.org/mailman/listinfo/python-list
 		 	   		  

[toc] | [prev] | [next] | [standalone]


#32671

FromSteven D'Aprano <steve+comp.lang.python@pearwood.info>
Date2012-11-02 22:39 +0000
Message-ID<50944ba2$0$29967$c3e8da3$5496439d@news.astraweb.com>
In reply to#32660
On Sat, 03 Nov 2012 00:13:19 +0300, Andriy Kornatskyy wrote:

> Requirements for `account number` generator:
> 
> 1. Issue pseudo random consistent number (must be unique for dozen
> millions of records) 

How much randomness do you need? From the perspective of any one user, a 
simple incrementing counter returns arbitrary values, which may be "close 
enough" to random.

last_num = 103872  # Pick an arbitrary starting value.
def get_account_number():
    """Return the next account number."""
    global last_num
    last_num += 1
    return last_num

Stick that value in a database instead of a global, and you're done.

What are the consequences of people guessing account numbers? If the 
consequences are serious, then you need to make account numbers 
cryptographically strong. If the account number alone is not important, 
then you don't.


> 2. Easy check validity (without a need to make a database call)

Add a check digit to the number you generate. There are all sorts of ways 
to do that. Here are two examples:

http://code.activestate.com/recipes/577692
http://code.activestate.com/recipes/577691


> Interested? Read more here:

If you ask a question here, please keep the discussion here, don't split 
it to your personal blog.

Tell us your requirements in more detail, and we will try to help you.


-- 
Steven

[toc] | [prev] | [next] | [standalone]


#32688

FromAndriy Kornatskyy <andriy.kornatskyy@live.com>
Date2012-11-03 11:42 +0300
Message-ID<mailman.3235.1351932226.27098.python-list@python.org>
In reply to#32671
Steven, see below, please.

----------------------------------------
> From: steve+comp.lang.python@pearwood.info
> Subject: Re: How to generate account number?
> Date: Fri, 2 Nov 2012 22:39:31 +0000
> To: python-list@python.org
>
> On Sat, 03 Nov 2012 00:13:19 +0300, Andriy Kornatskyy wrote:
>
>> Requirements for `account number` generator:
>>
>> 1. Issue pseudo random consistent number (must be unique for dozen
>> millions of records)
>
> How much randomness do you need? From the perspective of any one user, a
> simple incrementing counter returns arbitrary values, which may be "close
> enough" to random.
>
> last_num = 103872 # Pick an arbitrary starting value.
> def get_account_number():
> """Return the next account number."""
> global last_num
> last_num += 1
> return last_num
>
> Stick that value in a database instead of a global, and you're done.
>
> What are the consequences of people guessing account numbers? If the
> consequences are serious, then you need to make account numbers
> cryptographically strong. If the account number alone is not important,
> then you don't.

Yes. There are consequences to not use sequential numbers, yet humans deal with it (enter as input somewhere, etc). The approach suggested here:

http://mindref.blogspot.com/2012/11/generate-account-number.html

is using Feistel cipher to generate pseudo random thus makes guessing account numbers hard (impossible?).

>> 2. Easy check validity (without a need to make a database call)
>
> Add a check digit to the number you generate. There are all sorts of ways
> to do that. Here are two examples:
>
> http://code.activestate.com/recipes/577692
> http://code.activestate.com/recipes/577691

These tell me how to verify some code, but doesn't how to generate it. The approach suggested here:

http://mindref.blogspot.com/2012/11/generate-account-number.html

gives you ability to customize `sample_f` function to make it unique to your business case.

>> Interested? Read more here:
>
> If you ask a question here, please keep the discussion here, don't split
> it to your personal blog.

The question was rhetorical with my answer in the blog and discussion here to reach something.

> Tell us your requirements in more detail, and we will try to help you.

I have presented solution to `account number` challenge. So it was share with community and seek for thoughts if any.



 		 	   		  

[toc] | [prev] | [standalone]


Back to top | Article view | comp.lang.python


csiph-web