PHP Classes

sapient: Add a security layer to server to server requests

Recommend this page to a friend!
     
  Info   Example   View files Files   Install with Composer Install with Composer   Download Download   Reputation   Support forum   Blog    
Ratings Unique User Downloads Download Rankings
Not yet rated by the usersTotal: 132 All time: 9,326 This week: 36Up
Version License PHP version Categories
sapient 1.0.0MIT/X Consortium ...7HTTP, Cryptography, Libraries, Security, P..., P...
Description 

Author

This package add a security layer to server to server requests.

It can work with both Request and Response PSR-7 compliant objects by implementing security features like:

- Works with both Request and Response objects (PSR-7)
- Shared-key encryption
- Shared-key authentication
- Anonymous public-key encryption
- Public-key digital signatures
- Sends and receives signed or encrypted JSON
- Digital signatures and authentication are backwards-compatible with unsigned JSON API clients and servers
- The signaure and authentication tag will go into HTTP headers, rather than the request and response body
- Etc.

Innovation Award
PHP Programming Innovation award winner
July 2017
Winner
Nowadays sites use SSL/TLS to establish secure connections between the users browsers and the servers.

Some sites that use backend servers are connected from front-end servers without any security protection, thus allowing possible theft of information in transit by inflitrated malicious software.

This package provides a more secure solution to protect data that is exchanged between front-end and back-end servers by encrypting and decrypting the data with secure keys.

Manuel Lemos
Picture of Scott Arciszewski
  Performance   Level  
Name: Scott Arciszewski <contact>
Classes: 37 packages by
Country: United States United States
Age: ???
All time rank: 1173170 in United States United States
Week rank: 22 Up4 in United States United States Up
Innovation award
Innovation award
Nominee: 28x

Winner: 1x

Example

Sapient: Secure API toolkit

Build Status Latest Stable Version Latest Unstable Version License

Sapient secures your PHP applications' server-to-server HTTP(S) traffic even in the wake of a TLS security breakdown (compromised certificate authority, etc.).

Sapient allows you to quickly and easily add application-layer cryptography to your API requests and responses. Requires PHP 7.

Sapient was designed and implemented by the PHP security and cryptography team at Paragon Initiative Enterprises.

> See our blog post about using Sapient to harden your PHP-powered APIs > for more information about its design rationale and motivation.

