halite icon indicating copy to clipboard operation
halite copied to clipboard

Passphrases?

Open trymeouteh opened this issue 4 months ago • 2 comments

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);

trymeouteh avatar Nov 01 '25 19:11 trymeouteh

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:

  1. Salt
  2. Encrypted data key

If you use the same salt and passphrase, you will derive the same wrapping key. The salt is not considered sensitive.

paragonie-security avatar Nov 09 '25 07:11 paragonie-security

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;

trymeouteh avatar Nov 10 '25 01:11 trymeouteh