diff --git a/src/Symfony/Component/Mime/Crypto/SMime.php b/src/Symfony/Component/Mime/Crypto/SMime.php new file mode 100644 index 0000000000000..55941be9f4f29 --- /dev/null +++ b/src/Symfony/Component/Mime/Crypto/SMime.php @@ -0,0 +1,111 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Symfony\Component\Mime\Crypto; + +use Symfony\Component\Mime\Exception\RuntimeException; +use Symfony\Component\Mime\Part\SMimePart; + +/** + * @author Sebastiaan Stok + * + * @internal + */ +abstract class SMime +{ + protected function normalizeFilePath(string $path): string + { + if (!file_exists($path)) { + throw new RuntimeException(sprintf('File does not exist: %s.', $path)); + } + + return 'file://'.str_replace('\\', '/', realpath($path)); + } + + protected function iteratorToFile(iterable $iterator, $stream): void + { + foreach ($iterator as $chunk) { + fwrite($stream, $chunk); + } + } + + protected function convertMessageToSMimePart($stream, string $type, string $subtype): SMimePart + { + rewind($stream); + + $headers = ''; + + while (!feof($stream)) { + $buffer = fread($stream, 78); + $headers .= $buffer; + + // Detect ending of header list + if (preg_match('/(\r\n\r\n|\n\n)/', $headers, $match)) { + $headersPosEnd = strpos($headers, $headerBodySeparator = $match[0]); + + break; + } + } + + $headers = $this->getMessageHeaders(trim(substr($headers, 0, $headersPosEnd))); + + fseek($stream, $headersPosEnd + \strlen($headerBodySeparator)); + + return new SMimePart($this->getStreamIterator($stream), $type, $subtype, $this->getParametersFromHeader($headers['content-type'])); + } + + protected function getStreamIterator($stream): iterable + { + while (!feof($stream)) { + yield fread($stream, 16372); + } + } + + private function getMessageHeaders(string $headerData): array + { + $headers = []; + $headerLines = explode("\r\n", str_replace("\n", "\r\n", str_replace("\r\n", "\n", $headerData))); + $currentHeaderName = ''; + + // Transform header lines into an associative array + foreach ($headerLines as $headerLine) { + // Empty lines between headers indicate a new mime-entity + if ('' === $headerLine) { + break; + } + + // Handle headers that span multiple lines + if (false === strpos($headerLine, ':')) { + $headers[$currentHeaderName] .= ' '.trim($headerLine); + continue; + } + + $header = explode(':', $headerLine, 2); + $currentHeaderName = strtolower($header[0]); + $headers[$currentHeaderName] = trim($header[1]); + } + + return $headers; + } + + private function getParametersFromHeader(string $header): array + { + $params = []; + + preg_match_all('/(?P[a-z-0-9]+)=(?P"[^"]+"|(?:[^\s;]+|$))(?:\s+;)?/i', $header, $matches); + + foreach ($matches['value'] as $pos => $paramValue) { + $params[$matches['name'][$pos]] = trim($paramValue, '"'); + } + + return $params; + } +} diff --git a/src/Symfony/Component/Mime/Crypto/SMimeEncrypter.php b/src/Symfony/Component/Mime/Crypto/SMimeEncrypter.php new file mode 100644 index 0000000000000..72f59ce1bc935 --- /dev/null +++ b/src/Symfony/Component/Mime/Crypto/SMimeEncrypter.php @@ -0,0 +1,58 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Symfony\Component\Mime\Crypto; + +use Symfony\Component\Mime\Exception\RuntimeException; +use Symfony\Component\Mime\Message; + +/** + * @author Sebastiaan Stok + */ +final class SMimeEncrypter extends SMime +{ + private $certs; + private $cipher; + + /** + * @param string|string[] $certificate Either a lone X.509 certificate, or an array of X.509 certificates + */ + public function __construct($certificate, int $cipher = OPENSSL_CIPHER_AES_256_CBC) + { + if (\is_array($certificate)) { + $this->certs = array_map([$this, 'normalizeFilePath'], $certificate); + } else { + $this->certs = $this->normalizeFilePath($certificate); + } + + $this->cipher = $cipher; + } + + public function encrypt(Message $message): Message + { + $bufferFile = tmpfile(); + $outputFile = tmpfile(); + + $this->iteratorToFile($message->toIterable(), $bufferFile); + + if (!@openssl_pkcs7_encrypt(stream_get_meta_data($bufferFile)['uri'], stream_get_meta_data($outputFile)['uri'], $this->certs, [], 0, $this->cipher)) { + throw new RuntimeException(sprintf('Failed to encrypt S/Mime message. Error: "%s".', openssl_error_string())); + } + + $mimePart = $this->convertMessageToSMimePart($outputFile, 'application', 'pkcs7-mime'); + $mimePart->getHeaders() + ->addTextHeader('Content-Transfer-Encoding', 'base64') + ->addParameterizedHeader('Content-Disposition', 'attachment', ['name' => 'smime.p7m']) + ; + + return new Message($message->getHeaders(), $mimePart); + } +} diff --git a/src/Symfony/Component/Mime/Crypto/SMimeSigner.php b/src/Symfony/Component/Mime/Crypto/SMimeSigner.php new file mode 100644 index 0000000000000..71ce5df962ebf --- /dev/null +++ b/src/Symfony/Component/Mime/Crypto/SMimeSigner.php @@ -0,0 +1,69 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Symfony\Component\Mime\Crypto; + +use Symfony\Component\Mime\Exception\RuntimeException; +use Symfony\Component\Mime\Message; + +/** + * @author Sebastiaan Stok + */ +final class SMimeSigner extends SMime +{ + private $signCertificate; + private $signPrivateKey; + private $signOptions; + private $extraCerts; + + /** + * @var string|null + */ + private $privateKeyPassphrase; + + /** + * @see https://secure.php.net/manual/en/openssl.pkcs7.flags.php + * + * @param string $certificate + * @param string $privateKey A file containing the private key (in PEM format) + * @param string|null $privateKeyPassphrase A passphrase of the private key (if any) + * @param string $extraCerts A file containing intermediate certificates (in PEM format) needed by the signing certificate + * @param int $signOptions Bitwise operator options for openssl_pkcs7_sign() + */ + public function __construct(string $certificate, string $privateKey, ?string $privateKeyPassphrase = null, ?string $extraCerts = null, int $signOptions = PKCS7_DETACHED) + { + $this->signCertificate = $this->normalizeFilePath($certificate); + + if (null !== $privateKeyPassphrase) { + $this->signPrivateKey = [$this->normalizeFilePath($privateKey), $privateKeyPassphrase]; + } else { + $this->signPrivateKey = $this->normalizeFilePath($privateKey); + } + + $this->signOptions = $signOptions; + $this->extraCerts = $extraCerts ? realpath($extraCerts) : null; + $this->privateKeyPassphrase = $privateKeyPassphrase; + } + + public function sign(Message $message): Message + { + $bufferFile = tmpfile(); + $outputFile = tmpfile(); + + $this->iteratorToFile($message->getBody()->toIterable(), $bufferFile); + + if (!@openssl_pkcs7_sign(stream_get_meta_data($bufferFile)['uri'], stream_get_meta_data($outputFile)['uri'], $this->signCertificate, $this->signPrivateKey, [], $this->signOptions, $this->extraCerts)) { + throw new RuntimeException(sprintf('Failed to sign S/Mime message. Error: "%s".', openssl_error_string())); + } + + return new Message($message->getHeaders(), $this->convertMessageToSMimePart($outputFile, 'multipart', 'signed')); + } +} diff --git a/src/Symfony/Component/Mime/Part/SMimePart.php b/src/Symfony/Component/Mime/Part/SMimePart.php new file mode 100644 index 0000000000000..59142c3f77e0c --- /dev/null +++ b/src/Symfony/Component/Mime/Part/SMimePart.php @@ -0,0 +1,118 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Symfony\Component\Mime\Part; + +use Symfony\Component\Mime\Header\Headers; + +/** + * @author Sebastiaan Stok + * + * @experimental in 4.4 + */ +class SMimePart extends AbstractPart +{ + private $body; + private $type; + private $subtype; + private $parameters; + + /** + * @param iterable|string $body + */ + public function __construct($body, string $type, string $subtype, array $parameters) + { + parent::__construct(); + + if (!\is_string($body) && !is_iterable($body)) { + throw new \TypeError(sprintf('The body of "%s" must be a string or a iterable (got "%s").', self::class, \is_object($body) ? \get_class($body) : \gettype($body))); + } + + $this->body = $body; + $this->type = $type; + $this->subtype = $subtype; + $this->parameters = $parameters; + } + + public function getMediaType(): string + { + return $this->type; + } + + public function getMediaSubtype(): string + { + return $this->subtype; + } + + public function bodyToString(): string + { + if (\is_string($this->body)) { + return $this->body; + } + + $body = ''; + foreach ($this->body as $chunk) { + $body .= $chunk; + } + $this->body = $body; + + return $body; + } + + public function bodyToIterable(): iterable + { + if (\is_string($this->body)) { + yield $this->body; + + return; + } + + $body = ''; + foreach ($this->body as $chunk) { + $body .= $chunk; + yield $chunk; + } + $this->body = $body; + } + + public function getPreparedHeaders(): Headers + { + $headers = clone parent::getHeaders(); + + $headers->setHeaderBody('Parameterized', 'Content-Type', $this->getMediaType().'/'.$this->getMediaSubtype()); + + foreach ($this->parameters as $name => $value) { + $headers->setHeaderParameter('Content-Type', $name, $value); + } + + return $headers; + } + + public function __sleep(): array + { + // convert iterables to strings for serialization + if (is_iterable($this->body)) { + $this->body = $this->bodyToString(); + } + + $this->_headers = $this->getHeaders(); + + return ['_headers', 'body', 'type', 'subtype', 'parameters']; + } + + public function __wakeup(): void + { + $r = new \ReflectionProperty(AbstractPart::class, 'headers'); + $r->setAccessible(true); + $r->setValue($this, $this->_headers); + unset($this->_headers); + } +} diff --git a/src/Symfony/Component/Mime/Tests/Crypto/SMimeEncryptorTest.php b/src/Symfony/Component/Mime/Tests/Crypto/SMimeEncryptorTest.php new file mode 100644 index 0000000000000..a05b1e86625b1 --- /dev/null +++ b/src/Symfony/Component/Mime/Tests/Crypto/SMimeEncryptorTest.php @@ -0,0 +1,103 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Symfony\Component\Mime\Tests\Crypto; + +use Symfony\Component\Mime\Crypto\SMimeEncrypter; +use Symfony\Component\Mime\Crypto\SMimeSigner; +use Symfony\Component\Mime\Email; +use Symfony\Component\Mime\Message; + +class SMimeEncryptorTest extends SMimeTestCase +{ + public function testEncryptMessage() + { + $message = (new Email()) + ->date(new \DateTime('2019-04-07 10:36:30', new \DateTimeZone('Europe/Paris'))) + ->to('fabien@symfony.com') + ->subject('Testing') + ->from('noreply@example.com') + ->text('El Barto was not here'); + + $message->getHeaders()->addIdHeader('Message-ID', 'some@id'); + + $encrypter = new SMimeEncrypter($this->samplesDir.'encrypt.crt'); + $encryptedMessage = $encrypter->encrypt($message); + + $this->assertMessageIsEncryptedProperly($encryptedMessage, $message); + } + + public function testEncryptSignedMessage() + { + $message = (new Email()) + ->date(new \DateTime('2019-04-07 10:36:30', new \DateTimeZone('Europe/Paris'))) + ->to('fabien@symfony.com') + ->bcc('luna@symfony.com') + ->subject('Testing') + ->from('noreply@example.com') + ->text('El Barto was not here'); + + $message->getHeaders()->addIdHeader('Message-ID', 'some@id'); + + $signer = new SMimeSigner($this->samplesDir.'sign.crt', $this->samplesDir.'sign.key'); + $signedMessage = $signer->sign($message); + + $encrypter = new SMimeEncrypter($this->samplesDir.'encrypt.crt'); + $encryptedMessage = $encrypter->encrypt($signedMessage); + + $this->assertMessageIsEncryptedProperly($encryptedMessage, $signedMessage); + } + + public function testEncryptMessageWithMultipleCerts() + { + $message = (new Email()) + ->date(new \DateTime('2019-04-07 10:36:30', new \DateTimeZone('Europe/Paris'))) + ->to('fabien@symfony.com') + ->subject('Testing') + ->from('noreply@example.com') + ->text('El Barto was not here'); + + $message2 = (new Email()) + ->date(new \DateTime('2019-04-07 10:36:30', new \DateTimeZone('Europe/Paris'))) + ->to('luna@symfony.com') + ->subject('Testing') + ->from('noreply@example.com') + ->text('El Barto was not here'); + + $message->getHeaders()->addIdHeader('Message-ID', 'some@id'); + $message2->getHeaders()->addIdHeader('Message-ID', 'some@id2'); + + $encrypter = new SMimeEncrypter(['fabien@symfony.com' => $this->samplesDir.'encrypt.crt', 'luna@symfony.com' => $this->samplesDir.'encrypt2.crt']); + + $this->assertMessageIsEncryptedProperly($encrypter->encrypt($message), $message); + $this->assertMessageIsEncryptedProperly($encrypter->encrypt($message2), $message2); + } + + private function assertMessageIsEncryptedProperly(Message $message, Message $originalMessage): void + { + $messageFile = $this->generateTmpFilename(); + file_put_contents($messageFile, $message->toString()); + + $outputFile = $this->generateTmpFilename(); + + $this->assertMessageHeaders($message, $originalMessage); + $this->assertTrue( + openssl_pkcs7_decrypt( + $messageFile, + $outputFile, + 'file://'.$this->samplesDir.'encrypt.crt', + 'file://'.$this->samplesDir.'encrypt.key' + ), + sprintf('Decryption of the message failed. Internal error "%s".', openssl_error_string()) + ); + $this->assertEquals(str_replace("\r", '', $originalMessage->toString()), str_replace("\r", '', file_get_contents($outputFile))); + } +} diff --git a/src/Symfony/Component/Mime/Tests/Crypto/SMimeSignerTest.php b/src/Symfony/Component/Mime/Tests/Crypto/SMimeSignerTest.php new file mode 100644 index 0000000000000..ab645b3ce6132 --- /dev/null +++ b/src/Symfony/Component/Mime/Tests/Crypto/SMimeSignerTest.php @@ -0,0 +1,163 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Symfony\Component\Mime\Tests\Crypto; + +use Symfony\Component\Mime\Crypto\SMimeEncrypter; +use Symfony\Component\Mime\Crypto\SMimeSigner; +use Symfony\Component\Mime\Email; +use Symfony\Component\Mime\Header\Headers; +use Symfony\Component\Mime\Message; +use Symfony\Component\Mime\Part\TextPart; + +class SMimeSignerTest extends SMimeTestCase +{ + public function testSignedMessage() + { + $message = new Message( + (new Headers()) + ->addDateHeader('Date', new \DateTime('2019-04-07 10:36:30', new \DateTimeZone('Europe/Paris'))) + ->addMailboxListHeader('From', ['fabien@symfony.com']), + new TextPart('content') + ); + + $signer = new SMimeSigner($this->samplesDir.'sign.crt', $this->samplesDir.'sign.key'); + $signedMessage = $signer->sign($message); + + $this->assertMessageSignatureIsValid($signedMessage, $message); + } + + public function testSignEncryptedMessage() + { + $message = (new Email()) + ->date(new \DateTime('2019-04-07 10:36:30', new \DateTimeZone('Europe/Paris'))) + ->to('fabien@symfony.com') + ->subject('Testing') + ->from('noreply@example.com') + ->text('El Barto was not here'); + + $message->getHeaders()->addIdHeader('Message-ID', 'some@id'); + + $encrypter = new SMimeEncrypter($this->samplesDir.'encrypt.crt'); + $encryptedMessage = $encrypter->encrypt($message); + + $signer = new SMimeSigner($this->samplesDir.'sign.crt', $this->samplesDir.'sign.key'); + $signedMessage = $signer->sign($encryptedMessage); + + $this->assertMessageSignatureIsValid($signedMessage, $message); + } + + public function testSignedMessageWithPassphrase() + { + $message = new Message( + (new Headers()) + ->addDateHeader('Date', new \DateTime('2019-04-07 10:36:30', new \DateTimeZone('Europe/Paris'))) + ->addMailboxListHeader('From', ['fabien@symfony.com']), + new TextPart('content') + ); + + $signer = new SMimeSigner($this->samplesDir.'sign3.crt', $this->samplesDir.'sign3.key', 'symfony-rocks'); + $signedMessage = $signer->sign($message); + + $this->assertMessageSignatureIsValid($signedMessage, $message); + } + + public function testProperSerialiable() + { + $message = (new Email()) + ->date(new \DateTime('2019-04-07 10:36:30', new \DateTimeZone('Europe/Paris'))) + ->to('fabien@symfony.com') + ->subject('Testing') + ->from('noreply@example.com') + ->text('El Barto was not here'); + + $message->getHeaders()->addIdHeader('Message-ID', 'some@id'); + + $signer = new SMimeSigner($this->samplesDir.'sign.crt', $this->samplesDir.'sign.key'); + $signedMessage = $signer->sign($message); + + $restoredMessage = unserialize(serialize($signedMessage)); + + self::assertSame($this->iterableToString($signedMessage->toIterable()), $this->iterableToString($restoredMessage->toIterable())); + self::assertSame($signedMessage->toString(), $restoredMessage->toString()); + + $this->assertMessageSignatureIsValid($restoredMessage, $message); + } + + public function testSignedMessageWithBcc() + { + $message = (new Email()) + ->date(new \DateTime('2019-04-07 10:36:30', new \DateTimeZone('Europe/Paris'))) + ->addBcc('fabien@symfony.com', 's.stok@rollerscapes.net') + ->subject('I am your sign of fear') + ->from('noreply@example.com') + ->text('El Barto was not here'); + + $signer = new SMimeSigner($this->samplesDir.'sign.crt', $this->samplesDir.'sign.key'); + $signedMessage = $signer->sign($message); + + $this->assertMessageSignatureIsValid($signedMessage, $message); + } + + public function testSignedMessageWithAttachments() + { + $message = new Email((new Headers()) + ->addDateHeader('Date', new \DateTime('2019-04-07 10:36:30', new \DateTimeZone('Europe/Paris'))) + ->addMailboxListHeader('From', ['fabien@symfony.com']) + ); + $message->html($content = 'html content '); + $message->text('text content'); + $message->attach(fopen(__DIR__.'/../Fixtures/mimetypes/test', 'r')); + $message->attach(fopen(__DIR__.'/../Fixtures/mimetypes/test.gif', 'r'), 'test.gif'); + + $signer = new SMimeSigner($this->samplesDir.'sign.crt', $this->samplesDir.'sign.key'); + + $signedMessage = $signer->sign($message); + $this->assertMessageSignatureIsValid($signedMessage, $message); + } + + public function testSignedMessageExtraCerts() + { + $message = new Message( + (new Headers()) + ->addDateHeader('Date', new \DateTime('2019-04-07 10:36:30', new \DateTimeZone('Europe/Paris'))) + ->addMailboxListHeader('From', ['fabien@symfony.com']), + new TextPart('content') + ); + + $signer = new SMimeSigner( + $this->samplesDir.'sign.crt', + $this->samplesDir.'sign.key', + null, + $this->samplesDir.'intermediate.crt', + PKCS7_DETACHED + ); + $signedMessage = $signer->sign($message); + + $this->assertMessageSignatureIsValid($signedMessage, $message); + } + + private function assertMessageSignatureIsValid(Message $message, Message $originalMessage): void + { + $messageFile = $this->generateTmpFilename(); + $messageString = $message->toString(); + file_put_contents($messageFile, $messageString); + + $this->assertMessageHeaders($message, $originalMessage); + $this->assertTrue(openssl_pkcs7_verify($messageFile, 0, $this->generateTmpFilename(), [$this->samplesDir.'ca.crt']), sprintf('Verification of the message %s failed. Internal error "%s".', $messageFile, openssl_error_string())); + + if (false === strpos($messageString, 'enveloped-data')) { + // Tamper to ensure it actually verified + file_put_contents($messageFile, str_replace('Content-Transfer-Encoding: ', 'Content-Transfer-Encoding: ', $messageString)); + $this->assertFalse(openssl_pkcs7_verify($messageFile, 0, $this->generateTmpFilename(), [$this->samplesDir.'ca.crt']), sprintf('Verification of the message failed. Internal error "%s".', openssl_error_string())); + } + } +} diff --git a/src/Symfony/Component/Mime/Tests/Crypto/SMimeTestCase.php b/src/Symfony/Component/Mime/Tests/Crypto/SMimeTestCase.php new file mode 100644 index 0000000000000..f562f187f20eb --- /dev/null +++ b/src/Symfony/Component/Mime/Tests/Crypto/SMimeTestCase.php @@ -0,0 +1,73 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Symfony\Component\Mime\Tests\Crypto; + +use PHPUnit\Framework\TestCase; +use Symfony\Component\Mime\Exception\RuntimeException; +use Symfony\Component\Mime\Message; +use Symfony\Component\Mime\RawMessage; + +abstract class SMimeTestCase extends TestCase +{ + protected $samplesDir; + + protected function setUp(): void + { + $this->samplesDir = str_replace('\\', '/', realpath(__DIR__.'/../').'/_data/'); + } + + protected function generateTmpFilename(): string + { + return stream_get_meta_data(tmpfile())['uri']; + } + + protected function normalizeFilePath(string $path): string + { + if (!file_exists($path)) { + throw new RuntimeException(sprintf('File does not exist: %s', $path)); + } + + return str_replace('\\', '/', realpath($path)); + } + + protected function iterableToString(iterable $iterable): string + { + $string = ''; + + // Can't use iterator_to_array as the generators are merged internally, + // leading to overwritten keys + foreach ($iterable as $chunk) { + $string .= $chunk; + } + + return $string; + } + + protected function assertMessageHeaders(Message $message, RawMessage $originalMessage): void + { + $messageString = $message->toString(); + self::assertNotContains('Bcc: ', $messageString, '', true); + + if (!$originalMessage instanceof Message) { + return; + } + + if ($originalMessage->getHeaders()->has('Bcc')) { + self::assertEquals($originalMessage->getHeaders()->get('Bcc'), $message->getHeaders()->get('Bcc')); + } + + if ($originalMessage->getHeaders()->has('Subject')) { + self::assertEquals($originalMessage->getHeaders()->get('Subject'), $message->getPreparedHeaders()->get('Subject')); + self::assertContains('Subject:', $messageString, '', true); + } + } +} diff --git a/src/Symfony/Component/Mime/Tests/_data/ca.crt b/src/Symfony/Component/Mime/Tests/_data/ca.crt new file mode 100644 index 0000000000000..bca02b3acc4ed --- /dev/null +++ b/src/Symfony/Component/Mime/Tests/_data/ca.crt @@ -0,0 +1,19 @@ +-----BEGIN CERTIFICATE----- +MIIDFDCCAfwCCQDaMw8tuy1dgDANBgkqhkiG9w0BAQsFADBMMRcwFQYDVQQDDA5T +eW1mb255TWltZSBDQTEUMBIGA1UECgwLU3ltZm9ueU1pbWUxDjAMBgNVBAcMBVBh +cmlzMQswCQYDVQQGEwJGUjAeFw0xOTA0MTkxNDIwMTFaFw0yMzA0MTgxNDIwMTFa +MEwxFzAVBgNVBAMMDlN5bWZvbnlNaW1lIENBMRQwEgYDVQQKDAtTeW1mb255TWlt +ZTEOMAwGA1UEBwwFUGFyaXMxCzAJBgNVBAYTAkZSMIIBIjANBgkqhkiG9w0BAQEF +AAOCAQ8AMIIBCgKCAQEAnvxOWE8qOVkuYbTu6u4Oao2n91FPF6umrcF8mq0uD2G0 +dtOJuFaR7FeElmJnHfWvqvesCigXyA7kpdVBFGhEo83SGYTbPSGzehWDc7Kvc321 +UPvNb61T2Ekdo+5ufrpbzlOPtTTaVL98dFEZntYNM3CXnnSSdeKz38NlHHV3QsDZ +crQRMxHrYi2bgkhxVoAY03ZQRbb95rEE1cfyGZ0x6VSBrVC2nnEUT2vopwny/vy+ +QSn3oga+ucMkxJdoD8MA13Zh5I4Uiozl82xoWH/zmVrqrrO2lNBv7WYOnwbv6MSr +5kCE3Kcqzs8qAGv62GYyS4exIMEZsbbPv3cvp9hgYQIDAQABMA0GCSqGSIb3DQEB +CwUAA4IBAQBuJtPqAX6ApOymDux9sRqxx5FMIIEX2TmanSSSLesP0AVVLv8Am8/p +Xs8N9e49KoQhnQ3FmdtwY6IV6f3yIMnZxmkXZoUi4zCkSZd/+2iap1c51zV1b6NC +4C5LZtdWzhons4jOmtmxaMSy08oPPYv1wXATjjfHvqqYa/7axLY1mqbxLYC437Fv +H5zkdzQM2qXpIgtCjlXfOd/L9Az5DTSH4UvWiiocRdmnxGP+nMEOuUUvLzokJSeq +Otw4gjxczF8NQ/g/io6iG3w4OfjgRrCpuMv/l3eYClC7vDXOX9S172CpzaD/qkHM +NFxckxTgT4ylmivmHZWym4xS1bkAAAsd +-----END CERTIFICATE----- diff --git a/src/Symfony/Component/Mime/Tests/_data/ca.key b/src/Symfony/Component/Mime/Tests/_data/ca.key new file mode 100644 index 0000000000000..4832a1d6692d4 --- /dev/null +++ b/src/Symfony/Component/Mime/Tests/_data/ca.key @@ -0,0 +1,27 @@ +-----BEGIN RSA PRIVATE KEY----- +MIIEowIBAAKCAQEAnvxOWE8qOVkuYbTu6u4Oao2n91FPF6umrcF8mq0uD2G0dtOJ +uFaR7FeElmJnHfWvqvesCigXyA7kpdVBFGhEo83SGYTbPSGzehWDc7Kvc321UPvN +b61T2Ekdo+5ufrpbzlOPtTTaVL98dFEZntYNM3CXnnSSdeKz38NlHHV3QsDZcrQR +MxHrYi2bgkhxVoAY03ZQRbb95rEE1cfyGZ0x6VSBrVC2nnEUT2vopwny/vy+QSn3 +oga+ucMkxJdoD8MA13Zh5I4Uiozl82xoWH/zmVrqrrO2lNBv7WYOnwbv6MSr5kCE +3Kcqzs8qAGv62GYyS4exIMEZsbbPv3cvp9hgYQIDAQABAoIBAD/Y1WGzkSJsxSqp +7dTc+18hOlYhCiFYZtyaun6nk7rLoxyhQUqNQZbnYrC+HekzNHP1eNqvVTWbfYl3 +heY7JW2fB4QGDcGUGi6qGxtIpBs+XaWDKfJyahyO6F9gLnGoR5wphKnh6thj+ggA +Vciq76w7yDfzWqoK+++d2ao/JkDg7YrpOQonfceYgjTtiXXFDV4cm4GgKr7gWolt +AqZbHcbH6pmbwRduT+g5QjsYmYPven/ji6Mr2eTFwE0qjlwj4LHlEWuKgpwAnLc/ +jzdnx3UjRGTbiMnbxrv4sHApW9Bb02aRWHVG3axkxWFyWefKuGRvXUZAguGvMpeq +Ng6Jc9ECgYEA0YpHxa32IFRzkOC7Vs79uKWmkbiYZihSrAyCG7Xo5rxTtB5HUcB+ +qIrFU2t2OSDffrRS5C6Ewpw3kBgYElsoYyqL/h1Kb+SQzZVwgK3PAF9p4mcgzyCU +Q25Nqy2CyX3gZblQMK6ui5aI7ZC3WE2wl8fxAneZOtHEEw2e0DaiUP0CgYEAwjx+ +gQr+NHFbDSfhh1IdIz+kGBgR+TS0OIjE2/Mb5IUfDzMsWGo0JEpTH1ma+e7VrxCC +9o47dvz5PXlHAuxsgLEXN7NEPqhiluAbTG/YEpsYeqftqKJsFROmFa3TDeEp3LGz +2OVY/uZjxNVVfljS/weGhOXGfATwQQoAUFbEzDUCgYEAznRsmvz4EIqlAw4qBzIT +EydDozg6EA2Sxynb1+m3+/96iXF727TKFs4D9llfNpKJIpIRSfn7nLPGmxbiQNPI +S0zUeh/qA600bxraqi6WUkuwS/5IeUwkSPwZUpuYzWZU/mVD+XNjTu2XJFr+Cuch +I6tAb6nfM/ESO6Oj4oqyCxECgYBsXr4iF1UPQ3OOmoKtMnZJVVejjcJxbSNkK4LS +SQh17oQOwflq9w5SdRl9c0wRSFz2iNrY3zB0Sd5xmvmwuuIqxyNyE1XvM5mWHkF8 +2yYN83Sr8oeZv81X0ReoHsyTgN4PYSI70HJf/YEKsBA8JyjJ25QFEAI27bZyQzc7 +m72/RQKBgEtyibh8X7DC9B3oVMZAX1BJJDzDSH1RyRaoa+7nARSl90qJD877NZ8o +jteoRFNJJzruADouffK+lTlMtwdfQJQW4wGYGiyr1S5dKXNsPmcnKCj7HbvBphVA +oCzZi3txFcOmH4IZ5HA0VxvGViQwV7fyl5ch7XVqSFOeFaa6lIF5 +-----END RSA PRIVATE KEY----- diff --git a/src/Symfony/Component/Mime/Tests/_data/ca.srl b/src/Symfony/Component/Mime/Tests/_data/ca.srl new file mode 100644 index 0000000000000..8543646d2c208 --- /dev/null +++ b/src/Symfony/Component/Mime/Tests/_data/ca.srl @@ -0,0 +1 @@ +C51E36445BB0C79B diff --git a/src/Symfony/Component/Mime/Tests/_data/create-cert.sh b/src/Symfony/Component/Mime/Tests/_data/create-cert.sh new file mode 100755 index 0000000000000..3f36d2f1a1e04 --- /dev/null +++ b/src/Symfony/Component/Mime/Tests/_data/create-cert.sh @@ -0,0 +1,52 @@ +#!/bin/sh + +openssl genrsa -out ca.key 2048 +openssl req -x509 -new -nodes -key ca.key -days 1460 -subj '/CN=SymfonyMime CA/O=SymfonyMime/L=Paris/C=FR' -out ca.crt +openssl x509 -in ca.crt -clrtrust -out ca.crt + +## Sign + +openssl genrsa -out sign.key 2048 +openssl req -new -key sign.key -subj '/CN=fabien@symfony.com/O=SymfonyMime/L=Paris/C=FR/emailAddress=fabien@symfony.com' -out sign.csr +openssl x509 -req -in sign.csr -CA ca.crt -CAkey ca.key -out sign.crt -days 1460 -addtrust emailProtection +openssl x509 -in sign.crt -clrtrust -out sign.crt + +rm sign.csr + +openssl genrsa -out intermediate.key 2048 +openssl req -new -key intermediate.key -subj '/CN=SymfonyMime Intermediate/O=SymfonyMime/L=Paris/C=FR' -out intermediate.csr +openssl x509 -req -in intermediate.csr -CA ca.crt -CAkey ca.key -set_serial 01 -out intermediate.crt -days 1460 +openssl x509 -in intermediate.crt -clrtrust -out intermediate.crt + +rm intermediate.csr + +openssl genrsa -out sign2.key 2048 +openssl req -new -key sign2.key -subj '/CN=SymfonyMime-User2/O=SymfonyMime/L=Paris/C=FR' -out sign2.csr +openssl x509 -req -in sign2.csr -CA intermediate.crt -CAkey intermediate.key -set_serial 01 -out sign2.crt -days 1460 -addtrust emailProtection +openssl x509 -in sign2.crt -clrtrust -out sign2.crt + +rm sign2.csr + +### Sign with passphrase +openssl genrsa -aes256 -passout pass:symfony-rocks -out sign3.key 2048 +openssl req -new -key sign3.key -passin pass:symfony-rocks -subj '/CN=SymfonyMime-User3/O=SymfonyMime/L=Paris/C=FR' -out sign3.csr +openssl x509 -req -in sign3.csr -CA ca.crt -CAkey ca.key -out sign3.crt -days 1460 -addtrust emailProtection +openssl x509 -in sign3.crt -clrtrust -out sign3.crt + +rm sign3.csr + +## Encrypt + +openssl genrsa -out encrypt.key 2048 +openssl req -new -key encrypt.key -subj '/CN=SymfonyMime-User/O=SymfonyMime/L=Paris/C=FR' -out encrypt.csr +openssl x509 -req -in encrypt.csr -CA ca.crt -CAkey ca.key -CAcreateserial -out encrypt.crt -days 1460 -addtrust emailProtection +openssl x509 -in encrypt.crt -clrtrust -out encrypt.crt + +rm encrypt.csr + +openssl genrsa -out encrypt2.key 2048 +openssl req -new -key encrypt2.key -subj '/CN=SymfonyMime-User2/O=SymfonyMime/L=Paris/C=FR' -out encrypt2.csr +openssl x509 -req -in encrypt2.csr -CA ca.crt -CAkey ca.key -CAcreateserial -out encrypt2.crt -days 1460 -addtrust emailProtection +openssl x509 -in encrypt2.crt -clrtrust -out encrypt2.crt + +rm encrypt2.csr diff --git a/src/Symfony/Component/Mime/Tests/_data/encrypt.crt b/src/Symfony/Component/Mime/Tests/_data/encrypt.crt new file mode 100644 index 0000000000000..e8a5a7c242217 --- /dev/null +++ b/src/Symfony/Component/Mime/Tests/_data/encrypt.crt @@ -0,0 +1,19 @@ +-----BEGIN CERTIFICATE----- +MIIDFjCCAf4CCQDFHjZEW7DHmjANBgkqhkiG9w0BAQUFADBMMRcwFQYDVQQDDA5T +eW1mb255TWltZSBDQTEUMBIGA1UECgwLU3ltZm9ueU1pbWUxDjAMBgNVBAcMBVBh +cmlzMQswCQYDVQQGEwJGUjAeFw0xOTA0MTkxNDIwMTdaFw0yMzA0MTgxNDIwMTda +ME4xGTAXBgNVBAMMEFN5bWZvbnlNaW1lLVVzZXIxFDASBgNVBAoMC1N5bWZvbnlN +aW1lMQ4wDAYDVQQHDAVQYXJpczELMAkGA1UEBhMCRlIwggEiMA0GCSqGSIb3DQEB +AQUAA4IBDwAwggEKAoIBAQCxnMT1TGmWhBp4K6IKztiplKVsdoYvi8JsflTpBHiw +/tLB3ikytItSADuqb/aEX/upgpvPQNJWa0Gf7f9yOQ0CekhTsNtP+o7UA9LtGrcI +lM1szBoaVhjpBgBAyP5OXcK7pOSRmUgp+vD/I9TRdRdzwwoJzvb35gpWGNZJ3WF0 +k9z4KqjdJDpQ7QBcEwZXVr8z5VnQ3gl8olY0AyN9Dh6B52uejGd1fBHf5v+hAR+5 +A0AAOOsTCa4kSXU2KaX9fNd0z/oK+GowfYtfrcCCVLaA6rmEGATQ9meGb54VBFVY +xarMX0ZY+0C3r8a9h8dJ9qxisMWksKLW8mE97/CclNHlAgMBAAEwDQYJKoZIhvcN +AQEFBQADggEBAAP4r76F+5EF+wgOvDlDU+KYXI4LfAy/yIvI5cDOLh65iAwgSWKX +HQPBDzPbQoJaTwj4XPwc4Ygrk7yftgcdYXRm5GWs5pp7DvSfskaX7TSuvNHt0M2A +gAo/rPH5BXp0/C+zgcmFVL067uhB10YHgsrX1ppLFPOsWvXNGAsKA4Qt2pxquI/g +UpNoucZ45Y1+idUq99jQr7sXdL3o5o1LLUdI64vrV/y2AYhUGn+NJvz1bXsp5NIV +jfBaYrAdZ4BMOF6gDMaJekI4PMcoH9sJFr1OIcKnk+UlGir+gAuaQGjKjOKjhB2r +KpZ7PMSJTC+bJYl3KVoIjBJ9/Bf1yjygb38= +-----END CERTIFICATE----- diff --git a/src/Symfony/Component/Mime/Tests/_data/encrypt.key b/src/Symfony/Component/Mime/Tests/_data/encrypt.key new file mode 100644 index 0000000000000..b7d1e915aeeec --- /dev/null +++ b/src/Symfony/Component/Mime/Tests/_data/encrypt.key @@ -0,0 +1,27 @@ +-----BEGIN RSA PRIVATE KEY----- +MIIEowIBAAKCAQEAsZzE9UxploQaeCuiCs7YqZSlbHaGL4vCbH5U6QR4sP7Swd4p +MrSLUgA7qm/2hF/7qYKbz0DSVmtBn+3/cjkNAnpIU7DbT/qO1APS7Rq3CJTNbMwa +GlYY6QYAQMj+Tl3Cu6TkkZlIKfrw/yPU0XUXc8MKCc729+YKVhjWSd1hdJPc+Cqo +3SQ6UO0AXBMGV1a/M+VZ0N4JfKJWNAMjfQ4egedrnoxndXwR3+b/oQEfuQNAADjr +EwmuJEl1Niml/XzXdM/6CvhqMH2LX63AglS2gOq5hBgE0PZnhm+eFQRVWMWqzF9G +WPtAt6/GvYfHSfasYrDFpLCi1vJhPe/wnJTR5QIDAQABAoIBADhp4uVG8AKu0vl4 +Ym+sY4T5gdGBk/1mFsr/FVkt4mfViHurZMqGLfpNuKXaCiLhmb2tjm+11xk72AxE +O+670DYJQQ/UDNTKcLNGw6gr5BcFrHnyGhhjYGYjUdFCBgQ+I6wWI8NbPGCZJBLl +/qLI3joWqQmUgz0aBA50tRuhBWNRS9lNDfoPpibzFNjkxMzb3X3KdbsTfpH7Ocj/ +bOBuS1mnsm/xh30RzN0w/2yIzpxX4XvGy5eftMLWZY22NkbnDgGbGHDvNR3mjKkZ +8QF4Urx86VnfTnA6f0m/QS3YXEWk7RxUEGjzwIRv+6FcY+mFEsehWnly2KP3TG3S +65Z2SgECgYEA6Fe2NdjRbzBCukGa4/fZyrCggQq6Pr448QcyQEenf/X9CulroPtH +OiiIDuU6mCOBQVHp1FiCtZQT9hTfMszrhy7AMtJQncmQkMcbslEd8JgvDj4Jw64u +HcnKupNxfVew+at2u+GA4w88ntXxrcNl8Mde7aPnytAyUWPGsbKcCpkCgYEAw7Jy +yR2KFW0YhIePL1cEzA5J62Yy0yM8MJXHXshy3v1qU9LKsdVk7fbB9UojEnEGcu2R +T2sW2wQqxIo442KUmStisTtQ8pyAOyQyfzIVRSlHTh4BKlDp8SMuGdnOibavttHK +q/RgeOiXXG0Yfpf3sKDHSmQv7TGlsI07O6Z0vS0CgYEAgbc+jk+PlgEer/girrXY +jTYRVhoUIyV2ivKWlpaqqGFAtg/dvBGuEYVBePd3wCrKZhqCbsA/sXqLrm62shkA +QgfS3EzZH07CfGH9T4/EJGgClXQDZZFgQ9c+bO4WhYEo2CtnbbuXhq0iDheqB3Y4 ++rWEhS5mIbAc952598mdHrkCgYARF5jm7+mLjYfCq4RaAiOtHuJd6QMvZbhwFeTf +5moCB+gtgg+qEJVMI201W1BM4ApMJ2u1oAjTAD4sBFaLpaSM7DkmeaPMTNb2U2cF +rP4mmEBeFkjLxV1pbkUshNWBOa+HLDOjaSiz5ryxmeW1yNgdWS2O1clJ0jhCf1NZ +FmTD0QKBgGYjCX6vZl+aEchm3Ie18Vp8cNUu9CYAiDiDzEwgxgiTfRCIJywWjv5v +ll4lqtMgsrDrmI8fBFq4BKytMFvgPqW0sI7U4Fu1vArFeyTwCgfR8VMO7L+qvbWE +MKKKTeO8aTjTiNJ3b/eIkFDAKU+yQOhVR3VqbduqEeVtxRgzMOIh +-----END RSA PRIVATE KEY----- diff --git a/src/Symfony/Component/Mime/Tests/_data/encrypt2.crt b/src/Symfony/Component/Mime/Tests/_data/encrypt2.crt new file mode 100644 index 0000000000000..d3ba774435364 --- /dev/null +++ b/src/Symfony/Component/Mime/Tests/_data/encrypt2.crt @@ -0,0 +1,19 @@ +-----BEGIN CERTIFICATE----- +MIIDFzCCAf8CCQDFHjZEW7DHmzANBgkqhkiG9w0BAQUFADBMMRcwFQYDVQQDDA5T +eW1mb255TWltZSBDQTEUMBIGA1UECgwLU3ltZm9ueU1pbWUxDjAMBgNVBAcMBVBh +cmlzMQswCQYDVQQGEwJGUjAeFw0xOTA0MTkxNDIwMjFaFw0yMzA0MTgxNDIwMjFa +ME8xGjAYBgNVBAMMEVN5bWZvbnlNaW1lLVVzZXIyMRQwEgYDVQQKDAtTeW1mb255 +TWltZTEOMAwGA1UEBwwFUGFyaXMxCzAJBgNVBAYTAkZSMIIBIjANBgkqhkiG9w0B +AQEFAAOCAQ8AMIIBCgKCAQEAvGX70bC9IIjPKIGN3FKR3wNHD5UdXhgEWpMDuQeA +gZ01LRc+tTactRMsuI3lTXCGOmU+kXpT03GcUEB4sP4ykSw04umDn8UbZ0o9WfzW +8c2Es3iYY/sDr4f7KUMaGqrARZrA9mJM4jvT49lOVWoiyzZ2Jgx2gDtFyCEW1b+0 +Hqnx4zjhBlCfe6XLpGgEtMwZ9tcmV96BBmlNVNHJbjiSqrsE97FTxxXzQgAmYDRc +qVAZicNcoNlDo/nV9A0n5ygA2Mgx6LF0HUAjf9YRXvRQ4BARtDJV9q/dzu5zxolS +mZOWxdlaCkTbeITGmRJNRl6BJiQu5kFRmzTO/Egt6bd5DwIDAQABMA0GCSqGSIb3 +DQEBBQUAA4IBAQAO6gTF27+s2CaCFE9VOHsqr/+9Rj3jYXefPD1NR4VU7fARXOGA +dgXW4PhNs2yfgBG2YJwK0uHRsLLwosh6KXZeyBm5XGT8QnzGVj/pZFJKuY0iIK9y +v4liJkLRKfUNPNEW214c3wcgd7chSOM6eV8rJFtnNyju4LnfnnNGFT2w48rccAyU +ZsL3BsQ40b/RUqBB12rNoKRyzmLVhdkTU/gTPYAVz9VQqtGXmYrqYQNuyenOYWV9 +ttQHUD7jszGNtyjNKMmo422QMZzTx38YJ+aR5PfW/arkW3RJPpSn5ClbnH1TSmCd +oFHODRxroV7eu+L2fQMmHtcbXKCTWg7lfvgW +-----END CERTIFICATE----- diff --git a/src/Symfony/Component/Mime/Tests/_data/encrypt2.key b/src/Symfony/Component/Mime/Tests/_data/encrypt2.key new file mode 100644 index 0000000000000..2f58e199390e4 --- /dev/null +++ b/src/Symfony/Component/Mime/Tests/_data/encrypt2.key @@ -0,0 +1,27 @@ +-----BEGIN RSA PRIVATE KEY----- +MIIEowIBAAKCAQEAvGX70bC9IIjPKIGN3FKR3wNHD5UdXhgEWpMDuQeAgZ01LRc+ +tTactRMsuI3lTXCGOmU+kXpT03GcUEB4sP4ykSw04umDn8UbZ0o9WfzW8c2Es3iY +Y/sDr4f7KUMaGqrARZrA9mJM4jvT49lOVWoiyzZ2Jgx2gDtFyCEW1b+0Hqnx4zjh +BlCfe6XLpGgEtMwZ9tcmV96BBmlNVNHJbjiSqrsE97FTxxXzQgAmYDRcqVAZicNc +oNlDo/nV9A0n5ygA2Mgx6LF0HUAjf9YRXvRQ4BARtDJV9q/dzu5zxolSmZOWxdla +CkTbeITGmRJNRl6BJiQu5kFRmzTO/Egt6bd5DwIDAQABAoIBACtOojFUmFUXPc+I +4GxKCsAiB768P1D24mFTtCJfaBnjYmroEgEj+afiLYCLFa/UcvaPeW+FmCldz1nf +SB8ff85BRDL5DMm4TJFUzn+WEG7rGFsNGLK66+D4uDKG+0QwBhy58ytv8056BD43 +ILuftznRXh1m9gKKHYNgn9goxiXZ816WYgtNDyYw8kgb9v79VKQRqePW60ZcgquD +THmJWz3eO1Ewurbr4PfrhDtCUcHzz0GRDY0QATCUrAfyl4YbzHrsjnxy4fRq4dXb +01eYZjoD4wchbWOrIMV72urF/KGWYljwOQjwgRgY9q54VrM/Rgga6jj4gWNXLPwn +LN1+/AECgYEA9mnNjNMxAn5sOJkhN430DAv/MSheu0yrNsY3iMjrLJcoVpTxvmos +NxpjWETZFA0T4Yae1VtQjn3LGo1PWJ7j7bCyYdwxuVMHYjCTB107xYg977pMBa37 +6yoN9aZ97p/FeFrOmIoRCO1Xlyu32nhMVBtVCw8TRCks0VuE1gJ84gECgYEAw7pe +7iUaPFzPHzxQc53BcWNEnKSvsNYbiEHLad+kbH76VeVWyf8M6ZSdVE38h7wawYfN +UXPmB2+7ESvvWnXV8zKJCRPMt9ytzH7UxJVCPepvTO8rWPLldUJS3a7sbB9pFFGc +WkPvnKGsnqf6mtj7IO/O4SluR7M9qosg0lxQOw8CgYBzOeqKrb8/QUrt9H1Z8yFp ++LoujIgv4Zw2kt4pMnr2cQDF7ARXXGKsqcRG5Hr2K19emIrxji/PUfeFxQqTkElZ +PsVLiaIe3TqYqco3KVvn9NuxnFYsWb1xrEq20lIVIdU/gIcXQYjRudq5sBHbMWHP ++q/76eLCftacV8V4JdWsAQKBgHYOsjfetUZ3jI8AqF40Z3vnLnl1dGurmYvEc9d2 +iAzRQloRLRpF9xnlBEjXiVyt/02Ahj19NOCDakhfQc5EiTpZ3wJUqQS13TcdwWSZ +ywzhnSTAllrel7z0tlr0qbJF9/HDkBV6KMtHUYGZPLWt7zvcqeJyRQyGdsmphbCc +8d/NAoGBAJ1ahF7h9ezHs60EJ3AxDoA3SHfv9DM5lyz4Kahr7gxBeENkdD6vP+JC +E5LVlen6SgdNg2LDY6rcYm8uHT8Agf234FcTiq4IbiKuRu/QbdPXjN/LrXPFmjgw +hPaPjrm2jSDBdaHlO/wFUq2Oo8hSlWrqHiUCTLg/TfkGegYL+RUc +-----END RSA PRIVATE KEY----- diff --git a/src/Symfony/Component/Mime/Tests/_data/intermediate.crt b/src/Symfony/Component/Mime/Tests/_data/intermediate.crt new file mode 100644 index 0000000000000..cf9c422aba4a4 --- /dev/null +++ b/src/Symfony/Component/Mime/Tests/_data/intermediate.crt @@ -0,0 +1,19 @@ +-----BEGIN CERTIFICATE----- +MIIDFjCCAf4CAQEwDQYJKoZIhvcNAQEFBQAwTDEXMBUGA1UEAwwOU3ltZm9ueU1p +bWUgQ0ExFDASBgNVBAoMC1N5bWZvbnlNaW1lMQ4wDAYDVQQHDAVQYXJpczELMAkG +A1UEBhMCRlIwHhcNMTkwNDE5MTQyMDEzWhcNMjMwNDE4MTQyMDEzWjBWMSEwHwYD +VQQDDBhTeW1mb255TWltZSBJbnRlcm1lZGlhdGUxFDASBgNVBAoMC1N5bWZvbnlN +aW1lMQ4wDAYDVQQHDAVQYXJpczELMAkGA1UEBhMCRlIwggEiMA0GCSqGSIb3DQEB +AQUAA4IBDwAwggEKAoIBAQDMvRxMxQyecc1bTVZeRCSjBTEmHFZQ2Taqmk5UwO2T +UGsk4nJRnpFHKqSQJgUX8Lj/Y1sjEM+IWrzVAhCPvsAc5x5mU2smylRKzkTCBUkH +UBrbqRBAHVeWu0W58E6D6zo6kweGD7fX+gtMeJY/pcib9tlGPUaVST1TaXYbZD8f +dWD3cN+32FAUyH+TgCtOwYAcwpQ+Npe8X1P/JHIixZz9Eb2WvtiyYqnEDLhKdS9b +zrUZsknkxUguMdd3n3kOO8scd6PTI8k699hOewtDkR7LPDelxhhIazo3kClQV24f +Dd6ktX8L/sGCG7+YTTRpKB47fdEVtiZjLlyZ0K8ih8BZAgMBAAEwDQYJKoZIhvcN +AQEFBQADggEBAIn7oIEeFGCeAUto5PHv3/hHTqLMZZI+VgSxC7zCKBkH59S+ua/s +8HUPRVbBk8qtApz0kL+p4LeUr0mQIQUXSKeyvp6jplMnrgZ1NXck1D9x14oBesiS +q8aVEfwH2DsyJi/0UE4boIeSlk9I0Jh1JSN2jX+zSF0RYYPrTOJKqBfu3QgLgt9s +PbsgOAcHhmWdwDRdFyu/Ok0pieqcHM3TMOV1DPU1aXKtzkCMOHHWfR2bXnIuw1aT +7koX52/3nq9xQ/17ly7iiZAgTWXC9mlnbgO/izWb2WdXHoLkFPrl8IPi3Enf+lo5 +xbpVMU82bgYtgM/Sm2RYV0vUZ9kp50SYy4M= +-----END CERTIFICATE----- diff --git a/src/Symfony/Component/Mime/Tests/_data/intermediate.key b/src/Symfony/Component/Mime/Tests/_data/intermediate.key new file mode 100644 index 0000000000000..b622a6b48b711 --- /dev/null +++ b/src/Symfony/Component/Mime/Tests/_data/intermediate.key @@ -0,0 +1,27 @@ +-----BEGIN RSA PRIVATE KEY----- +MIIEpQIBAAKCAQEAzL0cTMUMnnHNW01WXkQkowUxJhxWUNk2qppOVMDtk1BrJOJy +UZ6RRyqkkCYFF/C4/2NbIxDPiFq81QIQj77AHOceZlNrJspUSs5EwgVJB1Aa26kQ +QB1XlrtFufBOg+s6OpMHhg+31/oLTHiWP6XIm/bZRj1GlUk9U2l2G2Q/H3Vg93Df +t9hQFMh/k4ArTsGAHMKUPjaXvF9T/yRyIsWc/RG9lr7YsmKpxAy4SnUvW861GbJJ +5MVILjHXd595DjvLHHej0yPJOvfYTnsLQ5Eeyzw3pcYYSGs6N5ApUFduHw3epLV/ +C/7Bghu/mE00aSgeO33RFbYmYy5cmdCvIofAWQIDAQABAoIBAQDMIfWYeZOWWsM0 +uExX2rtoquGRLQnGvHwr54QYLu/xRGo/sWPoCyCwg0zmyHGlqAbb4/VXZgh13HqQ +KunWWIr1hl6iCaQ5XdxjZXvasyhYGT9eKhegxWCyUfA4bufp0dwR0MzclslnltAz +I7wyo5n8H0gNJ0U7zXVOuEThFLd3JWg2oJLfnjgWYi1sq0sA3VTKX2L4iwY+vnlN +d/i4Q09jorR38YZzEFjirc6YgOYHmEa8rx5oAZxEViRyAS/yvPTfvxB6HwxYbF4e +EB95VHNft490diDm0RHO8vaw4G8jpP7r8ObXiqwAoKxb8+AHNy765DmbyXp89eFU +SSRNYgQxAoGBAPjTYiq3jU1ykyyhci/y+T1ix+Jhjy/5WKbogKYalEDFbErEChM7 +zMjQNo92Vl4CgN+CpcY/SBVIZozbsT2nJWCN8FaQnZjNK4BlndN30bCp+Mu3sBDl +jZaOdm4Svif9kXPooG7wTcxadvGb+pRNy8zmZCWej1y9/13/FQdh+L1dAoGBANKk +UJ0wJf8F4jR5PC2Db9JlluVHfPP39d1eGGS/FzfbSbmRZImU2eZI1ItWE0whYF06 +WMULqzdRLdcft/SHux8d832ZyHLqc5t4Xip5QE+XEk26S2ZCcjoOd2Ez4NIN5YNm +veac9udX7oiVX8cKn3zGxyrEHLjIB+XW5Yq+KeMtAoGAEQkv9GrCwuWwS+L11XCW +PeywcMBrNEanGi5a+IRjWBfsNSY85lo2yBzxT1szyJX1SthAD1Wv0r01QDmeZfE2 +ruio5tRZ5edOLilG5/6RHb5VaWU3KcD9s6wnUZv45vYGamAn89CCExayhBJA0ryM +0oeHncfAWwIrJL1dLDc594UCgYEAuSahjWlzHJUJXmJqWP89XUzatDKATNpaDPjW +rEejmv9v8GMyYhSq69Z8rPU+BR8ZWxkcSieVmgwLJRrGUXS1MAbdrjtsjEY01CWb +b+4gb1U1S4lDGWGykgGBQbmeFkUMxtGafojeJj+OdhQGmihmRAFds+Op82owNwEL +x0ab/wkCgYEAuCJQiyRzO/X/jq6CdaClDhCiMW6z5JZced6VZS+6s7aA5vmhcl8f +TAZp7BeHqGscPHfpzY6P7lZmqQL2OWURFFjgJYbRWZtXOYGH8ZhBsGA3uAIwyses +2XxUbSYZ5jNvp7r3GwqIsFFth4QRtGEBMdUgCS2mZkRsW6A5NXmeiKA= +-----END RSA PRIVATE KEY----- diff --git a/src/Symfony/Component/Mime/Tests/_data/sign.crt b/src/Symfony/Component/Mime/Tests/_data/sign.crt new file mode 100644 index 0000000000000..3cdb0cd0131e6 --- /dev/null +++ b/src/Symfony/Component/Mime/Tests/_data/sign.crt @@ -0,0 +1,20 @@ +-----BEGIN CERTIFICATE----- +MIIDOzCCAiMCCQDFHjZEW7DHnjANBgkqhkiG9w0BAQUFADBMMRcwFQYDVQQDDA5T +eW1mb255TWltZSBDQTEUMBIGA1UECgwLU3ltZm9ueU1pbWUxDjAMBgNVBAcMBVBh +cmlzMQswCQYDVQQGEwJGUjAeFw0xOTA1MTIxMjA0MzdaFw0yMzA1MTExMjA0Mzda +MHMxGzAZBgNVBAMMEmZhYmllbkBzeW1mb255LmNvbTEUMBIGA1UECgwLU3ltZm9u +eU1pbWUxDjAMBgNVBAcMBVBhcmlzMQswCQYDVQQGEwJGUjEhMB8GCSqGSIb3DQEJ +ARYSZmFiaWVuQHN5bWZvbnkuY29tMIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIB +CgKCAQEAqCDgfKFvJ1NdE0MmSjiVA6Z8ydmZZBsfAE57q9+2bjepW5qwVmL/Igvz +hjjeWFiFIDuLhKkBFZmDR22pkGm5yZRQY8DDXB3Oz0qXr3tVwY4/Iiq+AQhSQfPw +xA11ahRkU14U1CfPc+XdN+Bfv+iwcX8itlz/auHF5BnwFMWcE0A6UC9/70owayia +rVMEWKuYxHrG89t6p3CgKxBG4gF7uxZhy80qVfJWG5ZcCH57xwD/hgQ0We23H89M +G4cpYDX8FZfjzeaVEikOJ9/RK3P6pb5EHtfsO42s2G+j6MnrVTTIA9g326VLW3Vf +3xIrWpGQbwwvm9wiARhEUV+o7QmdXwIDAQABMA0GCSqGSIb3DQEBBQUAA4IBAQB+ +mQRLFCkuKfq+pPr9a5p5HfxBbVrNveAOEGRsC83aD4vtWT4X2NoE1MkW2n/AgXtv +AmF/duynnRurKGH8k0Fkw5fMEE+GChwwmJk6UxIV5oO6khk05QAua+5dI2c6rf0z +xanXQksuQDjynnUKNbwyMGAUBcWPlpBeyUKThNWGyRgVuM/7nihI77Rqm2WGHRac +RcCoosNXG0othSWzz0hsxuqsPneO0hGAf3UZI/b+gJk9/SJelUvIRStHBoQRB7YZ +y7kXDwcQZS/IkIGDyWxV1KIpZ0Ban5+0awEG1ShUyepy1dV/24frwu3VOgRN4jv4 +2CGR71B5H0zIRjazNERL +-----END CERTIFICATE----- diff --git a/src/Symfony/Component/Mime/Tests/_data/sign.key b/src/Symfony/Component/Mime/Tests/_data/sign.key new file mode 100644 index 0000000000000..68d1d570b689c --- /dev/null +++ b/src/Symfony/Component/Mime/Tests/_data/sign.key @@ -0,0 +1,27 @@ +-----BEGIN RSA PRIVATE KEY----- +MIIEpQIBAAKCAQEAqCDgfKFvJ1NdE0MmSjiVA6Z8ydmZZBsfAE57q9+2bjepW5qw +VmL/IgvzhjjeWFiFIDuLhKkBFZmDR22pkGm5yZRQY8DDXB3Oz0qXr3tVwY4/Iiq+ +AQhSQfPwxA11ahRkU14U1CfPc+XdN+Bfv+iwcX8itlz/auHF5BnwFMWcE0A6UC9/ +70owayiarVMEWKuYxHrG89t6p3CgKxBG4gF7uxZhy80qVfJWG5ZcCH57xwD/hgQ0 +We23H89MG4cpYDX8FZfjzeaVEikOJ9/RK3P6pb5EHtfsO42s2G+j6MnrVTTIA9g3 +26VLW3Vf3xIrWpGQbwwvm9wiARhEUV+o7QmdXwIDAQABAoIBAQCD/gOfdLGqAwVw +SOh3noJGcl9HrKCC+dPVzsfCwIgdcW9xLjlAKMo59X4DIwRUAXLKQlUfGfty9Kke +25YifQ5RljGijsQQvooNLXd2WfKSWVVxQnMWpmzFwHiFwjcqx8WXuaXKhVKVn6GT +63/gTxKul+wtlUckpwlQMZjNBfKpHR56GWTpvvMiEhssGvt601rRj9Dk+f/nWTJo +Qp2Ka2O616/2jF/BuDj7nsK5ePvDotHf4dlRsLLHk8hoqpamByQsepLltvGu4p7U +bAYGOkYJyPtBuLyoYxOBtJrrewUsxo7jEuTfO9j7JHaYqG99QDEWaGlqXGR3481x +emFDVDnBAoGBANaq6mYCkNb84EaR0OzVdj89b5wcECds3UNvGy/h8fx5X9s1Xal2 +EVG976nY4r2wEGKnwCb0qhh94BUmFoxF0iPe3dwlLz9H2ymmWu1v36CMKc92f0UM +3TzeaWrBHdk72PZE8nBTuKkQabboH9LHf2EUrnjNwoY0p9a4uZbLPNi/AoGBAMiA +BKg59MI6GN/9mp+n9D7jdl6ZqhLfYJFGPADRnRPIS89TKywACVNwYCpC2wBRHJ6W +F05BQW2U5ohF2w4n4UODwBadQhP1dg/l40ZO5+BL98Dx8g3bwItCTe25bYtAS0wI +dULj/AR4zdMQCdrh2zzWwPfoNT+6gXfI8V40nsNhAoGBAIvFBw9aVlIUnjZ0lLLP +nck5SCU9xGrXIA3bFrmLhNKdeIMy8QP4Yvh1Ecnl9GQLce+6R4tVvDZsJu2+Oeol +P9ipMI05DNVIBPPOY9+6+sD+4e45uk4MPTR3n+2pRbT+mZpnc+8dI9u4WwyDgMzt +pgtguuTfG+vj9vAAoJ4FQF3jAoGAbmSuK8HdVaOPVqTXodhjzsyGvAd3cPS0wsgc ++YZwKhg6RWjReGR8vgg9qocs9buzOk4BfwDG+YLme1mbBuxGR1ofRVRIsZyQ6Kf2 +vxtq6EBrpTyRvbelCAf1yFI0UluQGcj+Z1oHxJ6PFQrbojyA7bqAfP7JctFJv55P +50Kpt4ECgYEAqjYa3J1YJsK+xTMEG1mAzPZcGG09/Od5Zc7XRY8SkaKwW6eRRu7G +Eq0RuXLW5wxM32sIJyhNqTSchWcntqV/cwvLDmI+JFg3gJ9fNzEdRyHGccBDe7ad +bdR/9n23NVBfaLd6lLszFUQW8efmbzI0HQO1USKRTsFm2TkkcHlafts= +-----END RSA PRIVATE KEY----- diff --git a/src/Symfony/Component/Mime/Tests/_data/sign2.crt b/src/Symfony/Component/Mime/Tests/_data/sign2.crt new file mode 100644 index 0000000000000..c107dfdc193f3 --- /dev/null +++ b/src/Symfony/Component/Mime/Tests/_data/sign2.crt @@ -0,0 +1,19 @@ +-----BEGIN CERTIFICATE----- +MIIDGTCCAgECAQEwDQYJKoZIhvcNAQEFBQAwVjEhMB8GA1UEAwwYU3ltZm9ueU1p +bWUgSW50ZXJtZWRpYXRlMRQwEgYDVQQKDAtTeW1mb255TWltZTEOMAwGA1UEBwwF +UGFyaXMxCzAJBgNVBAYTAkZSMB4XDTE5MDQxOTE0MjAxNloXDTIzMDQxODE0MjAx +NlowTzEaMBgGA1UEAwwRU3ltZm9ueU1pbWUtVXNlcjIxFDASBgNVBAoMC1N5bWZv +bnlNaW1lMQ4wDAYDVQQHDAVQYXJpczELMAkGA1UEBhMCRlIwggEiMA0GCSqGSIb3 +DQEBAQUAA4IBDwAwggEKAoIBAQCuXCpZPt3ikKzhKePg4ra9ynLMyaRZI1PLHJ9G +01XjAJhz1w1yRk7N+AhtEHQK86UwAQLHTOt6XZU62Ifh2yWWkuhDCnO7leQFtJnr +GAzuvXwUfK/Fa+gqmhf0HU5QAnSMmH7w3ViprT2YyoP9aa4G5sD8/DoHBejV4oCE +QFevUuaeKov9rWo81pkREBM8CVkghFIdbbj/gegAmmK2SApkvATx7JCWh3oPtSJ8 +CCuPwLtE9aDfdT7LyuI8x+O8MHVeFB3LvBTOlzPPs43/N8RU7WX1/VTpREIyWC7J +I2bF8V6qLdYknYWm8VMlBlCWj73SuZreUWYesxUFmLrRgLeZAgMBAAEwDQYJKoZI +hvcNAQEFBQADggEBAFQlQzsZfdZ8Z5uZVRM2JG7Ga70cBMd/wS9J/We1ECujgGJD ++smJCONNHmobZswy3EoMaHlUDvUA35gTvEkA+XMXItEfJLPY75j9zRdOZWYI0Y+G +XWt4Bhrh7Dswtci8NUs8TPqJlmLMYJFFEbnxdZr+o2/KIkdVoCjpXM7fa4GLBnD3 +aM59/yclNFCghxGhCYF+nEOoIIet35lxsTC3Pmo/5nDI9fOgjt6yYeiWOM7eHIOJ +G37mWWFODhLnzlA6uRPCjkMzRZnJYiSx7/kJkxqsPJVzIH3vCgHzRnt7JYoKCxqE +nvM0FdQ9+HG4VKggElSdVbKAgt8XjGHeSmVPd+M= +-----END CERTIFICATE----- diff --git a/src/Symfony/Component/Mime/Tests/_data/sign2.key b/src/Symfony/Component/Mime/Tests/_data/sign2.key new file mode 100644 index 0000000000000..ae4ffcbe1ad5a --- /dev/null +++ b/src/Symfony/Component/Mime/Tests/_data/sign2.key @@ -0,0 +1,27 @@ +-----BEGIN RSA PRIVATE KEY----- +MIIEogIBAAKCAQEArlwqWT7d4pCs4Snj4OK2vcpyzMmkWSNTyxyfRtNV4wCYc9cN +ckZOzfgIbRB0CvOlMAECx0zrel2VOtiH4dsllpLoQwpzu5XkBbSZ6xgM7r18FHyv +xWvoKpoX9B1OUAJ0jJh+8N1Yqa09mMqD/WmuBubA/Pw6BwXo1eKAhEBXr1LmniqL +/a1qPNaZERATPAlZIIRSHW24/4HoAJpitkgKZLwE8eyQlod6D7UifAgrj8C7RPWg +33U+y8riPMfjvDB1XhQdy7wUzpczz7ON/zfEVO1l9f1U6URCMlguySNmxfFeqi3W +JJ2FpvFTJQZQlo+90rma3lFmHrMVBZi60YC3mQIDAQABAoIBAGL4/Cz2q5rdBtU1 +Ix5XcuXe0jV+zGSw0fK8h4j7k4gsoV04GHDiif8OqTHHoidJUF4kZMBe4FfwYTIr +EU7aR8bmEyNi/njfx7SZZLl3SHgIZTN354qICxyLpcczD24JRsE8Gup8qsR+CzX8 +1tl1MIzIVYoFXqb36sfmL49iuqNQ2qyrH+OnDKHhBYPrHt8FuhZ1XYyRhtqgjJAD +YMYE6+vA4gwN4Ajk/a9XE05awQTUiLcaXtMxVGB1fejK3xnN/HGOFR8xH5Qi0aSf +vMaJ7rh4fwYjRPQTBVPnm8HA7CVf0dyoCBjK63OJvd+RVj3w4t4/3BeV9VsDVRiT +PFEoJwECgYEA1RZcMkz+Os67e3Ot9NOFReup2PmFhh6PvrqJd0oAlTc/+f6fUI6G +INJNhuCCVg96cw76gfvdN4a3EPgyV708Y16m4EhHpu7jMtGprnbX3Y5H8NjGs62n +ziKw6sCa25xdXFV2c0M0uQVUJAk7sWxpDU3OWkxpmMRPdhbawEdKVyECgYEA0Xk7 +exS2+SRkrveMM2jj6dVZLQ00Tj0WQOovKloUXp9K8ACzXVdgcMeBSQhzQFN1SwAZ +EdEvR9c6dizRHTnfXK+sSMURjMw0e9Fca9vs43oYOW0bIzAzpRJrkh2ZlwDlDuZ0 +ST25nUpCKn7s6eq3XIIs0vNuJNaW2KKIoHqBaXkCgYAHdxkTyg6+ELAQyyS1BxQM +Nw1kRJmg8UEn9XELdNRAZgcfwwPh1pxsWfHNX+AxE6m+ji/IjgJaB6YyOf/Jgx+y +e4ZtJRsdhhD/nsjLC+7UHD/4+B89/D98wUphbw3906SRr4zOzPPz53PjL0+gD6Q+ +ixNHppWsfHQsNvDC+7xnAQKBgHWMi7V5HWjYZGvPXOzomqV45S8j7stM+nT5NfiV +TkL/LwVZz029H9CKFGIQjOR3MSYiau8VrWuqOxNf+QVmmZKgvpSjikKxwW4OQcgB +RYEt3fQz5vurLAAhQx5e3/beOKxQ5MbJDaVXq6O/UGHAJp+SKWdD1fZ0OXheVT+B +H6g5AoGAZBjDmmAca4SMT5nC4Ueh6PlYt0Yr4pMTdkrYTkGxzak6VnRlGg8rmiCP +LSO9vaCoriMSouhVKdBdTjD6lwYxxt4O2HY8D3RgqvU8T7uiI58l2XVdCbs0cBGE +IlNC0CjIiHPWuVhCQk5eLk4WLDvbLq6Oc+8J4BOFupvq3KrGKik= +-----END RSA PRIVATE KEY----- diff --git a/src/Symfony/Component/Mime/Tests/_data/sign3.crt b/src/Symfony/Component/Mime/Tests/_data/sign3.crt new file mode 100644 index 0000000000000..3f907cf4da97e --- /dev/null +++ b/src/Symfony/Component/Mime/Tests/_data/sign3.crt @@ -0,0 +1,19 @@ +-----BEGIN CERTIFICATE----- +MIIDFzCCAf8CCQDFHjZEW7DHnDANBgkqhkiG9w0BAQUFADBMMRcwFQYDVQQDDA5T +eW1mb255TWltZSBDQTEUMBIGA1UECgwLU3ltZm9ueU1pbWUxDjAMBgNVBAcMBVBh +cmlzMQswCQYDVQQGEwJGUjAeFw0xOTA0MjcwOTQ2MDRaFw0yMzA0MjYwOTQ2MDRa +ME8xGjAYBgNVBAMMEVN5bWZvbnlNaW1lLVVzZXIzMRQwEgYDVQQKDAtTeW1mb255 +TWltZTEOMAwGA1UEBwwFUGFyaXMxCzAJBgNVBAYTAkZSMIIBIjANBgkqhkiG9w0B +AQEFAAOCAQ8AMIIBCgKCAQEAyywWINcIgcxT8GUXTx/5Xa7rkwoMh3gwNcuOhbRg +08xupcsHAe3f6pPosqm5xweaPcw2xI+yrkXxmXEE0LU4qi7qgtBZt2GqYKcFEtZw +fh0YV4b2NHSO/CFTY25AtwW9wUW+GHq6yYRqrjVZnP9mEokNclPNS4QWSyaNuIav +jCB9xdDXjIc24zM4TeM5LaaFoH4qZGhp3MkjRadnMrrYsp9a3XKrYlQ5lqaXyVlC +/aKeBZy5qckoFj0Lep6LV2xlipX4+d5tcZ2FATkXjJK834WRzFMAVhYxqFyj/RIY +IoEk/AdYeg3b1HK19flNNQbpHPayiSg3l90ecbaN5vqgLQIDAQABMA0GCSqGSIb3 +DQEBBQUAA4IBAQBd+sTqEPXn5MLXMNRsV9HuP4VkX79K7ThA4kXW0fj7Bp+Mpfvg +LLUXRVcyzAKz2RgxyNIKHPr3u6OxHXbtGL5IgdH74uCR4MN+srKpLiGAMNjtvWBr +sGG3pIfpw4sFfVkj5zLFH9MLVSkKFu7Ub2KfOh310AnSnMOJpjy8a0MqY+iOcpj7 +ioOdPHaSQX7DZrECKozOzcfqryYBOwkbwrh1juhDYzy3WtgxZe1FRl3O3FKLtmAc +J4At8HbMDOBH/fMR4o4B1miP6K9QWc66hsAsgY3GWrmiBf67sf1u6kNeNPBGcviW +fQndtjrUUmwkAAQaFYjUnVEcfx55p8TrLhRC +-----END CERTIFICATE----- diff --git a/src/Symfony/Component/Mime/Tests/_data/sign3.key b/src/Symfony/Component/Mime/Tests/_data/sign3.key new file mode 100644 index 0000000000000..b8b51bd70cbf2 --- /dev/null +++ b/src/Symfony/Component/Mime/Tests/_data/sign3.key @@ -0,0 +1,30 @@ +-----BEGIN RSA PRIVATE KEY----- +Proc-Type: 4,ENCRYPTED +DEK-Info: AES-256-CBC,5485FF78699F76CB93A05FF9CE7FB4FD + +iaLWaPXmnAweLnqtXLk/NwQOUNTRIV1yN9gHo0aR4fWy3GDPa08AJz+pYuDULQDY +RCejCBHeSqH4UFbbRHkYHsOdpjEUWhOy07TesajkW3Kl3At1T7aa3cCjhYSpeWkc +4wqzbs5byRd/mzp4G17WjJnohBXBdxCea5WzgoGL4ZeX7nqgxwpnh51VvuOBk+vY +W6QHwpaq+lFa/G7lcoWJxmtQd3/O8apjZB9xT65II7ZeMsIP9NRLitoH7IX+GteU +MdVgTMWVyxhEko5SXlqpZUJJ/C7CReHipI8hkfub0zsQj4FkZ/jJa3X18MQFNQZE +YhhJOhGsv3U65J3PRkxEYeK9fIO8V4e+YeaJb3iItmgh4zfdfw0BieC08xYhuA5f +uEzkxqrk9nWaFHtam5/skmFcE5uH3raMLTHDYkFXxqMRQamddlONuZ4Z+oAdr+VM +zGf4oI7Dsie+PEzvbQNfphrI89TOkH8IhT6HATFKvyLG21lKgBMwFOdJg5B4zcuJ +bh/8cqDrP5byxjDe96fOBWoH2g72f4T9SrOmpgdhEL9AOiLuBnVMQDVLthMY1xxg +SuYxrmtPKn3eaeWHpv8RJSToFF4fl2zJm/HKEAd8ghAJa330/CnNCCQSqUrdE0xp +xjVURJvPZxzMS9UEQhXPyYp66GYs/uLuSTjaQwymFgc/l2UMm3zjHhjyn6S382u7 +ih+AM7y8+pIV2n8CbqoG4XR8UEr9w/ayeDSbFKGZhiqhACW8iZATgVOhmeoH7ON3 +ib7FTNHsyr2eEZ97JeKpbG9E3sFEfHJ51d0PScKmzENGP9LNjMzWb3uot0zP0q0s +kzulVIHnkh48gRICPIKeOL894gAL4PmRViP0x7chXk/xULueVb7T8WmCLYI+Kjaz +X/yGCpPmrBFNAiamrHMSh4qUE+zm7OI2jNOu87tRxcXid8O9wQZDZKaE19HZJ84j +bGghr9pKhIXdn3Z4hSyBqkBnUXNPc1g1er4DryluZ/+wKUvDkZpVmygYvQM1598b +p/xkRxlGE3BZiLX1++wIjMJ2xmwLKGiJOR0BexXJWYz0pD22YUSto7lwmGLm3oxg +MYIFqEgaYFc0MsZ7PRiMcovTUr/c2yHMpyveLHSLMFVmxfGKGZ+JcalCDFhkuZem +DcMQ0bs0DjmJZvC18SYH+iym1JXHnkVSUjsYWuVGGp7zArwlyP3W1MOhHcYDVcEl +TikNqrpgl04ti4qcdtH3TrPufMHq7Y9SM0dY1SUctyaO5yD52ozWriPuS1kTtkaL +GwvJhqvkPyO89bK/We0dIv5KoZPFhEWFwkNMNBIT1GI8XfQZTgi5ZJI3DSr1q022 +zvs5FruPwN2qFsvpmiakl4GhoIs8zwqqCDAO5JXhnSEZeEIB2Hsld7pRDAg3D8Me +T10ZOqM3XRzXPfi5zls81KhkrCh/RHiXEnMseT7aLYxvUHQM+Ktr9ar9Zv42BF+r +c5WFWDs58THPODiKYqPHpUBuIV2moTSsSWGzyvQF5TLw9/rtfrwCiBOiaqzO2odo +h7zLceAmxJfcQ6gIaAy8t5JgAUq5Uwkk0WK2Z3RyJAejdxghQI8XNxkmvu/pM5al +-----END RSA PRIVATE KEY----- pFad - Phonifier reborn

Pfad - The Proxy pFad of © 2024 Garber Painting. All rights reserved.

Note: This service is not intended for secure transactions such as banking, social media, email, or purchasing. Use at your own risk. We assume no liability whatsoever for broken pages.


Alternative Proxies:

Alternative Proxy

pFad Proxy

pFad v3 Proxy

pFad v4 Proxy