Powershell and AES: If the Salt and IV are both fixed or known, is the encryption inherently unsafe or easier to crack? - powershell

I have recently been using this script to do some data encryption for a different script that I will later on be passing to other users, and I'm currently using a fixed IV and Salt. The reason I am currently using a fixed Salt and IV is that the data I have encrypted only needs to be encrypted once, but will need to be decrypted every time my script is run. As such, having everything fixed means that only the password needs to be known to other users of my script.
From reading around, it seems that having the Salt known does not make too much difference to the ease at which the data can be maliciously decrypted if it is unique, however I assume that by using a fixed Salt I am currently mooting the point of applying it.
My Password that I am passing into this script is entered at the point of encryption/decryption, and is not stored anywhere.
By keeping the Password completely secret, does this strengthen the encryption somewhat?
In addition, does anyone have any advice for a potentially safer implementation?
Many thanks for all help.

Salts and IV's serve the same purpose, preventing the re-use of work by starting at a random starting point. When you are hashing you call it a Salt, when you are encrypting you call it a IV.
Having a fixed Salt and VI is the same affect as having no Salt or IV, the entire point of those two things is they are different every time so if I crack the key on File A I can't reuse the work for File B, I have to start from scratch again.
Normally the Salt and IV are just prepended to the front of the file or are in the file header. When you go to decrypt the file you read in the IV/Salt first then start reading your encrypted data.
What I would do is instead of using a fixed salt and fixed IV I would just let the program generate the Salt and IV.
$r = new-Object System.Security.Cryptography.RijndaelManaged
$r.GenerateIV();
#generate a new instance of our KDF with a random 32 bit salt.
$deriveBytes = new-Object Security.Cryptography.Rfc2898DeriveBytes($Passphrase, 32)
$r.Key =$deriveBytes.GetBytes(32) #generate a 32 bit key based off of $Passphrase
#store $r.IV.Length, $r.IV, $deriveBytes.Salt at the front of your file ($deriveBytes.Salt we know will be 32 bytes big because we set it)
Further reading:
- Is it safe to have the salt equal to IV?
- Secret vs. Non-secret Initialization Vector
- Why would you need a salt [...] when IV is already randomly generated and stored with the encrypted data?

Related

Upgrade password hash from md5 to bcrypt [closed]

Closed. This question does not meet Stack Overflow guidelines. It is not currently accepting answers.
This question does not appear to be about programming within the scope defined in the help center.
Closed 8 years ago.
Improve this question
Its been discussed here before, but there seems to be no conclusion.
Ideally, don't want to maintain state (upgraded/not upgraded) in the database etc. so, here is what I'm thinking:
bcrypt the MD5'd password, and use "username + something else" as a salt.
Does this scheme make any sense?
Also, in general is it a good idea to use the username as a part of the salt? I read somewhere that adding a different salt to each hash makes it more secure. Is that correct (especially in context of bcrypt)?
Surely it is a good idea to switch to a more secure hash algorithm. There is a function password_hash() you can use for creating a BCrypt hash:
// Hash a new password for storing in the database.
// The function automatically generates a cryptographically safe salt.
$hashToStoreInDb = password_hash($password, PASSWORD_DEFAULT);
// Check if the hash of the entered login password, matches the stored hash.
// The salt and the cost factor will be extracted from $existingHashFromDb.
$isPasswordCorrect = password_verify($password, $existingHashFromDb);
From your answer i guess that you used an unsalted MD5 value, so double hashing can be a good solution here. Just pass the MD5 hash to the password_hash() function, it will generate a safe salt on its own.
// Migrating the old MD5 hashes to MD5-BCrypt
$hashToStoreInDb = password_hash($existingMd5Hash, PASSWORD_DEFAULT);
For verification first check for a double hash, and then verify the password accordingly.
if (checkIfDoubleHash($existingHashFromDb))
{
$isPasswordCorrect = password_verify(MD5($password), $existingHashFromDb);
// Update database with pure BCrypt hash
if ($isPasswordCorrect)
$hashToStoreInDb = password_hash($password, PASSWORD_DEFAULT);
}
else
{
$isPasswordCorrect = password_verify($password, $existingHashFromDb)
}
The stored hashes can be recognized by the leading $ or by a separate db field, a BCrypt hash for example always starts with a $ character, an MD5 hash does not.
A salt should not be derrived from other parameters and it should be unique per password. The password_hash() function will take care of this. Since a rainbowtable must be built fore each salt, an attacker would have to build a rainbowtable for each password. For more information you can have a look at my tutorial about secure password storing.

