PHP Classes

File: tests/SapientSignTest.php

Recommend this page to a friend!
  Packages of Scott Arciszewski   sapient   tests/SapientSignTest.php   Download  
File: tests/SapientSignTest.php
Role: Class source
Content type: text/plain
Description: Class source
Class: sapient
Add a security layer to server to server requests
Author: By
Last change: Fix unit test. Describe verifySymmetricAuthenticated*()
Date: 9 years ago
Size: 9,565 bytes
 

Contents

Class file image Download
<?php
namespace ParagonIE\Sapient\UnitTests;

use GuzzleHttp\Psr7\Request;
use GuzzleHttp\Psr7\Response;
use ParagonIE\ConstantTime\Base64UrlSafe;
use ParagonIE\Sapient\Adapter\Guzzle;
use ParagonIE\Sapient\CryptographyKeys\{
    SigningPublicKey,
    SigningSecretKey
};
use ParagonIE\Sapient\Exception\HeaderMissingException;
use ParagonIE\Sapient\Exception\InvalidMessageException;
use ParagonIE\Sapient\Sapient;
use PHPUnit\Framework\TestCase;

/**
 * Class SapientTest
 * @package ParagonIE\Sapient\UnitTests
 */
class SapientSignTest extends TestCase
{
    /** @var Sapient */
    protected $sapient;

    /** @var SigningSecretKey */
    protected $clientSignSecret;

    /** @var SigningPublicKey */
    protected $clientSignPublic;

    /** @var SigningSecretKey */
    protected $serverSignSecret;

    /** @var SigningPublicKey */
    protected $serverSignPublic;

    /**
     * Setup the class properties
     */
    public function setUp()
    {
        $this->sapient = new Sapient(new Guzzle());

        $this->clientSignSecret = SigningSecretKey::generate();
        $this->clientSignPublic = $this->clientSignSecret->getPublickey();

        $this->serverSignSecret = SigningSecretKey::generate();
        $this->serverSignPublic = $this->serverSignSecret->getPublickey();
    }

    private function getSampleObjects(): array
    {
        return [
            [],
            ['test' => 'abcdefg'],
            ['random' => Base64UrlSafe::encode(
                \random_bytes(
                    \random_int(1, 100)
                )
            )
            ],
            ['structued' => [
                'abc' => 'def',
                'o' => null,
                'ghi' => ['j', 'k', 'l'],
                'm' => 1234,
                'n' => 56.78,
                'p' => ['q' => ['r' => []]]
            ]]
        ];
    }

    /**
     * @covers Sapient::createSignedJsonRequest()
     * @covers Sapient::verifySignedRequest()
     */
    public function testSignedJsonRequest()
    {
        $sampleObjects = $this->getSampleObjects();

        foreach ($sampleObjects as $obj) {
            $guzzle = new Guzzle();
            $request = $guzzle->createSignedJsonRequest(
                'POST',
                '/',
                $obj,
                $this->clientSignSecret
            );
            $valid = $this->sapient->verifySignedRequest(
                $request,
                $this->clientSignPublic
            );
            $this->assertInstanceOf(Request::class, $valid);
            $decoded = $this->sapient->decodeSignedJsonRequest($request, $this->clientSignPublic);
            $this->assertSame($obj, $decoded);

            /* We expect an exception: */
            try {
                $this->sapient->verifySignedRequest(
                    $request,
                    $this->serverSignPublic
                );
                $this->fail('Bad message signature');
            } catch (\Throwable $ex) {
            }

            $invalid = $request->withBody($this->sapient->stringToStream(('invalid message')));
            /* We expect an exception: */
            try {
                $this->sapient->verifySignedRequest(
                    $invalid,
                    $this->clientSignPublic
                );
                $this->fail('Bad message accepted');
            } catch (\Throwable $ex) {
            }
        }
    }

    /**
     * @covers Sapient::createSignedRequest()
     * @covers Sapient::verifySignedRequest()
     */
    public function testSignedRequest()
    {
        $randomMessage = Base64UrlSafe::encode(
            \random_bytes(
                \random_int(101, 200)
            )
        );
        $guzzle = new Guzzle();
        $request = $guzzle->createSignedRequest(
            'POST',
            '/',
            $randomMessage,
            $this->clientSignSecret
        );
        $valid = $this->sapient->verifySignedRequest(
            $request,
            $this->clientSignPublic
        );
        $this->assertInstanceOf(Request::class, $valid);

        $decoded = $this->sapient->verifySignedStringRequest($request, $this->clientSignPublic);
        $this->assertSame($randomMessage, $decoded);

        /* Test bad public key */
        try {
            $this->sapient->verifySignedRequest(
                $request,
                $this->serverSignPublic
            );
            $this->fail('Bad message signature');
        } catch (\Throwable $ex) {
        }

        $invalid = $request->withBody($this->sapient->stringToStream('invalid message'));

        /* Test bad message */
        try {
            $this->sapient->verifySignedRequest(
                $invalid,
                $this->clientSignPublic
            );
            $this->fail('Bad message accepted');
        } catch (\Throwable $ex) {
        }
    }

