Skip to content

Instantly share code, notes, and snippets.

@soatok
Last active March 1, 2023 05:28
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save soatok/03f379252c178bea26702a54eed5621e to your computer and use it in GitHub Desktop.
Save soatok/03f379252c178bea26702a54eed5621e to your computer and use it in GitHub Desktop.
HMAC Truncation
<?php
function canonicalize(string ...$pieces) {
$output []= pack('J', count($pieces));
foreach ($pieces as $piece) {
$output []= pack('J', mb_strlen($piece, '8bit'));
$output []= $piece;
}
return implode($output);
}
function encrypt(string $plaintext, string $key, array $identity): string
{
$nonce = random_bytes(24);
$identity []= $nonce;
$output = sodium_crypto_aead_xchacha20poly1305_ietf_encrypt(
$plaintext,
canonicalize(...$identity),
$nonce,
$key
);
return sodium_bin2hex($nonce . $output);
}
function decrypt(string $ciphertext_hex, string $key, array $identity): string
{
$ciphertext_raw = sodium_hex2bin($ciphertext_hex);
$nonce = mb_substr($ciphertext_raw, 0, 24, '8bit');
$encrypted = mb_substr($ciphertext_raw, 24, null, '8bit');
$identity []= $nonce;
return sodium_crypto_aead_xchacha20poly1305_ietf_decrypt(
$encrypted,
canonicalize(...$identity),
$nonce,
$key
);
}
$k1 = random_bytes(32);
$k2 = random_bytes(32);
$rows = [
['name' => 'foo', 'email' => 'foo@example.com'],
['name' => 'bar', 'email' => 'bar@example.com']
];
$encrypted = [];
$decrypted = [];
foreach ($rows as $i => $row) {
if (!isset($encrypted[$i])) {
$encrypted[$i] = [];
}
$encrypted[$i]['name'] = encrypt($row['name'], $k1, ['users', 'name']);
$encrypted[$i]['email'] = encrypt($row['email'], $k1, ['users', 'email']);
$encrypted[$i]['email_idx'] = substr(hash_hmac('sha256', $row['email'], $k1), 48);
if (!isset($decrypted[$i])) {
$decrypted[$i] = [];
}
$decrypted[$i]['name'] = decrypt($encrypted[$i]['name'], $k1, ['users', 'name']);
$decrypted[$i]['email'] = decrypt($encrypted[$i]['email'], $k1, ['users', 'email']);
}
var_dump($encrypted, $decrypted);
array(2) {
[0]=>
array(3) {
["name"]=>
string(86) "1744440ec2d27b4a8c7d092e2367daa4c1f3d33a5f8aabde7221a05796120c4df078b5fc99cee6a65ddc31"
["email"]=>
string(110) "444ca3f4092215884d04f360bc593a76a6776bdbbabc7950eb1129d182aac703c02368d617380883ec8fd43703f3f585492c142097ebb5"
["email_idx"]=>
string(16) "28e9ef076233d870"
}
[1]=>
array(3) {
["name"]=>
string(86) "4b09b22685b7c5c4c06a3c1d3deb7f731f0f00f0b10dd94f50cf8dccd76e7e7f8b018734facf5f663f2727"
["email"]=>
string(110) "8843320551b538f8fe3aa0e20d841fa2cc1fc12f10a771c063bef16d35bf14ccc4c3dee7e8cfae626641d252d475b515327e29e79965ca"
["email_idx"]=>
string(16) "04e48ca810a8b1ae"
}
}
array(2) {
[0]=>
array(2) {
["name"]=>
string(3) "foo"
["email"]=>
string(15) "foo@example.com"
}
[1]=>
array(2) {
["name"]=>
string(3) "bar"
["email"]=>
string(15) "bar@example.com"
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment