Skip to content

Instantly share code, notes, and snippets.

@defuse
Last active August 29, 2015 13:56
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 defuse/8903263 to your computer and use it in GitHub Desktop.
Save defuse/8903263 to your computer and use it in GitHub Desktop.
Proposal for side-channel safe encoding.
<?php
// THIS CODE IS EXPERIMENTAL. DO NOT USE IT.
// ALSO NOTE THERE IS NO ERROR CHECKING!
function side_channel_safe_encode($binary_string)
{
// We only use 5 bits from every byte, so for 256 bits we need 52 bytes.
$random = mcrypt_create_iv(52, MCRYPT_DEV_URANDOM);
$printable_blind_key = '';
for ($i = 0; $i < strlen($random); $i++) {
// We want $char_num to look like 01?????0, where the ? are random bits.
$char_num = ord($random[$i]);
// Set the MSB and LSB to zero.
$char_num = $char_num & 0x7E;
// Set the second-most significant bit to 1
$char_num = $char_num | 0x40;
$printable_blind_key .= chr($char_num);
}
$blind_key = hash("sha256", $printable_blind_key, true);
$encrypted = mcrypt_encrypt(
MCRYPT_RIJNDAEL_128,
$blind_key,
$binary_string,
'ctr',
str_repeat("\x00", 16) // zero IV!
);
// The zero IV should be ok, because with high probability, all messages are
// encrypted with a different key.
// We shouldn't care if bin2hex leaks $encrypted, since it's encrypted with
// a random key.
$encoded = $printable_blind_key . bin2hex($encrypted);
return $encoded;
}
function side_channel_safe_decode($encoded_string)
{
$printable_blind_key = substr($encoded_string, 0, 52);
$blind_key = hash("sha256", $printable_blind_key, true);
$ciphertext = substr($encoded_string, 52);
// Likewise, we shouldn't care if pack leaks $ciphertext, since it's
// encrypted with a random key.
$decoded = pack("H*", $ciphertext);
$decrypted = mcrypt_decrypt(
MCRYPT_RIJNDAEL_128,
$blind_key,
$decoded,
'ctr',
str_repeat("\x00", 16)
);
return $decrypted;
}
// TODO: what about encrypting with key H(80-bit random || message) ?
$message = "Hello, world!";
echo "Message: $message\n";
$encoded1 = side_channel_safe_encode($message);
$encoded2 = side_channel_safe_encode($message);
echo "Encoded #1: $encoded1\n";
echo "Encoded #2: $encoded2\n";
$decoded1 = side_channel_safe_decode($encoded1);
$decoded2 = side_channel_safe_decode($encoded2);
echo "Decoded #1: $decoded1\n";
echo "Decoded #2: $decoded2\n";
if ($message === $decoded1 && $message === $decoded2) {
echo "It works!\n";
} else {
echo "It doesn't work!\n";
}
?>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment