Issue authenticating SHA512 password encrypted from .NET in PHP - php

I have been trying for a while now to authenticate a password encrypted in .NET from a PHP API and despite trying different ways I can't seem to get it to match.
The password was encrypted using SHA512 and stored in the database in a binary(64) field, using this exact function (which I do not have control over, it cannot be modified. No salt is used) :
> public byte[] GetHashablePw(string pwByte)
> {
> System.Security.Cryptography.SHA512Managed sm = new System.Security.Cryptography.SHA512Managed();
> System.Text.UnicodeEncoding u = new System.Text.UnicodeEncoding();
> byte[] b = new byte[-1 + 1];
> b = sm.ComputeHash(u.GetBytes(pwByte));
> return b;
> }
When I want to compare the password the user supplies, I tried these different ways :
$pwhash = openssl_digest($_POST['pw'], 'sha512');
$pwhash = bin2hex(pack('H*', hash('SHA512',$_POST['pw'])));
$pwhash = openssl_digest(utf8_decode($_POST['pw']), 'sha512');
$pwhash = bin2hex(hash('sha512', $_POST['pw'], true));
which all return the same result really but none is matching what got stored in the database from .NET.
I get my password hash stored in the database with this :
bin2hex($pwFromDB);
In one particular case, I get this as a hash stored in the database:
4c0dc75a062dd4957f6f91350f6d3f54f910989e6ffe82749cdc580b9eae5dce0ee743cd513d005d0c399e23b0190809767fe1a57f9fecbce0a928296181c14e
while I get this from the PHP functions using the same password :
c3cf6055cbb36e3eace5ca470922de6e754ec93cf80f35459c910f4381899483e2c29565f062476724dad94929527d53eeae5a1cd708c6227574e58748d354aa
I would appreciate any help in understanding what I am missing.

The C# is using UnicodeEncoding, which is UTF-16LE.
You need to get the PHP data into that same representation, since cryptography operates on bytes, not text. http://php.net/manual/en/function.mb-convert-encoding.php might be what you want.
Also, the string is not encrypted. Encryption requires there be an undo operation (decryption). What has been done here is hashing. This password was hashed.

Related

Is there a PHP crypt($string,$salt) equivalent in Vb.Net? Can't find/create any with $salt

