Skip to content

Navigation Menu

Sign in
Appearance settings

Search code, repositories, users, issues, pull requests...

Provide feedback

We read every piece of feedback, and take your input very seriously.

Saved searches

Use saved searches to filter your results more quickly

Appearance settings

Commit a8311bd

Browse filesBrowse files
committed
Use JWE
1 parent d913417 commit a8311bd
Copy full SHA for a8311bd

File tree

Expand file treeCollapse file tree

7 files changed

+135
-99
lines changed
Filter options
Expand file treeCollapse file tree

7 files changed

+135
-99
lines changed

‎src/Symfony/Component/Encryption/Ciphertext.php

Copy file name to clipboardExpand all lines: src/Symfony/Component/Encryption/Ciphertext.php
-87Lines changed: 0 additions & 87 deletions
This file was deleted.

‎src/Symfony/Component/Encryption/Exception/MalformedCipherException.php

Copy file name to clipboardExpand all lines: src/Symfony/Component/Encryption/Exception/MalformedCipherException.php
+2-2Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -18,8 +18,8 @@
1818
*/
1919
class MalformedCipherException extends DecryptionException
2020
{
21-
public function __construct(\Throwable $previous = null)
21+
public function __construct($message = null, \Throwable $previous = null)
2222
{
23-
parent::__construct('The message you provided is not a valid cipher text.', $previous);
23+
parent::__construct($message ?? 'The message you provided is not a valid cipher text.', $previous);
2424
}
2525
}
+121Lines changed: 121 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,121 @@
1+
<?php
2+
3+
/*
4+
* This file is part of the Symfony package.
5+
*
6+
* (c) Fabien Potencier <fabien@symfony.com>
7+
*
8+
* For the full copyright and license information, please view the LICENSE
9+
* file that was distributed with this source code.
10+
*/
11+
12+
namespace Symfony\Component\Encryption;
13+
14+
use Lcobucci\JWT\Encoding\CannotDecodeContent;
15+
use Symfony\Component\Encryption\Exception\MalformedCipherException;
16+
17+
/**
18+
* A JSON Web Encryption representation of the encrypted message.
19+
*
20+
* This class is responsible over the payload API.
21+
*
22+
* @author Tobias Nyholm <tobias.nyholm@gmail.com>
23+
*
24+
* @experimental in 5.3
25+
*
26+
* @internal
27+
*/
28+
class JWE
29+
{
30+
private $algorithm;
31+
private $ciphertext;
32+
private $nonce;
33+
34+
public function __construct(string $algorithm, string $ciphertext, string $nonce)
35+
{
36+
$this->algorithm = $algorithm;
37+
$this->ciphertext = $ciphertext;
38+
$this->nonce = $nonce;
39+
}
40+
41+
/**
42+
* Take a string representation of the chiphertext and parse it into an object.
43+
*
44+
* @throws MalformedCipherException
45+
*/
46+
public static function parse(string $input): self
47+
{
48+
$parts = explode('.', $input);
49+
if (false === $parts || 5 !== \count($parts)) {
50+
throw new MalformedCipherException();
51+
}
52+
53+
[$header, $cek, $initializationVector, $ciphertext, $authenticationTag] = $parts;
54+
$header = json_decode(self::base64UrlDecode($header), true);
55+
$cek = self::base64UrlDecode($cek);
56+
$ciphertext = self::base64UrlDecode($ciphertext);
57+
$authenticationTag = self::base64UrlDecode($authenticationTag);
58+
59+
if (md5($ciphertext) !== $authenticationTag) {
60+
throw new MalformedCipherException();
61+
}
62+
63+
if (!is_array($header) || !array_key_exists('alg', $header)) {
64+
throw new MalformedCipherException();
65+
}
66+
67+
return new self($header['alg'], $ciphertext, $cek);
68+
}
69+
70+
/**
71+
* @return string
72+
*/
73+
public function __toString()
74+
{
75+
return $this->getString();
76+
}
77+
78+
public function getString(): string
79+
{
80+
$header = self::base64UrlEncode(json_encode([
81+
'alg' => $this->algorithm,
82+
'enc' => 'none', // How we encode the CEK/nonce
83+
]));
84+
$cek = self::base64UrlEncode($this->nonce);
85+
$initializationVector = self::base64UrlEncode(random_bytes(128));
86+
87+
return sprintf('%s.%s.%s.%s.%s', $header, $cek, $initializationVector, self::base64UrlEncode($this->ciphertext), self::base64UrlEncode(md5($this->ciphertext)));
88+
}
89+
90+
public function getAlgorithm(): string
91+
{
92+
return $this->algorithm;
93+
}
94+
95+
public function getCiphertext(): string
96+
{
97+
return $this->ciphertext;
98+
}
99+
100+
public function getNonce(): string
101+
{
102+
return $this->nonce;
103+
}
104+
105+
private static function base64UrlEncode(string $data): string
106+
{
107+
return rtrim(strtr(base64_encode($data), '+/', '-_'), '=');
108+
}
109+
110+
private static function base64UrlDecode(string $data): string
111+
{
112+
// Padding isn't added back because it isn't strictly necessary for decoding with PHP
113+
$decodedContent = base64_decode(strtr($data, '-_', '+/'), true);
114+
115+
if (! is_string($decodedContent)) {
116+
throw new MalformedCipherException('Could not base64 decode the content');
117+
}
118+
119+
return $decodedContent;
120+
}
121+
}