The cryptography is provided by sodium_compat (which, in turn, will use the libsodium extension in PECL if it's installed).

Because sodium_compat operates on strings rather than resources (a.k.a. streams), Sapient is not suitable for extremely large messages on systems with very low available memory. Sapient only encrypts or authenticates message bodies; if you need headers to be encrypted or authenticated, that's the job of Transport-Layer Security (TLS).

Features at a Glance

  • Works with both `Request` and `Response` objects (PSR-7) * Includes a Guzzle adapter for HTTP clients
  • Secure APIs: * Shared-key encryption * XChaCha20-Poly1305 * Shared-key authentication * HMAC-SHA512-256 * Anonymous public-key encryption * X25519 + BLAKE2b + XChaCha20-Poly1305 * Public-key digital signatures * Ed25519
  • Works with arrays * i.e. the methods with "Json" in the name * Sends/receives signed or encrypted JSON
  • Works with strings * i.e. the methods without "Json" in the name
  • Digital signatures and authentication are backwards-compatible with unsigned JSON API clients and servers * The signaure and authentication tag will go into HTTP headers, rather than the request/response body.

Additionally, Sapient is covered by both unit tests (provided by PHPUnit) and automated static analysis (provided by Psalm).

Sapient Adapters

If you're looking to integrate Sapient into an existing framework:

If your framework correctly implements PSR-7, you most likely do not need an adapter. However, some adapters provide convenience methods that make rapid development easier.

To learn more about adapters, see the documentation for AdapterInterface.

Example 1: Signed PSR-7 Responses

This demonstrats a minimal implementation that adds Ed25519 signatures to your existing PSR-7 HTTP responses.

Server-Side: Signing an HTTP Response

<?php
use ParagonIE\ConstantTime\Base64UrlSafe;
use ParagonIE\Sapient\Sapient;
use ParagonIE\Sapient\CryptographyKeys\SigningSecretKey;
use Psr\Http\Message\ResponseInterface;

/
 * @var ResponseInterface $response
 *
 * Let's assume we have a valid ResponseInterface object already.
 * (Most likely, after doing normal framework things.)  
 */

$sapient = new Sapient();
$serverSignSecret = new SigningSecretKey(
    Base64UrlSafe::decode(
        'q6KSHArUnD0sEa-KWpBCYLka805gdA6lVG2mbeM9kq82_Cwg1n7XLQXXXHF538URRov8xV7CF2AX20xh_moQTA=='
    )
);

$signedResponse = $sapient->signResponse($response, $serverSignSecret);

Client-Side: Verifying the Signature

<?php
use ParagonIE\ConstantTime\Base64UrlSafe;
use ParagonIE\Sapient\Sapient;
use ParagonIE\Sapient\CryptographyKeys\SigningPublicKey;
use ParagonIE\Sapient\Exception\{
    HeaderMissingException,
    InvalidMessageException
};
use Psr\Http\Message\ResponseInterface;

/
 * @var ResponseInterface $response
 *
 * Let's assume we have a valid ResponseInterface object already.
 * (Most likely the result of an HTTP request to the server.)  
 */

$sapient = new Sapient();
$serverPublicKey = new SigningPublicKey(
    Base64UrlSafe::decode(
        'NvwsINZ-1y0F11xxed_FEUaL_MVewhdgF9tMYf5qEEw='
    )
);

try {
    $verified = $sapient->verifySignedResponse($response, $serverPublicKey);
} catch (HeaderMissingException $ex) {
    /The server didn't provide a header. Discard and log the error!/
} catch (InvalidMessageException $ex) {
    /Invalid signature for the message. Discard and log the error!/
}

Example 2: Mutually Signed JSON API with the Guzzle Adapter

This example takes advantage of an Adapter the provides the convenience methods described in ConvenienceInterface.

Client-Side: Sending a Signed Request, Verifying the Response

<?php
use GuzzleHttp\Client;
use ParagonIE\ConstantTime\Base64UrlSafe;
use ParagonIE\Sapient\Adapter\Guzzle as GuzzleAdapter;
use ParagonIE\Sapient\Sapient;
use ParagonIE\Sapient\CryptographyKeys\SigningPublicKey;
use ParagonIE\Sapient\CryptographyKeys\SigningSecretKey;
use ParagonIE\Sapient\Exception\InvalidMessageException;

$http = new Client([
    'base_uri' => 'https://your-api.example.com'
]);
$sapient = new Sapient(new GuzzleAdapter($http));

// Keys
$clientSigningKey = new SigningSecretKey(
    Base64UrlSafe::decode(
        'AHxoibWhTylBMgFzJp6GGgYto24PVbQ-ognw9SPnvKppfti72R8By8XnIMTJ8HbDTks7jK5GmAnvtzaj3rbcTA=='
    )
);
$serverPublicKey = new SigningPublicKey(
    Base64UrlSafe::decode(
        'NvwsINZ-1y0F11xxed_FEUaL_MVewhdgF9tMYf5qEEw='
    )
);

// We use an array to define our message
$myMessage = [
    'date' => (new DateTime)->format(DateTime::ATOM),
    'body' => [
        'test' => 'hello world!'        
    ]
];

// Create the signed request:
$request = $sapient->createSignedJsonRequest(
    'POST',
     '/my/api/endpoint',
     $myMessage,
     $clientSigningKey
);

$response = $http->send($request);
try {
    / @var array $verifiedResponse */
    $verifiedResponse = $sapient->decodeSignedJsonResponse(
        $response,
        $serverPublicKey
    );
} catch (InvalidMessageException $ex) {
    \http_response_code(500);
    exit;
}

Server-Side: Verifying a Signed Request, Signing a Response

 <?php
use GuzzleHttp\Client;
use GuzzleHttp\Psr7\ServerRequest;
use ParagonIE\ConstantTime\Base64UrlSafe;
use ParagonIE\Sapient\Adapter\Guzzle as GuzzleAdapter;
use ParagonIE\Sapient\Sapient;
use ParagonIE\Sapient\CryptographyKeys\SigningPublicKey;
use ParagonIE\Sapient\CryptographyKeys\SigningSecretKey;
use ParagonIE\Sapient\Exception\InvalidMessageException;

$http = new Client([
    'base_uri' => 'https://your-api.example.com'
]);
$sapient = new Sapient(new GuzzleAdapter($http));
 
$clientPublicKey = new SigningPublicKey(
    Base64UrlSafe::decode(
        'aX7Yu9kfAcvF5yDEyfB2w05LO4yuRpgJ77c2o9623Ew='
    )
);
$request = ServerRequest::fromGlobals();
try {
    / @var array $decodedRequest */
    $decodedRequest = $sapient->decodeSignedJsonRequest(
        $request,
        $clientPublicKey
    );
} catch (InvalidMessageException $ex) {
    \http_response_code(500);
    exit;
}

/Business logic goes here/

// Signing a response:
$serverSignSecret = new SigningSecretKey(
    Base64UrlSafe::decode(
        'q6KSHArUnD0sEa-KWpBCYLka805gdA6lVG2mbeM9kq82_Cwg1n7XLQXXXHF538URRov8xV7CF2AX20xh_moQTA=='
    )
);

$responseMessage = [
    'date' => (new DateTime)->format(DateTime::ATOM),
    'body' => [
        'status' => 'OK',
        'message' => 'We got your message loud and clear.'
    ]
];

$response = $sapient->createSignedJsonResponse(
    200,
    $responseMessage,
    $serverSignSecret
);
/* If your framework speaks PSR-7, just return the response object and let it
   take care of the rest. */

Details

Sapient Documentation

To get started using Sapient, see the tutorial.

To learn more about building a Sapient-compatible library in another language, read the Sapient specification.

To learn more about each class, read through the Internals documentation:


  Files folder image Files (48)  
File Role Description
Files folder imagedocs (3 files, 1 directory)
Files folder imagesrc (3 files, 4 directories)
Files folder imagetests (5 files, 1 directory)
Accessible without login Plain text file .travis.yml Data Auxiliary data
Accessible without login Plain text file composer.json Data Auxiliary data
Accessible without login Plain text file LICENSE Lic. License text
Accessible without login Plain text file phpunit-autoload.php Aux. Auxiliary script
Accessible without login Plain text file phpunit.xml.dist Data Auxiliary data
Accessible without login Plain text file psalm.xml Data Auxiliary data
Accessible without login Plain text file README.md Example Example script

  Files folder image Files (48)  /  docs  
File Role Description
Files folder imageInternals (4 files, 2 directories)
  Accessible without login Plain text file README.md Doc. Documentation
  Accessible without login Plain text file Specification.md Data Auxiliary data
  Accessible without login Plain text file Tutorial.md Data Auxiliary data

  Files folder image Files (48)  /  docs  /  Internals  
File Role Description
Files folder imageAdapter (3 files, 1 directory)
Files folder imageTraits (3 files)
  Accessible without login Plain text file CryptographyKey.md Data Auxiliary data
  Accessible without login Plain text file README.md Doc. Documentation
  Accessible without login Plain text file Sapient.md Data Auxiliary data
  Accessible without login Plain text file Simple.md Data Auxiliary data

  Files folder image Files (48)  /  docs  /  Internals  /  Adapter  
File Role Description
Files folder imageGeneric (3 files)
  Accessible without login Plain text file AdapterInterface.md Data Auxiliary data
  Accessible without login Plain text file ConvenienceInterface.md Data Auxiliary data
  Accessible without login Plain text file README.md Doc. Documentation

  Files folder image Files (48)  /  docs  /  Internals  /  Adapter  /  Generic  
File Role Description
  Accessible without login Plain text file Adapter.md Data Auxiliary data
  Accessible without login Plain text file README.md Doc. Documentation
  Accessible without login Plain text file Stream.md Data Auxiliary data

  Files folder image Files (48)  /  docs  /  Internals  /  Traits  
File Role Description
  Accessible without login Plain text file JsonSugar.md Data Auxiliary data
  Accessible without login Plain text file README.md Doc. Documentation
  Accessible without login Plain text file StringSugar.md Data Auxiliary data

  Files folder image Files (48)  /  src  
File Role Description
Files folder imageAdapter (3 files, 1 directory)
Files folder imageCryptographyKeys (6 files)
Files folder imageException (2 files)
Files folder imageTraits (2 files)
  Accessible without login Plain text file CryptographyKey.php Class Class source
  Accessible without login Plain text file Sapient.php Class Class source
  Accessible without login Plain text file Simple.php Class Class source

  Files folder image Files (48)  /  src  /  Adapter  
File Role Description
Files folder imageGeneric (2 files)
  Accessible without login Plain text file AdapterInterface.php Class Class source
  Accessible without login Plain text file ConvenienceInterface.php Class Class source
  Accessible without login Plain text file Guzzle.php Class Class source

  Files folder image Files (48)  /  src  /  Adapter  /  Generic  
File Role Description
  Accessible without login Plain text file Adapter.php Class Class source
  Accessible without login Plain text file Stream.php Class Class source

  Files folder image Files (48)  /  src  /  CryptographyKeys  
File Role Description
  Accessible without login Plain text file SealingPublicKey.php Class Class source
  Accessible without login Plain text file SealingSecretKey.php Class Class source
  Accessible without login Plain text file SharedAuthenticationKey.php Class Class source
  Accessible without login Plain text file SharedEncryptionKey.php Class Class source
  Accessible without login Plain text file SigningPublicKey.php Class Class source
  Accessible without login Plain text file SigningSecretKey.php Class Class source

  Files folder image Files (48)  /  src  /  Exception  
File Role Description
  Accessible without login Plain text file HeaderMissingException.php Class Class source
  Accessible without login Plain text file InvalidMessageException.php Class Class source

  Files folder image Files (48)  /  src  /  Traits  
File Role Description
  Accessible without login Plain text file JsonSugar.php Class Class source
  Accessible without login Plain text file StringSugar.php Class Class source

  Files folder image Files (48)  /  tests  
File Role Description
Files folder imageAdapter (2 files)
  Accessible without login Plain text file KeyExchangeTest.php Class Class source
  Accessible without login Plain text file SapientSealTest.php Class Class source
  Accessible without login Plain text file SapientSignTest.php Class Class source
  Accessible without login Plain text file SapientSymmetricTest.php Class Class source
  Accessible without login Plain text file SimpleTest.php Class Class source

  Files folder image Files (48)  /  tests  /  Adapter  
File Role Description
  Accessible without login Plain text file GenericTest.php Class Class source
  Accessible without login Plain text file GuzzleTest.php Class Class source

The PHP Classes site has supported package installation using the Composer tool since 2013, as you may verify by reading this instructions page.
Install with Composer Install with Composer
 Version Control Unique User Downloads Download Rankings  
 100%
Total:132
This week:0
All time:9,326
This week:36Up