I'm trying to compile a software written in VB (I'm using VisualStudio2010, Framework 4) that lets users change their passwords on a website (sadly the website default changepassword form doesn't work, and I can't fix that via PHP).
I don't have much experience with PHP and encrypting, so I looked on the internet for some solutions for VB.Net, but didn't get the expected results after 2 days of trying.
I did some research, and that's what I learned:
Website's PHP code uses the crypt($string,$salt) function to create the hashed password.
The encoding is a MD5 algorithm, as my salt is something like '$1$ad000000$' for every password in website's database.
I tried to replicate it in VB and the issues start on the ComputeHash(buffer() as Byte), as it doesn't support a "Salt" String.
The code on PHP is as simple as that:
$EncryptedPassword = crypt($userPassword, $salt);
The salt is generated to look like, for example, "$1$ad000000$"
The $EncryptedPassword length is 34 (12salt + 22hash), but I guess this is a standard length of the crypt() function, given a specific salt.
This is what I'm currently trying on VB:
Dim Hashata = GetHash("asdkFAofkas", "$1$ad000000$")
Private Function GetHash(ByVal p1 As String, ByVal Salt As String) As Object
Using hasher As MD5 = MD5.Create()
Dim dbytes As Byte() = hasher.ComputeHash(Encoding.UTF8.GetBytes(p1 & Salt))
Dim Conversione = Convert.ToBase64String(dbytes)
Return Conversione
End Using
End Function
The return string is a 24-character string always ending with "==" no matter what "p1" is, and I read on the internet that these last two characters are optional, so when creating the password-hash with Salt, I just do:
Dim StoredPassword = Salt & Hashata.Substring(0,Hashata.Length-2)
The created StoredPassword (VB) doesn't coincide with the password (PHP) in the DataBase when I write the same Password.
I tried this with creating multiple users on the website with the same Password, and they are all hashed in the same way in the Database.
For example, this is what I have in the Database:
-------------------------------------------------
| Username | Password |
-------------------------------------------------
|test1 |$1$ad000000$kcpPLtMxsedGD0d39UnXQg |
-------------------------------------------------
|test2 |$1$ad000000$kcpPLtMxsedGD0d39UnXQg |
-------------------------------------------------
|test3 |$1$ad000000$kcpPLtMxsedGD0d39UnXQg |
-------------------------------------------------
|testVB |$1$ad000000$5u-9pdu3HDnXt5pGdXZNug |
-------------------------------------------------
test1,test2,test3 have passwords made on website
testVB has a password generated by VB's function above
I wrote the exact same password for test1,test2,test3 and testVB.
ALL passwords on the database have a length of 34 characters
I already tried the following (on VB, as I can't modify website's PHP):
Encode only p1, only Salt, both variables mixed (like in the code above)
Convert p1 and Salt to a hex string (first only one, then only the other one, then both, etc...) before encoding them singularly or while mixing them
Use different types of Encoding (UTF-7, UTF-16, UTF-32, "Default" and ASCII)
I'm pretty sure the issue is on the ComputeHash Function, which doesn't have a "Salt" property (it has an offset and count properties, but I didn't use them), and without that, it can't crypt in the way I'd like.
Is there a way to replicate PHP's crypt($string, $salt) function?
I can bet that without the $salt they coincide (I already found some solutions that worked like that, but I need that $salt for crypting because I cannot modify website's PHP code to crypt without $salt).
Thanks a lot, sorry for the long read, I want to make sure I didn't miss anything :)
If there's something else I need to add, let me know!
Bcrypt.NET gives you want you want.
string passwordHash = BCrypt.HashPassword("my password");
if (BCrypt.Verify("my password", passwordHash)) {
// Valid
} else {
// Incorrect password
}

Check password stored with PBKDF2 with php

I have a big problem, I have to write a php login page using an db where password are stored as PBKDF2 (with another perl script). When I get the password with a query I read this:
sha256:1000:2SeBDP88w4bqKbJaCJNpNuRHQhUM96X1:jgh/SZtmRWH5iDIwtXyFLtuuDf7YE+7HQEJZ4KFFNAg= (I know this password but I cannot regenerate it in php).
I tried with this script (get from php.net):
$password = "qqqqq";
$iterations = 1000;
$salt = "2SeBDP88w4bqKbJaCJNpNuRHQhUM96X1";
$hash = hash_pbkdf2("sha256", $password, $salt, $iterations, 20);
echo $hash // result a2ba3349194c38f828af
but the pass generate is a2ba3349194c38f828af and not jgh/SZtmRWH5iDIwtXyFLtuuDf7YE+7HQEJZ4KFFNAg=
who wrote the perl script that store these password told me "The passwords are getting encoded though one-way hashing scheme named 'PBKDF2'"
Some ideas? Someone know where I'm wrong?
jgh/SZtmRWH5iDIwtXyFLtuuDf7YE+7HQEJZ4KFFNAg= is Base64 (the = on the end is a dead giveaway, though Base64 exists without a trailing =).
Converted to hex, the value is 8E087F499B664561F9883230B57C852EDBAE0DFED813EEC7404259E0A1453408
This is still not your answer, but now we can easily see it is 64 hex characters => 32 bytes.
You asked for 20 bytes.
It also looks like your salt input is base64, but the function you're passing it to expects ... whatever the output of base64_decode is.
So, you need to consistently process the base64-encoded data. And then you'll need to make sure that your hash algorithm, iteration count, and output byte count all match what the perl script says.
try this
$hash = strtoupper(bin2hex($hash));

Decrypt password in php

How to decrypt password in plain text which are in ms-SQL database?
$encrypted_password="k??aU?????y-??N???tDRz????{?4R???G?aS4t?T";
$salt = "611233880";
So I need to decrypt password so that I insert into other database with md5 encryption.
I used this code, but not get success
$iv2 = '';
for($i=0;$i<16;$i++){
$iv2 .= "\0";
}
$plain_text_CBC = mcrypt_decrypt(MCRYPT_RIJNDAEL_128, $salt, $encrypted_password, MCRYPT_MODE_CBC, $iv2);
var_dump($plain_text_CBC);
$plaintext = openssl_decrypt($encrypted_password, 'AES-256-CBC', $salt, 0, $iv2);
var_dump($plaintext);
Need Help
The idea behind encrypted (or hashed) passwords is that it is a one way operation. Not quite like shredding, but that's the idea. If you take exactly the same input and shred it you should get exactly the same output. You may not be able to reconstruct the input from it, but you can confirm someone gave you the right input by looking at the output.
Some weak algorithms have been know to be hacked buy in principle what you are asking for is impossible.
The ought to be no reason reason to decrypt. You can always do the hashing operation twice - first with the old algorithm, then with the new one - and then compare with the entry in the database.
NEVER EVER store plaintext (or weakly encrypted) passwords. Just ask LinkedIn...
You don't simply decrypt a password. It should be hashed which means it is a one way encryption.
If you want to change your password hashing implementation, here is a way to do it.
You have the clear text password available when a user is in the process of logging in. So that's where you will have to place code to rehash the password with the new algorithm.
If you are using the new native password hashing functions (PHP Version >= 5.5) then you can use password_needs_rehash. If you are on a lower PHP Version but still >= 5.3.7 then you can use the userland implementation to get the same API to the password hashing functions.
So when a user is attempting to log in and the password needs rehashing, check if the hashes match with the old hashing function and then create and save the new one to the database. Over time you will be able to migrate most users and then you can think about a solution to migrate the rest of your userbase with a forced password reset if they never logged in during your migration timeframe.
Firstly, you encrypting your data by 2 different algorithms. Why? One algorithm is enough.
Answer: You can't decrypt old password.
Solution: You should encrypt data you wrote into password field and compare result with data in database. If they are equal, you will pass password check.
For example:
$login = mysqli_real_escape_string($_POST['login']);
$password = mysqli_real_escape_string($_POST['password']);
$password_hash = md5($input); // you can use there any other algorithm, just example
// make next query and control result
$sql = 'select count(id) from users where login = \'$login\' and password = \'$password_hash\'';
// now if there are 1 row with this login and same password hash let user log in to your site
If you write your code in the MVC structure, you can use the function n_decrypt() to decrypt passwords.

PHP version of ASP.net/VB.net Login

I am creating a PHP-version of a login script that is in ASP.net/VB.net. The database where the usernames and passwords are stored is in MSSQL and that will not change. Passwords are stored as binary data. Here's a part of the code in VB.net that compares the password to the one saved in the database.
Dim sha1 As sha1 = sha1.Create()
Dim password As Byte() = sha1.ComputeHash(Encoding.Unicode.GetBytes(Me.txtPwd.Text))
CustData = .GetCustomerByEmail(Me.txtUser.Text, password)
I found out that it's part of a library.
I am encountering problems after hashing the password in PHP's sha1. I don't know how to convert the hashed string to a binary that I could use to compare it to the database.
As an example, the password "Test100" in the MSSQL database has a value of (after unpack('H*', $binaryPassword)) 7397001ce5259b79c436a369b9d3a8c7bc2a85385fdec57a. I am not sure how to get that string above from the hashed password I am getting using PHP.
Here's what I have in PHP so far and where I am stuck in.
$password = sha1(mb_convert_encoding($_POST['password'], 'utf-16le'), false); // $_POST['password'] = 'Test100'
The output for that is 8415ec8cc9287a10f81db5a77341709d304bfa92.
So I am thinking there's one more step to change $password to $binaryPassword or the hexadecimal representation of the binary password.
From this page, it's saying Byte is an 8-bit unsigned integer, but not really sure how to get that from a PHP string.
Thanks in advance!
What happens if you try to run the sh1 on the static text "Test100"?

Matching 128 character password hash in PHP - encrypted with Ruby on Rails

We have a website built in Ruby on Rails.
User registration is processed through the site in Ruby and the password is hashed using SHA1.HexDigest function of Ruby with a different salt for every user.
What I need to do is that - create a webservice in PHP which will login the user already registered on the website.
For that I will need to produce a same hash from the user input.
As I have almost zero knowledge of Ruby, so I did a lot of research on how we can reproduce the same with PHP. I went through the following link, but to no avail.
How to generate the password in PHP as it did by Devise Gem in Ruby on Rails
Ruby also processes/hashes the input for a number of times (i.e. stretches, as you may call it in Ruby).
The hash saved in the database is 128 characters in length.
Salt length is 20 characters.
Don't know if some sort of pepper is used as well.
Example,
user input = 123456
salt = g0i3A51x0xa7wrfWCMbG
database password (128 char hash) = 5374f9853f96eaa5b3c1124f9eb1dbbb63fb5c5ce40abb41ec88c745ec3455328685f3046cac8c356a4d81dbd315fd09173c54dc94a4208e5bc091776b02eb77
If someone can replicate the same hash with PHP, using the above given user-input and salt, then please share the code.
Please help.
It'll be very helpful of urs.
Thanks
class Sha1 < Base
# Gererates a default password digest based on stretches, salt, pepper and the
# incoming password.
def self.digest(password, stretches, salt, pepper)
digest = pepper
stretches.times { digest = self.secure_digest(salt, digest, password, pepper) }
digest
end
private
# Generate a SHA1 digest joining args. Generated token is something like
# --arg1--arg2--arg3--argN--
def self.secure_digest(*tokens)
::Digest::SHA1.hexdigest('--' << tokens.flatten.join('--') << '--')
end
I would start with a simpler hashing routine on both sides, stretching and salt are great, but start without those and do a simple hash on both sides to see if you can get them to line up. Then you can go add salt/stretching later.
On the ruby side start with something like:
require 'digest/sha1'
Digest::SHA1.hexdigest(string)
When you hash you cant decrypt, you have to hash on both sides and compare the result.
If you really want to encrypt something and then decrypt, try this:
http://jnylund.typepad.com/joels_blog/2007/11/cross-language-.html.
A straightforward translation of the above Ruby code is:
function hashPassword($password, $stretches, $salt, $pepper) {
$digest = $pepper;
for ($i = 0; $i < $stretches; $i++) {
$digest = sha1("--$salt--$digest--$password--$pepper--");
}
return $digest;
}
To use SHA-512 (128 hex digit output) instead of SHA-1 (40 hex digit output), replace sha1(...) with hash('sha512', ...).
I cannot check this code against the hash you posted because the "pepper" is a secret configuration setting I do not know. If it is not configured, try the empty string.

Categories