I have a decrypted key that is salted with random special characters (it's been changed): J_a&3#000$0=f%4{4-f-1*1(1-d#0-3&e|0)1&987*5(b#123$1'1(4*0)1}c+f'59#d#8_6_c)4#1#c(3} I need to remove all the special characters and return the unsalted version of it, for example, right now I'm using:
def remove_salt(decrypted_key):
""" Remove salt from a decrypted key """
invalid_chars = set(string.punctuation)
return_key = []
for c in decrypted_key:
if c not in invalid_chars:
return_key.append(c)
return ''.join(return_key)
So it would look like this:
>>> remove_salt("J_a&3#000$0=f%4{4-f-1*1(1-d#0-3&e|0)1&987*5(b#123$1'1(4*0)1}c+f'59#d#8_6_c)4#1#c(3}")
'Ja30000f44f111d03e019875b12311401cf59d86c41c3'
>>>
Is there a safer way that I can remove the salt from the key without completely revealing what the salt is, what I mean is string.punctuation clearly states, that invalid characters are !##$ .. etc. How can I remove this salt without completely revealing what my salt is?
Please note, the way this is salted was not my choice. I just need to get this thing unsalted without it being super noticeable as to what the salt is.
I am confused with your use of salt. Salt is typically appended at the beginning or end of a password, and the result encrypted and stored. Salt values themselves are stored in the clear, and are use mainly to make dictionary attacks more difficult. So, when a user enters their password, you retrieve their designated salt from wherever you have stored it, append it to what they have entered, hash it with whatever password hash you have chosen, and check to see if the stored hash matches the provided hash. Perhaps some clarification is in need - why are you trying to remove a salt that is embedded in the password?
Related
I am taking in user input and need to turn it into an AES encryption key.
I have:
keyInput= input("Enter key:")
key = keyInput.encode()
print(key)
If I type in "computer" for the input. I get the result b'computer' for the output.
Shouldn't it look something more like this?
b'\xbf\xc0\x85)\x10nc\x94\x02)j\xdf\xcb\xc4\x94\x9d(\x9e[EX\xc8\xd5\xbfI{\xa2$\x05(\xd5\x18'
"computer" cannot be an AES key because it only consists of ASCII characters. Keys for algorithms such as AES should consist of fully randomized bits and of course of a specific size (128, 192 or 256 bits).
What you are after is password based encryption. For this there are standards, such as PKCS#5, literally the "Password-Based Cryptography Specification" (Version 2.1). Basically it uses PBKDF2 to calculate a key from a relatively weak password using a salt and a work factor (or, in the case of PBKDF2, an iteration count).
Long answer: https://crypto.stackexchange.com/questions/53552/aes-with-small-and-large-string-keys
Short answer. AES takes a 128-bit, 192-bit, or 256-bit key. Some APIs let you use a password instead of a key. How the password gets converted into the appropriate length key is not part of the AES standard. There are a large number of "Password Based Key Derivation Functions" (PBKDF) that perform this function.
I am given a hash ("1u9Tc6HX") and the salt ("Ff"), and I am told to crack the password knowing that it has been hashed with DES algorithm. Using hashcat, I have known that the password is ("michael") and I am now trying to hash this password in order to compare it with the hash given.
However, I have tried using (openssl enc) command but it always asks me for the password used for encryption, what I am not given, so I don't know how to hash ("michael") using DES and salt ("Ff") and get ("1u9Tc6HX"). I am open to change the procedure and try other things in case you think is easier to crack by other way. (I am working with python)
Any comment and help is appreciated.
Pd:
Example: Ff1u9Tc6HXxJo
Enunciate: The password has been hashed using the DES algorithm. The entry consists
in 13 printable ASCII characters, where the two first characters represent the salt.
With DES, only the first 8 characters of the password are used.
Passlib is a popular library for password hashing:
>>> import passlib.hash
>>> passlib.hash.des_crypt.hash('michael', salt='Ff')
'Ff1u9Tc6HXxJo'
I would like to generate a human-readable hash with customized properties -- e.g., a short string of specified length consisting entirely of upper case letters and digits excluding 0, 1, O, and I (to eliminate visual ambiguity):
"arbitrary string" --> "E3Y7UM8"
A 7-character string of the above form could take on over 34 billion unique values which, for my purposes, makes collisions extremely unlikely. Security is also not a major concern.
Is there an existing module or routine that implements something like the above? Alternatively, can someone suggest a straightforward algorithm?
The method you should be using has similarities with password one-way encryption. Of course since you are going for readable, a good password function is probably out of the question.
Here's what I would do:
Take an MD5 hash of the email
Convert base32 which already eliminates O and I
Replace any non-readable characters with readable ones
Here's an example based on the above:
import base64 # base32 is a function in base64
import hashlib
email = "somebody#example.com"
md5 = hashlib.md5()
md5.update(email.encode('utf-8'))
hash_in_bytes = md5.digest()
result = base64.b32encode(hash_in_bytes)
print(result)
# Or you can remove the extra "=" at the end
result = result.strip(b'=')
Since it's a one-way function (hash), you obviously don't need to worry about reversing the process (you can't anyway). You can also replace any other characters you find non-readable with readable ones (I would go for lowercase versions of the characters, e.g. q instead of Q)
More about base32 here: https://docs.python.org/3/library/base64.html
You can simply truncate the beginning of an MD5sum algorithm. It should have approximately the same statistical properties than the whole string anyway:
import md5
m = md5.new()
m.update("arbitrary string")
print(m.hexdigest()[:7])
Same code with hashlib module:
import hashlib
m = hashlib.md5()
m.update("arbitrary string")
print(m.hexdigest()[:7])
Using bcrypt with Python 2.7, I can see that the example uses the bcrypt.hashpw to both hash a password for storage and verify that the given password matches a hashed one, like so:
Hashing
import bcrypt
password = b"somepassword"
hashed = bcrypt.hashpw(password, bcrypt.gensalt())
Ok, so far so good. The given password is now hashed using bcrypt, so it is a string of hashed bytes.
Verifying
Now, here's the part that confuses me: to check that a plaintext password matches a hashed password, the same function is used, using the hashed password as a salt:
if bcrypt.hashpw(password, hashed) == hashed:
print("It Matches!")
else:
print("It Does not Match :(")
What's happening?
Shouldn't the results of both bcrypt.hashpw calls be different, since the input salts are different?
The only reasonable answer I can think of is that the salt is truncated to a fixed length before being prepended to the hashed password. That way, when using the result of the hash, only the generated salt is left (after stripping off the trailing hashed password), and the result of hashing the password with the truncated salt is the same as the original. I don't have any evidence to support this, though.
Why does this work?
In the expression bcrypt.hashpw(password, hashed) only the first couple of characters of hashed are used for the salt, not the entire string.
For instance, in this example how the output of hashpw() begins with the salt:
salt1 = b"$2a$12$w40nlebw3XyoZ5Cqke14M."
print "salt1:", salt1
print "hash1:", bcrypt.hashpw(password, salt1)
prints:
salt1: $2a$12$w40nlebw3XyoZ5Cqke14M.
hash1: $2a$12$w40nlebw3XyoZ5Cqke14M.d.7cdO2wJhr/K6ZSDjODIxLrPmYzY/a
so there is a convention where the salt only goes up the first period or the first 29 characters.
The hashpw function returns the salted hash (iterated many times, following bcyrpt spec), preceeded by the salt used (and with a dot as seperator).
In : salt = bcrypt.gensalt()
In : all(salt == bcrypt.hashpw(pw,salt)[:len(salt)] for pw in ('','12345','asdfgh'))
Out: True
If the second argument to bcrypt.hashpw is recognized as of the form VALID_SALT.VALID_HASH, then the salt is automagically set to VALID_SALT, thus producing the same salt-hash-pair as the original password on identical pw input.
I have code that outputs all possible combinations of characters from a given character list as follows:
def charList():
charSet = string.ascii_letters + string.digits
for wordchars in product(charSet, repeat=8):
print(''.join(wordchars))
Now I need to turn the output strings into a DES hash then compare the output to user input to see if any matches are found.
Have been doing some research and haven't made much progress. So wondering if anyone on here could help?
If you want to hash strings (and not encrypt them), you can use the built-in hashlib module:
>>> import hashlib
>>> m = hashlib.md5()
>>> m.update("Nobody inspects")
>>> m.update(" the spammish repetition")
>>> m.digest()
'\xbbd\x9c\x83\xdd\x1e\xa5\xc9\xd9\xde\xc9\xa1\x8d\xf0\xff\xe9'
EDIT: as said in the comments, prefer hashlib.sha256() which is far more secured today.
Quick search for DES and Python gave me these libraries:
http://pypi.python.org/pypi/pycrypto/2.6
http://packages.python.org/passlib/lib/passlib.hash.des_crypt.html
http://docs.python.org/2/library/crypt.html
Platforms: Unix
This module implements an interface to the 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.
Notice that the behavior of this module depends on the actual
implementation of the crypt(3) routine in the running system.
Therefore, any extensions available on the current implementation will
also be available on this module
crypt.crypt(word, salt)
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).
Since a few crypt(3) extensions allow different values, with different
sizes in the salt, it is recommended to use the full crypted password
as salt when checking for a password.
A simple example illustrating typical use:
import crypt, getpass, pwd
def login():
username = raw_input('Python login:')
cryptedpasswd = pwd.getpwnam(username)[1]
if cryptedpasswd:
if cryptedpasswd == 'x' or cryptedpasswd == '*':
raise NotImplementedError(
"Sorry, currently no support for shadow passwords")
cleartext = getpass.getpass()
return crypt.crypt(cleartext, cryptedpasswd) == cryptedpasswd
else:
return 1