Encoding user Input to get an encryption key - python

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.

Related

Cracking passwords with DES algorithm given hash and salt

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'

Guessing XOR secret key knowing some part of it

I'm trying to guess the secret key to decrypt a message using Python 3. I know the message is going to be something like: crypto{1XXXXXX} where the XXXXXXX is the unknown part of the message.
The encrypt message is: '0e0b213f26041e480b26217f27342e175d0e070a3c5b103e2526217f27342e175d0e077e263451150104' and I have the following code:
from pwn import xor
flkey=bytes.fromhex('0e0b213f26041e480b26217f27342e175d0e070a3c5b103e2526217f27342e175d0e077e263451150104')
print(flkey)
y = xor(flkey, "crypto{1xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx}")
print(y)
xor(flkey, y)
My question is, how can I find the rest of the message knowing only some part of it? I'm quite new in this topic related to XOR.
EDIT: when I print(y) I obtain:
b'crypto{1xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx}'
So i guess the length of between the brackets is 34.
The weak point of the XOR operation in cryptography is that A XOR B XOR A = B. So when you know the part of the plaintext message M for the corresponding encrypted message C, you immediately obtain that part of the key as K = M XOR C.
In particular:
>>> cypher = bytes.fromhex('0e0b213f26041e480b26217f27342e175d0e070a3c5b103e2526217f27342e175d0e077e263451150104')
>>> plaintext = b'crypto{1'
>>> key = ''.join(chr(c ^ m) for c, m in zip(cypher, plaintext))
>>> key
'myXORkey'
The chances are high that this is the entire key (it actually is, which is left as an exercise). This string will repeat as many times as needed to match the plain text length.
Suppose now, that this was not the entire key. We know, however, that the key repeats in a loop, so that part we alreaydy know, myXORkey, will be reused somewhere later. We can start applying it to various places in the cypher and see when it starts making sense. That way we know the key length and parts of the messages. There are few ways from here, the most simple is, because we know some parts of the plaintext, we can find the missing part by sense and from there find the remaining part of the key.
The following properties may help:
the key is sufficiently short
the key makes some sense
you know the language the plain text is written in
If the key is as long as the message, is truly random, and used only once, the cypher cannot be broken (See One-time pad).
In a generic case when the plaintext or/and the key length is unknown, there is more sophisticated method based on the Hamming distance and transposition (The method was first discovered in 19th century by Friedrich Kasiski to analyze the Vigenère cipher.

Safer way to remove salt from a decrypted key

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?

Hashing (hiding) strings in Python

What I need is to hash a string. It doesn't have to be secure because it's just going to be a hidden phrase in the text file (it just doesn't have to be recognizable for a human-eye).
It should not be just a random string because when the users types the string I would like to hash it and compare it with an already hashed one (from the text file).
What would be the best for this purpose? Can it be done with the built-in classes?
First off, let me say that you can't guarantee unique results. If you wanted unique results for all the strings in the universe, you're better off storing the string itself (or a compressed version).
More on that in a second. Let's get some hashes first.
hashlib way
You can use any of the main cryptographic hashes to hash a string with a few steps:
>>> import hashlib
>>> sha = hashlib.sha1("I am a cat")
>>> sha.hexdigest()
'576f38148ae68c924070538b45a8ef0f73ed8710'
You have a choice between SHA1, SHA224, SHA256, SHA384, SHA512, and MD5 as far as built-ins are concerned.
What's the difference between those hash algorithms?
A hash function works by taking data of variable length and turning it into data of fixed length.
The fixed length, in the case of each of the SHA algorithms built into hashlib, is the number of bits specified in the name (with the exception of sha1 which is 160 bits). If you want better certainty that two strings won't end up in the same bucket (same hash value), pick a hash with a bigger digest (the fixed length).
In sorted order, these are the digest sizes you have to work with:
Algorithm Digest Size (in bits)
md5 128
sha1 160
sha224 224
sha256 256
sha384 384
sha512 512
The bigger the digest the less likely you'll have a collision, provided your hash function is worth its salt.
Wait, what about hash()?
The built in hash() function returns integers, which could also be easy to use for the purpose you outline. There are problems though.
>>> hash('moo')
6387157653034356308
If your program is going to run on different systems, you can't be sure that hash will return the same thing. In fact, I'm running on a 64-bit box using 64-bit Python. These values are going to be wildly different than for 32-bit Python.
For Python 3.3+, as #gnibbler pointed out, hash() is randomized between runs. It will work for a single run, but almost definitely won't work across runs of your program (pulling from the text file you mentioned).
Why would hash() be built that way? Well, the built in hash is there for one specific reason. Hash tables/dictionaries/look up tables in memory. Not for cryptographic use but for cheap lookups at runtime.
Don't use hash(), use hashlib.
You can simply use the base64 module to achieve your goal:
>>> import base64
>>> a = 'helloworld'
>>> encoded_str = base64.encodestring(a)
>>> encoded_str
'aGVsbG93b3JsZA=='
>>> base64.decodestring(encoded_str)
'helloworld'
>>>
of course you can also use the the hashlib module, it's more secure , because the hashed string cannot(or very very hard) be decoded latter, but for your question base64 is enough -- "It doesn't really have to be secure"
Note that Python's string hash is not "defined" - it can, and does, vary across releases and implementations. So storing a Python string hash will create difficulties. CPython's string hash makes no attempt to be "obscure", either.
A standard approach is to use a hash function designed for this kind of thing. Like this:
>>> import hashlib
>>> encoded = hashlib.sha1("abcdef") # "abcdef" is the password
>>> encoded.hexdigest()
'1f8ac10f23c5b5bc1167bda84b833e5c057a77d2'
That long string of hexadecimal digits is "the hash". SHA-1 is a "strong" hash function. You can get famous if you find two strings that hash to the same value ;-) And given the same input, it will return the same "hexdigest" on all platforms across all releases and implementations of Python.
Simply use the hash() built-in function, for example:
s = 'a string'
hash(s)
=> -8411828025894108412

use python to create compatible ldap password (md5crypt) on windows

Do you know how to create a ldap compatible password (preferred md5crypt) via python on Windows
I used to write something like this in Linux but the crypt module is not present on Windows
char_set = string.ascii_uppercase + string.digits
salt = ''.join(random.sample(char_set,8))
salt = '$1$' + salt + '$'
pwd = "{CRYPT}" + crypt.crypt(str(old_password),salt)
The Passlib python library contains cross-platform implementations of all the crypt(3) algorithms. In particular, it contains ldap_md5_crypt, which sounds like exactly what you want. Here's how to use it (this code will work on windows or linux):
from passlib.hash import ldap_md5_crypt
#note salt generation is automatically handled
hash = ldap_md5_crypt.encrypt("password")
#hash will be similar to '{CRYPT}$1$wa6OLvW3$uzcIj2Puf3GcFDf2KztQN0'
#to verify a password...
valid = ldap_md5_crypt.verify("password", hash)
I should note that while MD5-Crypt is widely supported (Linux, all the BSDs, internally in openssl), it's none-the-less not the strongest hash available really horribly insecure, and should be avoided if at all possible. If you want the strongest hash that's compatible with linux crypt(), SHA512-Crypt is probably the way to go. It adds variable rounds, as well as some other improvements over MD5-Crypt internally.
From here http://www.openldap.org/faq/data/cache/347.html
One of the variants for generating SHA-hash can be:
import sha
from base64 import b64encode
ctx = sha.new("your_password")
hash = "{SHA}" + b64encode(ctx.digest())
print(hash)
This code is for Python.
# python my_sha.py
{SHA}Vk40DNSEN9Lf6HbuFUzJncTQ0Tc=
I (and not only me) don't recommend to use MD5 anymore.
PS. Follow the link you can try some windows variants.
You'll want to use fcrypt, which is a pure Python implementation of the Unix module crypt. It's a bit slower than crypt but it has the same functionality.
Disclaimer: I know Google, not cryptography.
From the crypt docs:
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.
You could have a look at md5crypt.py. Alternatively, crypt for Windows is part of GnuWin32. Here's some of the Unix man page; the Windows interface should be similar.
CRYPT(3) Linux
Programmer's Manual
CRYPT(3)
NAME
crypt, crypt_r - password and data encryption
SYNOPSIS
#define _XOPEN_SOURCE
#include <unistd.h>
char *crypt(const char *key, const char *salt);
char *crypt_r(const char *key, const char *salt,
struct crypt_data *data);
Link with -lcrypt.
DESCRIPTION
crypt() is the password encryption function. It is based on
the Data
Encryption Standard algorithm with variations intended (among
other
things) to discourage use of hardware implementations of a key
search.
key is a user's typed password.
salt is a two-character string chosen from the set [a–zA–Z0–9./].
This
string is used to perturb the algorithm in one of 4096 different
ways.
By taking the lowest 7 bits of each of the first eight characters
of
the key, a 56-bit key is obtained. This 56-bit key is used to
encrypt
repeatedly a constant string (usually a string consisting of
all
zeros). The returned value points to the encrypted password, a
series
of 13 printable ASCII characters (the first two characters
represent
the salt itself). The return value points to static data whose
content
is overwritten by each call.
Warning: The key space consists of 2**56 equal 7.2e16 possible
values.
Exhaustive searches of this key space are possible using massively
par‐
allel computers. Software, such as crack(1), is available which
will
search the portion of this key space that is generally used by
humans
for passwords. Hence, password selection should, at minimum,
avoid
common words and names. The use of a passwd(1) program that checks
for
crackable passwords during the selection process is recommended.
The DES algorithm itself has a few quirks which make the use of
the
crypt() interface a very poor choice for anything other than
password
authentication. If you are planning on using the crypt()
interface for
a cryptography project, don't do it: get a good book on encryption
and
one of the widely available DES libraries.

Categories

Resources