Skip to content

Commit 8bdd385

Browse files
Merge pull request #1 from InitPHP/2.x
2.x
2 parents 6b4604b + 24ab7f4 commit 8bdd385

36 files changed

Lines changed: 4048 additions & 320 deletions

.github/workflows/ci.yml

Lines changed: 106 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,106 @@
1+
name: CI
2+
3+
on:
4+
push:
5+
branches: [main, 2.x, 1.x]
6+
pull_request:
7+
branches: [main, 2.x, 1.x]
8+
9+
permissions:
10+
contents: read
11+
12+
jobs:
13+
tests:
14+
name: PHP ${{ matrix.php }} / ${{ matrix.dependencies }}
15+
runs-on: ubuntu-latest
16+
17+
strategy:
18+
fail-fast: false
19+
matrix:
20+
php: ['8.1', '8.2', '8.3', '8.4']
21+
dependencies: [highest]
22+
include:
23+
- php: '8.1'
24+
dependencies: lowest
25+
26+
steps:
27+
- name: Checkout
28+
uses: actions/checkout@v4
29+
30+
- name: Setup PHP
31+
uses: shivammathur/setup-php@v2
32+
with:
33+
php-version: ${{ matrix.php }}
34+
extensions: openssl, sodium
35+
coverage: none
36+
tools: composer:v2
37+
38+
- name: Validate composer.json
39+
run: composer validate --strict
40+
41+
- name: Get composer cache directory
42+
id: composer-cache
43+
run: echo "dir=$(composer config cache-files-dir)" >> $GITHUB_OUTPUT
44+
45+
- name: Cache composer dependencies
46+
uses: actions/cache@v4
47+
with:
48+
path: ${{ steps.composer-cache.outputs.dir }}
49+
key: ${{ runner.os }}-php-${{ matrix.php }}-${{ matrix.dependencies }}-${{ hashFiles('**/composer.json') }}
50+
restore-keys: |
51+
${{ runner.os }}-php-${{ matrix.php }}-${{ matrix.dependencies }}-
52+
53+
- name: Install dependencies (highest)
54+
if: matrix.dependencies == 'highest'
55+
run: composer update --no-interaction --no-progress --prefer-dist
56+
57+
- name: Install dependencies (lowest)
58+
if: matrix.dependencies == 'lowest'
59+
run: composer update --no-interaction --no-progress --prefer-dist --prefer-lowest
60+
61+
- name: Run tests
62+
run: composer test
63+
64+
static-analysis:
65+
name: Static analysis
66+
runs-on: ubuntu-latest
67+
68+
steps:
69+
- name: Checkout
70+
uses: actions/checkout@v4
71+
72+
- name: Setup PHP
73+
uses: shivammathur/setup-php@v2
74+
with:
75+
php-version: '8.3'
76+
extensions: openssl, sodium
77+
coverage: none
78+
tools: composer:v2
79+
80+
- name: Install dependencies
81+
run: composer update --no-interaction --no-progress --prefer-dist
82+
83+
- name: PHPStan
84+
run: composer phpstan
85+
86+
coding-style:
87+
name: Coding style
88+
runs-on: ubuntu-latest
89+
90+
steps:
91+
- name: Checkout
92+
uses: actions/checkout@v4
93+
94+
- name: Setup PHP
95+
uses: shivammathur/setup-php@v2
96+
with:
97+
php-version: '8.3'
98+
extensions: openssl, sodium
99+
coverage: none
100+
tools: composer:v2, php-cs-fixer
101+
102+
- name: Install dependencies
103+
run: composer update --no-interaction --no-progress --prefer-dist
104+
105+
- name: Check style
106+
run: composer cs-check

.github/workflows/security.yml

