Skip to content

Instantly share code, notes, and snippets.

@sbrl sbrl/comment_key.php Secret
Last active Oct 28, 2018

What would you like to do?
[Comment Key System] A comment key generation and verification system to prevent spam on low-value targets. #blog #antispam #microlibrary
* Comment Key Generation System
* By Starbeamrainbowlabs <>
* A set of functions to protect low-value comment boxes, contact us
* forms, etc. from spam.
* It works by recording the time the page the form is on was loaded,
* and then checking to make sure that it was loaded for at least
* 10 - 15 seconds, and not more than 24 hours.
* This is done by taking the current UNIX timestamp, running it through
* a number of (arbitrary) reversible transformations, and then
* embedding it in the form as a hidden field. When the form is
* submitted, the transformations are reversed and the time the page
* was loaded checked.
* Note that this is not suitable for high-value targets, as it can very
* easily be bypassed and reverse-engineered by any determined human.
* Changelog:
* 30th January 2018:
* Initial Release.
* 28th October 2018:
* Upgrade to use libsodium (PHP 7.2+ required, or the PECL module:
* Encodes the given data with base64, but replaces characters that could
* get mangled in transit with safer equivalents.
* @param mixed $data The data to encode.
* @return string The data, encoded as transmit-safe base64.
function base64_encode_safe($data) {
return str_replace(["/", "+"], ["-", "_"], base64_encode($data));
* Decodes data encoded with base64_encode_safe().
* @param mixed $base64 The data to decode.
* @return string The data, decoded from transmit-safe base64.
function base64_decode_safe($base64) {
return base64_decode(str_replace(["-", "_"], ["/", "+"], $base64));
* Generates a new random comment key system password.
* @return string The base64-encoded password.
function key_generate_password() {
return base64_encode_safe(random_bytes(SODIUM_CRYPTO_SECRETBOX_KEYBYTES));
* Generates a new comment key.
* Note that the 'encryption' used is not secure - it's just simple XOR!
* It's mainly to better support verification in complex setups and
* serve as a nother annoying hurdle for spammers.
* @param string $pass The password to encrypt with. Should be a base64-encoded string from key_generate_password().
* @return string A new comment key stamped at the current time.
function key_generate($pass) {
$pass = base64_decode_safe($pass);
$encrypt = sodium_crypto_secretbox(
strval(time()), // The thing we want to encrypt
$nonce, // The nonce
$pass // The password to encrypt with
return base64_encode_safe($nonce.$encrypt);
* Decodes the given key.
* @param string $key The key to decode.
* @param string $pass The password to decode it with.
* @return int|null The time that the key was generated, or null if the provided key was invalid.
function key_decode($key, $pass) {
$pass = base64_decode_safe($pass);
$key_enc_raw = base64_decode_safe($key);
$nonce = mb_substr($key_enc_raw, 0, SODIUM_CRYPTO_SECRETBOX_NONCEBYTES, "8bit");
$key_enc = mb_substr($key_enc_raw, SODIUM_CRYPTO_SECRETBOX_NONCEBYTES, null, "8bit");
$key_dec = sodium_crypto_secretbox_open($key_enc, $nonce, $pass);
if(!is_string($key_dec)) return null;
return intval($key_dec);
* Verifies a key.
* @param string $key The key to decode and verify.
* @param string $pass The password to decode the key with.
* @param int $min_age The minimum required age for the key.
* @param int $max_age The maximum allowed age for the key.
* @return bool Whether the key is valid or not.
function key_verify($key, $pass, $min_age, $max_age) {
$key_time = key_decode($key, $pass);
if($key_time == null) return false;
$age = time() - $key_time;
return $age >= $min_age && $age <= $max_age;
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
You can’t perform that action at this time.
You signed in with another tab or window. Reload to refresh your session. You signed out in another tab or window. Reload to refresh your session.