Translate encryption method from php to python [closed] - php

Closed. This question needs to be more focused. It is not currently accepting answers.
Want to improve this question? Update the question so it focuses on one problem only by editing this post.
Closed 4 years ago.
Improve this question
So I'm trying to implement a system where user authentication is based on external sql.
This external sql is on my first website where I have a lot of users and I simply want them to login with the same credentials.
The passwords stored in the database are encrypted so I need to figure out the encryption method. I have full access to the website so I found this php code (site is based on php):
/**
* Generate a password hash
*
* #param string $strPassword The unencrypted password
*
* #return string The encrypted password
*
* #throws \Exception If none of the algorithms is available
*/
public static function hash($strPassword)
{
if (CRYPT_SHA512 == 1)
{
return crypt($strPassword, '$6$' . md5(uniqid(mt_rand(), true)) . '$');
}
elseif (CRYPT_SHA256 == 1)
{
return crypt($strPassword, '$5$' . md5(uniqid(mt_rand(), true)) . '$');
}
elseif (CRYPT_BLOWFISH == 1)
{
return crypt($strPassword, '$2a$07$' . md5(uniqid(mt_rand(), true)) . '$');
}
else
{
throw new \Exception('None of the required crypt() algorithms is available');
}
}
and also this:
/**
* Run the controller and parse the password template
*/
public function run()
{
$this->Template = new BackendTemplate('be_password');
if (Input::post('FORM_SUBMIT') == 'tl_password')
{
$pw = Input::postRaw('password');
$cnf = Input::postRaw('confirm');
// The passwords do not match
if ($pw != $cnf)
{
Message::addError($GLOBALS['TL_LANG']['ERR']['passwordMatch']);
}
// Password too short
elseif (utf8_strlen($pw) < Config::get('minPasswordLength'))
{
Message::addError(sprintf($GLOBALS['TL_LANG']['ERR']['passwordLength'], Config::get('minPasswordLength')));
}
// Password and username are the same
elseif ($pw == $this->User->username)
{
Message::addError($GLOBALS['TL_LANG']['ERR']['passwordName']);
}
// Save the data
else
{
// Make sure the password has been changed
if (crypt($pw, $this->User->password) === $this->User->password)
{
Message::addError($GLOBALS['TL_LANG']['MSC']['pw_change']);
}
else
{
$this->loadDataContainer('tl_user');
// Trigger the save_callback
if (is_array($GLOBALS['TL_DCA']['tl_user']['fields']['password']['save_callback']))
{
foreach ($GLOBALS['TL_DCA']['tl_user']['fields']['password']['save_callback'] as $callback)
{
if (is_array($callback))
{
$this->import($callback[0]);
$pw = $this->$callback[0]->$callback[1]($pw);
}
elseif (is_callable($callback))
{
$pw = $callback($pw);
}
}
}
$objUser = UserModel::findByPk($this->User->id);
$objUser->pwChange = '';
$objUser->password = Encryption::hash($pw);
$objUser->save();
Message::addConfirmation($GLOBALS['TL_LANG']['MSC']['pw_changed']);
$this->redirect('contao/main.php');
}
}
$this->reload();
}
My question is:
how to translate this method to python?
I don't quite understand the randomness and how to repeat it. Cou;ld someone explain?
Thanks,
C
//edit:
I mean I don't understand where
return crypt($strPassword, '$6$' . **md5(uniqid(mt_rand(), true))** . '$');
this middle part is saved and thus how can it ever be compared to crypt(password, the_same_function(but gives totally different value);
succesfully
I feel like I'm missing something obvious here, could someone explain? I know it's basic.
Thanks again

Main magic here is in 2 lines:
the one that you mentioned:
return crypt($strPassword, '$6$' . **md5(uniqid(mt_rand(), true))** . '$');
and the one which checks if password is changed:
if (crypt($pw, $this->User->password) === $this->User->password)
in fist one the salt for the password is generated, in second hashed password from database is used to extract the salt which has to be used in crypt() method
Here you have more info: http://php.net/manual/en/faq.passwords.php#faq.passwords.salt
minus may be because you didn't put enough work at first and ( the thing that made it harder for me ) you didn't put your password verification code and you didn't put your python code.
I think you have enough now to write your own code. Take a look in the python hashlib documentation https://docs.python.org/3/library/hashlib.html and using salts.
I hope it's enough to get you going if not post your python code.

Related

Codeigniter Ion Auth generating a password

In an app i am making i need to edit and create some passwords with haste and i think i have found a way but i doubt its correctness.
I dug through ion auth and found this function in the ion_auth_model
/**
* Hashes the password to be stored in the database.
*
* #return void
* #author Mathew
**/
public function hash_password($password, $salt=false, $use_sha1_override=FALSE)
{
if (empty($password))
{
return FALSE;
}
//bcrypt
if ($use_sha1_override === FALSE && $this->hash_method == 'bcrypt')
{
return $this->bcrypt->hash($password);
}
if ($this->store_salt && $salt)
{
return sha1($password . $salt);
}
else
{
$salt = $this->salt();
return $salt . substr(sha1($salt . $password), 0, -$this->salt_length);
}
}
and tested by creating this public function in one of my controllers
public function Qpass_gen(){
$pass = $this->ion_auth_model->hash_password('password',FALSE,FALSE);
echo $pass;
}
and when i replaced the Qpass_gen() string with the one stored defaultly in the database by ion_auth,i managed to log in.
Is my method for quickly generating passwords guaranteed to work always?.
Yes, that's a good way to handle it. As the author of the library, that's what I would recommend.

Converting from MD5 Legacy Auth System to CakePHP

I have a site which runs off an MD5 hashing scheme for passwords. As a way of supporting this legacy system, I've this answer to manually override the login system for now. But this isn't really ideal, as MD5 is pretty much universally known to be awful at encryption. So in the interest of security, what's the best way to migrate users over to the safer CakePHP auth system without causing them undue grief?
Figured it out thanks to this answer (albeit lightly modified). Basically, it updates the user behind the scenes to use the new system if the current system doesn't match up with it.
/**
* Login method
*/
public function login() {
$this->layout = 'homepage';
// If the user is already logged in, redirect to their user page
if($this->Auth->user() != null) {
$this->redirect();
} else {
// If this is being POSTed, check for login information
if($this->request->is('post')) {
if($this->Auth->login($this->loginHelper($this->request->data))) {
// Redirect to origin path, ideally
} else {
$this->Session->setFlash('Invalid username or password, try again');
}
}
}
}
/**
* Update password method
* #param array The user's data array
* #param Returns either a user object if the user is valid or null otherwise
*/
private function loginHelper($data) {
$username = $this->data['User']['username'];
$plainText = $this->data['User']['password'];
$user = current($this->User->findByUsername($username));
$salted = Security::hash($plainText, null, true);
if ($salted === $user['password']) {
return $user; // user exists, password is correct
}
$md5ed = Security::hash($plainText, 'md5', null);
if ($md5ed === $user['password']) {
$this->User->id = $user['id'];
$this->User->saveField('password', $plainText);
return $user; // user exists, password now updated to blowfish
}
return null; // user's password does not exist.
}

PHP Register script

So I'm trying to write this script for my site.
It looks quite messed up and broken.
Maybe somebody can help me tidy it up a bit and explain what might be incorrect.
Also, is there a way to make it shorter, looks a bit unsafe to me.
Thank you.
<?php
class Register
{
private $username;
private $password;
private $password2;
private $passmd5;
private $email;
private $email2;
private $errors;
private $rtoken;
public function __construct()
{
$this->errors = array();
$this->username = $this->filter($_POST['ruser']);
$this->password = $this->filter($_POST['rpass']);
$this->password2 = $this->filter($_POST['rpass2']);
$this->email = $this->filter($_POST['remail']);
$this->email2 = $this->filter($_POST['remail2']);
$this->rtoken = $_POST['rtoken'];
$this->passmd5 = md5($this->password);
}
public function process()
{
if ($this->valid_rtoken() && $this->valid_data())
$this->register();
return count($this->errors) ? 0 : 1;
}
public function filter($var)
{
return preg_replace('/[^a-zA-Z0-9#.]/', '', $var);
}
public function register()
{
mysql_query("INSERT INTO users(username,password,email) VALUES ('{$this->username}','{$this->passmd5}','{$this->email}')");
if (mysql_affected_rows() < 1)
$this->errors[] = '<font color="red">Database error</font>';
}
public function user_exists()
{
$data = mysql_query("SELECT ID FROM users WHERE username = '{$this->username}'");
return mysql_num_rows($data) ? 1 : 0;
}
public function email_exists()
{
$data = mysql_query("SELECT ID FROM users WHERE email = '{$this->email}'");
return mysql_num_rows($data) ? 1 : 0;
}
public function show_errors()
{
echo "";
foreach ($this->errors as $key => $value)
echo $value . "<br>";
}
public function valid_data()
{
if ($this->user_exists())
$this->errors[] = '<font color="red">Username Exists</font>';
if ($this->email_exists())
$this->errors[] = '<font color="red">email exists</font>';
if (empty($this->username))
$this->errors[] = '<font color="red">check your username</font>';
if (empty($this->password))
$this->errors[] = '<font color="red">check your password</font>';
if ($this->password != $this->password2)
$this->errors[] = '<font color="red">Passwords do not match</font>';
if (empty($this->email) || !eregi('^[a-zA-Z0-9._-]+#[a-zA-Z0-9._-]+\.[a-zA-Z]{2,4}$', $this->email))
$this->errors[] = '<font color="red">Check your email</font>';
if ($this->email != $this->email2)
$this->errors[] = '<font color="red">Emails do not match</font>';
return count($this->errors) ? 0 : 1;
}
public function valid_rtoken()
{
if (!isset($_SESSION['rtoken']) || $this->rtoken != $_SESSION['rtoken'])
$this->errors[] = '<font color="red">Check</font>';
return count($this->errors) ? 0 : 1;
}
}
?>
Swoosh, there are always better ways to write code. I hope to challenge you to rethink why your code is long, and why it might be unsafe, rather than rewrite your code for you. Hopefully you will learn more this way.
To begin with, hashing the password with MD5 is completely insecure. Please forget that MD5 ever existed, and please don't use even SHA1 for anything secure. Instead, you should use bcrypt or PBKDF2 (with SHA2 or Whirlpool and ~2000+ rounds). I suggest you refer to my answer to Secure Hash and Salt for PHP Passwords for tips and links to articles and libraries to help implement better security.
Second, mysql_* functions are deprecated as of PHP 5.5. Using MySQLi will get you by, but you should use a consistent interface such as PDO to handle the connections, and query escaping/filtering. While you might not be building your software in PHP 5.5, you will not always have control over if a host decides to upgrade your version of PHP. Optimize for future compatibility as much as you can now. Plus, PDO has some nifty features that are explained in its documentation.
Third, you should not use a regular expression to "filter" your query variables. The safest thing you can do is use intval/floatval on any numbers, and escape the rest through the DB library you use such as mysql_escape_string (or mysqli_real_escape_string) OR use prepared statements (which will sanitize variables for you).
Fourth, you are putting display logic into your object. Think about it: what purpose/role does this object fulfill? Does it handle the registration logic? Does it store the registration data? It's a good idea to use the Single Responsibility Principle here. It looks like the object is supposed to act like a hybrid model-controller, with presentational information in it. You could expand this to RegistrationModel and RegistrationController classes to handle storing the data temporarily, or even decide to do something else. But remember, the more responsibilities that your class has the more ways it'll have to break.
Also, by making all the attributes of Register private, you cannot have more than one way to register. What if you wanted a short-cut to the process, such as log in via OAuth (such as Twitter or Facebook), but needed to reuse some of the logic in Register? These attributes should at least be protected so that you can inherit from them, or even public so another object can interface with them (such as an object that notifies the user that their registration is successful).

Does this code use Bcrypt or just plain blowfish?

I'm learning php security online (using php 5.4) and came across the following code that I'd like to learn about/use. Does the following code use bcrypt and is it a good implementation of blowfish?
If problems exist, can you please suggest a fix or resource. Thanks.
class PassHash {
// blowfish
private static $algo = '$2a';
// cost parameter
private static $cost = '$10';
// mainly for internal use
public static function unique_salt() {
return substr(sha1(mt_rand()),0,22);
}
// this will be used to generate a hash
public static function hash($password) {
return crypt($password,
self::$algo .
self::$cost .
'$' . self::unique_salt());
}
// this will be used to compare a password against a hash
public static function check_password($hash, $password) {
$full_salt = substr($hash, 0, 29);
$new_hash = crypt($password, $full_salt);
return ($hash == $new_hash);
}
}
Here is the usage during user registration:
// include the class
require ("PassHash.php");
// ...
// read all form input from $_POST
// ...
// do your regular form validation stuff
// ...
// hash the password
$pass_hash = PassHash::hash($_POST['password']);
// store all user info in the DB, excluding $_POST['password']
// store $pass_hash instead
// ...
And here is the usage during a user login process:
// include the class
require ("PassHash.php");
// read all form input from $_POST
// ...
// fetch the user record based on $_POST['username'] or similar
// ...
// ...
// check the password the user tried to login with
if (PassHash::check_password($user['pass_hash'], $_POST['password']) {
// grant access
// ...
} else {
// deny access
// ...
}
Short answer :
Yes it does use bcrypt blowfish (in PHP blowfish is the current algorithm for bcrypt)
Correct answer :
Why not use a trusted PHP compatibility library like this one?
The benefits of using this over the one you posted? :
It is widely used by many people (must be trusted and well taken by the community)
Allow for forward compatibility with php 5.5 native bcrypt function (hence name for passwd_compat) more info here : Info Here!
Allows for a rehash which is genius (pretty much if you decide to crank up the cost of the algorithm you can easily do so and check if the cost matches the one in the library file if not then you can just update the password)
Bottom line : You can only go wrong with bcrypt if you don't know what your doing. One thing to remember is : do not reinvent the wheel if there are already wheels out there.
Hopefully this answer can help you out / expand your knowledge.

PHP Digest authentication with MD5

I wrote a class to authenticate a user using HTTP Authentication the Digest way. I read a few articles and I got it working. Now, I would like to let it make use of Md5 passwords, but I can't seem to get it working, this is the function authenticating the users.
public function authenticate() {
// In case the user is not logged in already.
if (empty($_SERVER['PHP_AUTH_DIGEST'])) {
// Return the headers.
$this->show_auth();
} else {
// Parse the given Digest-data.
$data = $this->parse_request($_SERVER['PHP_AUTH_DIGEST']);
// Check the data.
if (!$data) {
// Display an error message.
die($this->unauthorized);
} else {
// Based on the given information, generate the valid response.
$usr_password = "test";
// Generate the response partly.
$A1 = md5($data['username'].":".$this->get_realm().":".$usr_password);
$A2 = md5($_SERVER['REQUEST_METHOD'].":".$data['uri']);
// Generate the valid response.
$val_response = md5($A1.":".$data['nonce'].":".$data['nc'].":".$data['cnonce'].":".$data['qop'].":".$A2);
// Compare the valid response with the given response.
if ($data['response'] != $val_response) {
// Display the login again.
$this->show_auth();
} else {
// Return true.
return true;
}
}
}
}
So imagine the $usr_password="test" will be $usr_password=md5("test");
How do I compare passwords then?
Thanks.
The MD5 function is hashing function, one-directional method to produce the same result for the same input.
Thus, to compare $password1 to $password2 without revealing (comparing directly) both of them it should be enough to compare their hashes:
$hash1 = md5($password1); // hash for pass 1
$hash2 = md5($password2); // hash for pass 2
if ($hash1 === $hash2) {
// here goes the code to support case of passwords being identical
} else {
// here goes the code to support case of passwords not being identical
}
Is it clear enough? Let me know.

Categories