Lines changed: 35 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,35 @@
1+
name: Security
2+
3+
on:
4+
push:
5+
branches: [main, 2.x, 1.x]
6+
pull_request:
7+
branches: [main, 2.x, 1.x]
8+
schedule:
9+
- cron: '17 6 * * 1'
10+
11+
permissions:
12+
contents: read
13+
14+
jobs:
15+
composer-audit:
16+
name: composer audit
17+
runs-on: ubuntu-latest
18+
19+
steps:
20+
- name: Checkout
21+
uses: actions/checkout@v4
22+
23+
- name: Setup PHP
24+
uses: shivammathur/setup-php@v2
25+
with:
26+
php-version: '8.3'
27+
extensions: openssl, sodium
28+
coverage: none
29+
tools: composer:v2
30+
31+
- name: Install dependencies
32+
run: composer update --no-interaction --no-progress --prefer-dist
33+
34+
- name: Run composer audit
35+
run: composer audit --no-dev --locked || composer audit

.gitignore

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,4 +2,10 @@
22
/.vs/
33
/.vscode/
44
/vendor/
5-
/composer.lock
5+
/composer.lock
6+
/build/
7+
/coverage/
8+
/.phpunit.cache/
9+
/.phpunit.result.cache
10+
/.php-cs-fixer.cache
11+
/.phpstan.cache

.php-cs-fixer.dist.php

Lines changed: 39 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,39 @@
1+
<?php
2+
3+
declare(strict_types=1);
4+
5+
$finder = (new PhpCsFixer\Finder())
6+
->in([__DIR__ . '/src', __DIR__ . '/tests'])
7+
->name('*.php')
8+
->ignoreDotFiles(true)
9+
->ignoreVCS(true);
10+
11+
return (new PhpCsFixer\Config())
12+
->setRiskyAllowed(true)
13+
->setFinder($finder)
14+
->setCacheFile(__DIR__ . '/.php-cs-fixer.cache')
15+
->setRules([
16+
'@PSR12' => true,
17+
'@PSR12:risky' => true,
18+
'declare_strict_types' => true,
19+
'array_syntax' => ['syntax' => 'short'],
20+
'ordered_imports' => [
21+
'sort_algorithm' => 'alpha',
22+
'imports_order' => ['class', 'function', 'const'],
23+
],
24+
'no_unused_imports' => true,
25+
'single_quote' => true,
26+
'trailing_comma_in_multiline' => ['elements' => ['arrays', 'arguments', 'parameters']],
27+
'no_trailing_whitespace' => true,
28+
'no_whitespace_in_blank_line' => true,
29+
'no_extra_blank_lines' => ['tokens' => ['extra', 'throw', 'use']],
30+
'blank_line_after_opening_tag' => true,
31+
'blank_line_before_statement' => ['statements' => ['return', 'throw', 'try']],
32+
'cast_spaces' => ['space' => 'single'],
33+
'concat_space' => ['spacing' => 'one'],
34+
'native_function_invocation' => [
35+
'include' => ['@compiler_optimized'],
36+
'scope' => 'namespaced',
37+
'strict' => true,
38+
],
39+
]);

CHANGELOG.md

Lines changed: 49 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,49 @@
1+
# Changelog
2+
3+
All notable changes to `initphp/encryption` will be documented in this file.
4+
5+
The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.1.0/),
6+
and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).
7+
8+
## [Unreleased]
9+
10+
### Planned for 2.0.0
11+
12+
This is the first development entry of the upcoming 2.0 release. The 2.x line is
13+
a deliberate hard reset of the public surface; ciphertexts produced by 1.x cannot
14+
be decrypted by 2.x and vice versa. A migration guide will ship with the final
15+
release.
16+
17+
#### Added
18+
19+
- Tooling: PHPUnit 10, PHPStan level 8, PHP-CS-Fixer (PSR-12), GitHub Actions CI
20+
matrix across PHP 8.1–8.4, `composer audit` workflow.
21+
- `composer.json` scripts: `test`, `test-coverage`, `phpstan`, `cs-check`,
22+
`cs-fix`, `qa`.
23+
- Package-level `CONTRIBUTING.md`, `SECURITY.md`, `CHANGELOG.md`.
24+
25+
#### Changed
26+
27+
- **BREAKING:** Minimum PHP version raised to `^8.1`.
28+
29+
#### To be done (tracked, not yet shipped)
30+
31+
- **BREAKING:** New self-describing ciphertext format (versioned header) — v1
32+
ciphertexts will not be readable by 2.x.
33+
- **BREAKING:** Default payload serialization switches from `serialize()`/
34+
`unserialize()` to JSON. PHP serialization remains available as an opt-in.
35+
- Sodium handler derives a 32-byte key from any-length user-supplied key
36+
material via `sodium_crypto_generichash`, fixing the silent failure when a
37+
short key was provided.
38+
- OpenSSL handler uses `random_bytes()` for IV generation.
39+
- OpenSSL handler computes the HMAC length from the actual hash output instead
40+
of parsing the algorithm name as a numeric suffix.
41+
- Mandatory key validation with a descriptive `EncryptionException` instead of
42+
obscure `TypeError`s deep inside the extensions.
43+
- Drop runtime dependency on `ext-mbstring`.
44+
- PSR-12 compliance across the codebase.
45+
- Removal of `Encrypt::create()` (alias of `Encrypt::use()`).
46+
47+
## [1.0.0] - 2022
48+
49+
Initial release.

