What exactly is the purpose of using the time.sleep() function in this snippet:
def check_user(user: User, password: str) -> bool:
hashpass, salt = user_info[user].hashed_password
target_hash_pass = hash_password(password, salt)[0]
sleep(random.expovariate(10))
return secrets.compare_digest(hashpass, target_hash_pass)
It's an attempt to introduce a random time delay when verifying passwords, presumably to counter timing attacks, where an attacker makes use of the fact that incorrect passwords result in a faster response.
I'd not expect this to be that useful. secrets.compare_digest() already does everything right to mitigate timing attacks. Provided hashpass and target_hash_pass are the same type (both are bytes or both are strings, always), and have equal length, the usual timing attack vectors are not available here.
However, it could be that the author doesn't trust that those two conditions are always true. Perhaps the user_info structure contains shorter or longer password hashes or there is a chance that you'll get a different type. If so, then those issues should be addressed directly, instead.
It should be noted that because a timing attack compares the statistical differences between multiple attempts, using different passwords, random noise is only going to marginally slow such attacks; it only adds some more noise on top of whatever the timing differences network connections and normal computer operations already add. See Can I prevent timing attacks with random delays? and Could a random sleep prevent timing attacks?. Worse, the code uses the standard random random number generator, which isn't cryptographically secure and so the sleep variations could be accounted for given a determined enough attacker.
I'd strongly recommend to the author to remove that line, it doesn't offer any actual security here.
This is the code I use to generate a password reset link for my app:
def create_unique_code():
return str(uuid.uuid4())
Is that strong enough? I use a one or two day expiry time.
In CPython, yes. In other Python implementations, probably, but you might want to double-check that a cryptographically strong source of randomness is used to generate the UUID.
There are two factors you might care about when judging whether some way of generating secure random tokens - such as UUIDs - is "strong enough":
Are there enough possible values for it not to be brute-forced?
Is the source of randomness used cryptographically secure?
Since there are 2122 version 4 UUIDs (that's a little over 5 trillion trillion trillion), the answer to point 1 is definitely "yes", in this case. The space of all possible UUIDs ain't going to be brute forceable any time soon.
Point 2 is not currently answered by the official Python docs on uuid.uuid4(), which make no mention of security or whether the randomness source used is strong. Indeed, the entire documentation of uuid4() is just:
Generate a random UUID.
which clearly provides no security guarantees.
Nor is it addressed by the UUID specification, which does not mandate a cryptographically strong source of randomness be used in UUID generation and indeed explicitly contemplates the possibility of a "predictable random number source" being used to generate UUIDs in the Security Considerations section.
However, we can look at the implementation at https://github.com/python/cpython/blob/master/Lib/uuid.py:
def uuid4():
"""Generate a random UUID."""
return UUID(bytes=os.urandom(16), version=4)
Since this uses os.urandom as its randomness source, it's secure. See the docs at https://docs.python.org/3/library/os.html#os.urandom which note that os.urandom returns:
a string of size random bytes suitable for cryptographic use.
Yes, a UUID4 is fully random and long enough to rule out brute forcing or lucky guesses. So as long as whatever RNG uuid.uuid4() provides sufficiently good randomness you should be fine.
However, consider using e.g. a cryptographically signed token (the itsdangerous lib can take care of it) - not only can you specify an expiry time right when generating it, you also won't necessarily have to store anything about the token on your server.
i have developed an AES256 encryption application with but i want to make it more secure. How can i understand how easy it is to reverse engineer and how can i make it less reverse engineerable ?
Note : it would be great if you recommend me some reverse engineering books.
code: http://pastebin.com/uiuBNJ0y
code: for the citizens of countries which has banned pastebin. http://paste.ubuntu.com/22563333/
Since you added the Python label, I guess your algorithm is written in Python. You could use my obfuscator to make your algorithm hard to decipher. It's one way only.
Don't rely on distributing only the .pyc files. They can be trivially reverse engineered without manual intervention even.
I'm testing some code that uses python-gnupg to encrypt/sign/decrypt some plaintext, and I'd like to generate a key pair on the fly. GnuPG is (of course) super paranoid in generating the key pair, and it sucks a lot of entropy from my system.
I found this answer on unix.stackexchange.com, but using rngd to have /dev/random pull from /dev/urandom sounds like a bad idea.
Since I'm testing I don't need high security, I just need the key pair to be generated as quickly as possible.
An idea is to pre-generate some keys offline, and use those keys on my tests. Anyway, I'd like to programmatically generate my temporary key pairs while executing the tests.
This is the code I'm using now (that is, again, super slow and not good for testing):
from tempfile import mkdtemp
import gnupg
def temp_identity():
identity = gnupg.GPG(gnupghome=mkdtemp())
input_data = gpg.gen_key_input(key_type='RSA', key_length=1024)
identity.gen_key(input_data)
return identity
Using any method to change /dev/random to pull out of /dev/urandom is totally fine once the entropy pool was initiated with a proper random state (which is not a problem on hardware x86 machines, but might require discussion for other devices). I strongly recommend watching The plain simple reality of entropy -- Or how I learned to stop worrying and love urandom, a lecture at 32C3.
If you want to fasten-up on-the-fly key generation, consider going for smaller key sizes like RSA 512 (1k keys aren't really secure, either). THis will render keys insecure, but if that's fine for testing -- go for it. Using another algorithm (for example elliptic curves if you already have GnuPG 2.1) might also speed up key generation.
If you really want to stick with /dev/random and smaller key sizes don't provide adequate performance, you can very well pre-generate keys, export them using gpg --export-secret-keys and import them instead of creating new ones.
gpg-agent also knows the option --debug-quick-random, which seems to fit your use case, but I've never used it before. From man gpg-agent:
--debug-quick-random
This option inhibits the use of the very secure random quality level (Libgcrypt’s GCRY_VERY_STRONG_RANDOM) and degrades all request down to standard random quality. It is
only used for testing and shall not be used for any production quality keys. This option is only effective when given on the command line.
Project Euler
I have recently begun to solve some of the Project Euler riddles. I found the discussion forum in the site a bit frustrating (most of the discussions are closed and poorly-threaded), So I have decided to publish my Python solutions on launchpad for discussion.
The problem is that it seems quite unethical to publish these solutions, as it would let other people gain reputation without doing the programming work, which the site deeply discourages.
My Encryption problem
I want to encrypt my answers so that only those who have already solved the riddles can see my code. The logical key would be the answer to the riddle, which is always numeric.
In order to prevent brute-force attacks on my answers, I want to find an encryption algorithm that takes a significantly long time (few seconds) to run.
Do you know any such algorithm? I would fancy a Python package, which I can attach to the code, over an external program that might have portability issues.
Thanks,
Adam
It sounds like people will have to write their own decryption utility, or use something off-the-shelf, or use off-the-shelf components to decrypt your posts.
PBKDF2 is a standardized algorithm for password-based key derivation, defined in PKCS #5. Basically, you can tune "iterations" parameter so that deriving the key from a password (the answer to the Euler problem) would take several seconds. The key can then be used for any common symmetric encryption algorithm, like AES-128.
This has the advantage that most crypto libraries already support PBKDF2. In fact, you might find mail clients that support password-based encryption for S/MIME messages. Then you could just post an S/MIME and people could read it with the mail client. Unfortunately, my mail client (Thunderbird) only supports public-key encryption.
I think Yin Zhu pegged the social aspect of it and Whirlwind the technical. Using your preferred approach of:
python decrypt.py --problem=123 --key=1234567
the key number is readily available to Google, and even without that, slamming through a million keys (assuming a median key length of 5 decimal digits yields less than 20 bits of key) is pretty fast. If I wanted to be more clever I could use plain-text assumptions (e.g. import, for) and vastly reduce my search space.
For all the trouble you're probably best off using something really complicated like:
>>> print codecs.getencoder('rot_13')('import codecs')[0]
vzcbeg pbqrpf
And if you want the solution to Project Euler problem 123, you'll have to beat it out of me...
Yes, you can do this with virtually any symmetric encryption algorithm: DSA, or AES, for example; just use the integer as the key, and pad the key out to the required length of the encryption algorithm's key, and use that key to decrypt the answer.
Keep in mind that if you extend a short key, the encryption won't be very good. The strength of the encryption has a lot more to do with key length and the algorithm itself than how long it takes to run.
This question seems to have some examples of libraries to use with python.
Just use triple DES and use different keys for each iteration, use the number to generate a each of the 3 keys. Pad up the key length with some text, and you're good.
Tripple DES was designed to increase effectiveness against brute force.
It's not the world's most secure option, but I'll keep most bruter's at bay.
If you encrypt your answers, those who have solved the problem simply do not want to see your answers with such effort, provided that they already have plenty of answers to see in the answer page. Those who haven't cannot see. Then your work becomes less useful.
Btw, there are many places providing answers to Project Euler, e.g. Haskell answers, Clojure answers, F# answers. If somebody only wants the answer to a question, he/she could simply run the program. Provided that Python is so popular, google "Python Euler xx" would give you plenty of blogs solving a specific problem.
The simplest approach would be to hash the answer using a secure hash function such as SHA-1, then provide the hash so users can verify their answer. If you want to make brute-forcing more difficult, iterate the hash - eg, provide the result of n recursive applications of SHA1, where n is some parameter you choose to make it difficult to brute-force.
If the number of possible answers is small, though, it'll be difficult to impossible to prevent someone from brute-forcing it even with an expensive hash function.
Edit: Sorry, I misread your original question. If you want to encrypt your answer, you could do that by using the resulting hash, above, as the encryption key for your answer, rather than posting the hash.
If you want an encryption routine that is easy to use and distribute, I recommend Paul Rubin's p3.py. It's probably on the fast side, for how secure it is, but since you seem to be in need of a hurdle to be jumped rather than a siege-resistant wall, it may be a good choice for your purposes.
You could also look into rijndael.py, which is an implementation of AES, and slower than p3.py.