Last active
August 29, 2015 13:56
-
-
Save defuse/8903263 to your computer and use it in GitHub Desktop.
Proposal for side-channel safe encoding.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
<?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