CONTRIBUTING.md

Lines changed: 77 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,77 @@
1+
# Contributing to `initphp/encryption`
2+
3+
This package follows the [InitPHP org-wide contribution guide](https://github.com/InitPHP/.github/blob/main/CONTRIBUTING.md).
4+
Please read it first — everything below is in addition to that guide, not a
5+
replacement for it.
6+
7+
## Local Development
8+
9+
```bash
10+
git clone https://github.com/InitPHP/Encryption.git
11+
cd Encryption
12+
composer install
13+
```
14+
15+
Required PHP extensions for the test suite:
16+
17+
- `ext-openssl`
18+
- `ext-sodium`
19+
20+
## Quality Gates
21+
22+
The CI pipeline runs three checks. Run them locally before pushing — every PR
23+
must pass all three.
24+
25+
| Command | What it does |
26+
| --- | --- |
27+
| `composer test` | Run the PHPUnit suite. |
28+
| `composer phpstan` | Static analysis at level 8. |
29+
| `composer cs-check` | Verify PSR-12 compliance (read-only). |
30+
| `composer cs-fix` | Apply PSR-12 fixes automatically. |
31+
| `composer qa` | Run cs-check, phpstan and tests in sequence. |
32+
33+
## Writing Tests
34+
35+
- Unit tests live in `tests/Unit/` and must not require any I/O or extension
36+
state beyond what `ext-openssl` and `ext-sodium` provide.
37+
- Integration tests live in `tests/Integration/` and may pin golden
38+
ciphertexts for backwards-compatibility verification.
39+
- A bug fix PR must include a regression test that fails on `main` and passes
40+
with the fix applied.
41+
- Cover both the happy path and the failure paths (tampered ciphertext,
42+
invalid configuration, missing key, etc.).
43+
44+
## Security-Sensitive Changes
45+
46+
Any change that affects cryptographic primitives, key derivation, ciphertext
47+
format, or the trust boundary between an attacker and the plaintext requires:
48+
49+
1. An explicit reviewer note in the PR description describing the threat model.
50+
2. A test that exercises the failure path (e.g. tampered HMAC must be rejected).
51+
3. A `CHANGELOG.md` entry under the appropriate section.
52+
53+
If you believe you have found a vulnerability, **do not open a public issue or
54+
PR.** Follow the [security policy](./SECURITY.md) instead.
55+
56+
## Commit Messages
57+
58+
We use [Conventional Commits](https://www.conventionalcommits.org/). Typical
59+
scopes for this repository:
60+
61+
- `openssl` — changes to `OpenSSL` handler
62+
- `sodium` — changes to `Sodium` handler
63+
- `base` — changes to `BaseHandler`
64+
- `factory` — changes to `Encrypt`
65+
- `docs`, `test`, `ci`, `chore` — as in the org guide
66+
67+
Example:
68+
69+
```
70+
fix(openssl): handle openssl_decrypt failure before unserialize
71+
72+
openssl_decrypt() returns false on failure, which then caused
73+
unserialize(false) to throw a TypeError on PHP 8.x. Detect the false
74+
return and throw EncryptionException with a meaningful message.
75+
76+
Closes #NN
77+
```

0 commit comments

Comments
 (0)