1.0.0 Alpha Release #59
8 changed files with 677 additions and 244 deletions
|
@ -2,15 +2,15 @@
|
|||
|
||||
namespace ncc\Abstracts;
|
||||
|
||||
abstract class RemoteAuthenticationType
|
||||
abstract class AuthenticationType
|
||||
{
|
||||
/**
|
||||
* A combination of a username and password is used for authentication
|
||||
*/
|
||||
const UsernamePassword = 'USERNAME_PASSWORD';
|
||||
const UsernamePassword = 1;
|
||||
|
||||
/**
|
||||
* A single private access token is used for authentication
|
||||
*/
|
||||
const PrivateAccessToken = 'PRIVATE_ACCESS_TOKEN';
|
||||
const AccessToken = 2;
|
||||
}
|
30
src/ncc/Interfaces/PasswordInterface.php
Normal file
30
src/ncc/Interfaces/PasswordInterface.php
Normal file
|
@ -0,0 +1,30 @@
|
|||
<?php
|
||||
|
||||
namespace ncc\Interfaces;
|
||||
|
||||
use ncc\Abstracts\AuthenticationType;
|
||||
|
||||
interface PasswordInterface
|
||||
{
|
||||
/**
|
||||
* @param bool $bytecode
|
||||
* @return array
|
||||
*/
|
||||
public function toArray(bool $bytecode=false): array;
|
||||
|
||||
/**
|
||||
* @param array $data
|
||||
* @return static
|
||||
*/
|
||||
public static function fromArray(array $data): self;
|
||||
|
||||
/**
|
||||
* @return string
|
||||
*/
|
||||
public function getAuthenticationType(): string;
|
||||
|
||||
/**
|
||||
* @return string
|
||||
*/
|
||||
public function __toString(): string;
|
||||
}
|
|
@ -8,7 +8,7 @@
|
|||
use ncc\Abstracts\Scopes;
|
||||
use ncc\Abstracts\Versions;
|
||||
use ncc\Exceptions\AccessDeniedException;
|
||||
use ncc\Exceptions\InvalidCredentialsEntryException;
|
||||
use ncc\Exceptions\FileNotFoundException;
|
||||
use ncc\Exceptions\IOException;
|
||||
use ncc\Exceptions\RuntimeException;
|
||||
use ncc\Objects\Vault;
|
||||
|
@ -20,10 +20,16 @@
|
|||
class CredentialManager
|
||||
{
|
||||
/**
|
||||
* @var null
|
||||
* @var string
|
||||
*/
|
||||
private $CredentialsPath;
|
||||
|
||||
|
||||
/**
|
||||
* @var Vault
|
||||
*/
|
||||
private $Vault;
|
||||
|
||||
/**
|
||||
* Public Constructor
|
||||
*/
|
||||
|
@ -31,23 +37,16 @@
|
|||
{
|
||||
/** @noinspection PhpUnhandledExceptionInspection */
|
||||
$this->CredentialsPath = PathFinder::getDataPath(Scopes::System) . DIRECTORY_SEPARATOR . 'credentials.store';
|
||||
}
|
||||
$this->Vault = null;
|
||||
|
||||
/**
|
||||
* Determines if CredentialManager has correct access to manage credentials on the system
|
||||
*
|
||||
* @return bool
|
||||
*/
|
||||
public function checkAccess(): bool
|
||||
try
|
||||
{
|
||||
$ResolvedScope = Resolver::resolveScope();
|
||||
|
||||
if($ResolvedScope !== Scopes::System)
|
||||
{
|
||||
return False;
|
||||
$this->loadVault();
|
||||
}
|
||||
catch(Exception $e)
|
||||
{
|
||||
unset($e);
|
||||
}
|
||||
|
||||
return True;
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -64,95 +63,67 @@
|
|||
if(file_exists($this->CredentialsPath))
|
||||
return;
|
||||
|
||||
if(!$this->checkAccess())
|
||||
{
|
||||
if(Resolver::resolveScope() !== Scopes::System)
|
||||
throw new AccessDeniedException('Cannot construct credentials store without system permissions');
|
||||
}
|
||||
|
||||
$VaultObject = new Vault();
|
||||
$VaultObject->Version = Versions::CredentialsStoreVersion;
|
||||
|
||||
IO::fwrite($this->CredentialsPath, ZiProto::encode($VaultObject->toArray()), 0600);
|
||||
IO::fwrite($this->CredentialsPath, ZiProto::encode($VaultObject->toArray()), 0744);
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the vault object from the credentials store file.
|
||||
* Loads the vault from the disk
|
||||
*
|
||||
* @return Vault
|
||||
* @throws AccessDeniedException
|
||||
* @throws IOException
|
||||
* @throws RuntimeException
|
||||
*/
|
||||
public function getVault(): Vault
|
||||
{
|
||||
$this->constructStore();
|
||||
|
||||
if(!$this->checkAccess())
|
||||
{
|
||||
throw new AccessDeniedException('Cannot read credentials store without system permissions');
|
||||
}
|
||||
|
||||
try
|
||||
{
|
||||
$Vault = ZiProto::decode(IO::fread($this->CredentialsPath));
|
||||
}
|
||||
catch(Exception $e)
|
||||
{
|
||||
// TODO: Implement error-correction for corrupted credentials store.
|
||||
throw new RuntimeException($e->getMessage(), $e);
|
||||
}
|
||||
|
||||
return Vault::fromArray($Vault);
|
||||
}
|
||||
|
||||
/**
|
||||
* Saves the vault object to the credentials store
|
||||
*
|
||||
* @param Vault $vault
|
||||
* @return void
|
||||
* @throws AccessDeniedException
|
||||
* @throws IOException
|
||||
* @throws RuntimeException
|
||||
* @throws FileNotFoundException
|
||||
*/
|
||||
public function saveVault(Vault $vault): void
|
||||
public function loadVault(): void
|
||||
{
|
||||
if(!$this->checkAccess())
|
||||
if($this->Vault !== null)
|
||||
return;
|
||||
|
||||
if(!file_exists($this->CredentialsPath))
|
||||
{
|
||||
throw new AccessDeniedException('Cannot write to credentials store without system permissions');
|
||||
$this->Vault = new Vault();
|
||||
return;
|
||||
}
|
||||
|
||||
IO::fwrite($this->CredentialsPath, ZiProto::encode($vault->toArray()), 0600);
|
||||
$VaultArray = ZiProto::decode(IO::fread($this->CredentialsPath));
|
||||
$VaultObject = new Vault();
|
||||
$VaultObject->fromArray($VaultArray);
|
||||
|
||||
if($VaultObject->Version !== Versions::CredentialsStoreVersion)
|
||||
throw new RuntimeException('Credentials store version mismatch');
|
||||
|
||||
$this->Vault = $VaultObject;
|
||||
}
|
||||
|
||||
/**
|
||||
* Registers an entry to the credentials store file
|
||||
* Saves the vault to the disk
|
||||
*
|
||||
* @param Vault\Entry $entry
|
||||
* @return void
|
||||
* @throws AccessDeniedException
|
||||
* @throws InvalidCredentialsEntryException
|
||||
* @throws RuntimeException
|
||||
* @throws IOException
|
||||
* @noinspection PhpUnused
|
||||
*/
|
||||
public function registerEntry(Vault\Entry $entry): void
|
||||
public function saveVault(): void
|
||||
{
|
||||
if(!preg_match('/^[\w-]+$/', $entry->Alias))
|
||||
{
|
||||
throw new InvalidCredentialsEntryException('The property \'Alias\' must be alphanumeric (Regex error)');
|
||||
if(Resolver::resolveScope() !== Scopes::System)
|
||||
throw new AccessDeniedException('Cannot save credentials store without system permissions');
|
||||
|
||||
IO::fwrite($this->CredentialsPath, ZiProto::encode($this->Vault->toArray()), 0744);
|
||||
}
|
||||
|
||||
// TODO: Implement more validation checks for the rest of the entry properties.
|
||||
// TODO: Implement encryption for entries that require encryption (For securing passwords and data)
|
||||
|
||||
$Vault = $this->getVault();
|
||||
$Vault->Entries[] = $entry;
|
||||
|
||||
$this->saveVault($Vault);
|
||||
}
|
||||
|
||||
/**
|
||||
* @return null
|
||||
* @return string
|
||||
* @noinspection PhpUnused
|
||||
*/
|
||||
public function getCredentialsPath(): ?string
|
||||
public function getCredentialsPath(): string
|
||||
{
|
||||
return $this->CredentialsPath;
|
||||
}
|
||||
|
|
|
@ -1,9 +1,16 @@
|
|||
<?php
|
||||
|
||||
/** @noinspection PhpMissingFieldTypeInspection */
|
||||
|
||||
namespace ncc\Objects;
|
||||
|
||||
use ncc\Objects\Vault\DefaultEntry;
|
||||
use ncc\Abstracts\AuthenticationType;
|
||||
use ncc\Defuse\Crypto\Crypto;
|
||||
use ncc\Exceptions\RuntimeException;
|
||||
use ncc\Interfaces\PasswordInterface;
|
||||
use ncc\Objects\Vault\Entry;
|
||||
use ncc\Utilities\Functions;
|
||||
use ncc\ZiProto\ZiProto;
|
||||
|
||||
class Vault
|
||||
{
|
||||
|
@ -21,13 +28,6 @@
|
|||
*/
|
||||
public $Entries;
|
||||
|
||||
/**
|
||||
*
|
||||
*
|
||||
* @var DefaultEntry[]
|
||||
*/
|
||||
public $DefaultEntries;
|
||||
|
||||
/**
|
||||
* Public Constructor
|
||||
*/
|
||||
|
@ -37,46 +37,168 @@
|
|||
}
|
||||
|
||||
/**
|
||||
* Returns an array representation of the object
|
||||
* Adds a new entry to the vault
|
||||
*
|
||||
* @return array
|
||||
* @param string $name
|
||||
* @param PasswordInterface $password
|
||||
* @param bool $encrypt
|
||||
* @return bool
|
||||
* @noinspection PhpUnused
|
||||
*/
|
||||
public function toArray(): array
|
||||
public function addEntry(string $name, PasswordInterface $password, bool $encrypt=true): bool
|
||||
{
|
||||
$Entries = [];
|
||||
|
||||
// Check if the entry already exists
|
||||
foreach($this->Entries as $entry)
|
||||
{
|
||||
$Entries[] = $entry->toArray();
|
||||
if($entry->getName() === $name)
|
||||
return false;
|
||||
}
|
||||
|
||||
// Create the new entry
|
||||
$entry = new Entry();
|
||||
$entry->setName($name);
|
||||
$entry->setEncrypted($encrypt);
|
||||
$entry->setAuthentication($password);
|
||||
|
||||
// Add the entry to the vault
|
||||
$this->Entries[] = $entry;
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* Deletes an entry from the vault
|
||||
*
|
||||
* @param string $name
|
||||
* @return bool
|
||||
* @noinspection PhpUnused
|
||||
*/
|
||||
public function deleteEntry(string $name): bool
|
||||
{
|
||||
foreach($this->Entries as $entry)
|
||||
{
|
||||
if($entry->getName() === $name)
|
||||
{
|
||||
$this->Entries = array_diff($this->Entries, [$entry]);
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns all the entries in the vault
|
||||
*
|
||||
* @return array|Entry[]
|
||||
* @noinspection PhpUnused
|
||||
*/
|
||||
public function getEntries(): array
|
||||
{
|
||||
return $this->Entries;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns an existing entry from the vault
|
||||
*
|
||||
* @param string $name
|
||||
* @return Entry|null
|
||||
*/
|
||||
public function getEntry(string $name): ?Entry
|
||||
{
|
||||
foreach($this->Entries as $entry)
|
||||
{
|
||||
if($entry->getName() === $name)
|
||||
return $entry;
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
/**
|
||||
* Authenticates an entry in the vault
|
||||
*
|
||||
* @param string $name
|
||||
* @param string $password
|
||||
* @return bool
|
||||
* @throws RuntimeException
|
||||
* @noinspection PhpUnused
|
||||
*/
|
||||
public function authenticate(string $name, string $password): bool
|
||||
{
|
||||
$entry = $this->getEntry($name);
|
||||
if($entry === null)
|
||||
return false;
|
||||
|
||||
if($entry->getPassword() === null)
|
||||
{
|
||||
if($entry->isEncrypted() && !$entry->isIsCurrentlyDecrypted())
|
||||
{
|
||||
return $entry->unlock($password);
|
||||
}
|
||||
}
|
||||
|
||||
$input = [];
|
||||
switch($entry->getPassword()->getAuthenticationType())
|
||||
{
|
||||
case AuthenticationType::UsernamePassword:
|
||||
$input = ['password' => $password];
|
||||
break;
|
||||
case AuthenticationType::AccessToken:
|
||||
$input = ['token' => $password];
|
||||
break;
|
||||
}
|
||||
|
||||
return $entry->authenticate($input);
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns an array representation of the object
|
||||
*
|
||||
* @param bool $bytecode
|
||||
* @return array
|
||||
*/
|
||||
public function toArray(bool $bytecode=false): array
|
||||
{
|
||||
$entries = [];
|
||||
foreach($this->Entries as $entry)
|
||||
{
|
||||
$entry_array = $entry->toArray($bytecode);
|
||||
|
||||
if($entry->getPassword() !== null && $entry->isEncrypted())
|
||||
{
|
||||
$entry_array['password'] = Crypto::encryptWithPassword(
|
||||
ZiProto::encode($entry_array['password']), $entry->getPassword()->__toString(), $bytecode
|
||||
);
|
||||
}
|
||||
|
||||
$entries[] = $entry_array;
|
||||
}
|
||||
|
||||
return [
|
||||
'version' => $this->Version,
|
||||
'entries' => $Entries
|
||||
($bytecode ? Functions::cbc('version') : 'version') => $this->Version,
|
||||
($bytecode ? Functions::cbc('entries') : 'entries') => $entries,
|
||||
];
|
||||
}
|
||||
|
||||
/**
|
||||
* Constructs an object from an array representation
|
||||
* Constructs a new object from an array
|
||||
*
|
||||
* @param array $data
|
||||
* @param array $array
|
||||
* @return Vault
|
||||
*/
|
||||
public static function fromArray(array $data): Vault
|
||||
public static function fromArray(array $array): Vault
|
||||
{
|
||||
$VaultObject = new Vault();
|
||||
$vault = new Vault();
|
||||
$vault->Version = Functions::array_bc($array, 'version');
|
||||
$entries = Functions::array_bc($array, 'entries');
|
||||
|
||||
if(isset($data['version']))
|
||||
$VaultObject->Version = $data['version'];
|
||||
|
||||
if(isset($data['entries']))
|
||||
foreach($entries as $entry)
|
||||
{
|
||||
foreach($data['entries'] as $entry)
|
||||
{
|
||||
$VaultObject->Entries[] = Entry::fromArray($entry);
|
||||
}
|
||||
$entry = Entry::fromArray($entry);
|
||||
$vault->Entries[] = $entry;
|
||||
}
|
||||
|
||||
return $VaultObject;
|
||||
return $vault;
|
||||
}
|
||||
|
||||
}
|
|
@ -1,60 +0,0 @@
|
|||
<?php
|
||||
|
||||
|
||||
/** @noinspection PhpMissingFieldTypeInspection */
|
||||
|
||||
namespace ncc\Objects\Vault;
|
||||
|
||||
class DefaultEntry
|
||||
{
|
||||
/**
|
||||
* The alias entry to use for default authentication
|
||||
*
|
||||
* @var string
|
||||
*/
|
||||
public $Alias;
|
||||
|
||||
/**
|
||||
* The source that the alias is for
|
||||
*
|
||||
* @var string
|
||||
*/
|
||||
public $Source;
|
||||
|
||||
/**
|
||||
* Returns an array representation of the object
|
||||
*
|
||||
* @return array
|
||||
*/
|
||||
public function toArray(): array
|
||||
{
|
||||
return [
|
||||
'alias' => $this->Alias,
|
||||
'source' => $this->Source
|
||||
];
|
||||
}
|
||||
|
||||
/**
|
||||
* Constructs the object from an array representation
|
||||
*
|
||||
* @param array $data
|
||||
* @return DefaultEntry
|
||||
*/
|
||||
public static function fromArray(array $data): DefaultEntry
|
||||
{
|
||||
$DefaultEntryObject = new DefaultEntry();
|
||||
|
||||
if(isset($data['alias']))
|
||||
{
|
||||
$DefaultEntryObject->Alias = $data['alias'];
|
||||
}
|
||||
|
||||
if(isset($data['source']))
|
||||
{
|
||||
$DefaultEntryObject->Source = $data['source'];
|
||||
}
|
||||
|
||||
return $DefaultEntryObject;
|
||||
}
|
||||
|
||||
}
|
|
@ -4,124 +4,327 @@
|
|||
|
||||
namespace ncc\Objects\Vault;
|
||||
|
||||
use ncc\Abstracts\RemoteAuthenticationType;
|
||||
use ncc\Abstracts\RemoteSource;
|
||||
use ncc\Abstracts\AuthenticationType;
|
||||
use ncc\Defuse\Crypto\Crypto;
|
||||
use ncc\Defuse\Crypto\Exception\EnvironmentIsBrokenException;
|
||||
use ncc\Defuse\Crypto\Exception\WrongKeyOrModifiedCiphertextException;
|
||||
use ncc\Exceptions\RuntimeException;
|
||||
use ncc\Interfaces\PasswordInterface;
|
||||
use ncc\Objects\Vault\Password\AccessToken;
|
||||
use ncc\Objects\Vault\Password\UsernamePassword;
|
||||
use ncc\Utilities\Functions;
|
||||
use ncc\ZiProto\ZiProto;
|
||||
|
||||
class Entry
|
||||
{
|
||||
/**
|
||||
* The unique alias of the source entry, can also be used for remote resource fetching for dependencies with the
|
||||
* following example schemes;
|
||||
*
|
||||
* - alias@github.com/org/package
|
||||
* - alias@git.example.org/org/package
|
||||
* - alias@gitlab.com/org/package
|
||||
* The entry's unique identifier
|
||||
*
|
||||
* @var string
|
||||
*/
|
||||
public $Alias;
|
||||
private $Name;
|
||||
|
||||
/**
|
||||
* The remote source of the entry, currently only supported sources are allowed.
|
||||
*
|
||||
* @var string|RemoteSource
|
||||
*/
|
||||
public $Source;
|
||||
|
||||
/**
|
||||
* The host of the remote source, eg; github.com or git.example.org, will be used for remote resource fetching
|
||||
* for dependencies with the following example schemes;
|
||||
*
|
||||
* - github.com/org/package
|
||||
* - git.example.org/org/package
|
||||
* - gitlab.com/org/package
|
||||
*
|
||||
* @var string
|
||||
*/
|
||||
public $SourceHost;
|
||||
|
||||
/**
|
||||
* @var string|RemoteAuthenticationType
|
||||
*/
|
||||
public $AuthenticationType;
|
||||
|
||||
/**
|
||||
* Indicates if the authentication details are encrypted or not, if encrypted a passphrase is required
|
||||
* by the user
|
||||
* Whether the entry's password is encrypted
|
||||
*
|
||||
* @var bool
|
||||
*/
|
||||
public $Encrypted;
|
||||
private $Encrypted;
|
||||
|
||||
/**
|
||||
* The authentication details.
|
||||
* The entry's password
|
||||
*
|
||||
* If the remote authentication type is private access token, the first index (0) would be the key itself
|
||||
* If the remote authentication type is a username and password, first index would be Username and second
|
||||
* would be the password.
|
||||
*
|
||||
* @var array
|
||||
* @var PasswordInterface|string|null
|
||||
*/
|
||||
public $Authentication;
|
||||
private $Password;
|
||||
|
||||
/**
|
||||
* Whether the entry's password is currently decrypted in memory
|
||||
* (Not serialized)
|
||||
*
|
||||
* @var bool
|
||||
*/
|
||||
private $IsCurrentlyDecrypted;
|
||||
|
||||
/**
|
||||
* Returns an array representation of the object
|
||||
*
|
||||
* @return array
|
||||
* @noinspection PhpArrayShapeAttributeCanBeAddedInspection
|
||||
*/
|
||||
public function toArray(): array
|
||||
public function __construct()
|
||||
{
|
||||
$this->Encrypted = true;
|
||||
$this->IsCurrentlyDecrypted = true;
|
||||
}
|
||||
|
||||
/**
|
||||
* Test Authenticates the entry
|
||||
*
|
||||
* For UsernamePassword the $input parameter expects an array with the keys 'username' and 'password'
|
||||
* For AccessToken the $input parameter expects an array with the key 'token'
|
||||
*
|
||||
* @param array $input
|
||||
* @return bool
|
||||
* @noinspection PhpUnused
|
||||
*/
|
||||
public function authenticate(array $input): bool
|
||||
{
|
||||
if(!$this->IsCurrentlyDecrypted)
|
||||
return false;
|
||||
|
||||
if($this->Password == null)
|
||||
return false;
|
||||
|
||||
switch($this->Password->getAuthenticationType())
|
||||
{
|
||||
case AuthenticationType::UsernamePassword:
|
||||
if(!($this->Password instanceof UsernamePassword))
|
||||
return false;
|
||||
|
||||
$username = $input['username'] ?? null;
|
||||
$password = $input['password'] ?? null;
|
||||
|
||||
if($username === null && $password === null)
|
||||
return false;
|
||||
|
||||
if($username == null)
|
||||
return $password == $this->Password->Password;
|
||||
|
||||
if($password == null)
|
||||
return $username == $this->Password->Username;
|
||||
|
||||
return $username == $this->Password->Username && $password == $this->Password->Password;
|
||||
|
||||
case AuthenticationType::AccessToken:
|
||||
if(!($this->Password instanceof AccessToken))
|
||||
return false;
|
||||
|
||||
$token = $input['token'] ?? null;
|
||||
|
||||
if($token === null)
|
||||
return false;
|
||||
|
||||
return $token == $this->Password->AccessToken;
|
||||
|
||||
default:
|
||||
return false;
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @param PasswordInterface $password
|
||||
* @return void
|
||||
*/
|
||||
public function setAuthentication(PasswordInterface $password): void
|
||||
{
|
||||
$this->Password = $password;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return bool
|
||||
* @noinspection PhpUnused
|
||||
*/
|
||||
public function isIsCurrentlyDecrypted(): bool
|
||||
{
|
||||
return $this->IsCurrentlyDecrypted;
|
||||
}
|
||||
|
||||
/**
|
||||
* Locks the entry by encrypting the password
|
||||
*
|
||||
* @return bool
|
||||
*/
|
||||
public function lock(): bool
|
||||
{
|
||||
if($this->Password == null)
|
||||
return false;
|
||||
|
||||
if($this->Encrypted)
|
||||
return false;
|
||||
|
||||
if(!$this->IsCurrentlyDecrypted)
|
||||
return false;
|
||||
|
||||
if(!($this->Password instanceof PasswordInterface))
|
||||
return false;
|
||||
|
||||
$this->Password = $this->encrypt();
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* Unlocks the entry by decrypting the password
|
||||
*
|
||||
* @param string $password
|
||||
* @return bool
|
||||
* @throws RuntimeException
|
||||
* @noinspection PhpUnused
|
||||
*/
|
||||
public function unlock(string $password): bool
|
||||
{
|
||||
if($this->Password == null)
|
||||
return false;
|
||||
|
||||
if(!$this->Encrypted)
|
||||
return false;
|
||||
|
||||
if($this->IsCurrentlyDecrypted)
|
||||
return false;
|
||||
|
||||
if(!is_string($this->Password))
|
||||
return false;
|
||||
|
||||
try
|
||||
{
|
||||
$password = Crypto::decryptWithPassword($this->Password, $password, true);
|
||||
}
|
||||
catch (EnvironmentIsBrokenException $e)
|
||||
{
|
||||
throw new RuntimeException('Cannot decrypt password', $e);
|
||||
}
|
||||
catch (WrongKeyOrModifiedCiphertextException $e)
|
||||
{
|
||||
unset($e);
|
||||
return false;
|
||||
}
|
||||
|
||||
$this->Password = ZiProto::decode($password);
|
||||
$this->IsCurrentlyDecrypted = true;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the password object as an encrypted binary string
|
||||
*
|
||||
* @return string|null
|
||||
*/
|
||||
private function encrypt(): ?string
|
||||
{
|
||||
if(!$this->IsCurrentlyDecrypted)
|
||||
return false;
|
||||
|
||||
if($this->Password == null)
|
||||
return false;
|
||||
|
||||
if(!($this->Password instanceof PasswordInterface))
|
||||
return null;
|
||||
|
||||
$password = ZiProto::encode($this->Password->toArray(true));
|
||||
return Crypto::encryptWithPassword($password, $password, true);
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns an array representation of the object
|
||||
*
|
||||
* @param bool $bytecode
|
||||
* @return array
|
||||
*/
|
||||
public function toArray(bool $bytecode=false): array
|
||||
{
|
||||
if(!$this->Password)
|
||||
{
|
||||
if($this->Encrypted && $this->IsCurrentlyDecrypted)
|
||||
{
|
||||
$password = $this->encrypt();
|
||||
}
|
||||
else
|
||||
{
|
||||
$password = $this->Password->toArray(true);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
$password = $this->Password;
|
||||
}
|
||||
|
||||
return [
|
||||
'alias' => $this->Alias,
|
||||
'source' => $this->Source,
|
||||
'source_host' => $this->SourceHost,
|
||||
'authentication_type' => $this->AuthenticationType,
|
||||
'encrypted' => $this->Encrypted,
|
||||
'authentication' => $this->Authentication
|
||||
($bytecode ? Functions::cbc('name') : 'name') => $this->Name,
|
||||
($bytecode ? Functions::cbc('encrypted') : 'encrypted') => $this->Encrypted,
|
||||
($bytecode ? Functions::cbc('password') : 'password') => $password,
|
||||
];
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns an array representation of the object
|
||||
* Constructs an object from an array representation
|
||||
*
|
||||
* @param array $data
|
||||
* @return Entry
|
||||
*/
|
||||
public static function fromArray(array $data): Entry
|
||||
public static function fromArray(array $data): self
|
||||
{
|
||||
$EntryObject = new Entry();
|
||||
$self = new self();
|
||||
|
||||
if(isset($data['alias']))
|
||||
$self->Name = Functions::array_bc($data, 'name');
|
||||
$self->Encrypted = Functions::array_bc($data, 'encrypted');
|
||||
|
||||
$password = Functions::array_bc($data, 'password');
|
||||
if($password !== null)
|
||||
{
|
||||
$EntryObject->Alias = $data['alias'];
|
||||
if($self->Encrypted)
|
||||
{
|
||||
$self->Password = $password;
|
||||
$self->IsCurrentlyDecrypted = false;
|
||||
}
|
||||
elseif(gettype($password) == 'array')
|
||||
{
|
||||
$self->Password = match (Functions::array_bc($data, 'authentication_type')) {
|
||||
AuthenticationType::UsernamePassword => UsernamePassword::fromArray($password),
|
||||
AuthenticationType::AccessToken => AccessToken::fromArray($password)
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
if(isset($data['source']))
|
||||
{
|
||||
$EntryObject->Source = $data['source'];
|
||||
return $self;
|
||||
}
|
||||
|
||||
if(isset($data['source_host']))
|
||||
/**
|
||||
* @return bool
|
||||
*/
|
||||
public function isEncrypted(): bool
|
||||
{
|
||||
$EntryObject->SourceHost = $data['source_host'];
|
||||
return $this->Encrypted;
|
||||
}
|
||||
|
||||
if(isset($data['authentication_type']))
|
||||
/**
|
||||
* Returns false if the entry needs to be decrypted first
|
||||
*
|
||||
* @param bool $Encrypted
|
||||
* @return bool
|
||||
*/
|
||||
public function setEncrypted(bool $Encrypted): bool
|
||||
{
|
||||
$EntryObject->AuthenticationType = $data['authentication_type'];
|
||||
if(!$this->IsCurrentlyDecrypted)
|
||||
return false;
|
||||
|
||||
$this->Encrypted = $Encrypted;
|
||||
return true;
|
||||
}
|
||||
|
||||
if(isset($data['encrypted']))
|
||||
/**
|
||||
* @return string
|
||||
*/
|
||||
public function getName(): string
|
||||
{
|
||||
$EntryObject->Encrypted = $data['encrypted'];
|
||||
return $this->Name;
|
||||
}
|
||||
|
||||
if(isset($data['authentication']))
|
||||
/**
|
||||
* @param string $Name
|
||||
*/
|
||||
public function setName(string $Name): void
|
||||
{
|
||||
$EntryObject->Authentication = $data['authentication'];
|
||||
$this->Name = $Name;
|
||||
}
|
||||
|
||||
return $EntryObject;
|
||||
/**
|
||||
* @return PasswordInterface|null
|
||||
*/
|
||||
public function getPassword(): ?PasswordInterface
|
||||
{
|
||||
if(!$this->IsCurrentlyDecrypted)
|
||||
return null;
|
||||
|
||||
return $this->Password;
|
||||
}
|
||||
}
|
74
src/ncc/Objects/Vault/Password/AccessToken.php
Normal file
74
src/ncc/Objects/Vault/Password/AccessToken.php
Normal file
|
@ -0,0 +1,74 @@
|
|||
<?php
|
||||
|
||||
/** @noinspection PhpMissingFieldTypeInspection */
|
||||
|
||||
namespace ncc\Objects\Vault\Password;
|
||||
|
||||
use ncc\Abstracts\AuthenticationType;
|
||||
use ncc\Interfaces\PasswordInterface;
|
||||
use ncc\Utilities\Functions;
|
||||
|
||||
class AccessToken implements PasswordInterface
|
||||
{
|
||||
/**
|
||||
* The entry's access token
|
||||
*
|
||||
* @var string
|
||||
*/
|
||||
public $AccessToken;
|
||||
|
||||
/**
|
||||
* Returns an array representation of the object
|
||||
*
|
||||
* @param bool $bytecode
|
||||
* @return array
|
||||
*/
|
||||
public function toArray(bool $bytecode=false): array
|
||||
{
|
||||
return [
|
||||
($bytecode ? Functions::cbc('authentication_type') : 'authentication_type') => AuthenticationType::AccessToken,
|
||||
($bytecode ? Functions::cbc('access_token') : 'access_token') => $this->AccessToken,
|
||||
];
|
||||
}
|
||||
|
||||
/**
|
||||
* Constructs an object from an array representation
|
||||
*
|
||||
* @param array $data
|
||||
* @return static
|
||||
*/
|
||||
public static function fromArray(array $data): self
|
||||
{
|
||||
$object = new self();
|
||||
|
||||
$object->AccessToken = Functions::array_bc($data, 'access_token');
|
||||
|
||||
return $object;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return string
|
||||
*/
|
||||
public function getAccessToken(): string
|
||||
{
|
||||
return $this->AccessToken;
|
||||
}
|
||||
|
||||
/**
|
||||
* @inheritDoc
|
||||
*/
|
||||
public function getAuthenticationType(): string
|
||||
{
|
||||
return AuthenticationType::AccessToken;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns a string representation of the object
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
public function __toString(): string
|
||||
{
|
||||
return $this->AccessToken;
|
||||
}
|
||||
}
|
93
src/ncc/Objects/Vault/Password/UsernamePassword.php
Normal file
93
src/ncc/Objects/Vault/Password/UsernamePassword.php
Normal file
|
@ -0,0 +1,93 @@
|
|||
<?php
|
||||
|
||||
/** @noinspection PhpMissingFieldTypeInspection */
|
||||
|
||||
namespace ncc\Objects\Vault\Password;
|
||||
|
||||
use ncc\Abstracts\AuthenticationType;
|
||||
use ncc\Interfaces\PasswordInterface;
|
||||
use ncc\Utilities\Functions;
|
||||
|
||||
class UsernamePassword implements PasswordInterface
|
||||
{
|
||||
/**
|
||||
* The entry's username
|
||||
*
|
||||
* @var string
|
||||
*/
|
||||
public $Username;
|
||||
|
||||
/**
|
||||
* The entry's password
|
||||
*
|
||||
* @var string
|
||||
*/
|
||||
public $Password;
|
||||
|
||||
/**
|
||||
* Returns an array representation of the object
|
||||
*
|
||||
* @param bool $bytecode
|
||||
* @return array
|
||||
*/
|
||||
public function toArray(bool $bytecode=false): array
|
||||
{
|
||||
return [
|
||||
($bytecode ? Functions::cbc('authentication_type') : 'authentication_type') => AuthenticationType::UsernamePassword,
|
||||
($bytecode ? Functions::cbc('username') : 'username') => $this->Username,
|
||||
($bytecode ? Functions::cbc('password') : 'password') => $this->Password,
|
||||
];
|
||||
}
|
||||
|
||||
/**
|
||||
* Constructs an object from an array representation
|
||||
*
|
||||
* @param array $data
|
||||
* @return static
|
||||
*/
|
||||
public static function fromArray(array $data): self
|
||||
{
|
||||
$instance = new self();
|
||||
|
||||
$instance->Username = Functions::array_bc($data, 'username');
|
||||
$instance->Password = Functions::array_bc($data, 'password');
|
||||
|
||||
return $instance;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return string
|
||||
* @noinspection PhpUnused
|
||||
*/
|
||||
public function getUsername(): string
|
||||
{
|
||||
return $this->Username;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return string
|
||||
* @noinspection PhpUnused
|
||||
*/
|
||||
public function getPassword(): string
|
||||
{
|
||||
return $this->Password;
|
||||
}
|
||||
|
||||
/**
|
||||
* @inheritDoc
|
||||
*/
|
||||
public function getAuthenticationType(): string
|
||||
{
|
||||
return AuthenticationType::UsernamePassword;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns a string representation of the object
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
public function __toString(): string
|
||||
{
|
||||
return $this->Password;
|
||||
}
|
||||
}
|
Loading…
Add table
Reference in a new issue