An interpreted, interactive, object-oriented programming language
CentOS Sources
2017-08-01 71084d584ff953f5463757ec6536406320560b4d
commit | author | age
6e8c2f 1 diff -up Python-2.7.3/Doc/library/crypt.rst.crypt-module-salt-backport Python-2.7.3/Doc/library/crypt.rst
CB 2 --- Python-2.7.3/Doc/library/crypt.rst.crypt-module-salt-backport    2012-04-09 19:07:28.000000000 -0400
3 +++ Python-2.7.3/Doc/library/crypt.rst    2013-02-19 16:44:20.465334062 -0500
4 @@ -16,9 +16,9 @@
5  
6  This module implements an interface to the :manpage:`crypt(3)` routine, which is
7  a one-way hash function based upon a modified DES algorithm; see the Unix man
8 -page for further details.  Possible uses include allowing Python scripts to
9 -accept typed passwords from the user, or attempting to crack Unix passwords with
10 -a dictionary.
11 +page for further details.  Possible uses include storing hashed passwords
12 +so you can check passwords without storing the actual password, or attempting
13 +to crack Unix passwords with a dictionary.
14  
15  .. index:: single: crypt(3)
16  
17 @@ -27,15 +27,81 @@ the :manpage:`crypt(3)` routine in the r
18  extensions available on the current implementation will also  be available on
19  this module.
20  
21 +Hashing Methods
22 +---------------
23  
24 -.. function:: crypt(word, salt)
25 +The :mod:`crypt` module defines the list of hashing methods (not all methods
26 +are available on all platforms):
27 +
28 +.. data:: METHOD_SHA512
29 +
30 +   A Modular Crypt Format method with 16 character salt and 86 character
31 +   hash.  This is the strongest method.
32 +
33 +.. versionadded:: 3.3
34 +
35 +.. data:: METHOD_SHA256
36 +
37 +   Another Modular Crypt Format method with 16 character salt and 43
38 +   character hash.
39 +
40 +.. versionadded:: 3.3
41 +
42 +.. data:: METHOD_MD5
43 +
44 +   Another Modular Crypt Format method with 8 character salt and 22
45 +   character hash.
46 +
47 +.. versionadded:: 3.3
48 +
49 +.. data:: METHOD_CRYPT
50 +
51 +   The traditional method with a 2 character salt and 13 characters of
52 +   hash.  This is the weakest method.
53 +
54 +.. versionadded:: 3.3
55 +
56 +
57 +Module Attributes
58 +-----------------
59 +
60 +
61 +.. attribute:: methods
62 +
63 +   A list of available password hashing algorithms, as
64 +   ``crypt.METHOD_*`` objects.  This list is sorted from strongest to
65 +   weakest, and is guaranteed to have at least ``crypt.METHOD_CRYPT``.
66 +
67 +.. versionadded:: 3.3
68 +
69 +
70 +Module Functions
71 +----------------
72 +
73 +The :mod:`crypt` module defines the following functions:
74 +
75 +.. function:: crypt(word, salt=None)
76  
77     *word* will usually be a user's password as typed at a prompt or  in a graphical
78 -   interface.  *salt* is usually a random two-character string which will be used
79 -   to perturb the DES algorithm in one of 4096 ways.  The characters in *salt* must
80 -   be in the set ``[./a-zA-Z0-9]``.  Returns the hashed password as a string, which
81 -   will be composed of characters from the same alphabet as the salt (the first two
82 -   characters represent the salt itself).
83 +   interface.  The optional *salt* is either a string as returned from
84 +   :func:`mksalt`, one of the ``crypt.METHOD_*`` values (though not all
85 +   may be available on all platforms), or a full encrypted password
86 +   including salt, as returned by this function.  If *salt* is not
87 +   provided, the strongest method will be used (as returned by
88 +   :func:`methods`.
89 +
90 +   Checking a password is usually done by passing the plain-text password
91 +   as *word* and the full results of a previous :func:`crypt` call,
92 +   which should be the same as the results of this call.
93 +
94 +   *salt* (either a random 2 or 16 character string, possibly prefixed with
95 +   ``$digit$`` to indicate the method) which will be used to perturb the
96 +   encryption algorithm.  The characters in *salt* must be in the set
97 +   ``[./a-zA-Z0-9]``, with the exception of Modular Crypt Format which
98 +   prefixes a ``$digit$``.
99 +
100 +   Returns the hashed password as a string, which will be composed of
101 +   characters from the same alphabet as the salt.
102  
103     .. index:: single: crypt(3)
104  
105 @@ -43,6 +109,27 @@ this module.
106     different sizes in the *salt*, it is recommended to use  the full crypted
107     password as salt when checking for a password.
108  
109 +.. versionchanged:: 3.3
110 +   Before version 3.3, *salt*  must be specified as a string and cannot
111 +   accept ``crypt.METHOD_*`` values (which don't exist anyway).
112 +
113 +
114 +.. function:: mksalt(method=None)
115 +
116 +   Return a randomly generated salt of the specified method.  If no
117 +   *method* is given, the strongest method available as returned by
118 +   :func:`methods` is used.
119 +
120 +   The return value is a string either of 2 characters in length for
121 +   ``crypt.METHOD_CRYPT``, or 19 characters starting with ``$digit$`` and
122 +   16 random characters from the set ``[./a-zA-Z0-9]``, suitable for
123 +   passing as the *salt* argument to :func:`crypt`.
124 +
125 +.. versionadded:: 3.3
126 +
127 +Examples
128 +--------
129 +
130  A simple example illustrating typical use::
131  
132     import crypt, getpass, pwd
133 @@ -59,3 +146,11 @@ A simple example illustrating typical us
134         else:
135             return 1
136  
137 +To generate a hash of a password using the strongest available method and
138 +check it against the original::
139 +
140 +   import crypt
141 +
142 +   hashed = crypt.crypt(plaintext)
143 +   if hashed != crypt.crypt(plaintext, hashed):
144 +      raise "Hashed version doesn't validate against original"
145 diff -up Python-2.7.3/Lib/crypt.py.crypt-module-salt-backport Python-2.7.3/Lib/crypt.py
146 --- Python-2.7.3/Lib/crypt.py.crypt-module-salt-backport    2013-02-19 16:44:20.465334062 -0500
147 +++ Python-2.7.3/Lib/crypt.py    2013-02-19 16:49:56.425311089 -0500
148 @@ -0,0 +1,71 @@
149 +"""Wrapper to the POSIX crypt library call and associated functionality.
150 +
151 +Note that the ``methods`` and ``METHOD_*`` attributes are non-standard
152 +extensions to Python 2.7, backported from 3.3"""
153 +
154 +import _crypt
155 +import string as _string
156 +from random import SystemRandom as _SystemRandom
157 +from collections import namedtuple as _namedtuple
158 +
159 +
160 +_saltchars = _string.ascii_letters + _string.digits + './'
161 +_sr = _SystemRandom()
162 +
163 +
164 +class _Method(_namedtuple('_Method', 'name ident salt_chars total_size')):
165 +
166 +    """Class representing a salt method per the Modular Crypt Format or the
167 +    legacy 2-character crypt method."""
168 +
169 +    def __repr__(self):
170 +        return '<crypt.METHOD_%s>' % self.name
171 +
172 +
173 +def mksalt(method=None):
174 +    """Generate a salt for the specified method.
175 +
176 +    If not specified, the strongest available method will be used.
177 +
178 +    This is a non-standard extension to Python 2.7, backported from 3.3
179 +    """
180 +    if method is None:
181 +        method = methods[0]
182 +    s = '$%s$' % method.ident if method.ident else ''
183 +    s += ''.join(_sr.sample(_saltchars, method.salt_chars))
184 +    return s
185 +
186 +
187 +def crypt(word, salt=None):
188 +    """Return a string representing the one-way hash of a password, with a salt
189 +    prepended.
190 +
191 +    If ``salt`` is not specified or is ``None``, the strongest
192 +    available method will be selected and a salt generated.  Otherwise,
193 +    ``salt`` may be one of the ``crypt.METHOD_*`` values, or a string as
194 +    returned by ``crypt.mksalt()``.
195 +
196 +    Note that these are non-standard extensions to Python 2.7's crypt.crypt()
197 +    entrypoint, backported from 3.3: the standard Python 2.7 crypt.crypt()
198 +    entrypoint requires two strings as the parameters, and does not support
199 +    keyword arguments.
200 +    """
201 +    if salt is None or isinstance(salt, _Method):
202 +        salt = mksalt(salt)
203 +    return _crypt.crypt(word, salt)
204 +
205 +
206 +#  available salting/crypto methods
207 +METHOD_CRYPT = _Method('CRYPT', None, 2, 13)
208 +METHOD_MD5 = _Method('MD5', '1', 8, 34)
209 +METHOD_SHA256 = _Method('SHA256', '5', 16, 63)
210 +METHOD_SHA512 = _Method('SHA512', '6', 16, 106)
211 +
212 +methods = []
213 +for _method in (METHOD_SHA512, METHOD_SHA256, METHOD_MD5):
214 +    _result = crypt('', _method)
215 +    if _result and len(_result) == _method.total_size:
216 +        methods.append(_method)
217 +methods.append(METHOD_CRYPT)
218 +del _result, _method
219 +
220 diff -up Python-2.7.3/Lib/test/test_crypt.py.crypt-module-salt-backport Python-2.7.3/Lib/test/test_crypt.py
221 --- Python-2.7.3/Lib/test/test_crypt.py.crypt-module-salt-backport    2012-04-09 19:07:31.000000000 -0400
222 +++ Python-2.7.3/Lib/test/test_crypt.py    2013-02-19 16:44:20.465334062 -0500
223 @@ -10,6 +10,25 @@ class CryptTestCase(unittest.TestCase):
224          if test_support.verbose:
225              print 'Test encryption: ', c
226  
227 +    def test_salt(self):
228 +        self.assertEqual(len(crypt._saltchars), 64)
229 +        for method in crypt.methods:
230 +            salt = crypt.mksalt(method)
231 +            self.assertEqual(len(salt),
232 +                    method.salt_chars + (3 if method.ident else 0))
233 +
234 +    def test_saltedcrypt(self):
235 +        for method in crypt.methods:
236 +            pw = crypt.crypt('assword', method)
237 +            self.assertEqual(len(pw), method.total_size)
238 +            pw = crypt.crypt('assword', crypt.mksalt(method))
239 +            self.assertEqual(len(pw), method.total_size)
240 +
241 +    def test_methods(self):
242 +        # Gurantee that METHOD_CRYPT is the last method in crypt.methods.
243 +        self.assertTrue(len(crypt.methods) >= 1)
244 +        self.assertEqual(crypt.METHOD_CRYPT, crypt.methods[-1])
245 +
246  def test_main():
247      test_support.run_unittest(CryptTestCase)
248  
249 diff -up Python-2.7.3/Modules/cryptmodule.c.crypt-module-salt-backport Python-2.7.3/Modules/cryptmodule.c
250 --- Python-2.7.3/Modules/cryptmodule.c.crypt-module-salt-backport    2012-04-09 19:07:34.000000000 -0400
251 +++ Python-2.7.3/Modules/cryptmodule.c    2013-02-19 16:44:20.466334063 -0500
252 @@ -43,7 +43,7 @@ static PyMethodDef crypt_methods[] = {
253  };
254  
255  PyMODINIT_FUNC
256 -initcrypt(void)
257 +init_crypt(void)
258  {
259 -    Py_InitModule("crypt", crypt_methods);
260 +    Py_InitModule("_crypt", crypt_methods);
261  }
262 diff -up Python-2.7.3/Modules/Setup.dist.crypt-module-salt-backport Python-2.7.3/Modules/Setup.dist
263 --- Python-2.7.3/Modules/Setup.dist.crypt-module-salt-backport    2013-02-19 16:44:20.463334063 -0500
264 +++ Python-2.7.3/Modules/Setup.dist    2013-02-19 16:44:20.466334063 -0500
265 @@ -221,7 +221,7 @@ _ssl _ssl.c \
266  #
267  # First, look at Setup.config; configure may have set this for you.
268  
269 -crypt cryptmodule.c # -lcrypt    # crypt(3); needs -lcrypt on some systems
270 +_crypt _cryptmodule.c -lcrypt    # crypt(3); needs -lcrypt on some systems
271  
272  
273  # Some more UNIX dependent modules -- off by default, since these
274 diff -up Python-2.7.3/setup.py.crypt-module-salt-backport Python-2.7.3/setup.py
275 --- Python-2.7.3/setup.py.crypt-module-salt-backport    2013-02-19 16:44:20.425334067 -0500
276 +++ Python-2.7.3/setup.py    2013-02-19 16:44:20.466334063 -0500
277 @@ -693,7 +693,7 @@ class PyBuildExt(build_ext):
278              libs = ['crypt']
279          else:
280              libs = []
281 -        exts.append( Extension('crypt', ['cryptmodule.c'], libraries=libs) )
282 +        exts.append( Extension('_crypt', ['_cryptmodule.c'], libraries=libs) )
283  
284          # CSV files
285          exts.append( Extension('_csv', ['_csv.c']) )