ciscoPWDhasher
ciscoPWDhasher copied to clipboard
Add support for Cisco's sha512 format
Cisco ASA 9.5 added a new SHA512-based pbkdf2 password hash. This one isn't technically numbered, but I think it's informally referred to as type 10?
I replied to your comment on the open issue in passlib but I'll add my comments here for visibility:
Here's what the hash typically gets serialized as:
$sha512$5000$zJZ/+1K9lmgpmVlRXjPEYQ==$9VOAeH+g4QIPkUyWfdq79w==
This follows a modular crypt syntax, which breaks down as follows:
-
sha512
is cisco-ese for the pbkdf2 password format -
5000
is the number of iterations the hash uses -
zJZ/+1K9lmgpmVlRXjPEYQ==
is a 16-byte salt encoded in standard base64 (not altered) -
9VOAeH+g4QIPkUyWfdq79w==
is the first 16 bytes of a standard SHA512 digest encoded in standard base64
quick proof-of-concept for generating a password hash:
import base64
import crypt
from passlib.crypto.digest import pbkdf2_hmac
# this is maybe not the best way to generate the salt? i.e. the salt bytes encoded in the example hash above
# decodes to:
# cc 96 7f fb
# 52 bd 96 68
# 29 99 59 51
# 5e 33 c4 61
# so i.e. it is not limited to 7-bit printable characters.
salt_bytes = crypt.mksalt(crypt.METHOD_SHA512)[3:].encode('utf8')
secret_bytes = 'my_password'.encode('utf8')
rounds = 5000
digest = pbkdf2_hmac('sha512', salt_bytes, secret_bytes, rounds)[0:16]
print('$sha512${rounds}${salt}${digest}'.format(
rounds=rounds,
salt=base64.b64encode(salt_bytes).decode('utf8'),
digest=base64.b64encode(digest).decode('utf8')
))
@gblues - thank you for this info. I should have access to an ASA as of next week to start testing.
As a matter of fact, I figured this out in the process of solving a deployment challenge for our ASA at my day job (Cisco ASAv running 9.12(4)4), so I can verify it works with at least one ASA 😁