generated from ansible-collections/collection_template
-
Notifications
You must be signed in to change notification settings - Fork 88
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Add salt parameter to hash generation for sha256 plugins (#631)
* add salt parameter to hash generation for sha256 plugin * technomax review modification * no general user test for salt
- Loading branch information
Showing
6 changed files
with
251 additions
and
7 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,3 @@ | ||
--- | ||
minor_changes: | ||
- mysql_user - Add salt parameter to generate static hash for `caching_sha2_password` and `sha256_password` plugins. |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,125 @@ | ||
""" | ||
Generate MySQL sha256 compatible plugins hash for a given password and salt | ||
based on | ||
* https://www.akkadia.org/drepper/SHA-crypt.txt | ||
* https://crypto.stackexchange.com/questions/77427/whats-the-algorithm-behind-mysqls-sha256-password-hashing-scheme/111174#111174 | ||
* https://github.com/hashcat/hashcat/blob/master/tools/test_modules/m07400.pm | ||
""" | ||
|
||
from __future__ import absolute_import, division, print_function | ||
|
||
__metaclass__ = type | ||
|
||
import hashlib | ||
|
||
|
||
def _to64(v, n): | ||
"""Convert a 32-bit integer to a base-64 string""" | ||
i64 = ( | ||
[".", "/"] | ||
+ [chr(x) for x in range(48, 58)] | ||
+ [chr(x) for x in range(65, 91)] | ||
+ [chr(x) for x in range(97, 123)] | ||
) | ||
result = "" | ||
while n > 0: | ||
n -= 1 | ||
result += i64[v & 0x3F] | ||
v >>= 6 | ||
return result | ||
|
||
|
||
def _hashlib_sha256(data): | ||
"""Return SHA-256 digest from hashlib .""" | ||
return hashlib.sha256(data).digest() | ||
|
||
|
||
def _sha256_digest(key, salt, loops): | ||
"""Return a SHA-256 digest of the concatenation of the key, the salt, and the key, repeated as necessary.""" | ||
# https://www.akkadia.org/drepper/SHA-crypt.txt | ||
num_bytes = 32 | ||
bytes_key = key.encode() | ||
bytes_salt = salt.encode() | ||
digest_b = _hashlib_sha256(bytes_key + bytes_salt + bytes_key) | ||
|
||
tmp = bytes_key + bytes_salt | ||
for i in range(len(bytes_key), 0, -num_bytes): | ||
tmp += digest_b if i > num_bytes else digest_b[:i] | ||
|
||
i = len(bytes_key) | ||
while i > 0: | ||
tmp += digest_b if (i & 1) != 0 else bytes_key | ||
i >>= 1 | ||
|
||
digest_a = _hashlib_sha256(tmp) | ||
|
||
tmp = b"" | ||
for i in range(len(bytes_key)): | ||
tmp += bytes_key | ||
|
||
digest_dp = _hashlib_sha256(tmp) | ||
|
||
byte_sequence_p = b"" | ||
for i in range(len(bytes_key), 0, -num_bytes): | ||
byte_sequence_p += digest_dp if i > num_bytes else digest_dp[:i] | ||
|
||
tmp = b"" | ||
til = 16 + digest_a[0] | ||
|
||
for i in range(til): | ||
tmp += bytes_salt | ||
|
||
digest_ds = _hashlib_sha256(tmp) | ||
|
||
byte_sequence_s = b"" | ||
for i in range(len(bytes_salt), 0, -num_bytes): | ||
byte_sequence_s += digest_ds if i > num_bytes else digest_ds[:i] | ||
|
||
digest_c = digest_a | ||
|
||
for i in range(loops): | ||
tmp = byte_sequence_p if (i & 1) else digest_c | ||
if i % 3: | ||
tmp += byte_sequence_s | ||
if i % 7: | ||
tmp += byte_sequence_p | ||
tmp += digest_c if (i & 1) else byte_sequence_p | ||
digest_c = _hashlib_sha256(tmp) | ||
|
||
inc1, inc2, mod, end = (10, 21, 30, 0) | ||
|
||
i = 0 | ||
tmp = "" | ||
|
||
while True: | ||
tmp += _to64( | ||
(digest_c[i] << 16) | ||
| (digest_c[(i + inc1) % mod] << 8) | ||
| digest_c[(i + inc1 * 2) % mod], | ||
4, | ||
) | ||
i = (i + inc2) % mod | ||
if i == end: | ||
break | ||
|
||
tmp += _to64((digest_c[31] << 8) | digest_c[30], 3) | ||
|
||
return tmp | ||
|
||
|
||
def mysql_sha256_password_hash(password, salt): | ||
"""Return a MySQL compatible caching_sha2_password hash in raw format.""" | ||
if len(salt) != 20: | ||
raise ValueError("Salt must be 20 characters long.") | ||
|
||
count = 5 | ||
iteration = 1000 * count | ||
|
||
digest = _sha256_digest(password, salt, iteration) | ||
return "$A${0:>03}${1}{2}".format(count, salt, digest) | ||
|
||
|
||
def mysql_sha256_password_hash_hex(password, salt): | ||
"""Return a MySQL compatible caching_sha2_password hash in hex format.""" | ||
return mysql_sha256_password_hash(password, salt).encode().hex().upper() |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters