diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 9ca9460..7eba2b9 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -28,7 +28,7 @@ jobs: coverage: none - name: Install Composer dependencies - uses: "ramsey/composer-install@v2" + uses: "ramsey/composer-install@v3" - name: PHPUnit tests run: vendor/bin/phpunit \ No newline at end of file diff --git a/.github/workflows/psalm.yml b/.github/workflows/psalm.yml index f5bd5c5..489eb95 100644 --- a/.github/workflows/psalm.yml +++ b/.github/workflows/psalm.yml @@ -26,7 +26,7 @@ jobs: coverage: none - name: Install Composer dependencies - uses: "ramsey/composer-install@v2" + uses: "ramsey/composer-install@v3" with: composer-options: --no-dev diff --git a/CHANGELOG.md b/CHANGELOG.md index b4a7cc4..1a3daf2 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,5 +1,11 @@ # Changelog +## Version 5.1.2 (2024-05-08) + +* Use `#[SensitiveParameter]` annotation on some inputs + * This is defense in depth; we already wrapped most in `HiddenString` +* Updated dependencies + ## Version 5.1.1 (2024-04-19) * Support both sodium_compat v1 and v2. diff --git a/psalm.xml b/psalm.xml index 5d159e6..132ad1c 100644 --- a/psalm.xml +++ b/psalm.xml @@ -11,6 +11,7 @@ + diff --git a/src/Asymmetric/Crypto.php b/src/Asymmetric/Crypto.php index 3f9362c..42c8baa 100644 --- a/src/Asymmetric/Crypto.php +++ b/src/Asymmetric/Crypto.php @@ -84,7 +84,9 @@ final private function __construct() * @throws TypeError */ public static function encrypt( + #[\SensitiveParameter] HiddenString $plaintext, + #[\SensitiveParameter] EncryptionSecretKey $ourPrivateKey, EncryptionPublicKey $theirPublicKey, string|bool $encoding = Halite::ENCODE_BASE64URLSAFE @@ -118,9 +120,12 @@ public static function encrypt( * @throws TypeError */ public static function encryptWithAD( + #[\SensitiveParameter] HiddenString $plaintext, + #[\SensitiveParameter] EncryptionSecretKey $ourPrivateKey, EncryptionPublicKey $theirPublicKey, + #[\SensitiveParameter] string $additionalData = '', string|bool $encoding = Halite::ENCODE_BASE64URLSAFE ): string { @@ -163,6 +168,7 @@ public static function encryptWithAD( */ public static function decrypt( string $ciphertext, + #[\SensitiveParameter] EncryptionSecretKey $ourPrivateKey, EncryptionPublicKey $theirPublicKey, string|bool $encoding = Halite::ENCODE_BASE64URLSAFE @@ -198,8 +204,10 @@ public static function decrypt( */ public static function decryptWithAD( string $ciphertext, + #[\SensitiveParameter] EncryptionSecretKey $ourPrivateKey, EncryptionPublicKey $theirPublicKey, + #[\SensitiveParameter] string $additionalData = '', string|bool $encoding = Halite::ENCODE_BASE64URLSAFE ): HiddenString { @@ -241,6 +249,7 @@ public static function decryptWithAD( * @throws TypeError */ public static function getSharedSecret( + #[\SensitiveParameter] EncryptionSecretKey $privateKey, EncryptionPublicKey $publicKey, bool $get_as_object = false, @@ -291,6 +300,7 @@ public static function getSharedSecret( * @throws TypeError */ public static function seal( + #[\SensitiveParameter] HiddenString $plaintext, EncryptionPublicKey $publicKey, string|bool $encoding = Halite::ENCODE_BASE64URLSAFE @@ -321,6 +331,7 @@ public static function seal( */ public static function sign( string $message, + #[\SensitiveParameter] SignatureSecretKey $privateKey, string|bool $encoding = Halite::ENCODE_BASE64URLSAFE ): string { @@ -355,6 +366,7 @@ public static function sign( */ public static function signAndEncrypt( HiddenString $message, + #[\SensitiveParameter] SignatureSecretKey $secretKey, PublicKey $recipientPublicKey, string|bool $encoding = Halite::ENCODE_BASE64URLSAFE @@ -393,6 +405,7 @@ public static function signAndEncrypt( */ public static function unseal( string $ciphertext, + #[\SensitiveParameter] EncryptionSecretKey $privateKey, string|bool $encoding = Halite::ENCODE_BASE64URLSAFE ): HiddenString { @@ -505,6 +518,7 @@ public static function verify( public static function verifyAndDecrypt( string $ciphertext, SignaturePublicKey $senderPublicKey, + #[\SensitiveParameter] SecretKey $givenSecretKey, string|bool $encoding = Halite::ENCODE_BASE64URLSAFE ): HiddenString { diff --git a/src/Asymmetric/EncryptionSecretKey.php b/src/Asymmetric/EncryptionSecretKey.php index ede9f8b..c361ab1 100644 --- a/src/Asymmetric/EncryptionSecretKey.php +++ b/src/Asymmetric/EncryptionSecretKey.php @@ -28,8 +28,11 @@ final class EncryptionSecretKey extends SecretKey * @throws InvalidKey * @throws TypeError */ - public function __construct(HiddenString $keyMaterial, ?HiddenString $pk = null) - { + public function __construct( + #[\SensitiveParameter] + HiddenString $keyMaterial, + ?HiddenString $pk = null + ) { if (Binary::safeStrlen($keyMaterial->getString()) !== SODIUM_CRYPTO_BOX_SECRETKEYBYTES) { throw new InvalidKey( sprintf( diff --git a/src/Asymmetric/SecretKey.php b/src/Asymmetric/SecretKey.php index 6da48fa..ee8d7f6 100644 --- a/src/Asymmetric/SecretKey.php +++ b/src/Asymmetric/SecretKey.php @@ -24,8 +24,11 @@ class SecretKey extends Key * * @throws TypeError */ - public function __construct(HiddenString $keyMaterial, ?HiddenString $pk = null) - { + public function __construct( + #[\SensitiveParameter] + HiddenString $keyMaterial, + ?HiddenString $pk = null + ) { parent::__construct($keyMaterial); if (!is_null($pk)) { $this->cachedPublicKey = $pk->getString(); diff --git a/src/Asymmetric/SignatureSecretKey.php b/src/Asymmetric/SignatureSecretKey.php index f834f6c..355db43 100644 --- a/src/Asymmetric/SignatureSecretKey.php +++ b/src/Asymmetric/SignatureSecretKey.php @@ -33,8 +33,11 @@ final class SignatureSecretKey extends SecretKey * @throws InvalidKey * @throws TypeError */ - public function __construct(HiddenString $keyMaterial, ?HiddenString $pk = null) - { + public function __construct( + #[\SensitiveParameter] + HiddenString $keyMaterial, + ?HiddenString $pk = null + ) { if (Binary::safeStrlen($keyMaterial->getString()) !== SODIUM_CRYPTO_SIGN_SECRETKEYBYTES) { throw new InvalidKey( sprintf( diff --git a/src/Cookie.php b/src/Cookie.php index c905f15..beb493b 100644 --- a/src/Cookie.php +++ b/src/Cookie.php @@ -86,8 +86,10 @@ public function __debugInfo() * @throws SodiumException * @throws TypeError */ - public function fetch(string $name) - { + public function fetch( + #[\SensitiveParameter] + string $name + ) { if (!isset($_COOKIE[$name])) { return null; } @@ -165,7 +167,9 @@ protected static function getConfig(string $stored): SymmetricConfig * @psalm-suppress MixedArgument */ public function store( + #[\SensitiveParameter] string $name, + #[\SensitiveParameter] $value, int $expire = 0, string $path = '/', diff --git a/src/EncryptionKeyPair.php b/src/EncryptionKeyPair.php index 4b675d5..182c855 100644 --- a/src/EncryptionKeyPair.php +++ b/src/EncryptionKeyPair.php @@ -131,8 +131,10 @@ public function __construct(Key ...$keys) * @throws InvalidKey * @throws \TypeError */ - protected function setupKeyPair(EncryptionSecretKey $secret): void - { + protected function setupKeyPair( + #[\SensitiveParameter] + EncryptionSecretKey $secret + ): void { $this->secretKey = $secret; $this->publicKey = $this->secretKey->derivePublicKey(); } diff --git a/src/Password.php b/src/Password.php index 8acd6d5..ba8dda9 100644 --- a/src/Password.php +++ b/src/Password.php @@ -64,9 +64,12 @@ final class Password * @throws TypeError */ public static function hash( + #[\SensitiveParameter] HiddenString $password, + #[\SensitiveParameter] EncryptionKey $secretKey, string $level = KeyFactory::INTERACTIVE, + #[\SensitiveParameter] string $additionalData = '' ): string { $kdfLimits = KeyFactory::getSecurityLevels($level); @@ -105,9 +108,12 @@ public static function hash( * @throws TypeError */ public static function needsRehash( + #[\SensitiveParameter] string $stored, + #[\SensitiveParameter] EncryptionKey $secretKey, string $level = KeyFactory::INTERACTIVE, + #[\SensitiveParameter] string $additionalData = '' ): bool { $config = self::getConfig($stored); @@ -203,9 +209,13 @@ protected static function getConfig(string $stored): SymmetricConfig * @throws TypeError */ public static function verify( + #[\SensitiveParameter] HiddenString $password, + #[\SensitiveParameter] string $stored, + #[\SensitiveParameter] EncryptionKey $secretKey, + #[\SensitiveParameter] string $additionalData = '' ): bool { $config = self::getConfig($stored); diff --git a/src/SignatureKeyPair.php b/src/SignatureKeyPair.php index d36386d..721b9e9 100644 --- a/src/SignatureKeyPair.php +++ b/src/SignatureKeyPair.php @@ -157,8 +157,10 @@ public function getEncryptionKeyPair(): EncryptionKeyPair * @throws InvalidKey * @throws SodiumException */ - protected function setupKeyPair(SignatureSecretKey $secret): void - { + protected function setupKeyPair( + #[\SensitiveParameter] + SignatureSecretKey $secret + ): void { $this->secretKey = $secret; $this->publicKey = $this->secretKey->derivePublicKey(); } diff --git a/src/Symmetric/AuthenticationKey.php b/src/Symmetric/AuthenticationKey.php index 3ef8f51..a53a69b 100644 --- a/src/Symmetric/AuthenticationKey.php +++ b/src/Symmetric/AuthenticationKey.php @@ -27,8 +27,10 @@ final class AuthenticationKey extends SecretKey * @throws InvalidKey * @throws TypeError */ - public function __construct(HiddenString $keyMaterial) - { + public function __construct( + #[\SensitiveParameter] + HiddenString $keyMaterial + ) { if (Binary::safeStrlen($keyMaterial->getString()) !== SODIUM_CRYPTO_AUTH_KEYBYTES) { throw new InvalidKey( sprintf( diff --git a/src/Symmetric/EncryptionKey.php b/src/Symmetric/EncryptionKey.php index 2443980..ea8fee2 100644 --- a/src/Symmetric/EncryptionKey.php +++ b/src/Symmetric/EncryptionKey.php @@ -25,8 +25,10 @@ final class EncryptionKey extends SecretKey * @throws InvalidKey * @throws TypeError */ - public function __construct(HiddenString $keyMaterial) - { + public function __construct( + #[\SensitiveParameter] + HiddenString $keyMaterial + ) { if (Binary::safeStrlen($keyMaterial->getString()) !== SODIUM_CRYPTO_STREAM_KEYBYTES) { throw new InvalidKey( sprintf(