How to do user authentication from wordpress database in nodeJS.
I need to validate user if username/password is correct, using wordpress database. Wordpress is using PHPass PHP library to encrypt passwords. But I need to match password in NodeJS.
Edit: Today there is an implementation which supports Wordpress portable hashes: wordpress-hash-node.
Previous reply:
Sigh... I took an interest in this, and spent half an hour pouring through PHPass source code. Then I googled for node phpass.
Edit: On closer inspection, this seems to only implement bcrypt encryption, while the PHPass default (which I think Wordpress uses) is something they call "Portable Hashes". node-phpass throws 'Portable hashes are not implemented' when you ask for Portable Hashes. I suggest you implement that for node-phpass and send a pull request.
For Wordpress 4.9.5, in NodeJS after
npm i wordpress-hash-node
var hasher = require('wordpress-hash-node');
let wordpressHashPass = "$P$BzPE3JGpq4CUpvpMHhtPh3lZmIoG.s1";
let wordpressPlainTextPass = '(&#fZsImcKq7K3Lmd&qBe!Jx';
var checked = hasher.CheckPassword(wordpressPlainTextPass, wordpressHashPass); //This will return true
console.log(checked); // returns true
var hasher = require('wordpress-hash-node');
let wordpressHashPass = "$P$BzPE3JGpq4CUpvpMHhtPh3lZmIoG.s1";
let wordpressPlainTextPass = 'goodday';
var checked = hasher.CheckPassword(wordpressPlainTextPass, wordpressHashPass); //This will return false
console.log(checked); // returns false
wordpressHashPass is the MD5 hashed password that you can find in the wp_users table of Wordpress for a user.
wordpressPlainTextPass is the plain text password that the user types in the password field.
The method CheckPassword compares the plain text password and the hash password. It returns true if it coincides and false if it does not coincides.
Related
I'm trying to migrate users from our legacy Cerberus SFTP server to a new AWS Transfer Family SFTP server. The problem is most of our Cerberus users have password based authentication and all I have access to is their one-way hashed password. Thus I'm trying to reverse engineer how Cerberus hashes it's password so I don't have to ask our 100+ customers to submit a new password to use or switch to a public key based authentication.
I came across this blog post that I think details how to do it but I can't seem to get it to work for some reason - https://support.cerberusftp.com/hc/en-us/articles/360000040039-Securely-Storing-User-Passwords.
Here are the steps I've taken so far -
created a user in Cerberus with a password of "asdf"
exported my collection of users to a CSV file
identified the hashed password from the export as follows -
{{PBKDF2 HMAC SHA256}}:5000:42ED67592D7D80F03BF3E2413EB80718C5DAFEB5237FC4E5E309C2940DF1DBB2A4ABD9BB63B8AD285858B532A573D9DE
attempted to write a Python script that could hash "asdf" to the same hash as shown above
Here is what my script looks like so far - https://replit.com/#ryangrush/sample.
import hashlib
import base64
password = b'asdf'
salt = b'sample_salt'
combined = salt + password
first = hashlib.pbkdf2_hmac('sha256', combined, b'', 5000)
combined = salt + first
second = hashlib.pbkdf2_hmac('sha256', combined, b'', 5000)
base_16 = base64.b16encode(second)
print(second.hex())
print(base_16)
The documentation must've been written before the v7.0 PBKDF2 HMAC functions were adopted. The salt and the password are now used just as described in the documentation for PBKDF2.
import hashlib
import base64
hashed_password_entry = '{{PBKDF2 HMAC SHA256}}:5000:42ED67592D7D80F03BF3E2413EB80718C5DAFEB5237FC4E5E309C2940DF1DBB2A4ABD9BB63B8AD285858B532A573D9DE'
entry_components_strings = hashed_password_entry.split(':')
password = b'asdf'
iterations = int(entry_components_strings[1])
salt_plus_hashvalue = base64.b16decode(entry_components_strings[2])
hash_len = 256 // 8
salt, hashvalue = salt_plus_hashvalue[:-hash_len], salt_plus_hashvalue[-hash_len:]
hashvalue_test = hashlib.pbkdf2_hmac('SHA256', password, salt, iterations)
print(hashvalue_test.hex())
the output is c5dafeb5237fc4e5e309c2940df1dbb2a4abd9bb63b8ad285858b532a573d9de which you can see matches the hashed value that is at the end of entry.
How can I change the admin password for a Glassfish Domain using a password file? I know the conventional method of manually typing the password upon prompt.
However I want to change the admin password using a script where in I do not have to manually type the password.
This is possible, but you will need 2 password files if you want to script this fully in the easiest way.
Create a temporary file (tmpfile in my example) which will hold the current password (blank by default) and the desired new password:
AS_ADMIN_PASSWORD=
AS_ADMIN_NEWPASSWORD=myNewPassword
Now create a password (pwdfile in my example) file which will contain the changed admin password:
AS_ADMIN_PASSWORD=myNewPassword
You can then use the files to change the password using the commands below, making sure to use tmpfile when changing the password, then pwdfile afterwards
$PAYARA_PATH/bin/asadmin start-domain
$PAYARA_PATH/bin/asadmin --user $ADMIN_USER --passwordfile=/opt/tmpfile change-admin-password
$PAYARA_PATH/bin/asadmin --user $ADMIN_USER --passwordfile=/opt/pwdfile enable-secure-admin
$PAYARA_PATH/bin/asadmin restart-domain
This example was adapted from the way the Payara Server dockerfile works
For anyone still interested in manually setting the admin account password:
I tried to generate the contents of the "admin-keyfile" located in "glassfish/domains/{ACTIVE_DOMAIN_NAME}/config/admin-keyfile" based on the current implementation of the Payara Repo. This file (as the data source for the FileRealm) is used to authenticate the admin user when accessing the admin interface under port 4848.
Each line of this text file represents an account and is structured as
USERNAME;PASSWORD;GROUPS
The field "PASSWORD" is prefixed with a hash algorithm keyword (wrapped in curly braces, e.g. "SSHA" or "SSHA256") followed by a BASE64 encoded hash of the concatenated salted hash and the salt value itself (some random bytes):
{SSHA}BASE64(SHA(password,salt),salt)
Long story short: If you want to generate user accounts manually you could for example use the following Python script:
import hashlib
from base64 import b64encode
from secrets import token_bytes
from getpass import getpass
username = 'admin' # input('Username: ')
plainTextPassword = getpass()
randomSalt = token_bytes(8)
passwordHash = hashlib.sha256()
passwordHash.update(plainTextPassword.encode('utf-8'))
passwordHash.update(randomSalt)
passwordDigest = passwordHash.digest()
# cryptic range reflects the strange implementation... feel free to change it to "range(98)"
# https://github.com/payara/Payara/blob/6488cbdc90fd0f6c42de6a42affcd09f697be715/nucleus/common/common-util/src/main/java/org/glassfish/security/common/SSHA.java#L108
for run in range(2, 101):
passwordHash = hashlib.sha256()
passwordHash.update(passwordDigest)
passwordDigest = passwordHash.digest()
saltedHashAndSalt = b64encode(passwordDigest + randomSalt).decode('utf-8')
result = '{0};{{SSHA256}}{1};asadmin'.format(username, saltedHashAndSalt)
print(result)
Insert the console output into the "admin-keyfile" and (re)start your server.
As far as I know, it is impossible to change it via a file as a parameter for security reasons.
You can consider an alternative solution (pipe) but the confirmation of the password is always necessary. https://docs.oracle.com/cd/E19798-01/821-1758/change-admin-password-1/index.html
I'm just digging into Symfony2 and just got my own user-provider running. ATM I use brypt with a cost of 12. If I now increase the cost, bcrypt should rehash the password again!?! But how can I persist the new password to database?
You can change the cost in any moment because as you can read in the official symfony2 docs you don't need to rehash the old passwords because they are automatically handled with the old cost (and if you want you can force the users in the future to change their password like happens in many large sites).
You can't reverse a hash function so you're left with two options:
Force on user to insert new password or...
Update the hash as users login to your system again (You can force to kick the cookie and sessions that allows the user to log in without retyping their password). This solution will allow your users to log in with the old hash and at the same time you will update the old hash with the new one. Next time your user will log in, the script will use the new version of the hash to login the user.
In this example, I have used md5 as a hash and I want to update it to BCRYPT with cost = 12 but feel free to change it to what ever you need. Change from BCRYPT cost=10 to BCRYPT cost = 12 would also work or any other combination. Consider this example:
$passwordFromDatabase = "0d107d09f5bbe40cade3de5c71e9e9b7"; // md5 hash of "letmein"
$passwordFromForm = $_POST['password']; // $_POST['password'] == "letmein"
if(password_needs_rehash($passwordFromDatabase, PASSWORD_BCRYPT, ["cost" => 12]) && md5($passwordFromForm) === $passwordFromDatabase){
// generate new password
$newPasswordHash = password_hash($passwordFromForm, PASSWORD_BCRYPT, ["cost" => 12]);
// update hash from databse - replace old hash $passwordFromDatabase with new hash $newPasswordHash
// after update login user
if(password_verify($passwordFromForm, $newPasswordHash)){
// user has logged in successfully and hash was updated
// redirect to user area
}else{
// ups something went wrong Exception
}
}else{
if(password_verify($passwordFromForm, $passwordFromDatabase)){
// user password hash from database is already BCRYPTed no need to rehash
// user has logged in successfully
// redirect to user area
}else{
// wrong password
// no access granted - stay where you are
}
}
I prefer the second option :). Make your own choice. If you pick the second option and choose not to kick the cookie and session that allow user to login without providing the password, it's OK too... The change will happen overtime. And no one will even notice the change.
Hi i am gooling but without result.
I am trying to check one field in DB while encoding password to user. How?
The service
services:
my_password_encoder:
class: TB\WelcomePageBundle\Security\Encoder\MyPasswordEncoder
<?php
namespace TB\WelcomePageBundle\Security\Encoder;
use Symfony\Component\Security\Core\Encoder\BasePasswordEncoder;
use TB\UserBundle\Entity\User;
class MyPasswordEncoder extends BasePasswordEncoder
{
public function encodePassword($raw, $salt)
{
$user = new User;
$old_or_new=$user->getOldNew();
print_r($user);
print_r($old_or_new);die();
The point:
1. withdrawn one field from DB from current logging user.
2. Depend on the value i need: encode his password MY WAY and log in + CHANGE THE PASSWORD THE SYMFONY WAY and update DB.
3. Depend on the value just use the symfony way.
There is easy condition. The problem is just how i can withdrawn this field + encode password symfony way. (how encode password my way i know). + encode the password not more via my way but symfony and update DB.
My points is to migrate low secure passwords to symfony2. Why? Because i have existing DB where the passwords are encoded my way. So i need to "update" them.
THE MAIN PART OF QUESTION:
HOW CAN I GET THE USERNAME OF USER WHO TRY LOG IN IN ENCODE PASSWORD FUNCTION??? THX!!!
I have a question about how to use md5 and a salt to secure a password, I have already made many searches for answers to my questions.
An article I saw was using c# to convert password to md5 string, something like this:
public static string md5(string <b>sPassword</b>)
{
System.Security.Cryptography.MD5CryptoServiceProvider x = new System.Security.Cryptography.MD5CryptoServiceProvider();
byte[] bs = System.Text.Encoding.UTF8.GetBytes(sPassword);
bs = x.ComputeHash(bs);
System.Text.StringBuilder s = new System.Text.StringBuilder();
foreach (byte b in bs)
{
s.Append(b.ToString("x2").ToLower());
}
return s.ToString();
}
}
My question is the above code seems server side is its mean password traveling over internet in plain text doesn't it create any security issue or it does not matter i don't know (may be i am getting it wrong way or i am not clear about password security concept) ?
What i have done in my project is i am creating a secure password at client side with java script md5.js file and with user's entered password before posting login.aspx form back to server then at server side i am fetching hashed password of user from database(which was stored at the time of registration of user with same technique) and match both client side and server side hashed passwords if they match user authenticated.
i don't know weather i am doing it right way or not please let me know right way if i am wrong .
Now the problem is i want to use SALT with the md5 (md5+salt) to make password more secure with Randomly generated salt string. how to do this should i make a random salt string at server side while page_load of login page and then send it to client side and at client mix this salt with user password before posting form. after post again mix the password(fetched from database) with same random string and match both password to authenticate.
One more question, at the time of registration of a new user, where should originally user entered password convert in md5 at client side or server side if at server side then password should post to server as it is means original password.(like "MyPassword")
Firstly you should be aware that SHA1 is now industry standard, but it's still fine to use Md5 for most things.
Secondly to stop plain text transmitting over the public network, use an HTTPS connection (you may need to purchase a certificate from a recognised vendor).
Also if this is for a user system, consider using ASP.net's membership system. It does this all for you and has been extensively reviewed.
The basic flow of what you describe anyway would be:
User enters password
Server generates random salt
Hashed password = md5(salt + raw password)
Store hashed password and salt along side username, dispose of raw
When user logs in, find the associated salt with the username login is being attempted for.
Is password valid = does md5(salt + entered password) = store hash?
If they do, login
Once they have logged in, it might be a good idea also to regenerate a new salt and hash. Also the md5() should be applied to the password thousands of times before storing to make a dictionary attack uneconomical.
There are plenty of resources out there that go into this in more detail.
Good luck!