Skip to content
Projects
Groups
Snippets
Help
Loading...
Help
Support
Keyboard shortcuts
?
Submit feedback
Contribute to GitLab
Sign in / Register
Toggle navigation
C
cpython
Project overview
Project overview
Details
Activity
Releases
Repository
Repository
Files
Commits
Branches
Tags
Contributors
Graph
Compare
Issues
0
Issues
0
List
Boards
Labels
Milestones
Merge Requests
0
Merge Requests
0
Analytics
Analytics
Repository
Value Stream
Wiki
Wiki
Members
Members
Collapse sidebar
Close sidebar
Activity
Graph
Create a new issue
Commits
Issue Boards
Open sidebar
Kirill Smelkov
cpython
Commits
e2dfefbe
Commit
e2dfefbe
authored
Feb 22, 2011
by
Sean Reifscheider
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
Issue #10924: Adding salt and Modular Crypt Format to crypt library.
parent
f3042782
Changes
7
Hide whitespace changes
Inline
Side-by-side
Showing
7 changed files
with
183 additions
and
13 deletions
+183
-13
Doc/library/crypt.rst
Doc/library/crypt.rst
+97
-9
Lib/crypt.py
Lib/crypt.py
+61
-0
Lib/test/test_crypt.py
Lib/test/test_crypt.py
+17
-0
Misc/NEWS
Misc/NEWS
+4
-0
Modules/Setup.dist
Modules/Setup.dist
+1
-1
Modules/_cryptmodule.c
Modules/_cryptmodule.c
+2
-2
setup.py
setup.py
+1
-1
No files found.
Doc/library/crypt.rst
View file @
e2dfefbe
...
...
@@ -15,9 +15,9 @@
This module implements an interface to the :manpage:`crypt(3)` routine, which is
a one-way hash function based upon a modified DES algorithm; see the Unix man
page for further details. Possible uses include
allowing Python scripts to
accept typed passwords from the user, or attempting to crack Unix passwords with
a dictionary.
page for further details. Possible uses include
storing hashed passwords
so you can check passwords without storing the actual password, or attempting
to crack Unix passwords with
a dictionary.
.. index:: single: crypt(3)
...
...
@@ -26,15 +26,67 @@ the :manpage:`crypt(3)` routine in the running system. Therefore, any
extensions available on the current implementation will also be available on
this module.
Hashing Methods
---------------
.. function:: crypt(word, salt)
The :mod:`crypt` module defines the list of hashing methods (not all methods
are available on all platforms):
.. data:: METHOD_SHA512
A Modular Crypt Format method with 16 character salt and 86 character
hash. This is the strongest method.
.. versionadded:: 3.3
.. data:: METHOD_SHA256
Another Modular Crypt Format method with 16 character salt and 43
character hash.
.. versionadded:: 3.3
.. data:: METHOD_MD5
Another Modular Crypt Format method with 8 character salt and 22
character hash.
.. versionadded:: 3.3
.. data:: METHOD_CRYPT
The traditional method with a 2 character salt and 13 characters of
hash. This is the weakest method.
.. versionadded:: 3.3
Module Functions
----------------
The :mod:`crypt` module defines the following functions:
.. function:: crypt(word, salt=None)
*word* will usually be a user's password as typed at a prompt or in a graphical
interface. *salt* is usually a random two-character string which will be used
to perturb the DES algorithm in one of 4096 ways. The characters in *salt* must
be in the set ``[./a-zA-Z0-9]``. Returns the hashed password as a string, which
will be composed of characters from the same alphabet as the salt (the first two
characters represent the salt itself).
interface. The optional *salt* is either a string as returned from
:func:`mksalt`, one of the ``crypt.METHOD_*`` values (though not all
may be available on all platforms), or a full encrypted password
including salt, as returned by this function. If *salt* is not
provided, the strongest method will be used (as returned by
:func:`methods`.
Checking a password is usually done by passing the plain-text password
as *word* and the full results of a previous :func:`crypt` call,
which should be the same as the results of this call.
*salt* (either a random 2 or 16 character string, possibly prefixed with
``$digit$`` to indicate the method) which will be used to perturb the
encryption algorithm. The characters in *salt* must be in the set
``[./a-zA-Z0-9]``, with the exception of Modular Crypt Format which
prefixes a ``$digit$``.
Returns the hashed password as a string, which will be composed of
characters from the same alphabet as the salt.
.. index:: single: crypt(3)
...
...
@@ -42,6 +94,34 @@ this module.
different sizes in the *salt*, it is recommended to use the full crypted
password as salt when checking for a password.
.. versionchanged:: 3.3
Before version 3.3, *salt* must be specified as a string and cannot
accept ``crypt.METHOD_*`` values (which don't exist anyway).
.. function:: methods()
Return a list of available password hashing algorithms, as
``crypt.METHOD_*`` objects. This list is sorted from strongest to
weakest, and is guaranteed to have at least ``crypt.METHOD_CRYPT``.
.. versionadded:: 3.3
.. function:: mksalt(method=None)
Return a randomly generated salt of the specified method. If no
*method* is given, the strongest method available as returned by
:func:`methods` is used.
The return value is a string either of 2 characters in length for
``crypt.METHOD_CRYPT``, or 19 characters starting with ``$digit$`` and
16 random characters from the set ``[./a-zA-Z0-9]``, suitable for
passing as the *salt* argument to :func:`crypt`.
.. versionadded:: 3.3
Examples
--------
A simple example illustrating typical use::
import crypt, getpass, pwd
...
...
@@ -57,3 +137,11 @@ A simple example illustrating typical use::
else:
return 1
To generate a hash of a password using the strongest available method and
check it against the original::
import crypt
hashed = crypt.crypt(plaintext)
if hashed != crypt.crypt(plaintext, hashed):
raise "Hashed version doesn't validate against original"
Lib/crypt.py
0 → 100644
View file @
e2dfefbe
'''Wrapper to the POSIX crypt library call and associated functionality.
'''
import
_crypt
saltchars
=
'abcdefghijklmnopqrstuvwxyz'
saltchars
+=
saltchars
.
upper
()
saltchars
+=
'0123456789./'
class
_MethodClass
:
'''Class representing a salt method per the Modular Crypt Format or the
legacy 2-character crypt method.'''
def
__init__
(
self
,
name
,
ident
,
salt_chars
,
total_size
):
self
.
name
=
name
self
.
ident
=
ident
self
.
salt_chars
=
salt_chars
self
.
total_size
=
total_size
def
__repr__
(
self
):
return
'<crypt.METHOD_%s>'
%
self
.
name
# available salting/crypto methods
METHOD_CRYPT
=
_MethodClass
(
'CRYPT'
,
None
,
2
,
13
)
METHOD_MD5
=
_MethodClass
(
'MD5'
,
'1'
,
8
,
34
)
METHOD_SHA256
=
_MethodClass
(
'SHA256'
,
'5'
,
16
,
63
)
METHOD_SHA512
=
_MethodClass
(
'SHA512'
,
'6'
,
16
,
106
)
def
methods
():
'''Return a list of methods that are available in the platform ``crypt()``
library, sorted from strongest to weakest. This is guaranteed to always
return at least ``[METHOD_CRYPT]``'''
method_list
=
[
METHOD_SHA512
,
METHOD_SHA256
,
METHOD_MD5
]
ret
=
[
method
for
method
in
method_list
if
len
(
crypt
(
''
,
method
))
==
method
.
total_size
]
ret
.
append
(
METHOD_CRYPT
)
return
ret
def
mksalt
(
method
=
None
):
'''Generate a salt for the specified method. If not specified, the
strongest available method will be used.'''
import
random
if
method
==
None
:
method
=
methods
()[
0
]
s
=
'$%s$'
%
method
.
ident
if
method
.
ident
else
''
s
+=
''
.
join
([
random
.
choice
(
saltchars
)
for
x
in
range
(
method
.
salt_chars
)
])
return
(
s
)
def
crypt
(
word
,
salt
=
None
):
'''Return a string representing the one-way hash of a password, preturbed
by a salt. If ``salt`` is not specified or is ``None``, the strongest
available method will be selected and a salt generated. Otherwise,
``salt`` may be one of the ``crypt.METHOD_*`` values, or a string as
returned by ``crypt.mksalt()``.'''
if
salt
==
None
:
salt
=
mksalt
()
elif
isinstance
(
salt
,
_MethodClass
):
salt
=
mksalt
(
salt
)
return
(
_crypt
.
crypt
(
word
,
salt
))
Lib/test/test_crypt.py
View file @
e2dfefbe
...
...
@@ -10,6 +10,23 @@ class CryptTestCase(unittest.TestCase):
if
support
.
verbose
:
print
(
'Test encryption: '
,
c
)
def
test_salt
(
self
):
self
.
assertEqual
(
len
(
crypt
.
saltchars
),
64
)
for
method
in
crypt
.
methods
():
salt
=
crypt
.
mksalt
(
method
)
self
.
assertEqual
(
len
(
salt
),
method
.
salt_chars
+
(
3
if
method
.
ident
else
0
))
def
test_saltedcrypt
(
self
):
for
method
in
crypt
.
methods
():
pw
=
crypt
.
crypt
(
'assword'
,
method
)
self
.
assertEqual
(
len
(
pw
),
method
.
total_size
)
pw
=
crypt
.
crypt
(
'assword'
,
crypt
.
mksalt
(
method
))
self
.
assertEqual
(
len
(
pw
),
method
.
total_size
)
def
test_methods
(
self
):
self
.
assertTrue
(
len
(
crypt
.
methods
())
>
1
)
def
test_main
():
support
.
run_unittest
(
CryptTestCase
)
...
...
Misc/NEWS
View file @
e2dfefbe
...
...
@@ -27,6 +27,10 @@ Core and Builtins
Library
-------
- Issue #10924: Adding salt and Modular Crypt Format to crypt library.
Moved old C wrapper to _crypt, and added a Python wrapper with
enhanced salt generation and simpler API for password generation.
- Issue #11074: Make '
tokenize
' so it can be reloaded.
- Issue #11085: Moved collections abstract base classes into a separate
...
...
Modules/Setup.dist
View file @
e2dfefbe
...
...
@@ -207,7 +207,7 @@ _symtable symtablemodule.c
#
# First, look at Setup.config; configure may have set this for you.
#
crypt
cryptmodule.c # -lcrypt # crypt(3); needs -lcrypt on some systems
#
_crypt _
cryptmodule.c # -lcrypt # crypt(3); needs -lcrypt on some systems
# Some more UNIX dependent modules -- off by default, since these
...
...
Modules/cryptmodule.c
→
Modules/
_
cryptmodule.c
View file @
e2dfefbe
...
...
@@ -45,7 +45,7 @@ static PyMethodDef crypt_methods[] = {
static
struct
PyModuleDef
cryptmodule
=
{
PyModuleDef_HEAD_INIT
,
"crypt"
,
"
_
crypt"
,
NULL
,
-
1
,
crypt_methods
,
...
...
@@ -56,7 +56,7 @@ static struct PyModuleDef cryptmodule = {
};
PyMODINIT_FUNC
PyInit_crypt
(
void
)
PyInit_
_
crypt
(
void
)
{
return
PyModule_Create
(
&
cryptmodule
);
}
setup.py
View file @
e2dfefbe
...
...
@@ -636,7 +636,7 @@ class PyBuildExt(build_ext):
libs
=
[
'crypt'
]
else
:
libs
=
[]
exts
.
append
(
Extension
(
'
crypt'
,
[
'
cryptmodule.c'
],
libraries
=
libs
)
)
exts
.
append
(
Extension
(
'
_crypt'
,
[
'_
cryptmodule.c'
],
libraries
=
libs
)
)
# CSV files
exts
.
append
(
Extension
(
'_csv'
,
[
'_csv.c'
])
)
...
...
Write
Preview
Markdown
is supported
0%
Try again
or
attach a new file
Attach a file
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Cancel
Please
register
or
sign in
to comment