use confkey for encrypting instead of fragile user password

This commit is contained in:
Daniel Seifert 2018-10-22 12:10:43 +02:00
parent 96057b594a
commit 58fb0cb803
6 changed files with 16 additions and 58 deletions

View File

@ -73,7 +73,8 @@ class d3user_totp extends AdminDetailsController
/** @var d3_totp_user $oUser */ /** @var d3_totp_user $oUser */
$oUser = oxNew(User::class); $oUser = oxNew(User::class);
if (false == $oUser->d3CheckPasswordPass($this->getEditObjectId(), $pwd)) { $oUser->load($this->getEditObjectId());
if (false == $oUser->isSamePassword($pwd)) {
$oException = oxNew(StandardException::class, 'D3_TOTP_ERROR_PWDONTPASS'); $oException = oxNew(StandardException::class, 'D3_TOTP_ERROR_PWDONTPASS');
throw $oException; throw $oException;
} }
@ -87,7 +88,7 @@ class d3user_totp extends AdminDetailsController
$seed = Registry::getRequest()->getRequestEscapedParameter("secret"); $seed = Registry::getRequest()->getRequestEscapedParameter("secret");
$otp = Registry::getRequest()->getRequestEscapedParameter("otp"); $otp = Registry::getRequest()->getRequestEscapedParameter("otp");
$oTotp->saveSecret($seed, $pwd); $oTotp->saveSecret($seed);
$oTotp->assign($aParams); $oTotp->assign($aParams);
$oTotp->verify($otp, $seed); $oTotp->verify($otp, $seed);
$oTotp->setId(); $oTotp->setId();

View File

