<?php
namespace ParagonIE\CipherSweet;
use ParagonIE\CipherSweet\Backend\FIPSCrypto;
use ParagonIE\CipherSweet\Backend\Key\SymmetricKey;
use ParagonIE\CipherSweet\Backend\ModernCrypto;
use ParagonIE\CipherSweet\Contract\BackendInterface;
use ParagonIE\CipherSweet\Contract\KeyProviderInterface;
use ParagonIE\CipherSweet\Exception\CryptoOperationException;
use ParagonIE_Sodium_Compat as SodiumCompat;
/**
* Class CipherSweet
* @package ParagonIE\CipherSweet
*/
final class CipherSweet
{
/*
* These domain separation constants has a hamming distance of 4 from each
* other, for each byte.
*/
const DS_BIDX = "\x7E\x7E\x7E\x7E\x7E\x7E\x7E\x7E\x7E\x7E\x7E\x7E\x7E\x7E\x7E\x7E\x7E\x7E\x7E\x7E\x7E\x7E\x7E\x7E\x7E\x7E\x7E\x7E\x7E\x7E\x7E\x7E";
const DS_FENC = "\xB4\xB4\xB4\xB4\xB4\xB4\xB4\xB4\xB4\xB4\xB4\xB4\xB4\xB4\xB4\xB4\xB4\xB4\xB4\xB4\xB4\xB4\xB4\xB4\xB4\xB4\xB4\xB4\xB4\xB4\xB4\xB4";
/**
* @var BackendInterface $backend
*/
private $backend;
/**
* @var KeyProviderInterface $keyProvider
*/
private $keyProvider;
/**
* CipherSweet constructor.
*
* @param KeyProviderInterface $keyProvider
* @param BackendInterface|null $backend
*/
public function __construct(
KeyProviderInterface $keyProvider,
BackendInterface $backend = null
) {
$this->keyProvider = $keyProvider;
if (\is_null($backend)) {
$backend = $this->keyProvider->getBackend();
}
$this->backend = $backend;
}
/**
* @return BackendInterface
*/
public function getBackend()
{
return $this->backend;
}
/**
* @param string $tableName
* @param string $fieldName
* @param string $indexName
* @return string
*/
public function getIndexTypeColumn(
$tableName,
$fieldName,
$indexName
) {
return $this->backend->getIndexTypeColumn(
$tableName,
$fieldName,
$indexName
);
}
/**
* Get the root key for calculating blind index keys for a given
* EncryptedField instance.
*
* Uses a 32 byte prefix for the HKDF "info" parameter, for domain
* separation.
*
* @param string $tableName
* @param string $fieldName
*
* @return SymmetricKey
* @throws CryptoOperationException
*/
public function getBlindIndexRootKey($tableName, $fieldName)
{
return new SymmetricKey(
$this->backend,
Util::HKDF(
$this->keyProvider->getSymmetricKey(),
$tableName,
self::DS_BIDX . $fieldName
)
);
}
/**
* Get the per-field encryption key.
*
* Uses a 32 byte prefix for the HKDF "info" parameter, for domain
* separation.
*
* @param string $tableName
* @param string $fieldName
*
* @return SymmetricKey
* @throws CryptoOperationException
*/
public function getFieldSymmetricKey($tableName, $fieldName)
{
return new SymmetricKey(
$this->backend,
Util::HKDF(
$this->keyProvider->getSymmetricKey(),
$tableName,
self::DS_FENC . $fieldName
)
);
}
/**
* Return the default backend for a given environment. Note that the
* stability of the result of this static method should not be depended on.
*
* @return BackendInterface
*/
public static function getDefaultBackend()
{
if (SodiumCompat::crypto_pwhash_is_available()) {
if (PHP_VERSION_ID >= 70000 && \extension_loaded('sodium')) {
return new ModernCrypto();
}
if (PHP_VERSION_ID >= 70000 && \extension_loaded('libsodium')) {
// This is a little weird but OK
return new ModernCrypto();
}
if (PHP_VERSION_ID < 70000 && \extension_loaded('libsodium')) {
return new ModernCrypto();
}
}
// FIPS mode will always work... but it only uses FIPS algorithms.
return new FIPSCrypto();
}
}
|