PHP Classes

File: src/Simple.php

Recommend this page to a friend!
  Classes of Scott Arciszewski   sapient   src/Simple.php   Download  
File: src/Simple.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: Boyscouting.
Date: 7 years ago
Size: 5,222 bytes
 

Contents

Class file image Download
<?php
declare(strict_types=1);
namespace
ParagonIE\Sapient;

use
ParagonIE\Sapient\CryptographyKeys\{
   
SealingPublicKey,
   
SealingSecretKey,
   
SharedEncryptionKey
};
use
ParagonIE\Sapient\Exception\InvalidMessageException;

/**
 * Class Simple
 * @package ParagonIE\Sapient
 */
abstract class Simple
{
   
/**
     * Simple authenticated encryption
     * XChaCha20-Poly1305
     *
     * @param string $plaintext
     * @param SharedEncryptionKey $key
     * @return string
     */
   
public static function encrypt(
       
string $plaintext,
       
SharedEncryptionKey $key
   
): string {
       
$nonce = random_bytes(\ParagonIE_Sodium_Compat::CRYPTO_AEAD_XCHACHA20POLY1305_IETF_NPUBBYTES);
        return
$nonce .
            \
ParagonIE_Sodium_Compat::crypto_aead_xchacha20poly1305_ietf_encrypt(
               
$plaintext,
               
$nonce,
               
$nonce,
               
$key->getString(true)
            );
    }

   
/**
     * Simple authenticated decryption
     * XChaCha20-Poly1305
     *
     * @param string $ciphertext
     * @param SharedEncryptionKey $key
     * @return string
     * @throws InvalidMessageException
     */
   
public static function decrypt(
       
string $ciphertext,
       
SharedEncryptionKey $key
   
): string {
       
$nonce = \ParagonIE_Sodium_Core_Util::substr($ciphertext, 0, 24);
       
$result = \ParagonIE_Sodium_Compat::crypto_aead_xchacha20poly1305_ietf_decrypt(
            \
ParagonIE_Sodium_Core_Util::substr($ciphertext, 24),
           
$nonce,
           
$nonce,
           
$key->getString(true)
        );
        if (!\
is_string($result)) {
            throw new
InvalidMessageException('Message authentication failed.');
        }
        return
$result;
    }

   
/**
     * Like libsodium's crypto_kx() but supports an arbitrary output length
     * in the range (16 <= N <= 64).
     *
     * @param SealingSecretKey $secretKey
     * @param SealingPublicKey $publicKey
     * @param bool $serverSide
     * @param int $outputLength
     * @return string
     */
   
public static function keyExchange(
       
SealingSecretKey $secretKey,
       
SealingPublicKey $publicKey,
       
bool $serverSide,
       
int $outputLength = 32
   
): string {
        if (
$serverSide) {
           
$suffix = $publicKey->getString(true) .
               
$secretKey->getPublickey()->getString(true);
        } else {
           
$suffix = $secretKey->getPublickey()->getString(true) .
               
$publicKey->getString(true);
        }
        return \
ParagonIE_Sodium_Compat::crypto_generichash(
            \
ParagonIE_Sodium_Compat::crypto_scalarmult(
               
$secretKey->getString(true),
               
$publicKey->getString(true)
            ) .
$suffix,
           
'',
           
$outputLength
       
);
    }

   
/**
     * Encrypt a message with a public key, so that it can only be decrypted
     * with the corresponding secret key.
     *
     * @param string $plaintext
     * @param SealingPublicKey $publicKey
     * @return string
     */
   
public static function seal(
       
string $plaintext,
       
SealingPublicKey $publicKey
   
): string {
       
$ephemeralSecret = SealingSecretKey::generate();
       
$sharedSecret = static::keyExchange(
           
$ephemeralSecret,
           
$publicKey,
           
false,
           
56
       
);
       
$ephemeralPublicKey = $ephemeralSecret->getPublickey()->getString(true);
       
$sharedKey = \ParagonIE_Sodium_Core_Util::substr($sharedSecret, 0, 32);
       
$nonce = \ParagonIE_Sodium_Core_Util::substr($sharedSecret, 32, 24);
        try {
            \
ParagonIE_Sodium_Compat::memzero($sharedSecret);
        } catch (\
Throwable $ex) {
        }

        return
$ephemeralPublicKey. \ParagonIE_Sodium_Compat::crypto_aead_xchacha20poly1305_ietf_encrypt(
           
$plaintext,
           
$ephemeralPublicKey,
           
$nonce,
           
$sharedKey
       
);
    }

   
/**
     * Decrypt a message with your secret key.
     *
     * @param string $ciphertext
     * @param SealingSecretKey $secretKey
     * @return string
     * @throws InvalidMessageException
     */
   
public static function unseal(
       
string $ciphertext,
       
SealingSecretKey $secretKey
   
): string {
       
$ephemeralPublicKey = \ParagonIE_Sodium_Core_Util::substr($ciphertext, 0, 32);

       
$sharedSecret = static::keyExchange(
           
$secretKey,
            new
SealingPublicKey($ephemeralPublicKey),
           
true,
           
56
       
);
       
$sharedKey = \ParagonIE_Sodium_Core_Util::substr($sharedSecret, 0, 32);
       
$nonce = \ParagonIE_Sodium_Core_Util::substr($sharedSecret, 32, 24);
        try {
            \
ParagonIE_Sodium_Compat::memzero($sharedSecret);
        } catch (\
Throwable $ex) {
        }

       
$plaintext = \ParagonIE_Sodium_Compat::crypto_aead_xchacha20poly1305_ietf_decrypt(
            \
ParagonIE_Sodium_Core_Util::substr($ciphertext, 32),
           
$ephemeralPublicKey,
           
$nonce,
           
$sharedKey
       
);
        if (!\
is_string($plaintext)) {
            throw new
InvalidMessageException('Incorrect message authentication tag');
        }
        return
$plaintext;
    }
}