‎src/Symfony/Component/Encryption/Provider/PhpseclibEncryption.php

Copy file name to clipboardExpand all lines: src/Symfony/Component/Encryption/Provider/PhpseclibEncryption.php
+3-3Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -14,7 +14,7 @@
1414
use phpseclib\Crypt\AES;
1515
use phpseclib\Crypt\RSA;
1616
use Symfony\Component\Encryption\AsymmetricEncryptionInterface;
17-
use Symfony\Component\Encryption\Ciphertext;
17+
use Symfony\Component\Encryption\JWE;
1818
use Symfony\Component\Encryption\Exception\DecryptionException;
1919
use Symfony\Component\Encryption\Exception\EncryptionException;
2020
use Symfony\Component\Encryption\Exception\InvalidArgumentException;
@@ -95,12 +95,12 @@ public function encrypt(string $message, ?string $publicKey = null, ?string $pri
9595
restore_error_handler();
9696
}
9797

98-
return (new Ciphertext($algorithm, $ciphertext, $nonce))->getUrlSafeRepresentation();
98+
return (new JWE($algorithm, $ciphertext, $nonce))->getString();
9999
}
100100

101101
public function decrypt(string $message, ?string $privateKey = null, ?string $publicKey = null): string
102102
{
103-
$parsedMessage = Ciphertext::parse($message);
103+
$parsedMessage = JWE::parse($message);
104104
$algorithm = $parsedMessage->getAlgorithm();
105105
$ciphertext = $parsedMessage->getCiphertext();
106106
$nonce = $parsedMessage->getNonce();

‎src/Symfony/Component/Encryption/Provider/SodiumEncryption.php

Copy file name to clipboardExpand all lines: src/Symfony/Component/Encryption/Provider/SodiumEncryption.php
+5-5Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -12,7 +12,7 @@
1212
namespace Symfony\Component\Encryption\Provider;
1313

1414
use Symfony\Component\Encryption\AsymmetricEncryptionInterface;
15-
use Symfony\Component\Encryption\Ciphertext;
15+
use Symfony\Component\Encryption\JWE;
1616
use Symfony\Component\Encryption\Exception\DecryptionException;
1717
use Symfony\Component\Encryption\Exception\EncryptionException;
1818
use Symfony\Component\Encryption\Exception\InvalidArgumentException;
@@ -56,14 +56,14 @@ public function encrypt(string $message, ?string $publicKey = null, ?string $pri
5656
if (null === $publicKey) {
5757
$ciphertext = sodium_crypto_secretbox($message, $nonce, $this->getSodiumKey($this->secret));
5858

59-
return (new Ciphertext('sodium_secretbox', $ciphertext, $nonce))->getUrlSafeRepresentation();
59+
return (new JWE('sodium_secretbox', $ciphertext, $nonce))->getString();
6060
} elseif (null === $privateKey) {
61-
return (new Ciphertext('sodium_crypto_box_seal', sodium_crypto_box_seal($message, $publicKey), $nonce))->getUrlSafeRepresentation();
61+
return (new JWE('sodium_crypto_box_seal', sodium_crypto_box_seal($message, $publicKey), $nonce))->getString();
6262
} elseif (null !== $publicKey && null !== $privateKey) {
6363
$keypair = sodium_crypto_box_keypair_from_secretkey_and_publickey($privateKey, $publicKey);
6464
$ciphertext = sodium_crypto_box($message, $nonce, $keypair);
6565

66-
return (new Ciphertext('sodium_crypto_box', $ciphertext, $nonce))->getUrlSafeRepresentation();
66+
return (new JWE('sodium_crypto_box', $ciphertext, $nonce))->getString();
6767
} else {
6868
throw new InvalidArgumentException('Private key cannot have a value when no public key is provided.');
6969
}
@@ -74,7 +74,7 @@ public function encrypt(string $message, ?string $publicKey = null, ?string $pri
7474

7575
public function decrypt(string $message, ?string $privateKey = null, ?string $publicKey = null): string
7676
{
77-
$parsedMessage = Ciphertext::parse($message);
77+
$parsedMessage = JWE::parse($message);
7878
$algorithm = $parsedMessage->getAlgorithm();
7979
$ciphertext = $parsedMessage->getCiphertext();
8080
$nonce = $parsedMessage->getNonce();

‎src/Symfony/Component/Encryption/Tests/AbstractAsymmetricEncryptionTest.php

Copy file name to clipboardExpand all lines: src/Symfony/Component/Encryption/Tests/AbstractAsymmetricEncryptionTest.php
+2-1Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,7 @@
1717
use Symfony\Component\Encryption\Exception\MalformedCipherException;
1818
use Symfony\Component\Encryption\Exception\SignatureVerificationRequiredException;
1919
use Symfony\Component\Encryption\Exception\UnsupportedAlgorithmException;
20+
use Symfony\Component\Encryption\JWE;
2021

2122
/**
2223
* @author Tobias Nyholm <tobias.nyholm@gmail.com>
@@ -102,7 +103,7 @@ public function testDecryptionThrowsOnUnsupportedAlgorithm()
102103
{
103104
$sodium = $this->getAsymmetricEncryption();
104105
$this->expectException(UnsupportedAlgorithmException::class);
105-
$sodium->decrypt('foo.bar.baz', 'private', 'public');
106+
$sodium->decrypt((new JWE('foo', 'xx', 'yy'))->getString(), 'private', 'public');
106107
}
107108

108109
public function testAsymmetricDecryptionThrowsExceptionOnWrongPublicKey()

‎src/Symfony/Component/Encryption/Tests/AbstractSymmetricEncryptionTest.php

Copy file name to clipboardExpand all lines: src/Symfony/Component/Encryption/Tests/AbstractSymmetricEncryptionTest.php
+2-1Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,7 @@
1414
use PHPUnit\Framework\TestCase;
1515
use Symfony\Component\Encryption\Exception\MalformedCipherException;
1616
use Symfony\Component\Encryption\Exception\UnsupportedAlgorithmException;
17+
use Symfony\Component\Encryption\JWE;
1718
use Symfony\Component\Encryption\SymmetricEncryptionInterface;
1819

1920
/**
@@ -53,7 +54,7 @@ public function testDecryptionThrowsOnUnsupportedAlgorithm()
5354
{
5455
$sodium = $this->getSymmetricEncryption();
5556
$this->expectException(UnsupportedAlgorithmException::class);
56-
$sodium->decrypt('foo.bar.baz');
57+
$sodium->decrypt((new JWE('foo', 'xx', 'yy'))->getString());
5758
}
5859

5960
abstract protected function getSymmetricEncryption(): SymmetricEncryptionInterface;

0 commit comments

Comments
0 (0)
Morty Proxy This is a proxified and sanitized view of the page, visit original site.