Passphrases?
Is there a way to add an optional passphrase when generating a public and private key?
This is my simple PHP code that generates a public and private key without a passphrase and uses it to encrypt and decrypt.
<?php
require 'vendor/autoload.php';
const MY_TEXT = 'My Text';
//Create private and public key
$publicPrivateKeyPairs = \ParagonIE\Halite\KeyFactory::generateEncryptionKeyPair();
$publicKey = $publicPrivateKeyPairs->getPublicKey();
$privateKey = $publicPrivateKeyPairs->getSecretKey();
//Encrypt
$encryptedText = \ParagonIE\Halite\Asymmetric\Crypto::seal(new \ParagonIE\HiddenString\HiddenString(MY_TEXT), $publicKey);
echo $encryptedText . PHP_EOL;
//Decrypt
$decryptedTextHiddenString = \ParagonIE\Halite\Asymmetric\Crypto::unseal($encryptedText, $privateKey);
//Convert HiddenString type into a string
echo $decryptedTextHiddenString->getString() . PHP_EOL;
This is my simple NodeJS code that generates a public and private key without a passphrase and uses it to encrypt and decrypt, to give an idea of how it is done in NodeJS.
import { generateKeyPairSync, publicEncrypt, privateDecrypt } from 'crypto';
const MY_TEXT = 'My Text';
const MY_PASSPHRASE = 'My Passphrase';
//Create private and public key
const { privateKey: PRIVATE_KEY, publicKey: PUBLIC_KEY } = generateKeyPairSync('rsa', {
modulusLength: 2048,
publicKeyEncoding: {
//Recommended to be spki by NodeJS
type: 'spki',
format: 'pem',
},
privateKeyEncoding: {
//Recommended to be pkcs8 by NodeJS
type: 'pkcs8',
format: 'pem',
//Add cipher and passphrase properties to add a passphrase.
cipher: 'aes-256-cbc',
passphrase: MY_PASSPHRASE,
},
});
//Encrypt in base64 encoding
const encrypedTextArrayBuffer = publicEncrypt(PUBLIC_KEY, MY_TEXT);
const ENCRYPTED_TEXT = encrypedTextArrayBuffer.toString('base64');
console.log(ENCRYPTED_TEXT);
//Decrypt in base64 encoding using string
const decryptedTextArrayBuffer = privateDecrypt(
{
key: PRIVATE_KEY,
passphrase: MY_PASSPHRASE,
},
Buffer.from(ENCRYPTED_TEXT, 'base64')
);
const DECRYPTED_TEXT = decryptedTextArrayBuffer.toString('utf8');
console.log(DECRYPTED_TEXT);
You can use passwords to derive a wrapping key. See https://github.com/paragonie/halite/blob/master/doc/Classes/KeyFactory.md#deriveencryptionkey
Then, use the wrapping key to encrypt your exported data key (see https://github.com/paragonie/halite/issues/209#issuecomment-3507599142 for prior guidance).
Then the only bits of information you need to store in the database are:
- Salt
- Encrypted data key
If you use the same salt and passphrase, you will derive the same wrapping key. The salt is not considered sensitive.
Is this a basic example of generating a key with a passphrase, converting keys to string, converting key strings into keys and using then to encrypt/decrypt?
And is the salt what makes the generated key random with the passphrase?
<?php
require 'vendor/autoload.php';
const MY_TEXT = 'My Text';
const MY_PASSPHRASE = 'My Passphrase';
$passphraseHiddenString = new \ParagonIE\HiddenString\HiddenString(MY_PASSPHRASE);
$salt = random_bytes(16);
//Create private and public key from passphrase
$publicPrivateKeyPairs = \ParagonIE\Halite\KeyFactory::deriveEncryptionKeyPair($passphraseHiddenString, $salt);
$publicKey = $publicPrivateKeyPairs->getPublicKey();
$privateKey = $publicPrivateKeyPairs->getSecretKey();
//Convert public key into a string
$publicKeyHiddenString = \ParagonIE\Halite\KeyFactory::export($publicKey);
$publicKeyString = $publicKeyHiddenString->getString();
echo $publicKeyString . PHP_EOL . PHP_EOL;
//Convert private key into a string
$privateKeyHiddenString = \ParagonIE\Halite\KeyFactory::export($privateKey);
$privateKeyString = $privateKeyHiddenString->getString();
echo $privateKeyString . PHP_EOL . PHP_EOL;
//...
//Convert public key string into a key
$publicKeyHiddenString = new \ParagonIE\HiddenString\HiddenString($publicKeyString);
$publicKey = \ParagonIE\Halite\KeyFactory::importEncryptionPublicKey($publicKeyHiddenString);
//Convert private key string into a key
$privateKeyHiddenString = new \ParagonIE\HiddenString\HiddenString($privateKeyString);
$privateKey = \ParagonIE\Halite\KeyFactory::importEncryptionSecretKey($privateKeyHiddenString);
//Encrypt
$encryptedText = \ParagonIE\Halite\Asymmetric\Crypto::seal(new \ParagonIE\HiddenString\HiddenString(MY_TEXT), $publicKey);
echo $encryptedText . PHP_EOL . PHP_EOL;
//...
//Decrypt
$decryptedTextHiddenString = \ParagonIE\Halite\Asymmetric\Crypto::unseal($encryptedText, $privateKey);
//Convert HiddenString type into a string
echo $decryptedTextHiddenString->getString() . PHP_EOL;