diff --git a/src/LaravelAge.php b/src/LaravelAge.php index 19b0594..b79ab19 100755 --- a/src/LaravelAge.php +++ b/src/LaravelAge.php @@ -9,14 +9,14 @@ class LaravelAge public function __construct(private ?PrivateKey $privateKey = null, private ?PublicKey $publicKey = null) { /* If no keys are provided, use the one from .env or create a pair. */ - if (! isset($privateKey) && ! isset($publicKey)) { + if (!isset($privateKey) && !isset($publicKey)) { /** @phpstan-ignore-next-line */ $this->privateKey = new PrivateKey(config('laravel-age.identity')); $this->publicKey = $this->privateKey->getPublicKey(); } /* If only the private key is provided, generate the public key. */ - if (isset($privateKey) && ! isset($publicKey)) { + if (isset($privateKey) && !isset($publicKey)) { $this->publicKey = $privateKey->getPublicKey(); } } @@ -30,7 +30,7 @@ public static function generateKeypair(): LaravelAge public function getPublicKey(): PublicKey { - if (! isset($this->publicKey)) { + if (!isset($this->publicKey)) { throw new Exception('Public key not set!'); } @@ -39,28 +39,37 @@ public function getPublicKey(): PublicKey public function getPrivateKey(): PrivateKey { - if (! isset($this->privateKey)) { + if (!isset($this->privateKey)) { throw new Exception('Private key not set!'); } return $this->privateKey; } - public function encrypt(string $message): string + /** + * Encrypt a message using the public key. + * Returns the base64 encoded encrypted message. + */ + public function encrypt(string $message, bool $base64 = true): string { - if (! isset($this->publicKey)) { + if (!isset($this->publicKey)) { throw new Exception('Public key not set!'); } - return $this->publicKey->encrypt($message); + return $this->publicKey->encrypt($message, $base64); } - public function decrypt(string $message): string + + /** + * Decrypt a base64 encoded message using the private key. + * Returns the decrypted message. + */ + public function decrypt(string $message, bool $base64 = true): string { - if (! isset($this->privateKey)) { + if (!isset($this->privateKey)) { throw new Exception('Private key not set!'); } - return $this->privateKey->decrypt($message); + return $this->privateKey->decrypt($message, $base64); } } diff --git a/src/PrivateKey.php b/src/PrivateKey.php index ede2b0a..0890985 100644 --- a/src/PrivateKey.php +++ b/src/PrivateKey.php @@ -13,7 +13,7 @@ class PrivateKey public function __construct(string $privateKey = '') { - if (! $privateKey) { + if (!$privateKey) { $result = Process::pipe([ 'age-keygen', 'grep -E "^AGE-SECRET-KEY-[A-Za-z0-9]{59}$"', @@ -28,7 +28,7 @@ public function __construct(string $privateKey = '') $privateKey = str($privateKey)->trim(); - if (! $privateKey->startsWith('AGE-SECRET-KEY-') || $privateKey->length() !== 74) { + if (!$privateKey->startsWith('AGE-SECRET-KEY-') || $privateKey->length() !== 74) { throw new Exception('Invalid private key provided!'); } @@ -51,10 +51,14 @@ public function getPublicKey(): PublicKey return new PublicKey($result->output()); } - public function decrypt(string $message): string + /** + * Decrypt a base64 encoded message using the private key. + * Returns the decrypted message. + */ + public function decrypt(string $message, bool $base64): string { $ulid = Str::ulid(); - Storage::put($ulid, base64_decode($message)); + Storage::put($ulid, $base64 ? base64_decode($message) : $message); $path = Storage::path($ulid); $result = Process::input($this->encode())->run("age -d -i - {$path}"); diff --git a/src/PublicKey.php b/src/PublicKey.php index 4352c21..76c97f8 100644 --- a/src/PublicKey.php +++ b/src/PublicKey.php @@ -13,7 +13,7 @@ public function __construct(string $publicKey) { $publicKey = str($publicKey)->trim(); - if (! $publicKey->startsWith('age') || $publicKey->length() !== 62) { + if (!$publicKey->startsWith('age') || $publicKey->length() !== 62) { throw new Exception('Invalid public key provided!'); } @@ -25,7 +25,11 @@ public function encode(): string return str($this->publicKey)->trim(); } - public function encrypt(string $message): string + /** + * Encrypt a message using the public key. + * Returns the base64 encoded encrypted message. + */ + public function encrypt(string $message, bool $base64): string { $result = Process::input($message)->run("age -r {$this->encode()}"); @@ -33,6 +37,6 @@ public function encrypt(string $message): string throw new Exception('Failed to encrypt message!'); } - return base64_encode($result->output()); + return $base64 ? base64_encode($result->output()) : $result->output(); } } diff --git a/tests/LaravelAgeTest.php b/tests/LaravelAgeTest.php index e264199..eb33a26 100644 --- a/tests/LaravelAgeTest.php +++ b/tests/LaravelAgeTest.php @@ -60,7 +60,7 @@ expect($age->encrypt('message'))->toBeString(); }); -it('can decrypt with an provided private key', function () { +it('can decrypt with an provided private key (using base64)', function () { $encodeKey = 'AGE-SECRET-KEY-1TKGRTQP4H79MTNHVDRSA3L0CS7MFSMW0DQX80CWP0JDUFL97RRJSPK9777'; $privateKey = new PrivateKey($encodeKey); $age = new LaravelAge(privateKey: $privateKey); @@ -72,6 +72,18 @@ expect($decrypted)->toBe($message); }); +it('can decrypt with an provided private key (without using base64)', function () { + $encodeKey = 'AGE-SECRET-KEY-1TKGRTQP4H79MTNHVDRSA3L0CS7MFSMW0DQX80CWP0JDUFL97RRJSPK9777'; + $privateKey = new PrivateKey($encodeKey); + $age = new LaravelAge(privateKey: $privateKey); + + $message = 'Hello, World!'; + $encrypted = $age->encrypt($message, false); + $decrypted = $age->decrypt($encrypted, false); + + expect($decrypted)->toBe($message); +}); + it('cannot decrypt with an provided public key', function () { $encodeKey = 'age1xqrfpqxz55ersvu6mmhwzcctqk27ppnatms7p9zruclrm8tt4y0q3apxuc'; $publicKey = new PublicKey($encodeKey); @@ -82,6 +94,26 @@ $decrypted = $age->decrypt($encrypted); })->throws(Exception::class); +it('cannot decrypt with an provided private key (using base64 only to encrypt)', function () { + $encodeKey = 'age1xqrfpqxz55ersvu6mmhwzcctqk27ppnatms7p9zruclrm8tt4y0q3apxuc'; + $publicKey = new PublicKey($encodeKey); + $age = new LaravelAge(publicKey: $publicKey); + + $message = 'Hello, World!'; + $encrypted = $age->encrypt($message); + $decrypted = $age->decrypt($encrypted, false); +})->throws(Exception::class); + +it('cannot decrypt with an provided private key (using base64 only to decrypt)', function () { + $encodeKey = 'age1xqrfpqxz55ersvu6mmhwzcctqk27ppnatms7p9zruclrm8tt4y0q3apxuc'; + $publicKey = new PublicKey($encodeKey); + $age = new LaravelAge(publicKey: $publicKey); + + $message = 'Hello, World!'; + $encrypted = $age->encrypt($message, false); + $decrypted = $age->decrypt($encrypted); +})->throws(Exception::class); + it('runs usage code from readme', function () { $message = 'Hello World!';