-
-
Save paragonie-scott/eb4403ef78f1a357f90e30f4da1eac3e to your computer and use it in GitHub Desktop.
Toy Randomized Ed25519 signature API (for interop with systems meant to resist fault attacks)
This file contains 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 | |
declare(strict_types=1); | |
define('SODIUM_CRYPTO_RSIGN_SIGBYTES', 96); | |
/** | |
* @param string $message | |
* @param string $sk | |
* @return string | |
* @throws SodiumException | |
*/ | |
function sodium_crypto_rsign(string $message, string $sk): string | |
{ | |
return sodium_crypto_sign(random_bytes(32) . $message, $sk); | |
} | |
/** | |
* @param string $sm | |
* @param string $pk | |
* @return string | |
*/ | |
function sodium_crypto_rsign_open(string $sm, string $pk): string | |
{ | |
$opened = sodium_crypto_sign_open($sm, $pk); | |
return mb_substr($opened, 32, null, '8bit'); | |
} | |
/** | |
* @param string $message | |
* @param string $sk | |
* @return string | |
* @throws SodiumException | |
*/ | |
function sodium_crypto_rsign_detached(string $message, string $sk): string | |
{ | |
$random = random_bytes(32); | |
return sodium_crypto_sign_detached($random . $message, $sk) . $random; | |
} | |
/** | |
* @param string $signature | |
* @param string $message | |
* @param string $pk | |
* @return bool | |
* @throws SodiumException | |
*/ | |
function sodium_crypto_rsign_verify_detached(string $signature, string $message, string $pk): bool | |
{ | |
$sig = mb_substr($signature, 0, 64, '8bit'); | |
$random = mb_substr($signature, 64, 32, '8bit'); | |
return sodium_crypto_sign_verify_detached($sig, $random . $message, $pk); | |
} | |
/*** TESTS ***/ | |
$kp = sodium_crypto_sign_keypair(); | |
$sk = sodium_crypto_sign_secretkey($kp); | |
$pk = sodium_crypto_sign_publickey($kp); | |
# First test: Does it work? | |
$message = 'This is a test message.'; | |
$signed = sodium_crypto_rsign($message, $sk); | |
$ropen = sodium_crypto_rsign_open($signed, $pk); | |
if (!hash_equals($message, $ropen)) { | |
echo bin2hex($signed), PHP_EOL; | |
echo bin2hex($ropen), PHP_EOL; | |
exit(255); | |
} | |
# Second test: Is it backwards compatible? | |
$random = mb_substr($signed, 64, 32, '8bit'); | |
$open = sodium_crypto_sign_open($signed, $pk); | |
if (!hash_equals($random . $message, $open)) { | |
echo bin2hex($signed), PHP_EOL; | |
echo bin2hex($open), PHP_EOL; | |
exit(255); | |
} | |
# Third test: Detached API | |
$msg2 = 'Cryptography nerds in the kitchen have too much thyme on their hands.'; // Do you feel timing attacked? | |
$sig = sodium_crypto_rsign_detached($msg2, $sk); | |
$len = mb_strlen($sig, '8bit'); | |
if ($len !== SODIUM_CRYPTO_RSIGN_SIGBYTES) { | |
echo 'Expected ', SODIUM_CRYPTO_RSIGN_SIGBYTES, '; got ', $len, '.', PHP_EOL; | |
exit(255); | |
} | |
if (!sodium_crypto_rsign_verify_detached($sig, $msg2, $pk)) { | |
echo 'Invalid signature.', PHP_EOL; | |
exit(255); | |
} | |
$sig2 = sodium_crypto_rsign_detached($msg2, $sk); | |
if (hash_equals($sig, $sig2)) { | |
echo 'RNG Failure.', PHP_EOL; | |
echo bin2hex($sig), PHP_EOL; | |
echo bin2hex($sig2), PHP_EOL; | |
exit(255); | |
} | |
$sigLeft = mb_substr($sig, 0, 64, '8bit'); | |
$sigRight = mb_substr($sig, 64, 32, '8bit'); | |
if (!sodium_crypto_rsign_verify_detached($sigLeft, $sigRight . $msg2, $pk)) { | |
echo 'Invalid signature.', PHP_EOL; | |
exit(255); | |
} | |
echo 'All tests pass!', PHP_EOL; | |
exit(0); |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment