Instantly share code, notes, and snippets.

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

Embed
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
<?php
/***********************************************
* Comment Key Generation System
***********************************************
* By Starbeamrainbowlabs <feedback@starbeamrainbowlabs.com>
*
* 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: https://pecl.php.net/package/libsodium)
*/
/**
* 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);
$nonce = random_bytes(SODIUM_CRYPTO_SECRETBOX_NONCEBYTES);
$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