PHP Classes

File: tests/SapientSignTest.php

Recommend this page to a friend!
  Classes 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: 6 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');
        }
    }
}