@ -20,6 +20,7 @@ use BaconQrCode\Writer;
use D3\ModCfg\Application\Model\d3database; use D3\ModCfg\Application\Model\d3database;
use D3\Totp\Application\Model\Exceptions\d3totp_wrongOtpException; use D3\Totp\Application\Model\Exceptions\d3totp_wrongOtpException;
use Doctrine\DBAL\DBALException; use Doctrine\DBAL\DBALException;
use Exception;
use OTPHP\TOTP; use OTPHP\TOTP;
use OxidEsales\Eshop\Application\Model\User; use OxidEsales\Eshop\Application\Model\User;
use OxidEsales\Eshop\Core\DatabaseProvider; use OxidEsales\Eshop\Core\DatabaseProvider;
@ -104,10 +105,9 @@ class d3totp extends BaseModel
public function getSavedSecret() public function getSavedSecret()
{ {
$seed_enc = $this->getFieldData('seed'); $seed_enc = $this->getFieldData('seed');
$sPwd = Registry::getSession()->getVariable('pwdTransmit');
if ($seed_enc && $sPwd) { if ($seed_enc) {
$seed = $this->decrypt($seed_enc, $sPwd); $seed = $this->decrypt($seed_enc);
if ($seed) { if ($seed) {
return $seed; return $seed;
} }
@ -171,13 +171,12 @@ class d3totp extends BaseModel
/** /**
* @param $seed * @param $seed
* @param $key
*/ */
public function saveSecret($seed, $key) public function saveSecret($seed)
{ {
$this->assign( $this->assign(
array( array(
'seed' => $this->encrypt($seed, $key) 'seed' => $this->encrypt($seed)
) )
); );
} }
@ -200,14 +199,12 @@ class d3totp extends BaseModel
} }
/** /**
* $key should have previously been generated in a cryptographically secure manner, e.g. via openssl_random_pseudo_bytes
*
* @param $plaintext * @param $plaintext
* @param $key
* @return string * @return string
*/ */
public function encrypt($plaintext, $key) public function encrypt($plaintext)
{ {
$key = Registry::getConfig()->getConfigParam('sConfigKey');
$ivlen = openssl_cipher_iv_length($cipher="AES-128-CBC"); $ivlen = openssl_cipher_iv_length($cipher="AES-128-CBC");
$iv = openssl_random_pseudo_bytes($ivlen); $iv = openssl_random_pseudo_bytes($ivlen);
$ciphertext_raw = openssl_encrypt($plaintext, $cipher, $key, $options=OPENSSL_RAW_DATA, $iv); $ciphertext_raw = openssl_encrypt($plaintext, $cipher, $key, $options=OPENSSL_RAW_DATA, $iv);
@ -216,14 +213,12 @@ class d3totp extends BaseModel
} }
/** /**
* $key should have previously been generated in a cryptographically secure manner, e.g. via openssl_random_pseudo_bytes
*
* @param $ciphertext * @param $ciphertext
* @param $key
* @return bool|string * @return bool|string
*/ */
public function decrypt($ciphertext, $key) public function decrypt($ciphertext)
{ {
$key = Registry::getConfig()->getConfigParam('sConfigKey');
$c = base64_decode($ciphertext); $c = base64_decode($ciphertext);
$ivlen = openssl_cipher_iv_length($cipher="AES-128-CBC"); $ivlen = openssl_cipher_iv_length($cipher="AES-128-CBC");
$iv = substr($c, 0, $ivlen); $iv = substr($c, 0, $ivlen);

View File

@ -32,7 +32,7 @@ $aLang = [
'D3_TOTP_SECRET' => 'QR-Code kann nicht gescannt werden?', 'D3_TOTP_SECRET' => 'QR-Code kann nicht gescannt werden?',
'D3_TOTP_SECRET_HELP' => 'Setzen Sie keine App ein, die den QR-Code scannen kann, können Sie diese Zeichenkette auch in Ihr Authentisierungstool kopieren. Stellen Sie bitte zusätzlich die Passwortlänge auf 6 Zeichen und das Zeitinterval auf 30 Sekunden ein.', 'D3_TOTP_SECRET_HELP' => 'Setzen Sie keine App ein, die den QR-Code scannen kann, können Sie diese Zeichenkette auch in Ihr Authentisierungstool kopieren. Stellen Sie bitte zusätzlich die Passwortlänge auf 6 Zeichen und das Zeitinterval auf 30 Sekunden ein.',
'D3_TOTP_CURRPWD' => 'Anmeldepasswort des Benutzerkontos', 'D3_TOTP_CURRPWD' => 'Anmeldepasswort des Benutzerkontos',
'D3_TOTP_CURRPWD_HELP' => 'Die Zeichenkette wird verschlüsselt im Shop abgelegt. Zum Verschlüsseln wird das Passwort des ausgewählten Kundenkontos benötigt. Zugleich stellt dies sicher, dass nur Berechtigte Änderungen an diesen Einstellungen vornehmen dürfen.', 'D3_TOTP_CURRPWD_HELP' => 'Dies stellt sicher, dass nur Berechtigte Änderungen an diesen Einstellungen vornehmen dürfen.',
'D3_TOTP_CURROTP' => 'Bestätigung mit Einmalpasswort', 'D3_TOTP_CURROTP' => 'Bestätigung mit Einmalpasswort',
'D3_TOTP_CURROTP_HELP' => 'Haben Sie dieses Kundenkonto in Ihrer Authentisierungs-App registriert, generieren Sie damit ein Einmalpasswort, tragen Sie es hier ein und senden das Formular direkt darauf hin ab.', 'D3_TOTP_CURROTP_HELP' => 'Haben Sie dieses Kundenkonto in Ihrer Authentisierungs-App registriert, generieren Sie damit ein Einmalpasswort, tragen Sie es hier ein und senden das Formular direkt darauf hin ab.',

View File

@ -32,7 +32,7 @@ $aLang = [
'D3_TOTP_SECRET' => 'Can not scan QR code?', 'D3_TOTP_SECRET' => 'Can not scan QR code?',
'D3_TOTP_SECRET_HELP' => 'If you do not use an app that can scan the QR code, you can also copy this string into your authentication tool. Please also set the password length to 6 characters and the time interval to 30 seconds.', 'D3_TOTP_SECRET_HELP' => 'If you do not use an app that can scan the QR code, you can also copy this string into your authentication tool. Please also set the password length to 6 characters and the time interval to 30 seconds.',
'D3_TOTP_CURRPWD' => 'Login password of the user account', 'D3_TOTP_CURRPWD' => 'Login password of the user account',
'D3_TOTP_CURRPWD_HELP' => 'The character string is stored encrypted in the shop. To encrypt, the password of the selected customer account is required. Concurrently, this ensures that only authorized users can make changes to these settings.', 'D3_TOTP_CURRPWD_HELP' => 'This ensures that only authorized users can make changes to these settings.',
'D3_TOTP_CURROTP' => 'Confirmation with one-time password', 'D3_TOTP_CURROTP' => 'Confirmation with one-time password',
'D3_TOTP_CURROTP_HELP' => 'If you have registered this customer account in your authentication app, you generate a one-time password, enter it here and send the form out immediately.', 'D3_TOTP_CURROTP_HELP' => 'If you have registered this customer account in your authentication app, you generate a one-time password, enter it here and send the form out immediately.',

View File

@ -41,7 +41,6 @@ class d3_totp_LoginController extends d3_totp_LoginController_parent
if ($auth if ($auth
&& $totp->isActive() && $totp->isActive()
&& false == Registry::getSession()->getVariable(d3totp::TOTP_SESSION_VARNAME) && false == Registry::getSession()->getVariable(d3totp::TOTP_SESSION_VARNAME)
&& Registry::getSession()->hasVariable('pwdTransmit')
) { ) {
// set auth as secured parameter; // set auth as secured parameter;
Registry::getSession()->setVariable("auth", $auth); Registry::getSession()->setVariable("auth", $auth);
@ -63,10 +62,6 @@ class d3_totp_LoginController extends d3_totp_LoginController_parent
$totp = oxNew(d3totp::class); $totp = oxNew(d3totp::class);
$totp->loadByUserId(Registry::getSession()->getVariable("auth")); $totp->loadByUserId(Registry::getSession()->getVariable("auth"));
if (Registry::getRequest()->getRequestParameter('pwd')) {
Registry::getSession()->setVariable('pwdTransmit', Registry::getRequest()->getRequestParameter('pwd'));
}
$return = 'login'; $return = 'login';
try { try {
@ -74,7 +69,6 @@ class d3_totp_LoginController extends d3_totp_LoginController_parent
$return = parent::checklogin(); $return = parent::checklogin();
} elseif ($this->hasValidTotp($sTotp, $totp)) { } elseif ($this->hasValidTotp($sTotp, $totp)) {
Registry::getSession()->setVariable(d3totp::TOTP_SESSION_VARNAME, $sTotp); Registry::getSession()->setVariable(d3totp::TOTP_SESSION_VARNAME, $sTotp);
Registry::getSession()->deleteVariable('pwdTransmit');
$return = "admin_start"; $return = "admin_start";
} }
} catch (d3totp_wrongOtpException $oEx) { } catch (d3totp_wrongOtpException $oEx) {

View File

@ -17,9 +17,11 @@ namespace D3\Totp\Modules\Application\Model;
use D3\Totp\Application\Model\d3totp; use D3\Totp\Application\Model\d3totp;
use Doctrine\DBAL\DBALException; use Doctrine\DBAL\DBALException;
use OxidEsales\Eshop\Application\Controller\ForgotPasswordController;
use OxidEsales\Eshop\Core\DatabaseProvider; use OxidEsales\Eshop\Core\DatabaseProvider;
use OxidEsales\Eshop\Core\Exception\DatabaseConnectionException; use OxidEsales\Eshop\Core\Exception\DatabaseConnectionException;
use OxidEsales\Eshop\Core\Registry; use OxidEsales\Eshop\Core\Registry;
use OxidEsales\EshopCommunity\Application\Controller\Admin\UserMain;
class d3_totp_user extends d3_totp_user_parent class d3_totp_user extends d3_totp_user_parent
{ {
@ -33,40 +35,6 @@ class d3_totp_user extends d3_totp_user_parent
return $return; return $return;
} }
/**
* @param $sUserId
* @param $sPassword
* @return bool
* @throws DatabaseConnectionException
*/
public function d3CheckPasswordPass($sUserId, $sPassword)
{
return (bool) DatabaseProvider::getDb(DatabaseProvider::FETCH_MODE_ASSOC)->getOne(
$this->d3GetPasswordCheckQuery($sUserId, $sPassword)
);
}
/**
* @param $sUserId
* @param $sPassword
* @return string
* @throws DatabaseConnectionException
*/
public function d3GetPasswordCheckQuery($sUserId, $sPassword)
{
$oDb = \OxidEsales\Eshop\Core\DatabaseProvider::getDb();
$sUserSelect = "oxuser.oxid = " . $oDb->quote($sUserId);
$sSalt = $oDb->getOne("SELECT `oxpasssalt` FROM `oxuser` WHERE " . $sUserSelect);
$sPassSelect = " oxuser.oxpassword = " . $oDb->quote($this->encodePassword($sPassword, $sSalt));
$sSelect = "select `oxid` from oxuser where 1 and {$sPassSelect} and {$sUserSelect} ";
return $sSelect;
}
/** /**
* @return d3totp * @return d3totp
* @throws DatabaseConnectionException * @throws DatabaseConnectionException