In addition to its core functionality, Halite offers some useful APIs for solving common problems.
Cookie
- Authenticated encryption for your HTTPS cookiesFile
- Cryptography library for working with filesPassword
- Secure password storage and password verification API
Unlike the core Halite APIs, the Cookie class is not static. You must create an
instance of Cookie
and work with it.
$enc_key = \ParagonIE\Halite\KeyFactory::loadEncryptionKey('/path/to/key');
$cookie = new \ParagonIE\Halite\Cookie($enc_key);
From then on, all you need to do is use the fetch()
and store()
APIs.
Storing data in an encrypted cookie:
$cookie->store(
'auth',
['s' => $selector, 'v' => $verifier],
time() + 2592000
);
Fetching data from an encrypted cookie:
$token = $cookie->fetch('auth');
var_dump($token); // array(2) ...
Halite's File
class provides streaming file cryptography features, such as
authenticated encryption and digital signatures. File
allows developers to
perform secure cryptographic operations on large files with a low memory
footprint.
The File
API looks like this:
File::checksum
(file
,AuthenticationKey?
,bool?
):string
File::encrypt
(file
,file
,EncryptionKey
)File::decrypt
(file
,file
,EncryptionKey
)File::seal
(file
,file
,EncryptionPublicKey
)File::unseal
(file
,file
,EncryptionSecretKey
)File::sign
(file
,SignatureSecretKey
):string
File::verify
(file
,SignaturePublicKey
):bool
The file
type indicates that the argument can be either a string
containing
the file's path, or a resource
(open file handle).
Each of these features is designed to work in a streaming fashion.
Basic usage:
$checksum = \ParagonIE\Halite\File::checksum('/source/file/path');
If for some reason you desire to use a keyed hash rather than just a plain one,
you can pass an AuthenticationKey
to
an optional second parameter, or null
.
$keyed = \ParagonIE\Halite\File::checksum('/source/file/path', $auth_key);
Finally, you can pass true
as the optional third argument if you would like a
raw binary string rather than a hexadecimal string.
$keyed_checksum = \ParagonIE\Halite\File::checksum('/source/file/path', null, true);
If you need to encrypt a file larger than the amount of memory available to PHP,
you'll run into problems with just the basic \ParagonIE\Halite\Symmetric\Crypto
API. To work around these limitations, use File::encrypt()
instead.
For example:
\ParagonIE\Halite\File::encrypt(
$inputFilename,
$outputFilename,
$enc_key
);
This will encrypt the contents of the file located at $inputFilename
and write
its contents to $outputFilename
.
Decryption is straightforward as well:
\ParagonIE\Halite\File::decrypt(
$inputFilename,
$outputFilename,
$enc_key
);
This feature encrypts files with a public key so that they can be decrypted offline with a secret key.
$seal_keypair = \ParagonIE\Halite\KeyFactory::generateEncryptionKeyPair();
$seal_secret = $seal_keypair->getSecretKey();
$seal_public = $seal_keypair->getPublicKey();
Sealing the contents of a file using Halite:
\ParagonIE\Halite\File::seal(
$inputFilename,
$outputFilename,
$seal_public
);
Opening the contents of a sealed file using Halite:
\ParagonIE\Halite\File::unseal(
$inputFilename,
$outputFilename,
$seal_secret
);
First, you need a key pair.
$sign_keypair = \ParagonIE\Halite\KeyFactory::generateSignatureKeyPair();
$sign_secret = $sign_keypair->getSecretKey();
$sign_public = $sign_keypair->getPublicKey();
Signing the contents of a file using your secret key:
$signature = \ParagonIE\Halite\File::sign(
$inputFilename,
$sign_secret
);
Verifying the contents of a file using a known public key:
$valid = \ParagonIE\Halite\File::verify(
$inputFilename,
$sign_public,
$signature
);
Like checksumFile()
, you can pass an optional true
to get a raw binary
signature instead of a hexadecimal-encoded string.
This feature serves a very narrow use case: You have the webserver and database on separate hardware, and would like to prevent a database compromise from leaking the actual password hashes.
If your webserver and database server are the same machine, there is no advantage to using this feature over libsodium's Argon2 implementation.
Hashing then Encrypting a password:
$stored_hash = \ParagonIE\Halite\Password::hash(
$plaintext_password, // HiddenString
$encryption_key // \ParagonIE\Halite\Symmetric\EncryptionKey
);
Validating a password:
try {
if (\ParagonIE\Halite\Password::verify(
$plaintext_password, // HidddenString
$stored_hash, // string
$encryption_key // \ParagonIE\Halite\Symmetric\EncryptionKey
)) {
// Password matches
}
} catch (\ParagonIE\Halite\Alerts\InvalidMessage $ex) {
// Handle an invalid message here. This usually means tampered ciphertext.
}