Updated defuse\php-encryption
to version 2.4.0
This commit is contained in:
parent
56a220f704
commit
ffa48ca0aa
12 changed files with 215 additions and 46 deletions
|
@ -9,6 +9,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
|
|||
|
||||
### Changed
|
||||
- Refactored `\ncc\Objects > PackageLock`
|
||||
- Updated `defuse\php-encryption` to version 2.4.0
|
||||
|
||||
|
||||
## [1.0.2] - 2023-06-29
|
||||
|
|
|
@ -4,6 +4,7 @@ namespace ncc\Defuse\Crypto;
|
|||
|
||||
use ncc\Defuse\Crypto\Exception as Ex;
|
||||
|
||||
|
||||
final class Core
|
||||
{
|
||||
const HEADER_VERSION_SIZE = 4;
|
||||
|
@ -98,9 +99,14 @@ final class Core
|
|||
*/
|
||||
public static function secureRandom($octets)
|
||||
{
|
||||
if ($octets <= 0) {
|
||||
throw new Ex\CryptoException(
|
||||
'A zero or negative amount of random bytes was requested.'
|
||||
);
|
||||
}
|
||||
self::ensureFunctionExists('random_bytes');
|
||||
try {
|
||||
return \random_bytes($octets);
|
||||
return \random_bytes(max(1, $octets));
|
||||
} catch (\Exception $ex) {
|
||||
throw new Ex\EnvironmentIsBrokenException(
|
||||
'Your system does not have a secure random number generator.'
|
||||
|
@ -285,7 +291,7 @@ final class Core
|
|||
{
|
||||
static $exists = null;
|
||||
if ($exists === null) {
|
||||
$exists = \extension_loaded('mbstring') && \ini_get('mbstring.func_overload') !== false && (int)\ini_get('mbstring.func_overload') & MB_OVERLOAD_STRING;
|
||||
$exists = \extension_loaded('mbstring') && \function_exists('mb_strlen');
|
||||
}
|
||||
if ($exists) {
|
||||
$length = \mb_strlen($str, '8bit');
|
||||
|
@ -311,7 +317,7 @@ final class Core
|
|||
{
|
||||
static $exists = null;
|
||||
if ($exists === null) {
|
||||
$exists = \extension_loaded('mbstring') && \ini_get('mbstring.func_overload') !== false && (int)\ini_get('mbstring.func_overload') & MB_OVERLOAD_STRING;
|
||||
$exists = \extension_loaded('mbstring') && \function_exists('mb_substr');
|
||||
}
|
||||
|
||||
// This is required to make mb_substr behavior identical to substr.
|
||||
|
@ -381,7 +387,15 @@ final class Core
|
|||
*
|
||||
* @return string A $key_length-byte key derived from the password and salt.
|
||||
*/
|
||||
public static function pbkdf2($algorithm, $password, $salt, $count, $key_length, $raw_output = false)
|
||||
public static function pbkdf2(
|
||||
$algorithm,
|
||||
#[\SensitiveParameter]
|
||||
$password,
|
||||
$salt,
|
||||
$count,
|
||||
$key_length,
|
||||
$raw_output = false
|
||||
)
|
||||
{
|
||||
// Type checks:
|
||||
if (! \is_string($algorithm)) {
|
||||
|
|
|
@ -10,8 +10,11 @@ class Crypto
|
|||
* Encrypts a string with a Key.
|
||||
*
|
||||
* @param string $plaintext
|
||||
* @param Key $key
|
||||
* @param bool $raw_binary
|
||||
* @param Key $key
|
||||
* @param bool $raw_binary
|
||||
*
|
||||
* @throws Ex\EnvironmentIsBrokenException
|
||||
* @throws \TypeError
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
|
@ -45,11 +48,19 @@ class Crypto
|
|||
*
|
||||
* @param string $plaintext
|
||||
* @param string $password
|
||||
* @param bool $raw_binary
|
||||
* @param bool $raw_binary
|
||||
*
|
||||
* @throws Ex\EnvironmentIsBrokenException
|
||||
* @throws \TypeError
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
public static function encryptWithPassword($plaintext, $password, $raw_binary = false)
|
||||
public static function encryptWithPassword(
|
||||
$plaintext,
|
||||
#[\SensitiveParameter]
|
||||
$password,
|
||||
$raw_binary = false
|
||||
)
|
||||
{
|
||||
if (!\is_string($plaintext)) {
|
||||
throw new \TypeError(
|
||||
|
@ -124,7 +135,12 @@ class Crypto
|
|||
*
|
||||
* @return string
|
||||
*/
|
||||
public static function decryptWithPassword($ciphertext, $password, $raw_binary = false)
|
||||
public static function decryptWithPassword(
|
||||
$ciphertext,
|
||||
#[\SensitiveParameter]
|
||||
$password,
|
||||
$raw_binary = false
|
||||
)
|
||||
{
|
||||
if (!\is_string($ciphertext)) {
|
||||
throw new \TypeError(
|
||||
|
@ -160,7 +176,11 @@ class Crypto
|
|||
*
|
||||
* @return string
|
||||
*/
|
||||
public static function legacyDecrypt($ciphertext, $key)
|
||||
public static function legacyDecrypt(
|
||||
$ciphertext,
|
||||
#[\SensitiveParameter]
|
||||
$key
|
||||
)
|
||||
{
|
||||
if (!\is_string($ciphertext)) {
|
||||
throw new \TypeError(
|
||||
|
@ -372,7 +392,13 @@ class Crypto
|
|||
*
|
||||
* @return string
|
||||
*/
|
||||
protected static function plainEncrypt($plaintext, $key, $iv)
|
||||
protected static function plainEncrypt(
|
||||
$plaintext,
|
||||
#[\SensitiveParameter]
|
||||
$key,
|
||||
#[\SensitiveParameter]
|
||||
$iv
|
||||
)
|
||||
{
|
||||
Core::ensureConstantExists('OPENSSL_RAW_DATA');
|
||||
Core::ensureFunctionExists('openssl_encrypt');
|
||||
|
@ -402,7 +428,14 @@ class Crypto
|
|||
*
|
||||
* @return string
|
||||
*/
|
||||
protected static function plainDecrypt($ciphertext, $key, $iv, $cipherMethod)
|
||||
protected static function plainDecrypt(
|
||||
$ciphertext,
|
||||
#[\SensitiveParameter]
|
||||
$key,
|
||||
#[\SensitiveParameter]
|
||||
$iv,
|
||||
$cipherMethod
|
||||
)
|
||||
{
|
||||
Core::ensureConstantExists('OPENSSL_RAW_DATA');
|
||||
Core::ensureFunctionExists('openssl_decrypt');
|
||||
|
@ -431,7 +464,12 @@ class Crypto
|
|||
*
|
||||
* @return bool
|
||||
*/
|
||||
protected static function verifyHMAC($expected_hmac, $message, $key)
|
||||
protected static function verifyHMAC(
|
||||
$expected_hmac,
|
||||
$message,
|
||||
#[\SensitiveParameter]
|
||||
$key
|
||||
)
|
||||
{
|
||||
$message_hmac = \hash_hmac(Core::HASH_FUNCTION_NAME, $message, $key, true);
|
||||
return Core::hashEquals($message_hmac, $expected_hmac);
|
||||
|
|
|
@ -4,7 +4,7 @@ namespace ncc\Defuse\Crypto;
|
|||
|
||||
/**
|
||||
* Class DerivedKeys
|
||||
* @package ncc\Defuse\Crypto
|
||||
* @package Defuse\Crypto
|
||||
*/
|
||||
final class DerivedKeys
|
||||
{
|
||||
|
|
|
@ -175,7 +175,11 @@ final class Encoding
|
|||
*
|
||||
* @return string
|
||||
*/
|
||||
public static function saveBytesToChecksummedAsciiSafeString($header, $bytes)
|
||||
public static function saveBytesToChecksummedAsciiSafeString(
|
||||
$header,
|
||||
#[\SensitiveParameter]
|
||||
$bytes
|
||||
)
|
||||
{
|
||||
// Headers must be a constant length to prevent one type's header from
|
||||
// being a prefix of another type's header, leading to ambiguity.
|
||||
|
@ -207,7 +211,11 @@ final class Encoding
|
|||
*
|
||||
* @return string
|
||||
*/
|
||||
public static function loadBytesFromChecksummedAsciiSafeString($expected_header, $string)
|
||||
public static function loadBytesFromChecksummedAsciiSafeString(
|
||||
$expected_header,
|
||||
#[\SensitiveParameter]
|
||||
$string
|
||||
)
|
||||
{
|
||||
// Headers must be a constant length to prevent one type's header from
|
||||
// being a prefix of another type's header, leading to ambiguity.
|
||||
|
|
|
@ -38,7 +38,12 @@ final class File
|
|||
* @throws Ex\EnvironmentIsBrokenException
|
||||
* @throws Ex\IOException
|
||||
*/
|
||||
public static function encryptFileWithPassword($inputFilename, $outputFilename, $password)
|
||||
public static function encryptFileWithPassword(
|
||||
$inputFilename,
|
||||
$outputFilename,
|
||||
#[\SensitiveParameter]
|
||||
$password
|
||||
)
|
||||
{
|
||||
self::encryptFileInternal(
|
||||
$inputFilename,
|
||||
|
@ -81,7 +86,12 @@ final class File
|
|||
* @throws Ex\IOException
|
||||
* @throws Ex\WrongKeyOrModifiedCiphertextException
|
||||
*/
|
||||
public static function decryptFileWithPassword($inputFilename, $outputFilename, $password)
|
||||
public static function decryptFileWithPassword(
|
||||
$inputFilename,
|
||||
$outputFilename,
|
||||
#[\SensitiveParameter]
|
||||
$password
|
||||
)
|
||||
{
|
||||
self::decryptFileInternal(
|
||||
$inputFilename,
|
||||
|
@ -125,7 +135,12 @@ final class File
|
|||
* @throws Ex\IOException
|
||||
* @throws Ex\WrongKeyOrModifiedCiphertextException
|
||||
*/
|
||||
public static function encryptResourceWithPassword($inputHandle, $outputHandle, $password)
|
||||
public static function encryptResourceWithPassword(
|
||||
$inputHandle,
|
||||
$outputHandle,
|
||||
#[\SensitiveParameter]
|
||||
$password
|
||||
)
|
||||
{
|
||||
self::encryptResourceInternal(
|
||||
$inputHandle,
|
||||
|
@ -169,7 +184,12 @@ final class File
|
|||
* @throws Ex\IOException
|
||||
* @throws Ex\WrongKeyOrModifiedCiphertextException
|
||||
*/
|
||||
public static function decryptResourceWithPassword($inputHandle, $outputHandle, $password)
|
||||
public static function decryptResourceWithPassword(
|
||||
$inputHandle,
|
||||
$outputHandle,
|
||||
#[\SensitiveParameter]
|
||||
$password
|
||||
)
|
||||
{
|
||||
self::decryptResourceInternal(
|
||||
$inputHandle,
|
||||
|
@ -196,7 +216,9 @@ final class File
|
|||
}
|
||||
|
||||
/* Open the input file. */
|
||||
self::removePHPUnitErrorHandler();
|
||||
$if = @\fopen($inputFilename, 'rb');
|
||||
self::restorePHPUnitErrorHandler();
|
||||
if ($if === false) {
|
||||
throw new Ex\IOException(
|
||||
'Cannot open input file for encrypting: ' .
|
||||
|
@ -209,7 +231,9 @@ final class File
|
|||
}
|
||||
|
||||
/* Open the output file. */
|
||||
self::removePHPUnitErrorHandler();
|
||||
$of = @\fopen($outputFilename, 'wb');
|
||||
self::restorePHPUnitErrorHandler();
|
||||
if ($of === false) {
|
||||
\fclose($if);
|
||||
throw new Ex\IOException(
|
||||
|
@ -265,7 +289,9 @@ final class File
|
|||
}
|
||||
|
||||
/* Open the input file. */
|
||||
self::removePHPUnitErrorHandler();
|
||||
$if = @\fopen($inputFilename, 'rb');
|
||||
self::restorePHPUnitErrorHandler();
|
||||
if ($if === false) {
|
||||
throw new Ex\IOException(
|
||||
'Cannot open input file for decrypting: ' .
|
||||
|
@ -279,7 +305,9 @@ final class File
|
|||
}
|
||||
|
||||
/* Open the output file. */
|
||||
self::removePHPUnitErrorHandler();
|
||||
$of = @\fopen($outputFilename, 'wb');
|
||||
self::restorePHPUnitErrorHandler();
|
||||
if ($of === false) {
|
||||
\fclose($if);
|
||||
throw new Ex\IOException(
|
||||
|
@ -770,9 +798,38 @@ final class File
|
|||
{
|
||||
$error = error_get_last();
|
||||
if ($error === null) {
|
||||
return '[no PHP error]';
|
||||
return '[no PHP error, or you have a custom error handler set]';
|
||||
} else {
|
||||
return $error['message'];
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* PHPUnit sets an error handler, which prevents getLastErrorMessage() from working,
|
||||
* because error_get_last does not work when custom handlers are set.
|
||||
*
|
||||
* This is a workaround, which should be a no-op in production deployments, to make
|
||||
* getLastErrorMessage() return the error messages that the PHPUnit tests expect.
|
||||
*
|
||||
* If, in a production deployment, a custom error handler is set, the exception
|
||||
* handling will still work as usual, but the error messages will be confusing.
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
private static function removePHPUnitErrorHandler() {
|
||||
if (defined('PHPUNIT_COMPOSER_INSTALL') || defined('__PHPUNIT_PHAR__')) {
|
||||
set_error_handler(null);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Undoes what removePHPUnitErrorHandler did.
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
private static function restorePHPUnitErrorHandler() {
|
||||
if (defined('PHPUNIT_COMPOSER_INSTALL') || defined('__PHPUNIT_PHAR__')) {
|
||||
restore_error_handler();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
11
src/ncc/ThirdParty/defuse/php-encryption/Key.php
vendored
11
src/ncc/ThirdParty/defuse/php-encryption/Key.php
vendored
|
@ -41,7 +41,11 @@ final class Key
|
|||
*
|
||||
* @return Key
|
||||
*/
|
||||
public static function loadFromAsciiSafeString($saved_key_string, $do_not_trim = false)
|
||||
public static function loadFromAsciiSafeString(
|
||||
#[\SensitiveParameter]
|
||||
$saved_key_string,
|
||||
$do_not_trim = false
|
||||
)
|
||||
{
|
||||
if (!$do_not_trim) {
|
||||
$saved_key_string = Encoding::trimTrailingWhitespace($saved_key_string);
|
||||
|
@ -82,7 +86,10 @@ final class Key
|
|||
*
|
||||
* @throws Ex\EnvironmentIsBrokenException
|
||||
*/
|
||||
private function __construct($bytes)
|
||||
private function __construct(
|
||||
#[\SensitiveParameter]
|
||||
$bytes
|
||||
)
|
||||
{
|
||||
Core::ensureTrue(
|
||||
Core::ourStrlen($bytes) === self::KEY_BYTE_SIZE,
|
||||
|
|
|
@ -39,7 +39,10 @@ final class KeyOrPassword
|
|||
*
|
||||
* @return KeyOrPassword
|
||||
*/
|
||||
public static function createFromPassword($password)
|
||||
public static function createFromPassword(
|
||||
#[\SensitiveParameter]
|
||||
$password
|
||||
)
|
||||
{
|
||||
return new KeyOrPassword(self::SECRET_TYPE_PASSWORD, $password);
|
||||
}
|
||||
|
@ -133,7 +136,11 @@ final class KeyOrPassword
|
|||
* @param int $secret_type
|
||||
* @param mixed $secret (either a Key or a password string)
|
||||
*/
|
||||
private function __construct($secret_type, $secret)
|
||||
private function __construct(
|
||||
$secret_type,
|
||||
#[\SensitiveParameter]
|
||||
$secret
|
||||
)
|
||||
{
|
||||
// The constructor is private, so these should never throw.
|
||||
if ($secret_type === self::SECRET_TYPE_KEY) {
|
||||
|
|
|
@ -22,7 +22,10 @@ final class KeyProtectedByPassword
|
|||
*
|
||||
* @return KeyProtectedByPassword
|
||||
*/
|
||||
public static function createRandomPasswordProtectedKey($password)
|
||||
public static function createRandomPasswordProtectedKey(
|
||||
#[\SensitiveParameter]
|
||||
$password
|
||||
)
|
||||
{
|
||||
$inner_key = Key::createNewRandomKey();
|
||||
/* The password is hashed as a form of poor-man's domain separation
|
||||
|
@ -47,7 +50,10 @@ final class KeyProtectedByPassword
|
|||
*
|
||||
* @return KeyProtectedByPassword
|
||||
*/
|
||||
public static function loadFromAsciiSafeString($saved_key_string)
|
||||
public static function loadFromAsciiSafeString(
|
||||
#[\SensitiveParameter]
|
||||
$saved_key_string
|
||||
)
|
||||
{
|
||||
$encrypted_key = Encoding::loadBytesFromChecksummedAsciiSafeString(
|
||||
self::PASSWORD_KEY_CURRENT_VERSION,
|
||||
|
@ -82,7 +88,10 @@ final class KeyProtectedByPassword
|
|||
* @param string $password
|
||||
* @return Key
|
||||
*/
|
||||
public function unlockKey($password)
|
||||
public function unlockKey(
|
||||
#[\SensitiveParameter]
|
||||
$password
|
||||
)
|
||||
{
|
||||
try {
|
||||
$inner_key_encoded = Crypto::decryptWithPassword(
|
||||
|
@ -115,7 +124,12 @@ final class KeyProtectedByPassword
|
|||
*
|
||||
* @return KeyProtectedByPassword
|
||||
*/
|
||||
public function changePassword($current_password, $new_password)
|
||||
public function changePassword(
|
||||
#[\SensitiveParameter]
|
||||
$current_password,
|
||||
#[\SensitiveParameter]
|
||||
$new_password
|
||||
)
|
||||
{
|
||||
$inner_key = $this->unlockKey($current_password);
|
||||
/* The password is hashed as a form of poor-man's domain separation
|
||||
|
|
|
@ -1,7 +1,7 @@
|
|||
php-encryption
|
||||
===============
|
||||
|
||||
[](https://travis-ci.org/defuse/php-encryption)
|
||||

|
||||
[](https://codecov.io/gh/defuse/php-encryption)
|
||||
[](https://packagist.org/packages/defuse/php-encryption)
|
||||
[](https://packagist.org/packages/defuse/php-encryption)
|
||||
|
@ -15,10 +15,10 @@ This is a library for encrypting data with a key or password in PHP. **It
|
|||
requires PHP 5.6 or newer and OpenSSL 1.0.1 or newer.** We recommend using a
|
||||
version of PHP that [still has security
|
||||
support](https://www.php.net/supported-versions.php), which at the time of
|
||||
writing means PHP 7.3 or later. Using this library with an unsupported
|
||||
writing means PHP 8.0 or later. Using this library with an unsupported
|
||||
version of PHP could lead to security vulnerabilities.
|
||||
|
||||
The current version of `php-encryption` is v2.3.1. This library is expected to
|
||||
The current version of `php-encryption` is v2.4.0. This library is expected to
|
||||
remain stable and supported by its authors with security and bugfixes until at
|
||||
least January 1st, 2024.
|
||||
|
||||
|
@ -99,23 +99,26 @@ a formal audit, please [contact Taylor Hornby](https://defuse.ca/contact.htm).
|
|||
Public Keys
|
||||
------------
|
||||
|
||||
The GnuPG public key used to sign current and older releases is available in
|
||||
[dist/signingkey.asc](https://github.com/defuse/php-encryption/raw/master/dist/signingkey.asc). Its fingerprint is:
|
||||
|
||||
```
|
||||
2FA6 1D8D 99B9 2658 6BAC 3D53 385E E055 A129 1538
|
||||
```
|
||||
|
||||
You can verify it against Taylor Hornby's [contact
|
||||
page](https://defuse.ca/contact.htm) and
|
||||
[twitter](https://twitter.com/DefuseSec/status/723741424253059074).
|
||||
|
||||
Due to the old key expiring, new releases will be signed with a new public key
|
||||
available in [dist/signingkey-new.asc](https://github.com/defuse/php-encryption/raw/master/dist/signingkey-new.asc). Its fingerprint is:
|
||||
The GnuPG public key used to sign the current and new releases is available in
|
||||
[dist/signingkey-new.asc](https://github.com/defuse/php-encryption/raw/master/dist/signingkey-new.asc). Its fingerprint is:
|
||||
|
||||
```
|
||||
6DD6 E677 0281 5846 FC85 25A3 DD2E 507F 7BDB 1669
|
||||
```
|
||||
|
||||
You can verify it against Taylor Hornby's [contact
|
||||
page](https://defuse.ca/contact.htm) and
|
||||
[twitter](https://twitter.com/DefuseSec/status/1670840796743081984).
|
||||
|
||||
Older releases were signed with a (now-expired) available in
|
||||
[dist/signingkey-old.asc](https://github.com/defuse/php-encryption/raw/master/dist/signingkey-old.asc). The old key's fingerprint is:
|
||||
|
||||
```
|
||||
2FA6 1D8D 99B9 2658 6BAC 3D53 385E E055 A129 1538
|
||||
```
|
||||
|
||||
The old key's fingerprint can be verified against Taylor Hornby's [contact page](https://defuse.ca/contact.htm) and
|
||||
[twitter](https://twitter.com/DefuseSec/status/723741424253059074).
|
||||
|
||||
A signature of this new key by the old key is available in
|
||||
[dist/signingkey-new.asc.sig](https://github.com/defuse/php-encryption/raw/master/dist/signingkey-new.asc.sig).
|
||||
|
|
|
@ -1,4 +1,24 @@
|
|||
<?php
|
||||
/*
|
||||
* Copyright (c) Nosial 2022-2023, all rights reserved.
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a copy of this software and
|
||||
* associated documentation files (the "Software"), to deal in the Software without restriction, including without
|
||||
* limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the
|
||||
* Software, and to permit persons to whom the Software is furnished to do so, subject to the following
|
||||
* conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included in all copies or substantial portions
|
||||
* of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED,
|
||||
* INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR
|
||||
* PURPOSE AND NON-INFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
|
||||
* LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR
|
||||
* OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
|
||||
* DEALINGS IN THE SOFTWARE.
|
||||
*
|
||||
*/
|
||||
|
||||
namespace ncc\Defuse\Crypto;
|
||||
|
||||
|
|
|
@ -1 +1 @@
|
|||
2.3.1
|
||||
2.4.0
|
Loading…
Add table
Reference in a new issue