Composer update
This commit is contained in:
5
www/composer.lock
generated
5
www/composer.lock
generated
@@ -12,7 +12,7 @@
|
||||
"dist": {
|
||||
"type": "path",
|
||||
"url": "/storage/var/www/html/developers/clemens/core_data/composer-packages/CoreLibs-Composer-All",
|
||||
"reference": "1357b98883c6e4bcac163c5fb29e28c8f968a814"
|
||||
"reference": "3eb122959045f8de10f9dd35e6632199021752b8"
|
||||
},
|
||||
"require": {
|
||||
"php": ">=8.2",
|
||||
@@ -20,7 +20,8 @@
|
||||
},
|
||||
"require-dev": {
|
||||
"egrajp/smarty-extended": "^4.3",
|
||||
"gullevek/dotenv": "dev-master"
|
||||
"gullevek/dotenv": "dev-master",
|
||||
"phpunit/phpunit": "^9"
|
||||
},
|
||||
"type": "library",
|
||||
"autoload": {
|
||||
|
||||
5
www/vendor/composer/installed.json
vendored
5
www/vendor/composer/installed.json
vendored
@@ -7,7 +7,7 @@
|
||||
"dist": {
|
||||
"type": "path",
|
||||
"url": "/storage/var/www/html/developers/clemens/core_data/composer-packages/CoreLibs-Composer-All",
|
||||
"reference": "1357b98883c6e4bcac163c5fb29e28c8f968a814"
|
||||
"reference": "3eb122959045f8de10f9dd35e6632199021752b8"
|
||||
},
|
||||
"require": {
|
||||
"php": ">=8.2",
|
||||
@@ -15,7 +15,8 @@
|
||||
},
|
||||
"require-dev": {
|
||||
"egrajp/smarty-extended": "^4.3",
|
||||
"gullevek/dotenv": "dev-master"
|
||||
"gullevek/dotenv": "dev-master",
|
||||
"phpunit/phpunit": "^9"
|
||||
},
|
||||
"type": "library",
|
||||
"installation-source": "dist",
|
||||
|
||||
2
www/vendor/composer/installed.php
vendored
2
www/vendor/composer/installed.php
vendored
@@ -13,7 +13,7 @@
|
||||
'egrajp/corelibs-composer-all' => array(
|
||||
'pretty_version' => 'dev-development',
|
||||
'version' => 'dev-development',
|
||||
'reference' => '1357b98883c6e4bcac163c5fb29e28c8f968a814',
|
||||
'reference' => '3eb122959045f8de10f9dd35e6632199021752b8',
|
||||
'type' => 'library',
|
||||
'install_path' => __DIR__ . '/../egrajp/corelibs-composer-all',
|
||||
'aliases' => array(),
|
||||
|
||||
@@ -1,2 +1,3 @@
|
||||
vendor
|
||||
vendor/
|
||||
composer.lock
|
||||
tools/
|
||||
|
||||
@@ -1,8 +1,8 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<phive xmlns="https://phar.io/phive">
|
||||
<phar name="phpunit" version="^9.6" installed="9.6.19" location="./tools/phpunit" copy="false"/>
|
||||
<phar name="phpcs" version="^3.7.2" installed="3.9.2" location="./tools/phpcs" copy="false"/>
|
||||
<phar name="phpcbf" version="^3.7.2" installed="3.9.2" location="./tools/phpcbf" copy="false"/>
|
||||
<phar name="phpcs" version="^3.7.2" installed="3.10.0" location="./tools/phpcs" copy="false"/>
|
||||
<phar name="phpcbf" version="^3.7.2" installed="3.10.0" location="./tools/phpcbf" copy="false"/>
|
||||
<phar name="psalm" version="^5.15.0" installed="5.24.0" location="./tools/psalm" copy="false"/>
|
||||
<phar name="phpstan" version="^1.10.37" installed="1.11.1" location="./tools/phpstan" copy="false"/>
|
||||
<phar name="phan" version="^5.4.2" installed="5.4.3" location="./tools/phan" copy="false"/>
|
||||
|
||||
@@ -9,16 +9,41 @@ For local install only
|
||||
- Template\SmartyExtended
|
||||
- Admin\EditBase
|
||||
|
||||
## Setup from central composer
|
||||
## Publish to gitea or gitlab server
|
||||
|
||||
Setup from gitea internal servers
|
||||
Currently there are only gitea and gitlab supported, github does not have support for composer packages
|
||||
|
||||
```sh
|
||||
composer config repositories.git.egplusww.jp.Composer composer https://git.egplusww.jp/api/packages/Composer/composer
|
||||
`publish\publish.sh go` will run the publish script
|
||||
|
||||
All the configuration is done in the `publish\.env.deploy` file
|
||||
|
||||
```ini
|
||||
# downlaod file name is "Repository name" "-" "version" where
|
||||
# version is "vN.N.N"
|
||||
GITEA_PUBLISH=1
|
||||
GITEA_UPLOAD_FILENAME="Upload-File-Name";
|
||||
GITEA_USER=gitea-user
|
||||
GITEA_TOKEN=gitea-tokek
|
||||
GITEA_URL_DL=https://[gitea.hostname]/[to/package/folder]/archive
|
||||
GITEA_URL_PUSH=https://[gitea.hostname]/api/packages/[organization]/composer
|
||||
|
||||
GITLAB_PUBLISH=1
|
||||
GITLAB_URL=gitlab URl to repository
|
||||
GITLAB_DEPLOY_TOKEN=gitlab-token
|
||||
```
|
||||
|
||||
Alternative setup composer local zip file repot:
|
||||
`composer config repositories.composer.egplusww.jp composer http://composer.egplusww.jp`
|
||||
At the moment there is only one gitea or gitlab target setable
|
||||
|
||||
## Setup from central composer
|
||||
|
||||
Setup from gitea servers
|
||||
|
||||
[hostname] is the hostname for your gitea server (or wherever this is published)
|
||||
[OrgName] is the organization name where the composer packages are hosted
|
||||
|
||||
```sh
|
||||
composer config repositories.[hostname].Composer composer https://[hostname]/api/packages/[OrgName]/composer
|
||||
```
|
||||
|
||||
## Install package
|
||||
|
||||
|
||||
@@ -21,7 +21,8 @@
|
||||
},
|
||||
"require-dev": {
|
||||
"egrajp/smarty-extended": "^4.3",
|
||||
"gullevek/dotenv": "dev-master"
|
||||
"gullevek/dotenv": "dev-master",
|
||||
"phpunit/phpunit": "^9"
|
||||
},
|
||||
"repositories": {
|
||||
"git.egplusww.jp.Composer": {
|
||||
|
||||
@@ -2,7 +2,7 @@
|
||||
includes:
|
||||
- phpstan-conditional.php
|
||||
parameters:
|
||||
tmpDir: /tmp/phpstan-corelibs-composer
|
||||
tmpDir: %currentWorkingDirectory%/tmp/phpstan-corelibs-composer
|
||||
level: 8 # max is now 9
|
||||
checkMissingCallableSignature: true
|
||||
treatPhpDocTypesAsCertain: false
|
||||
|
||||
@@ -1 +1 @@
|
||||
9.12.2
|
||||
9.13.2
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
#!/usr/bin/env bash
|
||||
|
||||
BASE_FOLDER=$(dirname $(readlink -f $0))"/";
|
||||
BASE_FOLDER=$(dirname "$(readlink -f "$0")")"/";
|
||||
PACKAGE_DOWNLOAD="${BASE_FOLDER}package-download/";
|
||||
if [ ! -d "${PACKAGE_DOWNLOAD}" ]; then
|
||||
mkdir "${PACKAGE_DOWNLOAD}";
|
||||
@@ -15,30 +15,35 @@ if [ -z "${VERSION}" ]; then
|
||||
fi;
|
||||
# compare version, if different or newer, deploy
|
||||
if [ -f "${file_last_published}" ]; then
|
||||
LAST_PUBLISHED_VERSION=$(cat ${file_last_published});
|
||||
if $(dpkg --compare-versions "${VERSION}" le "${LAST_PUBLISHED_VERSION}"); then
|
||||
LAST_PUBLISHED_VERSION=$(cat "${file_last_published}");
|
||||
if dpkg --compare-versions "${VERSION}" le "${LAST_PUBLISHED_VERSION}"; then
|
||||
echo "git tag version ${VERSION} is not newer than previous published version ${LAST_PUBLISHED_VERSION}";
|
||||
exit;
|
||||
fi;
|
||||
fi;
|
||||
|
||||
# read in the .env.deploy file and we must have
|
||||
# for gitea
|
||||
# GITEA_PUBLISH: must be set with a value to trigger publish run
|
||||
# GITEA_UPLOAD_FILENAME
|
||||
# GITLAB_USER
|
||||
# GITLAB_TOKEN
|
||||
# GITLAB_URL
|
||||
# GITEA_USER
|
||||
# GITEA_DEPLOY_TOKEN
|
||||
# GITEA_URL_DL
|
||||
# GITEA_URL_PUSH
|
||||
# for gitlab
|
||||
# GITLAB_PUBLISH: must be set with a value to trigger publish run
|
||||
# GITLAB_USER
|
||||
# GITLAB_TOKEN
|
||||
# GITLAB_URL
|
||||
if [ ! -f "${BASE_FOLDER}.env.deploy" ]; then
|
||||
echo "Deploy enviroment file .env.deploy is missing";
|
||||
exit;
|
||||
fi;
|
||||
set -o allexport;
|
||||
cd ${BASE_FOLDER};
|
||||
cd "${BASE_FOLDER}" || exit;
|
||||
# shellcheck source=.env.deploy
|
||||
source .env.deploy;
|
||||
cd -;
|
||||
cd - || exit;
|
||||
set +o allexport;
|
||||
|
||||
if [ "${go_flag}" != "go" ]; then
|
||||
@@ -50,37 +55,42 @@ fi;
|
||||
|
||||
echo "[START]";
|
||||
# gitea
|
||||
if [ ! -z "${GITEA_UPLOAD_FILENAME}" ] &&
|
||||
[ ! -z "${GITEA_URL_DL}" ] && [ ! -z "${GITEA_URL_PUSH}" ] &&
|
||||
[ ! -z "${GITEA_USER}" ] && [ ! -z "${GITEA_TOKEN}" ]; then
|
||||
if [ ! -f "${PACKAGE_DOWNLOAD}${GITEA_UPLOAD_FILENAME}-v${VERSION}.zip" ]; then
|
||||
curl -LJO \
|
||||
--output-dir "${PACKAGE_DOWNLOAD}" \
|
||||
${GITEA_URL_DL}/v${VERSION}.zip;
|
||||
fi;
|
||||
if [ ! -f "${PACKAGE_DOWNLOAD}${GITEA_UPLOAD_FILENAME}-v${VERSION}.zip" ]; then
|
||||
echo "Version file does not exist for ${VERSION}";
|
||||
# skip iof
|
||||
if [ -n "${GITEA_PUBLISH}" ]; then
|
||||
if [ -n "${GITEA_UPLOAD_FILENAME}" ] &&
|
||||
[ -n "${GITEA_URL_DL}" ] && [ -n "${GITEA_URL_PUSH}" ] &&
|
||||
[ -n "${GITEA_USER}" ] && [ -n "${GITEA_TOKEN}" ]; then
|
||||
if [ ! -f "${PACKAGE_DOWNLOAD}${GITEA_UPLOAD_FILENAME}-v${VERSION}.zip" ]; then
|
||||
curl -LJO \
|
||||
--output-dir "${PACKAGE_DOWNLOAD}" \
|
||||
"${GITEA_URL_DL}"/v"${VERSION}".zip;
|
||||
fi;
|
||||
if [ ! -f "${PACKAGE_DOWNLOAD}${GITEA_UPLOAD_FILENAME}-v${VERSION}.zip" ]; then
|
||||
echo "Version file does not exist for ${VERSION}";
|
||||
else
|
||||
curl --user "${GITEA_USER}":"${GITEA_TOKEN}" \
|
||||
--upload-file "${PACKAGE_DOWNLOAD}${GITEA_UPLOAD_FILENAME}-v${VERSION}.zip" \
|
||||
"${GITEA_URL_PUSH}"?version="${VERSION}";
|
||||
echo "${VERSION}" > "${file_last_published}";
|
||||
fi;
|
||||
else
|
||||
curl --user ${GITEA_USER}:${GITEA_TOKEN} \
|
||||
--upload-file "${PACKAGE_DOWNLOAD}${GITEA_UPLOAD_FILENAME}-v${VERSION}.zip" \
|
||||
${GITEA_URL_PUSH}?version=${VERSION};
|
||||
echo "${VERSION}" > "${file_last_published}";
|
||||
echo "Missing either GITEA_UPLOAD_FILENAME, GITEA_URL_DL, GITEA_URL_PUSH, GITEA_USER or GITEA_TOKEN environment variable";
|
||||
fi;
|
||||
else
|
||||
echo "Missing either GITEA_UPLOAD_FILENAME, GITEA_URL_DL, GITEA_URL_PUSH, GITEA_USER or GITEA_TOKEN environment variable";
|
||||
fi;
|
||||
|
||||
# gitlab
|
||||
if [ ! -z "${GITLAB_URL}" ] && [ ! -z "${GITLAB_DEPLOY_TOKEN}" ]; then
|
||||
curl --data tag=v${VERSION} \
|
||||
--header "Deploy-Token: ${GITLAB_DEPLOY_TOKEN}" \
|
||||
"${GITLAB_URL}";
|
||||
curl --data branch=master \
|
||||
--header "Deploy-Token: ${GITLAB_DEPLOY_TOKEN}" \
|
||||
"${GITLAB_URL}";
|
||||
echo "${VERSION}" > "${file_last_published}";
|
||||
else
|
||||
echo "Missing GITLAB_DEPLOY_TOKEN environment variable";
|
||||
if [ -n "${GITLAB_PUBLISH}" ]; then
|
||||
if [ -n "${GITLAB_URL}" ] && [ -n "${GITLAB_DEPLOY_TOKEN}" ]; then
|
||||
curl --data tag=v"${VERSION}" \
|
||||
--header "Deploy-Token: ${GITLAB_DEPLOY_TOKEN}" \
|
||||
"${GITLAB_URL}";
|
||||
curl --data branch=master \
|
||||
--header "Deploy-Token: ${GITLAB_DEPLOY_TOKEN}" \
|
||||
"${GITLAB_URL}";
|
||||
echo "${VERSION}" > "${file_last_published}";
|
||||
else
|
||||
echo "Missing GITLAB_URL or GITLAB_DEPLOY_TOKEN environment variable";
|
||||
fi;
|
||||
fi;
|
||||
echo "";
|
||||
echo "[DONE]";
|
||||
|
||||
@@ -16,16 +16,22 @@ class Html
|
||||
/**
|
||||
* full wrapper for html entities
|
||||
*
|
||||
* uses default params as: ENT_QUOTES | ENT_HTML5
|
||||
* switches from ENT_HTML401 to ENT_HTML5 as we assume all our pages have <!DOCTYPE html>
|
||||
* removed: ENT_SUBSTITUTE -> wrong characters will be replaced with space
|
||||
* encodes in UTF-8
|
||||
* does not double encode
|
||||
*
|
||||
* @param mixed $string string to html encode
|
||||
* @param int $flags [default: ENT_QUOTES | ENT_HTML5]
|
||||
* @return mixed if string, encoded, else as is (eg null)
|
||||
*/
|
||||
public static function htmlent(mixed $string): mixed
|
||||
public static function htmlent(mixed $string, int $flags = ENT_QUOTES | ENT_HTML5): mixed
|
||||
{
|
||||
if (is_string($string)) {
|
||||
return htmlentities($string, ENT_COMPAT | ENT_HTML401, 'UTF-8', false);
|
||||
} else {
|
||||
return $string;
|
||||
return htmlentities($string, $flags, 'UTF-8', false);
|
||||
}
|
||||
return $string;
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -54,14 +60,10 @@ class Html
|
||||
*/
|
||||
public static function checked(array|string $haystack, string $needle, int $type = 0): ?string
|
||||
{
|
||||
if (is_array($haystack)) {
|
||||
if (in_array($needle, $haystack)) {
|
||||
return $type ? 'checked' : 'selected';
|
||||
}
|
||||
} else {
|
||||
if ($haystack == $needle) {
|
||||
return $type ? 'checked' : 'selected';
|
||||
}
|
||||
if (is_array($haystack) && in_array($needle, $haystack)) {
|
||||
return $type ? 'checked' : 'selected';
|
||||
} elseif (!is_array($haystack) && $haystack == $needle) {
|
||||
return $type ? 'checked' : 'selected';
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
@@ -1324,8 +1324,12 @@ class IO
|
||||
// /s for matching new line in . list
|
||||
// [disabled, we don't used ^ or $] /m for multi line match
|
||||
// Matches in 1:, must be array_filtered to remove empty, count with array_unique
|
||||
$query_split = '[(=,?-]|->|->>|#>|#>>|@>|<@|\?\|\?\&|\|\||#-';
|
||||
preg_match_all(
|
||||
'/(?:\'.*?\')?\s*(?:\?\?|<>|[(=,])\s*(?:\d+|(?:\'.*?\')|(\$[1-9]{1}(?:[0-9]{1,})?))/s',
|
||||
'/'
|
||||
. '(?:\'.*?\')?\s*(?:\?\?|<>|' . $query_split . ')\s*'
|
||||
. '(?:\d+|(?:\'.*?\')|(\$[1-9]{1}(?:[0-9]{1,})?))'
|
||||
. '/s',
|
||||
$query,
|
||||
$match
|
||||
);
|
||||
|
||||
@@ -39,9 +39,11 @@ class ConvertPlaceholder
|
||||
): array {
|
||||
$convert_to = strtolower($convert_to);
|
||||
$matches = [];
|
||||
$query_split = '[(=,?-]|->|->>|#>|#>>|@>|<@|\?\|\?\&|\|\||#-';
|
||||
$pattern = '/'
|
||||
// prefix string part, must match towards
|
||||
. '(?:\'.*?\')?\s*(?:\?\?|[(=,])\s*'
|
||||
// seperator for ( = , ? - [and json/jsonb in pg doc section 9.15]
|
||||
. '(?:\'.*?\')?\s*(?:\?\?|' . $query_split . ')\s*'
|
||||
// match for replace part
|
||||
. '(?:'
|
||||
// digit -> ignore
|
||||
@@ -96,7 +98,10 @@ class ConvertPlaceholder
|
||||
$type = 'named';
|
||||
$matches_return = $named_matches;
|
||||
// only check for :named
|
||||
$pattern_replace = '/((?:\'.*?\')?\s*(?:\?\?|[(=,])\s*)(\d+|(?:\'.*?\')|(:\w+))/s';
|
||||
$pattern_replace = '/'
|
||||
. '((?:\'.*?\')?\s*(?:\?\?|' . $query_split . ')\s*)'
|
||||
. '(\d+|(?:\'.*?\')|(:\w+))'
|
||||
. '/s';
|
||||
// 0: full
|
||||
// 1: pre part
|
||||
// 2: keep part UNLESS '3' is set
|
||||
@@ -134,7 +139,10 @@ class ConvertPlaceholder
|
||||
// order and data stays the same
|
||||
$params_new = $params;
|
||||
// only check for ?
|
||||
$pattern_replace = '/((?:\'.*?\')?\s*(?:\?\?|[(=,])\s*)(\d+|(?:\'.*?\')|(?:(?:\?\?)?\s*(\?{1})))/s';
|
||||
$pattern_replace = '/'
|
||||
. '((?:\'.*?\')?\s*(?:\?\?|' . $query_split . ')\s*)'
|
||||
. '(\d+|(?:\'.*?\')|(?:(?:\?\?)?\s*(\?{1})))'
|
||||
. '/s';
|
||||
// 0: full
|
||||
// 1: pre part
|
||||
// 2: keep part UNLESS '3' is set
|
||||
@@ -163,7 +171,10 @@ class ConvertPlaceholder
|
||||
$type = 'numbered';
|
||||
$matches_return = $numbered_matches;
|
||||
// only check for $n
|
||||
$pattern_replace = '/((?:\'.*?\')?\s*(?:\?\?|[(=,])\s*)(\d+|(?:\'.*?\')|(\$[1-9]{1}(?:[0-9]{1,})?))/s';
|
||||
$pattern_replace = '/'
|
||||
. '((?:\'.*?\')?\s*(?:\?\?|' . $query_split . ')\s*)'
|
||||
. '(\d+|(?:\'.*?\')|(\$[1-9]{1}(?:[0-9]{1,})?))'
|
||||
. '/s';
|
||||
// 0: full
|
||||
// 1: pre part
|
||||
// 2: keep part UNLESS '3' is set
|
||||
|
||||
@@ -46,7 +46,7 @@ class CachedFileReader extends \CoreLibs\Language\Core\StringReader
|
||||
if (!is_resource($fd)) {
|
||||
$this->error = 3; // Cannot read file, probably permissions
|
||||
} else {
|
||||
$this->fd_str = fread($fd, filesize($filename) ?: 0) ?: '';
|
||||
$this->fd_str = fread($fd, filesize($filename) ?: 1) ?: '';
|
||||
fclose($fd);
|
||||
}
|
||||
} else {
|
||||
|
||||
@@ -21,66 +21,82 @@ use SodiumException;
|
||||
|
||||
class SymmetricEncryption
|
||||
{
|
||||
/** @var SymmetricEncryption self instance */
|
||||
private static SymmetricEncryption $instance;
|
||||
|
||||
/** @var string bin hex key */
|
||||
private string $key = '';
|
||||
|
||||
/**
|
||||
* init class
|
||||
* if key not passed, key must be set with createKey
|
||||
*
|
||||
* @param string|null|null $key
|
||||
*/
|
||||
public function __construct(
|
||||
string|null $key = null
|
||||
) {
|
||||
if ($key != null) {
|
||||
$this->setKey($key);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the singleton self object.
|
||||
* For function wrapper use
|
||||
*
|
||||
* @return SymmetricEncryption object
|
||||
*/
|
||||
public static function getInstance(string|null $key = null): self
|
||||
{
|
||||
if (empty(self::$instance)) {
|
||||
self::$instance = new self($key);
|
||||
}
|
||||
return self::$instance;
|
||||
}
|
||||
|
||||
/* ************************************************************************
|
||||
* MARK: PRIVATE
|
||||
* *************************************************************************/
|
||||
|
||||
/**
|
||||
* create key and check validity
|
||||
*
|
||||
* @param string $key The key from which the binary key will be created
|
||||
* @return string Binary key string
|
||||
*/
|
||||
public static function createKey(string $key): string
|
||||
private function createKey(string $key): string
|
||||
{
|
||||
try {
|
||||
$key = CreateKey::hex2bin($key);
|
||||
} catch (SodiumException $e) {
|
||||
throw new \UnexpectedValueException('Invalid hex key');
|
||||
throw new \UnexpectedValueException('Invalid hex key: ' . $e->getMessage());
|
||||
}
|
||||
if (mb_strlen($key, '8bit') !== SODIUM_CRYPTO_SECRETBOX_KEYBYTES) {
|
||||
throw new \RangeException(
|
||||
'Key is not the correct size (must be '
|
||||
. 'SODIUM_CRYPTO_SECRETBOX_KEYBYTES bytes long).'
|
||||
. SODIUM_CRYPTO_SECRETBOX_KEYBYTES . ' bytes long).'
|
||||
);
|
||||
}
|
||||
return $key;
|
||||
}
|
||||
|
||||
/**
|
||||
* Encrypt a message
|
||||
* Decryption call
|
||||
*
|
||||
* @param string $message Message to encrypt
|
||||
* @param string $key Encryption key (as hex string)
|
||||
* @return string
|
||||
* @throws \Exception
|
||||
* @param string $encrypted Text to decrypt
|
||||
* @param ?string $key Mandatory encryption key, will throw exception if empty
|
||||
* @return string Plain text
|
||||
* @throws \RangeException
|
||||
* @throws \UnexpectedValueException
|
||||
* @throws \UnexpectedValueException
|
||||
*/
|
||||
public static function encrypt(string $message, string $key): string
|
||||
private function decryptData(string $encrypted, ?string $key): string
|
||||
{
|
||||
$key = self::createKey($key);
|
||||
$nonce = random_bytes(SODIUM_CRYPTO_SECRETBOX_NONCEBYTES);
|
||||
|
||||
$cipher = base64_encode(
|
||||
$nonce
|
||||
. sodium_crypto_secretbox(
|
||||
$message,
|
||||
$nonce,
|
||||
$key
|
||||
)
|
||||
);
|
||||
sodium_memzero($message);
|
||||
sodium_memzero($key);
|
||||
return $cipher;
|
||||
}
|
||||
|
||||
/**
|
||||
* Decrypt a message
|
||||
*
|
||||
* @param string $encrypted Message encrypted with safeEncrypt()
|
||||
* @param string $key Encryption key (as hex string)
|
||||
* @return string
|
||||
* @throws \Exception
|
||||
*/
|
||||
public static function decrypt(string $encrypted, string $key): string
|
||||
{
|
||||
$key = self::createKey($key);
|
||||
if (empty($key)) {
|
||||
throw new \UnexpectedValueException('Key not set');
|
||||
}
|
||||
$key = $this->createKey($key);
|
||||
$decoded = base64_decode($encrypted);
|
||||
$nonce = mb_substr($decoded, 0, SODIUM_CRYPTO_SECRETBOX_NONCEBYTES, '8bit');
|
||||
$ciphertext = mb_substr($decoded, SODIUM_CRYPTO_SECRETBOX_NONCEBYTES, null, '8bit');
|
||||
@@ -93,7 +109,7 @@ class SymmetricEncryption
|
||||
$key
|
||||
);
|
||||
} catch (SodiumException $e) {
|
||||
throw new \UnexpectedValueException('Invalid ciphertext (too short)');
|
||||
throw new \UnexpectedValueException('Decipher message failed: ' . $e->getMessage());
|
||||
}
|
||||
if (!is_string($plain)) {
|
||||
throw new \UnexpectedValueException('Invalid Key');
|
||||
@@ -102,6 +118,117 @@ class SymmetricEncryption
|
||||
sodium_memzero($key);
|
||||
return $plain;
|
||||
}
|
||||
|
||||
/**
|
||||
* Encrypt a message
|
||||
*
|
||||
* @param string $message Message to encrypt
|
||||
* @param ?string $key Mandatory encryption key, will throw exception if empty
|
||||
* @return string
|
||||
* @throws \Exception
|
||||
* @throws \RangeException
|
||||
*/
|
||||
private function encryptData(string $message, ?string $key): string
|
||||
{
|
||||
if (empty($this->key) || $key === null) {
|
||||
throw new \UnexpectedValueException('Key not set');
|
||||
}
|
||||
$key = $this->createKey($key);
|
||||
$nonce = random_bytes(SODIUM_CRYPTO_SECRETBOX_NONCEBYTES);
|
||||
try {
|
||||
$cipher = base64_encode(
|
||||
$nonce
|
||||
. sodium_crypto_secretbox(
|
||||
$message,
|
||||
$nonce,
|
||||
$key,
|
||||
)
|
||||
);
|
||||
} catch (SodiumException $e) {
|
||||
throw new \UnexpectedValueException("Create encrypted message failed: " . $e->getMessage());
|
||||
}
|
||||
sodium_memzero($message);
|
||||
sodium_memzero($key);
|
||||
return $cipher;
|
||||
}
|
||||
|
||||
/* ************************************************************************
|
||||
* MARK: PUBLIC
|
||||
* *************************************************************************/
|
||||
|
||||
|
||||
/**
|
||||
* set a new key for encryption
|
||||
*
|
||||
* @param string $key
|
||||
* @return void
|
||||
*/
|
||||
public function setKey(string $key)
|
||||
{
|
||||
if (empty($key)) {
|
||||
throw new \UnexpectedValueException('Key cannot be empty');
|
||||
}
|
||||
$this->key = $key;
|
||||
}
|
||||
|
||||
/**
|
||||
* Decrypt a message
|
||||
* static version
|
||||
*
|
||||
* @param string $encrypted Message encrypted with safeEncrypt()
|
||||
* @param string $key Encryption key (as hex string)
|
||||
* @return string
|
||||
* @throws \Exception
|
||||
* @throws \RangeException
|
||||
* @throws \UnexpectedValueException
|
||||
* @throws \UnexpectedValueException
|
||||
*/
|
||||
public static function decryptKey(string $encrypted, string $key): string
|
||||
{
|
||||
return self::getInstance()->decryptData($encrypted, $key);
|
||||
}
|
||||
|
||||
/**
|
||||
* Decrypt a message
|
||||
*
|
||||
* @param string $encrypted Message encrypted with safeEncrypt()
|
||||
* @return string
|
||||
* @throws \RangeException
|
||||
* @throws \UnexpectedValueException
|
||||
* @throws \UnexpectedValueException
|
||||
*/
|
||||
public function decrypt(string $encrypted): string
|
||||
{
|
||||
return $this->decryptData($encrypted, $this->key);
|
||||
}
|
||||
|
||||
/**
|
||||
* Encrypt a message
|
||||
* static version
|
||||
*
|
||||
* @param string $message Message to encrypt
|
||||
* @param string $key Encryption key (as hex string)
|
||||
* @return string
|
||||
* @throws \Exception
|
||||
* @throws \RangeException
|
||||
*/
|
||||
public static function encryptKey(string $message, string $key): string
|
||||
{
|
||||
return self::getInstance()->encryptData($message, $key);
|
||||
}
|
||||
|
||||
/**
|
||||
* Encrypt a message
|
||||
*
|
||||
* @param string $message Message to encrypt
|
||||
* @return string
|
||||
* @throws \Exception
|
||||
* @throws \RangeException
|
||||
*/
|
||||
public function encrypt(string $message): string
|
||||
{
|
||||
return $this->encryptData($message, $this->key);
|
||||
}
|
||||
}
|
||||
|
||||
// __END__
|
||||
|
||||
@@ -185,7 +185,7 @@ class SmartyExtend extends \Smarty
|
||||
// call basic smarty
|
||||
// or Smarty::__construct();
|
||||
parent::__construct();
|
||||
// iinit lang
|
||||
// init lang
|
||||
$this->l10n = $l10n;
|
||||
// parse and read, legacy stuff
|
||||
$locale = $this->l10n->getLocaleAsArray();
|
||||
|
||||
@@ -46,12 +46,34 @@ final class CoreLibsSecuritySymmetricEncryptionTest extends TestCase
|
||||
public function testEncryptDecryptSuccess(string $input, string $expected): void
|
||||
{
|
||||
$key = CreateKey::generateRandomKey();
|
||||
$encrypted = SymmetricEncryption::encrypt($input, $key);
|
||||
$decrypted = SymmetricEncryption::decrypt($encrypted, $key);
|
||||
|
||||
// test class
|
||||
$crypt = new SymmetricEncryption($key);
|
||||
$encrypted = $crypt->encrypt($input);
|
||||
$decrypted = $crypt->decrypt($encrypted);
|
||||
$this->assertEquals(
|
||||
$expected,
|
||||
$decrypted,
|
||||
'Class call',
|
||||
);
|
||||
|
||||
// test indirect
|
||||
$encrypted = SymmetricEncryption::getInstance($key)->encrypt($input);
|
||||
$decrypted = SymmetricEncryption::getInstance($key)->decrypt($encrypted);
|
||||
$this->assertEquals(
|
||||
$expected,
|
||||
$decrypted,
|
||||
'Class Instance call',
|
||||
);
|
||||
|
||||
// test static
|
||||
$encrypted = SymmetricEncryption::encryptKey($input, $key);
|
||||
$decrypted = SymmetricEncryption::decryptKey($encrypted, $key);
|
||||
|
||||
$this->assertEquals(
|
||||
$expected,
|
||||
$decrypted
|
||||
$decrypted,
|
||||
'Static call',
|
||||
);
|
||||
}
|
||||
|
||||
@@ -86,10 +108,24 @@ final class CoreLibsSecuritySymmetricEncryptionTest extends TestCase
|
||||
public function testEncryptFailed(string $input, string $exception_message): void
|
||||
{
|
||||
$key = CreateKey::generateRandomKey();
|
||||
$encrypted = SymmetricEncryption::encrypt($input, $key);
|
||||
$wrong_key = CreateKey::generateRandomKey();
|
||||
|
||||
// wrong key in class call
|
||||
$crypt = new SymmetricEncryption($key);
|
||||
$encrypted = $crypt->encrypt($input);
|
||||
$this->expectExceptionMessage($exception_message);
|
||||
SymmetricEncryption::decrypt($encrypted, $wrong_key);
|
||||
$crypt->setKey($key);
|
||||
$crypt->decrypt($encrypted);
|
||||
|
||||
// class instance
|
||||
$encrypted = SymmetricEncryption::getInstance($key)->encrypt($input);
|
||||
$this->expectExceptionMessage($exception_message);
|
||||
SymmetricEncryption::getInstance($wrong_key)->decrypt($encrypted);
|
||||
|
||||
// class static
|
||||
$encrypted = SymmetricEncryption::encryptKey($input, $key);
|
||||
$this->expectExceptionMessage($exception_message);
|
||||
SymmetricEncryption::decryptKey($encrypted, $wrong_key);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -107,7 +143,6 @@ final class CoreLibsSecuritySymmetricEncryptionTest extends TestCase
|
||||
'too short hex key' => [
|
||||
'key' => '1cabd5cba9e042f12522f4ff2de5c31d233b',
|
||||
'excpetion_message' => 'Key is not the correct size (must be '
|
||||
. 'SODIUM_CRYPTO_SECRETBOX_KEYBYTES bytes long).'
|
||||
],
|
||||
];
|
||||
}
|
||||
@@ -126,13 +161,33 @@ final class CoreLibsSecuritySymmetricEncryptionTest extends TestCase
|
||||
*/
|
||||
public function testWrongKey(string $key, string $exception_message): void
|
||||
{
|
||||
$this->expectExceptionMessage($exception_message);
|
||||
SymmetricEncryption::encrypt('test', $key);
|
||||
// we must encrypt valid thing first so we can fail with the wrong kjey
|
||||
$enc_key = CreateKey::generateRandomKey();
|
||||
$encrypted = SymmetricEncryption::encrypt('test', $enc_key);
|
||||
|
||||
// class
|
||||
$crypt = new SymmetricEncryption($key);
|
||||
$this->expectExceptionMessage($exception_message);
|
||||
SymmetricEncryption::decrypt($encrypted, $key);
|
||||
$crypt->encrypt('test');
|
||||
$crypt->setKey($enc_key);
|
||||
$encrypted = $crypt->encrypt('test');
|
||||
$this->expectExceptionMessage($exception_message);
|
||||
$crypt->setKey($key);
|
||||
$crypt->decrypt($encrypted);
|
||||
|
||||
// class instance
|
||||
$this->expectExceptionMessage($exception_message);
|
||||
SymmetricEncryption::getInstance($key)->encrypt('test');
|
||||
// we must encrypt valid thing first so we can fail with the wrong key
|
||||
$encrypted = SymmetricEncryption::getInstance($enc_key)->encrypt('test');
|
||||
$this->expectExceptionMessage($exception_message);
|
||||
SymmetricEncryption::getInstance($key)->decrypt($encrypted);
|
||||
|
||||
// class static
|
||||
$this->expectExceptionMessage($exception_message);
|
||||
SymmetricEncryption::encryptKey('test', $key);
|
||||
// we must encrypt valid thing first so we can fail with the wrong key
|
||||
$encrypted = SymmetricEncryption::encryptKey('test', $enc_key);
|
||||
$this->expectExceptionMessage($exception_message);
|
||||
SymmetricEncryption::decryptKey($encrypted, $key);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -145,7 +200,7 @@ final class CoreLibsSecuritySymmetricEncryptionTest extends TestCase
|
||||
return [
|
||||
'too short ciphertext' => [
|
||||
'input' => 'short',
|
||||
'exception_message' => 'Invalid ciphertext (too short)'
|
||||
'exception_message' => 'Decipher message failed: '
|
||||
],
|
||||
];
|
||||
}
|
||||
@@ -164,8 +219,18 @@ final class CoreLibsSecuritySymmetricEncryptionTest extends TestCase
|
||||
public function testWrongCiphertext(string $input, string $exception_message): void
|
||||
{
|
||||
$key = CreateKey::generateRandomKey();
|
||||
// class
|
||||
$crypt = new SymmetricEncryption($key);
|
||||
$this->expectExceptionMessage($exception_message);
|
||||
SymmetricEncryption::decrypt($input, $key);
|
||||
$crypt->decrypt($input);
|
||||
|
||||
// class instance
|
||||
$this->expectExceptionMessage($exception_message);
|
||||
SymmetricEncryption::getInstance($key)->decrypt($input);
|
||||
|
||||
// class static
|
||||
$this->expectExceptionMessage($exception_message);
|
||||
SymmetricEncryption::decryptKey($input, $key);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user