    /**
     * @covers Sapient::createSignedJsonResponse()
     * @covers Sapient::verifySignedResponse()
     */
    public function testSignedJsonResponse()
    {
        $sampleObjects = $this->getSampleObjects();

        foreach ($sampleObjects as $obj) {
            $guzzle = new Guzzle();
            $response = $guzzle->createSignedJsonResponse(
                200,
                $obj,
                $this->serverSignSecret
            );
            $valid = $this->sapient->verifySignedResponse($response, $this->serverSignPublic);
            $this->assertInstanceOf(Response::class, $valid);

            $decoded = $this->sapient->decodeSignedJsonResponse($response, $this->serverSignPublic);
            $this->assertSame($obj, $decoded);

            /* Test bad public key */
            try {
                $this->sapient->verifySignedResponse(
                    $valid,
                    $this->clientSignPublic
                );
                $this->fail('Bad message accepted');
            } catch (\Throwable $ex) {
            }

            $invalid = $response->withBody($this->sapient->stringToStream('invalid message'));
            /* Test bad message */
            try {
                $this->sapient->verifySignedResponse(
                    $invalid,
                    $this->serverSignPublic
                );
                $this->fail('Bad message accepted');
            } catch (\Throwable $ex) {
            }
        }
    }

    /**
     * @covers Sapient::createSignedResponse()
     * @covers Sapient::verifySignedResponse()
     */
    public function testSignedResponse()
    {
        $randomMessage = Base64UrlSafe::encode(
            \random_bytes(
                \random_int(101, 200)
            )
        );

        $response = $this->sapient->createSignedResponse(
            200,
            $randomMessage,
            $this->serverSignSecret
        );
        $valid = $this->sapient->verifySignedResponse($response, $this->serverSignPublic);
        $this->assertInstanceOf(Response::class, $valid);

        $decoded = $this->sapient->verifySignedStringResponse($response, $this->serverSignPublic);
        $this->assertSame($randomMessage, $decoded);

        /* Test bad public key */
        try {
            $this->sapient->verifySignedResponse(
                $valid,
                $this->clientSignPublic
            );
            $this->fail('Bad message accepted');
        } catch (\Throwable $ex) {
        }

        $invalid = $response->withBody($this->sapient->stringToStream('invalid message'));
        /* Test bad message */
        try {
            $this->sapient->verifySignedResponse(
                $invalid,
                $this->serverSignPublic
            );
            $this->fail('Bad message accepted');
        } catch (\Throwable $ex) {
        }
    }

    /**
     * @covers Sapient::signRequest()
     * @covers Sapient::signResponse()
     */
    public function testPsr7()
    {
        $randomMessage = Base64UrlSafe::encode(
            \random_bytes(
                \random_int(101, 200)
            )
        );

        $request = new Request('POST', '/test', [], $randomMessage);
        $signedRequest = $this->sapient->signRequest($request, $this->clientSignSecret);
        try {
            $verified = $this->sapient->verifySignedRequest(
                $signedRequest,
                $this->clientSignPublic
            );
            $this->assertSame(
                $randomMessage,
                (string) $verified->getBody()
            );
            $this->assertNotEmpty(
                $verified->getHeader(Sapient::HEADER_SIGNATURE_NAME)
            );
        } catch (HeaderMissingException $exception) {
            $this->fail('No header added');
        } catch (InvalidMessageException $exception) {
            $this->fail('Invalid signature');
        }

        $response = new Response(200, [], $randomMessage);
        $signedResponse = $this->sapient->signResponse($response, $this->serverSignSecret);
        try {
            $verified = $this->sapient->verifySignedResponse(
                $signedResponse,
                $this->serverSignPublic
            );
            $this->assertSame(
                $randomMessage,
                (string) $verified->getBody()
            );
            $this->assertNotEmpty(
                $verified->getHeader(Sapient::HEADER_SIGNATURE_NAME)
            );
        } catch (HeaderMissingException $exception) {
            $this->fail('No header added');
        } catch (InvalidMessageException $exception) {
            $this->fail('Invalid signature');
        }
    }
}