Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@

## 1.0.3 under development

- no changes in this release.
- Enh #62: Use `SensitiveParameter` attribute to mark sensitive parameters (@dehbka, @vjik)

## 1.0.2 March 18, 2024

Expand Down
49 changes: 37 additions & 12 deletions src/Crypt.php
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@

namespace Yiisoft\Security;

use SensitiveParameter;
use Yiisoft\Strings\StringHelper;

final class Crypt
Expand Down Expand Up @@ -55,7 +56,7 @@
throw new \RuntimeException('Encryption requires the OpenSSL PHP extension.');
}
if (!array_key_exists($cipher, self::ALLOWED_CIPHERS)) {
throw new \RuntimeException($cipher . ' is not an allowed cipher.');

Check warning on line 59 in src/Crypt.php

View workflow job for this annotation

GitHub Actions / mutation / PHP 8.3-ubuntu-latest

Escaped Mutant for Mutator "Concat": --- Original +++ New @@ @@ throw new \RuntimeException('Encryption requires the OpenSSL PHP extension.'); } if (!array_key_exists($cipher, self::ALLOWED_CIPHERS)) { - throw new \RuntimeException($cipher . ' is not an allowed cipher.'); + throw new \RuntimeException(' is not an allowed cipher.' . $cipher); } $this->cipher = $cipher; }

Check warning on line 59 in src/Crypt.php

View workflow job for this annotation

GitHub Actions / mutation / PHP 8.3-ubuntu-latest

Escaped Mutant for Mutator "ConcatOperandRemoval": --- Original +++ New @@ @@ throw new \RuntimeException('Encryption requires the OpenSSL PHP extension.'); } if (!array_key_exists($cipher, self::ALLOWED_CIPHERS)) { - throw new \RuntimeException($cipher . ' is not an allowed cipher.'); + throw new \RuntimeException(' is not an allowed cipher.'); } $this->cipher = $cipher; }

Check warning on line 59 in src/Crypt.php

View workflow job for this annotation

GitHub Actions / mutation / PHP 8.3-ubuntu-latest

Escaped Mutant for Mutator "ConcatOperandRemoval": --- Original +++ New @@ @@ throw new \RuntimeException('Encryption requires the OpenSSL PHP extension.'); } if (!array_key_exists($cipher, self::ALLOWED_CIPHERS)) { - throw new \RuntimeException($cipher . ' is not an allowed cipher.'); + throw new \RuntimeException($cipher); } $this->cipher = $cipher; }
}

