diff --git a/sodium.php b/sodium.php index d8727b0..709b21b 100644 --- a/sodium.php +++ b/sodium.php @@ -1,23 +1,48 @@ bytes = sodium_crypto_secretbox( - $data, - $this->iv->getBytes(), - $this->key->getBytes(), - ); + try { + $this->bytes = sodium_crypto_secretbox( + $data, + $this->iv->getBytes(), + $this->key->getBytes(), + ); + } + catch(Throwable $throwable) { + throw new EncryptionFailureException( + "Error encrypting cipher message", + previous: $throwable, + ); + } } public function __toString():string { diff --git a/src/EncryptedUri.php b/src/EncryptedUri.php index 911d1c2..38abda8 100644 --- a/src/EncryptedUri.php +++ b/src/EncryptedUri.php @@ -1,10 +1,10 @@ encryptedBytes, - $this->iv->getBytes(), - $key->getBytes(), - ); + try { + $decrypted = sodium_crypto_secretbox_open( + $this->encryptedBytes, + $this->iv->getBytes(), + $key->getBytes(), + ); + } + catch(Throwable $throwable) { + throw new UriDecryptionFailureException( + "Error decrypting cipher URI", + previous: $throwable, + ); + } if($decrypted === false) { - throw new DecryptionFailureException("Error decrypting cipher message"); + throw new UriDecryptionFailureException("Error decrypting cipher URI"); } return new PlainTextMessage( $decrypted, diff --git a/src/EncryptionFailureException.php b/src/EncryptionFailureException.php new file mode 100644 index 0000000..9abf0d6 --- /dev/null +++ b/src/EncryptionFailureException.php @@ -0,0 +1,4 @@ +data), - $this->iv->getBytes(), - $key->getBytes(), - ); + try { + $decrypted = sodium_crypto_secretbox_open( + base64_decode($this->data), + $this->iv->getBytes(), + $key->getBytes(), + ); + } + catch(Throwable $throwable) { + throw new DecryptionFailureException( + "Error decrypting cipher message", + previous: $throwable, + ); + } if($decrypted === false) { throw new DecryptionFailureException("Error decrypting cipher message"); } diff --git a/src/UriDecryptionFailureException.php b/src/UriDecryptionFailureException.php new file mode 100644 index 0000000..056fa56 --- /dev/null +++ b/src/UriDecryptionFailureException.php @@ -0,0 +1,4 @@ +getScheme() . "://" . $uri->getAuthority()); self::assertSame(http_build_query($expectedQueryParts), $uri->getQuery()); } + + public function testConstruct_wrapsSodiumFailure():void { + $data = "test data"; + $iv = self::createMock(InitVector::class); + $iv->method("getBytes") + ->willReturn(str_repeat("0", SODIUM_CRYPTO_SECRETBOX_NONCEBYTES)); + $key = self::createMock(Key::class); + $key->method("getBytes") + ->willReturn("bad"); + + self::expectException(EncryptionFailureException::class); + new CipherText($data, $iv, $key); + } } diff --git a/test/phpunit/EncryptedUriTest.php b/test/phpunit/EncryptedUriTest.php index 29f3b1d..801446d 100644 --- a/test/phpunit/EncryptedUriTest.php +++ b/test/phpunit/EncryptedUriTest.php @@ -4,8 +4,8 @@ use Gt\Cipher\EncryptedUri; use Gt\Cipher\InitVector; use Gt\Cipher\Key; -use Gt\Cipher\Message\DecryptionFailureException; use Gt\Cipher\MissingQueryStringException; +use Gt\Cipher\UriDecryptionFailureException; use PHPUnit\Framework\TestCase; class EncryptedUriTest extends TestCase { @@ -38,19 +38,38 @@ public function testConstruct_missingCipherValue():void { } public function testDecryptMessage_error():void { - $ivString = base64_encode(str_repeat("0", SODIUM_CRYPTO_SECRETBOX_NONCEBYTES)); + $ivString = base64_encode( + str_repeat("0", SODIUM_CRYPTO_SECRETBOX_NONCEBYTES) + ); $uri = "https://example.com/test/?cipher=0000&iv=$ivString"; $sut = new EncryptedUri($uri); $key = self::createMock(Key::class); $key->method("getBytes") ->willReturn(str_repeat("0", SODIUM_CRYPTO_SECRETBOX_KEYBYTES)); - self::expectException(DecryptionFailureException::class); + self::expectException(UriDecryptionFailureException::class); + $sut->decryptMessage($key); + } + + public function testDecryptMessage_wrapsSodiumFailure():void { + $ivString = base64_encode( + str_repeat("0", SODIUM_CRYPTO_SECRETBOX_NONCEBYTES) + ); + $uri = "https://example.com/test/?cipher=0000&iv=$ivString"; + $sut = new EncryptedUri($uri); + + $key = self::createMock(Key::class); + $key->method("getBytes") + ->willReturn("bad"); + + self::expectException(UriDecryptionFailureException::class); $sut->decryptMessage($key); } public function testDecryptMessage():void { - $uri = "https://example.com/?cipher=lmEClve%2FuhmK32ghM0%2BA%2FI%2Btysm00AL37YD6eg%3D%3D&iv=UVunn3laPVnK4CfHZuS2AnvJ1KfsPM1r"; + $uri = "https://example.com/" + . "?cipher=lmEClve%2FuhmK32ghM0%2BA%2FI%2Btysm00AL37YD6eg%3D%3D" + . "&iv=UVunn3laPVnK4CfHZuS2AnvJ1KfsPM1r"; $sut = new EncryptedUri($uri); $key = self::createMock(Key::class); diff --git a/test/phpunit/Message/EncryptedMessageTest.php b/test/phpunit/Message/EncryptedMessageTest.php index 7bf97df..57df7ac 100644 --- a/test/phpunit/Message/EncryptedMessageTest.php +++ b/test/phpunit/Message/EncryptedMessageTest.php @@ -41,4 +41,18 @@ public function testDecrypt_failure():void { self::expectException(DecryptionFailureException::class); $sut->decrypt($key); } + + public function testDecrypt_wrapsSodiumFailure():void { + $iv = self::createMock(InitVector::class); + $iv->method("getBytes") + ->willReturn(str_repeat("0", SODIUM_CRYPTO_SECRETBOX_NONCEBYTES)); + $sut = new EncryptedMessage("badly formed data", $iv); + + $key = self::createMock(Key::class); + $key->method("getBytes") + ->willReturn("bad"); + + self::expectException(DecryptionFailureException::class); + $sut->decrypt($key); + } }