How to calculate a 256-bit HMAC_SHA3 hash with CryptoJS?

Recent CryptoJS versions support SHA3 hashing.
SHA3 can output different hash sizes, including 512-bit (default) and 256-bit. These two work fine:
var sha3_512_hash = CryptoJS.SHA3( 'test' );
var sha3_256_hash = CryptoJS.SHA3( 'test' , { outputLength:256 } );
Similarly, CryptoJS can also calculate HMAC values. However, I can't figure out how to change the default output size there:
var sha3_512_hmac = CryptoJS.HmacSHA3( 'test' , 'key' );
var sha3_256_hmac = CryptoJS.HmacSHA3( 'test' , 'key' , { outputLength:256 } );
The first works OK (the result is a 512-bit hmac value) but the second is the same (i.e. also 512-bit), as if it ignores the {outputLength:256} parameter!
Here's a live example: http://jsfiddle.net/M8xf3/ (using hmac-sha3.js from CryptoJS 3.1.2)
Does anyone know how to create 256-bit SHA3-based HMAC hashes?
P.S. For the SHA2 family of functions, CryptoJS has separate Hmac functions for each output size (that's HmacSHA256 and HmacSHA512). But this doesn't seem to be the case for SHA3?
This doesn't answer the actual question, but note that with SHA3 you don't really need HMAC hashes. Unlike SHA1 and SHA2 and MD5, SHA3 is not vulnerable to length-extension attacks.
Therefore with SHA3 it would suffice to just prepend or append the secret key to your input.
Or, if you're paranoid of a single hash step becoming compromised (not to be expected in the foreseeable future, especially not with SHA3, but still) you could do something like SHA3(key+SHA3(key+data)) or SHA3(key+SHA3(key+data)+data) (obviously with "+" denoting binary concatenation).
You can just edit hmac-sha3.js and change the outputLength to 256-bit instead of 512-bit.
Open hmac-sha3.js file, using your text editor.
Find "{outputLength:512}" and replace it with "{outputLength:256}"
Then the hash output will be 256-bit in length.
To be sure that you did not messed up things, double check your 256-bit hmac-sha3 output with some test cases available on the internet, for example: http://www.di-mgt.com.au/hmac_sha3_testvectors.html

Password hashing (crackstation.net)

I have a question regarding password hashing. I found a great tutorial on http://crackstation.net/hashing-security.htm. This is how I create a hash from the password using this code:
$hashed_password = create_hash(form_password);
The problem with this code is that it creates a different hash for the same password every time. I guess it's because of adding a random salt to the password:
function create_hash($password)
{
// format: algorithm:iterations:salt:hash
$salt = base64_encode(mcrypt_create_iv(PBKDF2_SALT_BYTES, MCRYPT_DEV_URANDOM));
return PBKDF2_HASH_ALGORITHM . ":" . PBKDF2_ITERATIONS . ":" . $salt . ":" .
base64_encode(pbkdf2(
PBKDF2_HASH_ALGORITHM,
$password,
$salt,
PBKDF2_ITERATIONS,
PBKDF2_HASH_BYTES,
true
));
}
So due to this, I cannot compare the hash created from the password typed by the user at the login with the hash retrieved from the database, because that hash will never be the same with the one stored in the database. The only way I see that it can be done is to store the salt in another column, or am I wrong?
A thing also annoys me. The format of the hast is e.g. sha256:1000:u9p+OqAZgVkIBtlTBkr9ZxhFvtt+zjcA:PvhJY+oesrdBeD5pjeXMQ/3wficCU0EG. A hacker obviously knows this form of hash so the algorythm that created this hash is clear for him. Let's suppose the database has been compromised and thousands of these hash codes were revealed. Doesn't having this form of hash code raise security issues? I guess a simple OqAZgVkIBtlTBkr9ZxhFvtt+zjcA:PvhJY+oesrdBeD5pjeXMQ/3wfic would be better because it reveals nothing about the encryption mechanism.
Read this link to Wikipedia here
It explains more about the use of a random salt. The key information there is that the random salt is stored in the same database as the hashed password. It is only created randomly a few time, when the user creates or changes their password. It is used whenever authentication is required.
Leaving the info about which algorithm it used to create the password hash leaves you the option of changing the algorithm at some time in the future without interrupting your users. If you decide up upgrade the hash algorithm you wait until a user logs in. At that point you have their password in plain text. Once you authenticate against the old algorithm, you rehash and store the new hash in their database row. It may take months or years for all users to log in but once they have they will accrue the benefits of better hashing. So you would then send out an email asking them to login and read your special news about better security (and as a side effect, improve their hashed password).
Here is an interesting discussion of password hashing StackOverflow:Passwords Storage Hash ...
The reason two hashes of the same password don't match for you is because the result of create_hash() includes the salt, which is randomly generated.
To get the same hash, you have to provide the salt as you validate. The code CrackStation.net provides makes this super simple - just store the result of create_hash() in your database, exactly as-is. To confirm a user entered the correct password, use
validate_password('provided-password','hash-from-database');
This will return a boolean of whether the password was correct. Using this method is better than writing your own, because it is specifically designed to prevent certain hints at what the correct password might be based on the time it takes to return an answer. This is a minor weakness, but better to avoid it anyway, especially since the provided function takes care of it for you.
The provided functions give you a solid implementation, so don't mess with it too much. The hash includes those extra details - sha256:1000 - in order to allow future changes to your hashing without affecting the ability of existing users to login; it will simply use the method provided in the hash, no matter what the current method is.
As far as showing a potential attacker how the hash was created: the format does show everything about how, but this doesn't matter very much at all. An attacker can easily figure out the method used from one or two known password:hash pairs. Far more important than this is using a good algorithm. The goal is to make it difficult to impossible to crack the password even with all the details, as security by obscurity is poor security.
Finally, just to reiterate, you do not need to store the salt in a separate column, just leave the big 70-80 character chunk it returns alone as your hash and let the functions take care of everything for you - anything else is a waste of time and resources
To add a bit more to the excellent accepted answer:
The point about salting the hash is to make it impossible for someone to come along with a huge pile of pre-encrypted hashes and try them one by one. Even with the salt in your database, they'd have to hash every possible dictionary entry against that salt to successfully match a hash. And the salt needs to be different every time to prevent duplicate entries (they hack one password, they have that same password that other users have entered).
As for not being able to compare the login hash to the stored hash, that is on purpose: you use a validation function to check the login password against the stored password, not a string comparison function.
Store the salt then add the salt to the password then turn it into a hash then store it.
Then to compare the passwords you retrieve the salt and add it to he password, convert it into a hash and then compare the two hashes.
(python example, the indentation is messed up when I copied the code from my code)
def Createpassword():
import random
import hashlib
username = input("type your username")
newpassword = input("type your new password? ")
#adds some salt
b = random.randint(1, 2000000000000)
randomsalt = str(b)
saltedpassword = (newpassword + randomsalt)
#hashes the newpassword
saltedpassword = saltedpassword.encode('utf-8')
h = hashlib.sha256(saltedpassword)
finsh = h.hexdigest()
#creates file names
saltname = username + "salt.txt"
username = username + ".txt"
#saves the hashedpassword and the salt
text_file = open(username, "w")
text_file.write(finsh)
text_file.close()
text_file = open(saltname, "w")
text_file.write(randomsalt)
text_file.close()
print("your new password has been saved")
def EnterPassword():
trys = 0
while (trys < 3):
username = input("type your username: ")
#takes password input
password = input("type your password: ")
#gets file names
saltname = username + "salt.txt"
username = username + ".txt"
#opens salt file
text_file = open(saltname, "r")
salt1 = text_file.read(50)
text_file.close()
#opens the hashed passwords file
text_file = open(username, "r")
correctpassword = text_file.read(500)
text_file.close()
#adds the salt to the password input
saltedpassword = password + salt1
#hashes the saltedpassword
saltedpassword = saltedpassword.encode('utf-8')
m = hashlib.sha256(saltedpassword)
hashedpassword = m.hexdigest()
#compears hashed passwords
if hashedpassword != correctpassword:
trys += 1
print("your password or username is incorrect")
if trys == 3:
print("you have been locked out for using to many failed trys")
if hashedpassword == correctpassword:
print ("Password Correct ")
#done give access
trys = 0
break
(I'm new to programming so feel free to correct me)

Which hash function can this be?

I have some strings and some hashes of them, but I don't know which hash function is used. Any idea?
String hash
NN34W f8b46bcdc3b3c92
EM3M3 d8015ca876fd051
HXDKD a740e97464e5dfe
AKREJ aa7aa2dadfcbe53
3bNMK 0f11440639191d9
Edit:
Thank for answers, it's a hash of the captcha.
https://registracia.azet.sk/
If you check URL of captcha image, on the end is HASH value. This
On the server are send in HTTP POST are send TEXT: (P92M4) and HASH (72fec89a2e0ade2) and other values.
I like know how comptute hash of the TEXT P92M4, and control with HASH value, which is send on server.
Because I like make own captcha system for my school project, so I first analyzing situation and weakness.
As I understand your situation, a POST request sends both the "text" and the "hash" to the CAPTCHA server. This then uses whatever hash function they use to hash your text, checks to see if it matches the hash, and decides whether or not you succeeded. Presumably, the server sends you the image, as well as the hash, and then you enter the text.
As such, if you figured out the hashing function, you'd have completely broken this CAPTCHA system: All you would need to do is hash any string using their hashing function, and then when sending your POST request, ignore the hash they sent you and merely send them your computed text and hash pair. Thus, you could very easily automate successfully passing the CAPTCHA challenge.
To illustrate how difficult "reversing" the hash might be, consider the following hash that they very well might use:
Split the TEXT up alternating letters: thus ABCDE becomes ACE and BD
md5 the two halves using salts "fj49w0utw4a" and "r8h3wlsd"
md5("fj49w0utw4a"."ACE") is 115c05f0e5300f958ba01caa64b989f
md5("r8h3wlsd"."BD") is 74eecae86ef46382eb95443a1b1fa8f5
Take every 3rd char of the first string and every 4th char of the second, and alternate them until you have 15 chars
115c05f0e5300f958ba01caa64b989f becomes 55e09b1ab9
74eecae86ef46382eb95443a1b1fa8f5 becomes e8425af5
Final hash value for "ABCDE": 5e58e40295ba1fa
There is really no way you are ever going to reverse engineer that.
UPDATE
Note that CAPTCHAs as described above (and implemented on that site) are extremely insecure, as they only require one valid text/hash combination to be known
To demonstrate, use Firebug or equivalent and navigate to the CAPTCHA area of the form. We will be editing some hidden values.
Change the form[captcha_url] value from https://pokec.azet.sk/sluzby/system/captcha/[somehash] to https://pokec.azet.sk/sluzby/system/captcha/ee2be1f239e5d17
Change the form[captcha_hash] value from [somehash] to ee2be1f239e5d17
Regardless of what the picture says, type "P22KD" for the CAPTCHA
There are several ways to mitigate this vulnerability. As Tangrs suggested, you can store the hash value in a session variable so that it cannot be manipulated by the client. Less elegant but also effective is to store the submitted CAPTCHA in a database and not allow duplicate CAPTCHAs, as is implemented on the link in the question. This is fine, until you start running out of unused CAPTCHAs and end up getting collisions.
Seems smaller than any industry hash... possibly it's propriety?
A bit more info would help though, what language, where did you get it from?

Examples of Hash-Collisions?

For demonstration-purposes, what are a couple examples of strings that collide when hashed? MD5 is a relatively standard hashing-option, so this will be sufficient.
The second-most interesting collision I know of is this:
(30820432)3082039ba003020102020309cfc7300d06092a864886f70d0101040500305a310b300906
0355040613025553311c301a060355040a1313457175696661782053656375726520496e632e312d
302b06035504031324457175696661782053656375726520476c6f62616c2065427573696e657373
2043412d31301e170d3038313130333037353230325a170d3039313130343037353230325a308201
1c310b300906035504061302555331493047060355040a1340692e62726f6b652e7468652e696e74
65726e65742e616e642e616c6c2e692e676f742e7761732e746869732e742d73686972742e706872
6565646f6d2e6f726731133011060355040b130a475431313032393030313131302f060355040b13
28536565207777772e726170696473736c2e636f6d2f7265736f75726365732f6370732028632930
38312f302d060355040b1326446f6d61696e20436f6e74726f6c2056616c696461746564202d2052
6170696453534c2852293149304706035504031340692e62726f6b652e7468652e696e7465726e65
742e616e642e616c6c2e692e676f742e7761732e746869732e742d73686972742e7068726565646f
6d2e6f726730820122300d06092a864886f70d01010105000382010f003082010a0282010100b2d3
2581aa28e878b1e50ad53c0f36576ea95f06410e6bb4cb07170000005bfd6b1c7b9ce8a9a3c5450b
36bb01d153aac3088f6ff84f3e87874411dc60e0df9255f9b8731b5493c59fd046c460b63562cdb9
af1ca86b1ac95b3c9637c0ed67efbbfec08b9c502f29bd83229e8e08faac1370a2587f62628a11f7
89f6dfb667597316fb63168ab49138ce2ef5b6be4ca49449e465510a4215c9c130e269d5457da526
bbb961ec6264f039e1e7bc68d850519e1d60d3d1a3a70af80320a170011791364f0270318683ddf7
0fd8071d11b31304a5daf0ae50b1280e63692a0c826f8f4733df6ca20692f14f45bed93036a32b8c
d677ae35637f4e4c9a934836d99f0203010001a381bd3081ba300e0603551d0f0101ff0404030204
f0301d0603551d0e04160414cda683faa56037f796371729de4178f1878955e7303b0603551d1f04
3430323030a02ea02c862a687474703a2f2f63726c2e67656f74727573742e636f6d2f63726c732f
676c6f62616c6361312e63726c301f0603551d23041830168014bea8a07472506b44b7c923d8fba8
ffb3576b686c301d0603551d250416301406082b0601050507030106082b06010505070302300c06
03551d130101ff04023000(300d06092a864886f70d010104050003818100a721028dd10ea2807725
fd4360158fecef9047d484421526111ccdc23c1029a9b6dfab577591dae52bb390451c3063563f8a
d950faed586cc065ac6657de1cc6763bf5000e8e45ce7f4c90ec2bc6cdb3b48f62d0feb7c5267244
edf6985baecbd195f5da08be6846b175c8ec1d8f1e7a94f1aa5378a245ae54ead19e74c87667)
which collides with this (remove the parts in parentheses):
(30820432)3082039ba003020102020141300d06092a864886f70d0101040500305a310b3009060355
040613025553311c301a060355040a1313457175696661782053656375726520496e632e312d302b
06035504031324457175696661782053656375726520476c6f62616c2065427573696e6573732043
412d31301e170d3034303733313030303030305a170d3034303930323030303030305a303c313a30
38060355040313314d443520436f6c6c6973696f6e7320496e632e2028687474703a2f2f7777772e
7068726565646f6d2e6f72672f6d64352930819f300d06092a864886f70d010101050003818d0030
818902818100baa659c92c28d62ab0f8ed9f46a4a437ee0e196859d1b3039951d6169a5e376b15e0
0e4bf58464f8a3db416f35d59b151fdbc438527081975e8fa0b5f77e39f032ac1ead44d2b3fa48c3
ce919becf49c7ce15af5c8376b9a83dee7ca2097314273159168f488aff92828c5e90f73b0174b13
4c9975d044e67e086c1af24f1b410203010001a382022430820220300b0603551d0f0404030201c6
300f0603551d130101ff040530030101ff301d0603551d0e04160414a704601fab724308c57f0890
55561cd6cee638eb301f0603551d23041830168014bea8a07472506b44b7c923d8fba8ffb3576b68
6c308201be06096086480186f842010d048201af168201ab33000000275e39e089610f4ea3c5450b
36bb01d153aac3088f6ff84f3e87874411dc60e0df9255f9b8731b5493c59fd046c460b63562cdb9
af1ca8691ac95b3c9637c0ed67efbbfec08b9c502f29bd83229e8e08faac1370a2587f62628a11f7
89f6dfb667597316fb63168ab49138ce2ef5b6be4ca49449e465110a4215c9c130e269d5457da526
bbb961ec6264f039e1e7bc68d850519e1d60d3d1a3a70af80320a170011791364f0270318683ddf7
0fd8071d11b31304a5dcf0ae50b1280e63692a0c826f8f4733df6ca20692f14f45bed93036a32b8c
d677ae35637f4e4c9a934836d99f0203010001a381bd3081ba300e0603551d0f0101ff0404030204
f0301d0603551d0e04160414cda683faa56037f796371729de4178f1878955e7303b0603551d1f04
3430323030a02ea02c862a687474703a2f2f63726c2e67656f74727573742e636f6d2f63726c732f
676c6f62616c6361312e63726c301f0603551d23041830168014bea8a07472506b44b7c923d8fba8
ffb3576b686c301d0603551d250416301406082b0601050507030106082b06010505070302300c06
03551d130101ff04023000(300d06092a864886f70d010104050003818100a721028dd10ea2807725
fd4360158fecef9047d484421526111ccdc23c1029a9b6dfab577591dae52bb390451c3063563f8a
d950faed586cc065ac6657de1cc6763bf5000e8e45ce7f4c90ec2bc6cdb3b48f62d0feb7c5267244
edf6985baecbd195f5da08be6846b175c8ec1d8f1e7a94f1aa5378a245ae54ead19e74c87667)
Those are two X.509 certificates of which only the first one was actually signed by the Certificate Authority. The first part is just a header, but the last part (which you will note is the same in the two certificates) is an RSA signature of the MD5 hash of the colliding messages. This means that the second (fake) certificate will validate as having been signed by the Certificate Authority's private RSA key.
This attack involved more than 200 Playstation 3 to prepare the attack and some clever timing on the part of the attackers. For more details see: MD5 considered harmful today.
The most interesting collision I know of is the one used in the Flame espionage malware. Using a different, but similar, technique, an advanced persistent threat (most probably a western intelligence agency) created a fake code signing certificate that claimed to have been signed by Microsoft. See for instance this article. Unfortunately, I don't have access to the actual certificates and the actual MD5-collision.
This page provides these examples of 128 byte values hashing to the same value:
d131dd02c5e6eec4693d9a0698aff95c 2fcab58712467eab4004583eb8fb7f89
55ad340609f4b30283e488832571415a 085125e8f7cdc99fd91dbdf280373c5b
d8823e3156348f5bae6dacd436c919c6 dd53e2b487da03fd02396306d248cda0
e99f33420f577ee8ce54b67080a80d1e c69821bcb6a8839396f9652b6ff72a70
and
d131dd02c5e6eec4693d9a0698aff95c 2fcab50712467eab4004583eb8fb7f89
55ad340609f4b30283e4888325f1415a 085125e8f7cdc99fd91dbd7280373c5b
d8823e3156348f5bae6dacd436c919c6 dd53e23487da03fd02396306d248cda0
e99f33420f577ee8ce54b67080280d1e c69821bcb6a8839396f965ab6ff72a70
Note that although your question asked for "strings" which collide, MD5 is defined over binary data, so the normal text meaning of "string" doesn't really apply. Languages and libraries which allow you to take the MD5 hash of text data usually mean "encode the string in a specified encoding, then hash the result."
Søren Steffen Thomsen released a md5 collision finder utility written in C. Might be fun to play with.
(For the future readers I want to add this resource)
Here is a pretty recent collection at GitHub, ranging from pictures to poc-scripts.
*Includes shattered