$this->cipher = $cipher;
Expand Down Expand Up @@ -123,8 +124,11 @@
* @see decryptByPassword()
* @see encryptByKey()
*/
public function encryptByPassword(string $data, string $password): string
{
public function encryptByPassword(
string $data,
#[SensitiveParameter]
string $password
): string {
return $this->encrypt($data, true, $password, '');
}

Expand All @@ -150,8 +154,12 @@
* @see decryptByKey()
* @see encryptByPassword()
*/
public function encryptByKey(string $data, string $inputKey, string $info = ''): string
{
public function encryptByKey(
string $data,
#[SensitiveParameter]
string $inputKey,
string $info = ''
): string {
return $this->encrypt($data, false, $inputKey, $info);
}

Expand All @@ -169,8 +177,11 @@
*
* @see encryptByPassword()
*/
public function decryptByPassword(string $data, string $password): string
{
public function decryptByPassword(
string $data,
#[SensitiveParameter]
string $password
): string {
return $this->decrypt($data, true, $password, '');
}

Expand All @@ -190,8 +201,12 @@
*
* @see encryptByKey()
*/
public function decryptByKey(string $data, string $inputKey, string $info = ''): string
{
public function decryptByKey(
string $data,
#[SensitiveParameter]
string $inputKey,
string $info = ''
): string {
return $this->decrypt($data, false, $inputKey, $info);
}

Expand All @@ -211,8 +226,13 @@
*
* @see decrypt()
*/
private function encrypt(string $data, bool $passwordBased, string $secret, string $info = ''): string
{
private function encrypt(
string $data,
bool $passwordBased,
#[SensitiveParameter]
string $secret,
string $info = ''
): string {
[$blockSize, $keySize] = self::ALLOWED_CIPHERS[$this->cipher];

$keySalt = random_bytes($keySize);
Expand All @@ -226,7 +246,7 @@

$encrypted = openssl_encrypt($data, $this->cipher, $key, OPENSSL_RAW_DATA, $iv);
if ($encrypted === false) {
throw new \RuntimeException('OpenSSL failure on encryption: ' . openssl_error_string());

Check warning on line 249 in src/Crypt.php

View workflow job for this annotation

GitHub Actions / mutation / PHP 8.3-ubuntu-latest

Escaped Mutant for Mutator "Concat": --- Original +++ New @@ @@ $iv = random_bytes($blockSize); $encrypted = openssl_encrypt($data, $this->cipher, $key, OPENSSL_RAW_DATA, $iv); if ($encrypted === false) { - throw new \RuntimeException('OpenSSL failure on encryption: ' . openssl_error_string()); + throw new \RuntimeException(openssl_error_string() . 'OpenSSL failure on encryption: '); } $authKey = hash_hkdf($this->kdfAlgorithm, $key, $keySize, $this->authorizationKeyInfo); $signed = (new Mac())->sign($iv . $encrypted, $authKey);

Check warning on line 249 in src/Crypt.php

View workflow job for this annotation

GitHub Actions / mutation / PHP 8.3-ubuntu-latest

Escaped Mutant for Mutator "ConcatOperandRemoval": --- Original +++ New @@ @@ $iv = random_bytes($blockSize); $encrypted = openssl_encrypt($data, $this->cipher, $key, OPENSSL_RAW_DATA, $iv); if ($encrypted === false) { - throw new \RuntimeException('OpenSSL failure on encryption: ' . openssl_error_string()); + throw new \RuntimeException('OpenSSL failure on encryption: '); } $authKey = hash_hkdf($this->kdfAlgorithm, $key, $keySize, $this->authorizationKeyInfo); $signed = (new Mac())->sign($iv . $encrypted, $authKey);
}

$authKey = hash_hkdf($this->kdfAlgorithm, $key, $keySize, $this->authorizationKeyInfo);
Expand Down Expand Up @@ -257,8 +277,13 @@
*
* @see encrypt()
*/
private function decrypt(string $data, bool $passwordBased, string $secret, string $info): string
{
private function decrypt(
string $data,
bool $passwordBased,
#[SensitiveParameter]
string $secret,
string $info
): string {
[$blockSize, $keySize] = self::ALLOWED_CIPHERS[$this->cipher];

$keySalt = StringHelper::byteSubstring($data, 0, $keySize);
Expand All @@ -281,7 +306,7 @@

$decrypted = openssl_decrypt($encrypted, $this->cipher, $key, OPENSSL_RAW_DATA, $iv);
if ($decrypted === false) {
throw new \RuntimeException('OpenSSL failure on decryption: ' . openssl_error_string());

Check warning on line 309 in src/Crypt.php

View workflow job for this annotation

GitHub Actions / mutation / PHP 8.3-ubuntu-latest

Escaped Mutant for Mutator "Concat": --- Original +++ New @@ @@ $encrypted = StringHelper::byteSubstring($data, $blockSize); $decrypted = openssl_decrypt($encrypted, $this->cipher, $key, OPENSSL_RAW_DATA, $iv); if ($decrypted === false) { - throw new \RuntimeException('OpenSSL failure on decryption: ' . openssl_error_string()); + throw new \RuntimeException(openssl_error_string() . 'OpenSSL failure on decryption: '); } return $decrypted; } }

Check warning on line 309 in src/Crypt.php

View workflow job for this annotation

GitHub Actions / mutation / PHP 8.3-ubuntu-latest

Escaped Mutant for Mutator "ConcatOperandRemoval": --- Original +++ New @@ @@ $encrypted = StringHelper::byteSubstring($data, $blockSize); $decrypted = openssl_decrypt($encrypted, $this->cipher, $key, OPENSSL_RAW_DATA, $iv); if ($decrypted === false) { - throw new \RuntimeException('OpenSSL failure on decryption: ' . openssl_error_string()); + throw new \RuntimeException('OpenSSL failure on decryption: '); } return $decrypted; } }
}

return $decrypted;
Expand Down
17 changes: 13 additions & 4 deletions src/Mac.php
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@

namespace Yiisoft\Security;

use SensitiveParameter;
use Yiisoft\Strings\StringHelper;

/**
Expand Down Expand Up @@ -51,8 +52,12 @@ public function __construct(string $algorithm = 'sha256')
* @see hkdf()
* @see pbkdf2()
*/
public function sign(string $data, string $key, bool $rawHash = false): string
{
public function sign(
string $data,
#[SensitiveParameter]
string $key,
bool $rawHash = false
): string {
$hash = hash_hmac($this->algorithm, $data, $key, $rawHash);
if (!$hash) {
throw new \RuntimeException("Failed to generate HMAC with hash algorithm: {$this->algorithm}.");
Expand Down Expand Up @@ -80,8 +85,12 @@ public function sign(string $data, string $key, bool $rawHash = false): string
*
* @see hash()
*/
public function getMessage(string $data, string $key, bool $rawHash = false): string
{
public function getMessage(
string $data,
#[SensitiveParameter]
string $key,
bool $rawHash = false
): string {
$test = hash_hmac($this->algorithm, '', '', $rawHash);
if (!$test) {
throw new \RuntimeException("Failed to generate HMAC with hash algorithm: {$this->algorithm}.");
Expand Down
16 changes: 12 additions & 4 deletions src/PasswordHasher.php
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,8 @@

namespace Yiisoft\Security;

use SensitiveParameter;

/**
* PasswordHasher allows generating password hash and verifying passwords against a hash.
*/
Expand Down Expand Up @@ -65,8 +67,10 @@ public function __construct(?string $algorithm = PASSWORD_DEFAULT, array $parame
* @psalm-suppress InvalidNullableReturnType
* @psalm-suppress NullableReturnStatement
*/
public function hash(string $password): string
{
public function hash(
#[SensitiveParameter]
string $password
): string {
return password_hash($password, $this->algorithm, $this->parameters);
}

Expand All @@ -83,8 +87,12 @@ public function hash(string $password): string
*
* @see hash()
*/
public function validate(string $password, string $hash): bool
{
public function validate(
#[SensitiveParameter]
string $password,
#[SensitiveParameter]
string $hash
): bool {
if ($password === '') {
throw new \InvalidArgumentException('Password must be a string and cannot be empty.');
}
Expand Down
13 changes: 9 additions & 4 deletions src/TokenMask.php
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@

namespace Yiisoft\Security;

use SensitiveParameter;
use Yiisoft\Strings\StringHelper;

/**
Expand All @@ -22,12 +23,14 @@
*
* @return string A masked token.
*/
public static function apply(string $token): string
{
public static function apply(
#[SensitiveParameter]
string $token
): string {
// The number of bytes in a mask is always equal to the number of bytes in a token.
/** @psalm-suppress ArgumentTypeCoercion */
$mask = random_bytes(StringHelper::byteLength($token));
return StringHelper::base64UrlEncode($mask . ($mask ^ $token));

Check warning on line 33 in src/TokenMask.php

View workflow job for this annotation

GitHub Actions / mutation / PHP 8.3-ubuntu-latest

Escaped Mutant for Mutator "Concat": --- Original +++ New @@ @@ // The number of bytes in a mask is always equal to the number of bytes in a token. /** @psalm-suppress ArgumentTypeCoercion */ $mask = random_bytes(StringHelper::byteLength($token)); - return StringHelper::base64UrlEncode($mask . ($mask ^ $token)); + return StringHelper::base64UrlEncode(($mask ^ $token) . $mask); } /** * Unmasks a token previously masked by `mask`.
}

/**
Expand All @@ -37,8 +40,10 @@
*
* @return string An unmasked token, or an empty string in case of token format is invalid.
*/
public static function remove(string $maskedToken): string
{
public static function remove(
#[SensitiveParameter]
string $maskedToken
): string {
$decoded = StringHelper::base64UrlDecode($maskedToken);
$length = StringHelper::byteLength($decoded) / 2;
// Check if the masked token has an even length.
Expand Down
Loading