mirror of
https://github.com/the-djmaze/snappymail.git
synced 2026-09-07 00:17:03 +03:00
Improved data encryption for Contacts sync
This commit is contained in:
parent
b1e895907f
commit
b102fc0e4c
6 changed files with 54 additions and 26 deletions
|
|
@ -22,14 +22,17 @@ trait Contacts
|
||||||
|
|
||||||
$mData = $this->getContactsSyncData($oAccount);
|
$mData = $this->getContactsSyncData($oAccount);
|
||||||
|
|
||||||
$bResult = $this->StorageProvider()->Put($oAccount,
|
$sPassword = APP_DUMMY === $sPassword && isset($mData['Password'])
|
||||||
|
? $mData['Password'] : (APP_DUMMY === $sPassword ? '' : $sPassword);
|
||||||
|
|
||||||
|
$bResult = $this->StorageProvider()->Put(
|
||||||
|
$oAccount,
|
||||||
\RainLoop\Providers\Storage\Enumerations\StorageType::CONFIG,
|
\RainLoop\Providers\Storage\Enumerations\StorageType::CONFIG,
|
||||||
'contacts_sync',
|
'contacts_sync',
|
||||||
\RainLoop\Utils::EncodeKeyValues(array(
|
\json_encode(array(
|
||||||
'Enable' => $bEnabled,
|
'Enable' => $bEnabled,
|
||||||
'User' => $sUser,
|
'User' => $sUser,
|
||||||
'Password' => APP_DUMMY === $sPassword && isset($mData['Password']) ?
|
'Password' => $sPassword ? \SnappyMail\Crypt::Encrypt($sPassword, $oAccount->Password() ?: APP_SALT) : null,
|
||||||
$mData['Password'] : (APP_DUMMY === $sPassword ? '' : $sPassword),
|
|
||||||
'Url' => $sUrl
|
'Url' => $sUrl
|
||||||
))
|
))
|
||||||
);
|
);
|
||||||
|
|
@ -240,15 +243,25 @@ trait Contacts
|
||||||
|
|
||||||
protected function getContactsSyncData(\RainLoop\Model\Account $oAccount) : ?array
|
protected function getContactsSyncData(\RainLoop\Model\Account $oAccount) : ?array
|
||||||
{
|
{
|
||||||
$mResult = null;
|
|
||||||
$sData = $this->StorageProvider()->Get($oAccount,
|
$sData = $this->StorageProvider()->Get($oAccount,
|
||||||
\RainLoop\Providers\Storage\Enumerations\StorageType::CONFIG,
|
\RainLoop\Providers\Storage\Enumerations\StorageType::CONFIG,
|
||||||
'contacts_sync'
|
'contacts_sync'
|
||||||
);
|
);
|
||||||
if (!empty($sData)) {
|
if (!empty($sData)) {
|
||||||
|
$aData = \json_decode($sData);
|
||||||
|
if ($aData) {
|
||||||
|
if ($aData['Password']) {
|
||||||
|
$aData['Password'] = \SnappyMail\Crypt::DecryptFromJSON(
|
||||||
|
$aData['Password'],
|
||||||
|
$oAccount->Password() ?: APP_SALT
|
||||||
|
);
|
||||||
|
}
|
||||||
|
return $aData;
|
||||||
|
}
|
||||||
|
|
||||||
$aData = \RainLoop\Utils::DecodeKeyValues($sData);
|
$aData = \RainLoop\Utils::DecodeKeyValues($sData);
|
||||||
if ($aData) {
|
if ($aData) {
|
||||||
$mResult = array(
|
return array(
|
||||||
'Enable' => isset($aData['Enable']) ? !!$aData['Enable'] : false,
|
'Enable' => isset($aData['Enable']) ? !!$aData['Enable'] : false,
|
||||||
'Url' => isset($aData['Url']) ? \trim($aData['Url']) : '',
|
'Url' => isset($aData['Url']) ? \trim($aData['Url']) : '',
|
||||||
'User' => isset($aData['User']) ? \trim($aData['User']) : '',
|
'User' => isset($aData['User']) ? \trim($aData['User']) : '',
|
||||||
|
|
@ -256,7 +269,7 @@ trait Contacts
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return $mResult;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
public function RawContactsVcf() : bool
|
public function RawContactsVcf() : bool
|
||||||
|
|
|
||||||
|
|
@ -178,8 +178,10 @@ trait UserAuth
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
$aData = \json_decode(\MailSo\Base\Utils::UrlSafeBase64Decode($this->sSpecAuthToken), true);
|
$aData = \SnappyMail\Crypt::DecryptFromJSON(
|
||||||
$aData = \is_array($aData) ? \SnappyMail\Crypt::Decrypt(\array_map('base64_decode', $aData)) : null;
|
\MailSo\Base\Utils::UrlSafeBase64Decode($this->sSpecAuthToken),
|
||||||
|
APP_SALT . Utils::GetShortToken()
|
||||||
|
);
|
||||||
if (!empty($aData)) {
|
if (!empty($aData)) {
|
||||||
$this->oSpecAuthAccount = Account::NewInstanceFromTokenArray(
|
$this->oSpecAuthAccount = Account::NewInstanceFromTokenArray(
|
||||||
$this,
|
$this,
|
||||||
|
|
@ -198,13 +200,10 @@ trait UserAuth
|
||||||
|
|
||||||
public function SetAuthToken(Account $oAccount): void
|
public function SetAuthToken(Account $oAccount): void
|
||||||
{
|
{
|
||||||
$sSpecAuthToken = \MailSo\Base\Utils::UrlSafeBase64Encode(\json_encode(\array_map(
|
$sSpecAuthToken = \MailSo\Base\Utils::UrlSafeBase64Encode(\SnappyMail\Crypt::EncryptToJSON(
|
||||||
'base64_encode',
|
$oAccount,
|
||||||
\SnappyMail\Crypt::Encrypt(
|
APP_SALT . Utils::GetShortToken()
|
||||||
$oAccount,
|
));
|
||||||
APP_SALT . Utils::GetShortToken()
|
|
||||||
)
|
|
||||||
)));
|
|
||||||
|
|
||||||
$this->sSpecAuthToken = $sSpecAuthToken;
|
$this->sSpecAuthToken = $sSpecAuthToken;
|
||||||
$this->oSpecAuthAccount = null;
|
$this->oSpecAuthAccount = null;
|
||||||
|
|
|
||||||
|
|
@ -165,16 +165,14 @@ class Api
|
||||||
{
|
{
|
||||||
$sSsoHash = \MailSo\Base\Utils::Sha1Rand(\sha1($sPassword.$sEmail));
|
$sSsoHash = \MailSo\Base\Utils::Sha1Rand(\sha1($sPassword.$sEmail));
|
||||||
|
|
||||||
$data = \SnappyMail\Crypt::Encrypt(array(
|
|
||||||
'Email' => $sEmail,
|
|
||||||
'Password' => $sPassword,
|
|
||||||
'AdditionalOptions' => $aAdditionalOptions,
|
|
||||||
'Time' => $bUseTimeout ? \time() : 0
|
|
||||||
), $sSsoHash);
|
|
||||||
|
|
||||||
return static::Actions()->Cacher()->Set(
|
return static::Actions()->Cacher()->Set(
|
||||||
KeyPathHelper::SsoCacherKey($sSsoHash),
|
KeyPathHelper::SsoCacherKey($sSsoHash),
|
||||||
\json_encode(\array_map('base64_encode', $data))
|
\SnappyMail\Crypt::EncryptToJSON(array(
|
||||||
|
'Email' => $sEmail,
|
||||||
|
'Password' => $sPassword,
|
||||||
|
'AdditionalOptions' => $aAdditionalOptions,
|
||||||
|
'Time' => $bUseTimeout ? \time() : 0
|
||||||
|
), $sSsoHash)
|
||||||
) ? $sSsoHash : null;
|
) ? $sSsoHash : null;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -172,6 +172,14 @@ class Account implements \JsonSerializable
|
||||||
public function GetAuthToken() : string
|
public function GetAuthToken() : string
|
||||||
{
|
{
|
||||||
return Utils::EncodeKeyValues($this->jsonSerialize());
|
return Utils::EncodeKeyValues($this->jsonSerialize());
|
||||||
|
/*
|
||||||
|
return \MailSo\Base\Utils::UrlSafeBase64Encode(
|
||||||
|
\MailSo\Base\Crypt::Encrypt(
|
||||||
|
\json_encode($this),
|
||||||
|
\md5(APP_SALT.$sCustomKey)
|
||||||
|
)
|
||||||
|
);
|
||||||
|
*/
|
||||||
}
|
}
|
||||||
|
|
||||||
public static function NewInstanceByLogin(\RainLoop\Actions $oActions, string $sEmail, string $sLogin, string $sPassword, string $sClientCert = '', bool $bThrowException = false): ?self
|
public static function NewInstanceByLogin(\RainLoop\Actions $oActions, string $sEmail, string $sLogin, string $sPassword, string $sClientCert = '', bool $bThrowException = false): ?self
|
||||||
|
|
|
||||||
|
|
@ -671,8 +671,7 @@ class ServiceActions
|
||||||
$sSsoSubData = $this->Cacher()->Get(KeyPathHelper::SsoCacherKey($sSsoHash));
|
$sSsoSubData = $this->Cacher()->Get(KeyPathHelper::SsoCacherKey($sSsoHash));
|
||||||
if (!empty($sSsoSubData))
|
if (!empty($sSsoSubData))
|
||||||
{
|
{
|
||||||
$aData = \json_decode($sSsoSubData, true);
|
$aData = \SnappyMail\Crypt::DecryptFromJSON($sSsoSubData, $sSsoHash);
|
||||||
$aData = \is_array($aData) ? \SnappyMail\Crypt::Decrypt(\array_map('base64_decode', $aData), $sSsoHash) : null;
|
|
||||||
|
|
||||||
$this->Cacher()->Delete(KeyPathHelper::SsoCacherKey($sSsoHash));
|
$this->Cacher()->Delete(KeyPathHelper::SsoCacherKey($sSsoHash));
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -85,6 +85,12 @@ abstract class Crypt
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public static function DecryptFromJSON(string $data, string $key = null) /* : mixed */
|
||||||
|
{
|
||||||
|
$aData = \json_decode($data, true);
|
||||||
|
$aData = \is_array($aData) ? static::Decrypt(\array_map('base64_decode', $aData), $key) : null;
|
||||||
|
}
|
||||||
|
|
||||||
public static function Encrypt($data, string $key = null) : array
|
public static function Encrypt($data, string $key = null) : array
|
||||||
{
|
{
|
||||||
if (\is_callable('sodium_crypto_aead_xchacha20poly1305_ietf_encrypt')) {
|
if (\is_callable('sodium_crypto_aead_xchacha20poly1305_ietf_encrypt')) {
|
||||||
|
|
@ -101,6 +107,11 @@ abstract class Crypt
|
||||||
return ['xxtea', $salt, static::XxteaEncrypt($data, $salt)];
|
return ['xxtea', $salt, static::XxteaEncrypt($data, $salt)];
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public static function EncryptToJSON($data, string $key = null) : string
|
||||||
|
{
|
||||||
|
return \json_encode(\array_map('base64_encode', static::Encrypt($data, $key)));
|
||||||
|
}
|
||||||
|
|
||||||
public static function SodiumDecrypt(string $data, string $nonce, string $key = null) /* : mixed */
|
public static function SodiumDecrypt(string $data, string $nonce, string $key = null) /* : mixed */
|
||||||
{
|
{
|
||||||
if (!\is_callable('sodium_crypto_aead_xchacha20poly1305_ietf_decrypt')) {
|
if (!\is_callable('sodium_crypto_aead_xchacha20poly1305_ietf_decrypt')) {
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue