Search code examples
phpcaching

How to make PHP variable "stick" across multiple invocations of script?


In PHP, is there any way to make a variable "stick" across multiple invocations of my script? Specifically, I need to compute hash_hmac('sha-256', $data, $key) where data will probably be different on each invocation of my script, but key needs to remain the same for all invocations on a specific server (Apache2) instance. Actually what I need is that key is initialized to a pseudo-random value once per server (Apache2) instance. Please note that I do not want the key to be hard-coded or loaded from a config file. The key should be generated pseudo-randomly when the server (Apache2) instance is starting up, or when it is needed (read) for the first time. Also the key should "stick" in the memory for as long as the specific server instance running, but, as soon as the server instance is shutting down, it should be discarded with no way to re-construct it!

I would be fine if $_SERVER contained any value that is "unique" per server instance, with very high probability, so that I could just take that seed and pump it through a KDF in order to derive my unique key. But it seems there is no such entry in $_SERVER, or am I missing something?

Also, I can not use uniqid(), because it will give a different unique value on each call (script invocation), not a value that is unique per server (Apache2) instance.

Furthermore, I can not use Cookies or session_start(), because key is not supposed to be per-user, and it must not be visible to the users! I understand that contents of $_SESSION are not visible to the user(s), but I do not want to track any data per user when that is not necessary – and when it would only serve as a workaround for the inability to retain a single "global" value.

I could probably use an "in-memory" DB with something like SQLite, but this really feels like taking a sledgehammer to crack a nut. This "problem" of requiring a variable (value) to be initialized once and then "stick" across multiple invocations of a script seems like something that would arise naturally in many applications! So is there no simple straight-forward solution for this? 🤔


EDIT

For clarification: In this particular setup, there is no security risk in using the same MAC key for all users (of a particular server instance), because we never show that key to the user(s). We want to ensure that the user returns the "authentic" message to the same server instance where it was originally obtained from. If a user modifies its given message, we detect this on return, because the MAC doesn't match anymore. The same holds true, if the message was returned to the "wrong" server, because different servers shall have different MAC keys and so the MAC won't match. Using a separate key per user doesn't improve things in this scenario and just is not necessary, but it would add new complication (i.e. session management) that I really want to avoid...


Solution

  • Since a satisfying solution was not readily available, I spent the afternoon creating a simple PHP extension that does exactly what I need. Since it may be helpful for others, I'm posting it here.

    It generates a unique ID, via getentropy() system call, in the module initialization function, converts it to Base64 string and exposes it to the PHP user script as a constant via REGISTER_STRING_CONSTANT(). That is a straight-forward and efficient way to ensure that the ID is generated exactly once per server instance, when the server is starting up. It is then kept in "static" memory. Accessing the ID as a PHP constant also is much simpler than other approaches 😀

    It can be used like this:

    <?php
    echo 'Unique instance ID: "' . PHP_INSTANCE_UNIQID . '"' . PHP_EOL;
    ?>
    
    <?php
    $unique_key = hash_hkdf('sha256', PHP_INSTANCE_UNIQID_BINARY, 16, 'my-context');
    ?>
    

    See also:
    https://php-uniqueid.bitbucket.io/

    I'm still a bit surprised that something like this doesn't exist in PHP already...